Topolo Docs Topolo Platform
Open workspace

Revoke resource grant

Revoke one resource grant when the caller can manage its organization or holds target application grant authority.

Outcome

Revoke one resource grant when the caller can manage its organization or holds target application grant authority.

These examples prove local handler behavior with real isolated SQL and explicitly simulated identity/permission dependencies.

Before you start

  • Verify identity and the current credential-scoped action contract before preparing input. Resource-grant operations authorize the target organization/app at runtime; metadata discovery does not prove execution permission.

  • Discover the recipient and existing application resource. Use one exact organization/app/type/id tuple consistently; a grant never creates the target resource.

  • Review the validated plan and intended effect before confirmation. Capture previous grant settings before replacing/updating/revoking and all organization grants/membership before promotion.

Discover the target

topolo whoami --json
topolo apps --json
topolo actions get app_topolo_auth.resource_grants.revoke --detail --json

Discover the recipient and target resource using owning-application actions. Read app_topolo_auth.resource_grants.list_resource with the exact resource tuple and follow all pages.

Input fields

FieldRequiredMeaning
grantIdYesStored resource-grant id discovered through the exact resource listing; update and revoke resolve its own organization/app boundary. For an expired unrevoked row, use a previously captured exact id: live listings omit it, and no public historical grant lookup is exposed by this action family.
reasonNoOptional internal revocation reason; defaults to revoked. Repeated revocation returns the id without rewriting the original revocation reason.

Effects

  • Soft revokes this grant only; repeated revocation returns its id without restoring access.

Interpret the response

The raw target success envelope is success/message/data/timestamp. Create returns HTTP 201; all other successes return 200. CLI and MCP may wrap or project this envelope.

Grant id and createdAt remain stable when create updates the same user/organization/app/resourceType/resourceId key or reactivates a revoked grant. Omitted scope/type/metadata/expiry reset to create defaults rather than preserve previous values. Take a snapshot before replacing an existing grant.

Live lists omit revoked and expired rows. page.hasMore controls continuation; nextCursor is null at the end. list_mine contains only the authenticated subject, never a supplied userId. list_resource additionally returns recipient id/email/name or null when identity lookup is unavailable.

Create data.provisioned means this call created an unverified identity. It does not imply membership, invitation, sign-in, recipient acceptance or resource access. A create with past expiry can succeed with data.grant null because its stored row is already absent from live access.

Grant createdAt, expiresAt and revokedAt are epoch seconds; response timestamp is ISO text. Legacy create expiry strings can remain strings in stored output. Convert dates before planning; never infer live access from a successful storage response.

Update preserves identity and can extend an expired unrevoked grant. A revoked row is refused. Revoke returns only data.id, including on repeated revocation, and does not delete the recipient identity or affect separate membership/other grants.

Promote creates organization membership before revoking all non-workspace resource grants for that user and organization across apps. appId limits the permission check, not the revocation scope. These writes span databases and are not atomic; a 500 can leave membership active while grants remain. Read membership/effective access and remaining grants before any reviewed retry or compensation.

Promote data.role echoes the requested/default role. Existing membership, stored user role and effective authorization require separate verification. Notification delivery is nonfatal and is not proven by success. An empty list_mine after promotion does not mean the user has lost organization access.

AUTH_ERROR (401) is used both for absent/invalid tokens and for authenticated callers lacking organization or app grant authority. Inspect the error and identity before assuming OAuth expired; preserve authorization denials rather than changing credential context automatically.

Worked examples

These are complete raw target-handler responses, not CLI/gateway envelopes or live authorization proof. Replace synthetic identifiers using authorized discovery. Save only the reviewed input as payload.json; inspect validation and plan before executing. --confirm assumes the intended operation is approved. Metadata read-back requires separate recipient-principal and owning-application access tests.

Soft revoke removes this grant from live access

Input · payload.json:

{
  "grantId": "rg_JOD6QZYnE1JA",
  "reason": "review_completed"
}

CLI:

topolo actions validate app_topolo_auth.resource_grants.revoke --data @payload.json --json
topolo actions plan app_topolo_auth.resource_grants.revoke --data @payload.json --confirm --json
topolo actions call app_topolo_auth.resource_grants.revoke --data @payload.json --confirm --json

MCP call after validation and plan review:

{
  "tool": "topolo_call_action",
  "arguments": {
    "actionId": "app_topolo_auth.resource_grants.revoke",
    "input": {
      "grantId": "rg_JOD6QZYnE1JA",
      "reason": "review_completed"
    },
    "confirm": true
  }
}

Captured local handler response · HTTP 200:

{
  "success": true,
  "message": "Resource grant revoked",
  "data": {
    "id": "rg_JOD6QZYnE1JA"
  },
  "timestamp": "2026-10-02T18:01:40.148Z"
}

Repeated revoke returns the same id without undoing revocation

Input · payload.json:

{
  "grantId": "rg_JOD6QZYnE1JA"
}

CLI:

topolo actions validate app_topolo_auth.resource_grants.revoke --data @payload.json --json
topolo actions plan app_topolo_auth.resource_grants.revoke --data @payload.json --confirm --json
topolo actions call app_topolo_auth.resource_grants.revoke --data @payload.json --confirm --json

MCP call after validation and plan review:

{
  "tool": "topolo_call_action",
  "arguments": {
    "actionId": "app_topolo_auth.resource_grants.revoke",
    "input": {
      "grantId": "rg_JOD6QZYnE1JA"
    },
    "confirm": true
  }
}

Captured local handler response · HTTP 200:

{
  "success": true,
  "message": "Resource grant revoked",
  "data": {
    "id": "rg_JOD6QZYnE1JA"
  },
  "timestamp": "2026-10-02T18:01:40.148Z"
}

Verify the result

  • List the exact resource and confirm the revoked grant is absent. Read the recipient own live grants and verify the owning application denies this resource unless an independent membership/override still authorizes it.

  • Preserve recipient identity and unrelated grants/membership; data.id is acknowledgement, not a changed-row count or proof of global access removal.

Errors and recovery

Authenticated recipient cannot revoke own grant

Captured local refusal · HTTP 401:

{
  "input": {
    "grantId": "rg_JOD6QZYnE1JA"
  },
  "response": {
    "success": false,
    "error": {
      "message": "Not authorized to manage this organization",
      "code": "AUTH_ERROR",
      "details": null,
      "timestamp": "2026-10-02T18:01:40.150Z"
    }
  }
}

Missing grant cannot be revoked

Captured local refusal · HTTP 404:

{
  "input": {
    "grantId": "rg_missing"
  },
  "response": {
    "success": false,
    "error": {
      "message": "Resource grant not found",
      "code": "NOT_FOUND",
      "details": null,
      "timestamp": "2026-10-02T18:01:40.151Z"
    }
  }
}

Published recovery guidance

  • state_conflict (HTTP 409): Read the current resource state, reconcile the intended change, and retry only if still valid.

  • VALIDATION_ERROR (HTTP 400): Correct reported fields. Pair resource filters, preserve pagination cursors and use workspace access actions for workspace grants.

  • AUTH_ERROR (HTTP 401): Inspect identity and error message: invalid token and insufficient grant authority both use 401. Refresh an expired token when necessary; obtain intended access through its authorized owner for permission denials.

  • NOT_FOUND (HTTP 404): Rediscover the exact live resource grant. Revoked rows cannot be updated; creation reactivation is a separate reviewed access grant.

  • SERVER_ERROR (HTTP 500): Inspect actual stored state before retrying. Create can fail after identity provisioning; promote can fail after membership creation. Correct unsupported SQL-constrained scope/type input; do not treat a failure as proof that nothing changed.

Recovery boundaries

Reactivation requires separately approved create with the captured natural key and full previous settings. Do not automatically restore access after intentional revocation; independent memberships and grants are unaffected.

Discovery and evidence

This record belongs to app_topolo_auth. Local tests prove real resource-grant SQL and handler responses with simulated identity, permissions, identity lookup/provisioning and stored-role synchronization. They do not prove recipient sign-in, invitation delivery, owning-application resource enforcement, live permissions, deployment or production completion.