Outcome
Insert a new declared permission allow/deny override; repeated creation can duplicate rows and does not assign app access.
These examples prove local handler behavior with real isolated SQL and explicitly simulated identity/permission dependencies.
Before you start
-
Verify the intended authenticated identity and the current credential-scoped action before preparing input. Self and managed-user security operations have different authority; an override id does not authorize a different user or organization.
-
Use authorized identity and user/session discovery. Recovery security data and session/device identifiers must remain inside the caller-approved workflow.
-
Review the validated plan and intended effect before confirmation. Allow/deny changes and deny removal can change effective access. Capture current rows and evaluate the reviewed user/organization/application permissions before and after the confirmed decision. Fixture examples authorize no live mutation or external delivery.
Discover the target
topolo whoami --json
topolo apps --json
topolo actions get app_topolo_auth.user_permission_overrides.create --detail --json
Discover the exact user and organization membership, application and service_permissions.list entries. Read user_permission_overrides.list with exact org/app filters; use its row id, user and organization together. Read user_permissions.get separately for effective access.
Input fields
| Field | Required | Meaning |
|---|---|---|
userId | Yes | Existing Topolo identity from authorized user discovery. Read allows self or a permitted manager. Writes require an organization administrator role and authority over the actual override organization, not merely a known row id. |
orgId | Yes | Read filter or required create organization. The target identity must belong to it under the handler membership resolution. An omitted read filter queries this user across organizations; it is not a pagination cursor. Delete obtains organization from the exact stored user/override row and checks that organization authority. |
appId | Yes | Canonical application from credential-scoped discovery. Select the exact application owning the declared permission. An omitted read filter queries stored overrides across applications; override creation does not assign application access or a seat. |
permissionName | Yes | Declared permission name from service_permissions.list for this application. Unknown names currently produce SERVER_ERROR. Use the returned local permission name, not a fabricated cross-application wildcard. |
effect | Yes | allow or deny stored as a new explicit override. Duplicate and conflicting rows are permitted; repeated creation is not an upsert. Deny removal can increase effective access, so verify the complete role/grant/override evaluation before and after a change. |
expiresAt | No | Optional nonnegative integer epoch seconds or null. null/omission stores unbounded expiry. A past positive timestamp remains visible in stored-row listing while current evaluation treats it as inactive. Current evaluation treats zero as unbounded; do not use zero to expire access. |
Effects
-
Inserts one new declared permission allow/deny row with a fresh id, including on repeated identical calls.
-
Does not create app entitlement, membership, a seat or a role; audit errors are nonfatal.
Interpret the response
Raw target successes have success/message/data/timestamp; creation is HTTP 201 and read/delete are 200. CLI/MCP may wrap or project the response. Stored fields are snake_case with epoch seconds; the envelope timestamp is ISO text. Fixtures prove local canonical SQL/handler behavior with simulated token identity, target memberships and permission catalog partitions, not live effective permission enforcement.
Creation always inserts a fresh id; repeated calls can produce duplicate user/org/app/permission rows. allow and deny can coexist. The application must declare permissionName, but the write itself does not grant app membership or entitlement. Unknown declared permission is a current SERVER_ERROR. Nonfatal audit errors can follow a successful write.
A past positive expiry is stored, not rejected or omitted from the row list. Current evaluation treats null and zero as unbounded. Review actual user_permissions.get and protected application requests to establish effective access; the new row alone cannot prove an allow is effective or a deny is the only denying source.
The write requires organization role owner, super_admin or admin and actual organization authority. A direct platform_super_admin role alone is refused by this existing organization-role gate; discovery is not runtime authorization. Authenticated authority denial uses 401 AUTH_ERROR and does not by itself mean OAuth expired.
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. Storage read-back and actual sign-in outcomes require separate verification. Explicit rows do not assign app access or seats, and duplicate/conflicting overrides can remain. Removing a deny can increase access. Cookies and Bearer tokens must identify the intended principal consistently.
Create a declared allow override for the reviewed target organization/application
Input · payload.json:
{
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "allow"
}
CLI:
topolo actions validate app_topolo_auth.user_permission_overrides.create --data @payload.json --json
topolo actions plan app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
MCP call after validation and plan review:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_auth.user_permission_overrides.create",
"input": {
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "allow"
},
"confirm": true
}
}
Captured local handler response · HTTP 201:
{
"success": true,
"message": "User permission override created",
"data": {
"override": {
"id": "upo_FfLusJrOwlvd",
"user_id": "usr_managed",
"organization_id": "org_example",
"app_id": "app_topolo_campaigns",
"permission_name": "campaigns.read",
"effect": "allow",
"expires_at": null,
"created_at": 1790899200
}
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
Repeated creation creates a distinct stored override instead of an idempotent replacement
Input · payload.json:
{
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "allow"
}
CLI:
topolo actions validate app_topolo_auth.user_permission_overrides.create --data @payload.json --json
topolo actions plan app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
MCP call after validation and plan review:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_auth.user_permission_overrides.create",
"input": {
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "allow"
},
"confirm": true
}
}
Captured local handler response · HTTP 201:
{
"success": true,
"message": "User permission override created",
"data": {
"override": {
"id": "upo_E-G6cLsM_852",
"user_id": "usr_managed",
"organization_id": "org_example",
"app_id": "app_topolo_campaigns",
"permission_name": "campaigns.read",
"effect": "allow",
"expires_at": null,
"created_at": 1790899200
}
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
A deny for the same permission is a separate row alongside existing allows
Input · payload.json:
{
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "deny"
}
CLI:
topolo actions validate app_topolo_auth.user_permission_overrides.create --data @payload.json --json
topolo actions plan app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
MCP call after validation and plan review:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_auth.user_permission_overrides.create",
"input": {
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "deny"
},
"confirm": true
}
}
Captured local handler response · HTTP 201:
{
"success": true,
"message": "User permission override created",
"data": {
"override": {
"id": "upo_JnwqYI7Kow_Z",
"user_id": "usr_managed",
"organization_id": "org_example",
"app_id": "app_topolo_campaigns",
"permission_name": "campaigns.read",
"effect": "deny",
"expires_at": null,
"created_at": 1790899200
}
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
A past positive expiry is stored; current permission evaluation must treat it as expired
Input · payload.json:
{
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.write",
"effect": "allow",
"expiresAt": 1790899199
}
CLI:
topolo actions validate app_topolo_auth.user_permission_overrides.create --data @payload.json --json
topolo actions plan app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
MCP call after validation and plan review:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_auth.user_permission_overrides.create",
"input": {
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.write",
"effect": "allow",
"expiresAt": 1790899199
},
"confirm": true
}
}
Captured local handler response · HTTP 201:
{
"success": true,
"message": "User permission override created",
"data": {
"override": {
"id": "upo_7xT5fqF91l9B",
"user_id": "usr_managed",
"organization_id": "org_example",
"app_id": "app_topolo_campaigns",
"permission_name": "campaigns.write",
"effect": "allow",
"expires_at": 1790899199,
"created_at": 1790899200
}
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
Zero expiry is stored and current evaluator treats zero as unbounded, not expired
Input · payload.json:
{
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.write",
"effect": "allow",
"expiresAt": 0
}
CLI:
topolo actions validate app_topolo_auth.user_permission_overrides.create --data @payload.json --json
topolo actions plan app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
MCP call after validation and plan review:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_auth.user_permission_overrides.create",
"input": {
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.write",
"effect": "allow",
"expiresAt": 0
},
"confirm": true
}
}
Captured local handler response · HTTP 201:
{
"success": true,
"message": "User permission override created",
"data": {
"override": {
"id": "upo_nNFZ7808mFji",
"user_id": "usr_managed",
"organization_id": "org_example",
"app_id": "app_topolo_campaigns",
"permission_name": "campaigns.write",
"effect": "allow",
"expires_at": 0,
"created_at": 1790899200
}
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
Unbounded override creation stays successful when audit persistence fails
Input · payload.json:
{
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.write",
"effect": "allow",
"expiresAt": null
}
CLI:
topolo actions validate app_topolo_auth.user_permission_overrides.create --data @payload.json --json
topolo actions plan app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_permission_overrides.create --data @payload.json --confirm --json
MCP call after validation and plan review:
{
"tool": "topolo_call_action",
"arguments": {
"actionId": "app_topolo_auth.user_permission_overrides.create",
"input": {
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.write",
"effect": "allow",
"expiresAt": null
},
"confirm": true
}
}
Captured local handler response · HTTP 201:
{
"success": true,
"message": "User permission override created",
"data": {
"override": {
"id": "upo_D-HNMcoMC0yj",
"user_id": "usr_managed",
"organization_id": "org_example",
"app_id": "app_topolo_campaigns",
"permission_name": "campaigns.write",
"effect": "allow",
"expires_at": null,
"created_at": 1790899200
}
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
Verify the result
-
Read exact target org/app overrides and find the returned id with the requested effect/expiry. Check other duplicate/conflicting rows independently.
-
Read user_permissions.get in the exact organization/application and verify the intended protected request as the affected user. Expired and denied/role/app-access interactions need independent evaluation.
Errors and recovery
Undeclared application permission is a current repository server error
Captured local refusal · HTTP 500:
{
"input": {
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.unknown",
"effect": "allow"
},
"response": {
"success": false,
"error": {
"message": "Permission does not exist for this service",
"code": "SERVER_ERROR",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Admin cannot create a row in another target membership organization
Captured local refusal · HTTP 401:
{
"input": {
"userId": "usr_managed",
"orgId": "org_other",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "allow"
},
"response": {
"success": false,
"error": {
"message": "Access denied: You can only create overrides within your organization",
"code": "AUTH_ERROR",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Ordinary self member cannot create an administrator override
Captured local refusal · HTTP 401:
{
"input": {
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "allow"
},
"response": {
"success": false,
"error": {
"message": "Admin access required",
"code": "AUTH_ERROR",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Direct platform role is not accepted by the organization-admin role gate
Captured local refusal · HTTP 401:
{
"input": {
"userId": "usr_managed",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "allow"
},
"response": {
"success": false,
"error": {
"message": "Admin access required",
"code": "AUTH_ERROR",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Unknown target membership is refused before SQL
Captured local refusal · HTTP 400:
{
"input": {
"userId": "usr_managed",
"orgId": "org_missing",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "allow"
},
"response": {
"success": false,
"error": {
"message": "Target user does not belong to the provided organization",
"code": "VALIDATION_ERROR",
"details": {
"orgId": true
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Missing override target is not provisioned
Captured local refusal · HTTP 404:
{
"input": {
"userId": "usr_missing",
"orgId": "org_example",
"appId": "app_topolo_campaigns",
"permissionName": "campaigns.read",
"effect": "allow"
},
"response": {
"success": false,
"error": {
"message": "User not found",
"code": "NOT_FOUND",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
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 fields and resolve the target organization membership through authorized identity discovery. An app permission name must be declared; stored-row metadata does not assign an app entitlement. -
AUTH_ERROR(HTTP 401): Verify approved identity, organization-admin role, exact row organization authority and transport. Authenticated role/authority denial also uses 401; do not assume expiry or switch credential context automatically. -
NOT_FOUND(HTTP 404): Refresh the exact user/organization/application row list. Missing target or already-deleted/exact-user-mismatched override is not a successful new deletion. -
SERVER_ERROR(HTTP 500): Preserve the original error and rediscover current rows before reviewing a retry. Unknown permission names, token exceptions or storage errors are possible. Creation has no idempotency key; blindly retrying an unknown outcome can duplicate an override.
Recovery boundaries
Capture the prior stored rows and effective access. Deleting this exact newly returned id is a separate reviewed access decision: removing a deny may increase access. After an unknown response read rows before any retry; repeated create is not idempotent. Do not remove older valid grants or duplicate rows automatically.
Discovery and evidence
This record belongs to app_topolo_auth. Local tests prove real canonical override SQL, declared permission validation and exact stored-row organization authority with simulated tokens, target memberships and a permission catalog partition. They do not prove actual app assignment, effective access enforcement, live permissions, deployment or production completion.