Outcome
List published logo assets from Brand kits the caller may read; workspace management access is also required.
Captures exercise real Auth/workspace handlers and canonical isolated SQL. Identity, Brand responses and the object store are simulated.
Before you start
-
Verify the pinned identity and exact app/organization/workspace from workspaces.list. Runtime authorization requires its workspace owner, organization owner/super_admin or verified platform authority; an ordinary organization admin who is not its owner is refused.
-
Resolve Brand choices through workspaces.avatar.options for this target; its Brand workspace is separate from the workspace whose avatar changes. Brand access and immutable logo publication require their own proof.
-
Retain the prior preset/Brand reference or original image before a mutation, review the exact plan and its compensation, and read canonical state after an unknown result before retrying.
-
Uploaded raster URLs are public to anyone holding the URL and permit a five-minute browser cache. Use an image suitable for public access; replacing/removing stored bytes cannot recall downloaded or cached copies.
Discover the target
topolo whoami --json
topolo actions get app_topolo_auth.workspaces.avatar.options --detail --json
After discovering the application, run topolo workspaces list <discovered-application> --json, replacing <discovered-application> with its exact published application id or slug.
Read workspaces.avatar.options with the exact workspaceId, app_id and org_id to discover accessible published Brand kit/asset choices.
Input fields
| Field | Required | Meaning |
|---|---|---|
workspaceId | Yes | Existing exact-app workspace id from workspaces.list. This is the workspace whose avatar changes, not the Brand workspace used to resolve logo choices. |
app_id | Yes | GET query spelling of the canonical target application id. Resolve it with the workspace; do not replace this published field with appId. |
org_id | Yes | GET query spelling of the authorized target organization id. Keep it consistent with the workspace and verified principal. |
Effects
-
Reads eligible published logo/icon choices under the caller-accessible Brand workspace context.
-
Does not grant Brand entitlement, publish a kit or change an avatar.
Interpret the response
Workspace management is authorized for this exact app, organization and workspace. The workspace owner can manage its own workspace. Organization owner/super_admin and verified platform authority can manage others; an ordinary organization admin who is not the workspace owner is refused. Seating in the application is separate from this management authority.
brands is a complete unpaginated list of eligible published logo/icon choices from the caller-accessible Brand workspaces. brandKitId and assetId form the selection; name is a display label and url is the resolved public asset URL.
No Brand entitlement/workspace returns an empty list without contacting Brand. Retired/unpublished kits are omitted. An upstream permission or availability failure is a refusal, not a successful empty list. Resolve Brand access and publication separately; this read grants neither.
Local fixture Brand responses and entitlement checks are explicitly simulated. Live Brand visibility, immutable publication, user authority and browser rendering need separate development/staging proof.
Worked examples
All ids, public URLs and raster bytes below are synthetic local fixtures. Resolve authorized live targets and review the exact unchanged plan before execution. These raw target responses do not prove the live gateway, provider persistence, public rendering or cache invalidation.
Owner discovers published Brand logo and icon choices through its Brand workspace
Input · payload.json:
{
"workspaceId": "ws_avatar_fixture",
"app_id": "app_topolo_web",
"org_id": "org_avatar_fixture"
}
CLI:
topolo actions validate app_topolo_auth.workspaces.avatar.options --data @payload.json --json
topolo actions plan app_topolo_auth.workspaces.avatar.options --data @payload.json --json
topolo actions call app_topolo_auth.workspaces.avatar.options --data @payload.json --detail --json
MCP call after topolo_validate_action and topolo_plan_action on this same input:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.workspaces.avatar.options",
"input": {
"workspaceId": "ws_avatar_fixture",
"app_id": "app_topolo_web",
"org_id": "org_avatar_fixture"
}
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Brand avatars",
"data": {
"brands": [
{
"brandKitId": "kit_fixture",
"assetId": "logo_fixture",
"name": "Fixture Brand · Mark",
"url": "https://brand.topolo.dev/public/fixture-logo.png"
},
{
"brandKitId": "kit_fixture",
"assetId": "icon_fixture",
"name": "Fixture Brand · Icon",
"url": "https://brand.topolo.dev/public/fixture-icon.png"
}
]
},
"timestamp": "2026-10-03T00:00:00.000Z"
}
No Brand entitlement yields empty choices without a Brand request
Input · payload.json:
{
"workspaceId": "ws_avatar_fixture",
"app_id": "app_topolo_web",
"org_id": "org_avatar_fixture"
}
CLI:
topolo actions validate app_topolo_auth.workspaces.avatar.options --data @payload.json --json
topolo actions plan app_topolo_auth.workspaces.avatar.options --data @payload.json --json
topolo actions call app_topolo_auth.workspaces.avatar.options --data @payload.json --detail --json
MCP call after topolo_validate_action and topolo_plan_action on this same input:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.workspaces.avatar.options",
"input": {
"workspaceId": "ws_avatar_fixture",
"app_id": "app_topolo_web",
"org_id": "org_avatar_fixture"
}
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Brand avatars",
"data": {
"brands": []
},
"timestamp": "2026-10-03T00:00:00.000Z"
}
Verify the result
- Use only returned brandKitId/assetId pairs with workspaces.avatar.set; verify the intended target workspace and published public logo independently.
Errors and recovery
Ordinary non-owner cannot enumerate choices for another workspace
Input:
{
"workspaceId": "ws_avatar_fixture",
"app_id": "app_topolo_web",
"org_id": "org_avatar_fixture"
}
Captured local refusal · HTTP 403 · application/json:
{
"success": false,
"error": {
"message": "Only the workspace owner or an organization administrator can manage this workspace",
"code": "FORBIDDEN",
"details": null,
"timestamp": "2026-10-03T00:00:00.000Z"
}
}
Brand permission failure is a refusal rather than an empty list
Input:
{
"workspaceId": "ws_avatar_fixture",
"app_id": "app_topolo_web",
"org_id": "org_avatar_fixture"
}
Captured local refusal · HTTP 403 · application/json:
{
"success": false,
"error": {
"message": "Topolo Brand refused this consumer",
"code": "FORBIDDEN",
"details": null,
"timestamp": "2026-10-03T00:00:00.000Z"
}
}
Brand availability failure is not proof of zero choices
Input:
{
"workspaceId": "ws_avatar_fixture",
"app_id": "app_topolo_web",
"org_id": "org_avatar_fixture"
}
Captured local refusal · HTTP 500 · application/json:
{
"success": false,
"error": {
"message": "Could not update workspace avatar",
"code": "SERVER_ERROR",
"details": null,
"timestamp": "2026-10-03T00:00:00.000Z"
}
}
Published recovery guidance
-
AUTH_ERROR(HTTP 401): Verify the pinned identity and cookie/Bearer context. Refresh only an actually expired credential; do not substitute another identity after target denial. -
FORBIDDEN(HTTP 403): Resolve the same app/organization/workspace and its exact management authority. An ordinary seated member or organization admin is not authority over another owner’s workspace; respect refusal. -
NOT_FOUND(HTTP 404): Rediscover the existing exact-app workspace. This action does not provision it. -
VALIDATION_ERROR(HTTP 400): Validate the declared input. For Brand selections discover current published logo/icon choices; for uploads correct encoding, signature, MIME and decoded size. -
SERVER_ERROR(HTTP 500): Read canonical workspace/profile state before retrying: the write may have committed before old-object cleanup. Preserve sanitized evidence and use the authorized maintainer for storage/upstream incidents; no direct storage repair is published here.
Recovery boundaries
This read has no rollback. Verify the authorized workspace, Brand access and published kit state; after the underlying issue is resolved, perform a fresh read. Upstream failure is not an empty catalog.
Discovery and evidence
This record belongs to Auth. Candidate human/machine URLs become valid only after native publication. Real canonical core/access migrations, identity/workspace SQL, raster validation, Brand response parsing and JSON/binary response construction were exercised. In-memory image storage, identities, seating, Brand workspace discovery and HTTP responses, ids/clock and fault injection are simulated. No live user photo, workspace avatar, Brand publication, OAuth state or Cloudflare object was changed.