Outcome
Read current account and work-resource availability without selecting or changing the browser organisation or the credential context.
Before you start
-
Verify the human identity and intended pinned credential context, then discover the canonical application. The fixture identities and signing output below are synthetic and unusable.
-
Keep account eligibility, surface/workspace availability and operation-specific permission or conversation consent separate. A result here never widens authority.
Discover the application
topolo whoami --json
topolo apps --json
topolo actions get app_topolo_auth.surface_sessions.get --detail --json
Input fields
| Field | Required | Meaning |
|---|---|---|
app_id | Yes | Registered application to scope the surface to. Does not select an account or organisation. |
Interpret the response
Use app_id from application discovery. data.account_id identifies the caller; surface_session.version=1 and appId identify the projection. Each context has its own permissions and workspace resources. A verified Chat account may retain a personal context with role=account, no permissions and no workspaces after work access is removed; this grants no messaging entitlement or conversation consent.
The handler reads fresh active identity and memberships. Suspended/inactive memberships and unauthorized application contexts are omitted. Workspace IDs, default flags and access levels are observations; the target operation must recheck authority. A first-party context-RBAC CLI/MCP credential remains within its pinned organization, including when the account has other memberships.
Bearer reads return no csrf_token and set no cookies. A browser Chat read uses X-Topolo-Auth: 1 plus a live session and unrevoked refresh cookie. It returns a matching existing host-only CSRF nonce or sets one when absent. Keep that nonce in memory for a cookie-authenticated create; it is not an access token or sign-in renewal.
No accessible context is HTTP 403, a revoked account is HTTP 401 and policy failure is HTTP 503 SURFACE_UNAVAILABLE. The read uses Cache-Control: private, no-store.
Run the action
Write the discovered application id to payload.json. Validate and plan the unchanged input. This published read requires no mutation confirmation.
topolo actions validate app_topolo_auth.surface_sessions.get --data @payload.json --json
topolo actions plan app_topolo_auth.surface_sessions.get --data @payload.json --json
topolo actions call app_topolo_auth.surface_sessions.get --data @payload.json --detail --json
MCP uses topolo_validate_action and topolo_plan_action for the same input, followed by topolo_read_action.
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.surface_sessions.get",
"input": {
"app_id": "app_topolo_chat"
}
}
}
Worked responses
Every example uses synthetic identities and a fixed clock. Cookie/browser and credential state described in a title is a fixture precondition, not an extra action-input field. Responses below are the raw handler envelope; protected tooling may replace returned credential values with opaque references.
Verified account retains personal history context and only the currently authorized Alpha workspace
Input · payload.json:
{
"app_id": "app_topolo_chat"
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Surface session retrieved",
"data": {
"account_id": "usr_surface_fixture",
"surface_session": {
"version": 1,
"appId": "app_topolo_chat",
"contexts": [
{
"type": "personal",
"id": "usr_surface_fixture",
"label": "Personal",
"slug": null,
"role": "account",
"permissions": [],
"resources": []
},
{
"type": "organization",
"id": "org_surface_alpha",
"label": "Alpha fixture",
"slug": "alpha-fixture",
"role": "member",
"permissions": [
"direct_messages:read"
],
"resources": [
{
"type": "workspace",
"id": "ws_surface_alpha",
"label": "Alpha workspace",
"slug": "alpha-workspace",
"isDefault": true,
"accessLevel": "read_write"
}
]
}
]
}
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
Verified account retains personal history context and only the currently authorized Alpha workspace. The decision reflects only the disclosed fixture state; resolve live identifiers and runtime authority separately.
Revoked work membership leaves a personal context with no workspace grants
Input · payload.json:
{
"app_id": "app_topolo_chat"
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Surface session retrieved",
"data": {
"account_id": "usr_surface_fixture",
"surface_session": {
"version": 1,
"appId": "app_topolo_chat",
"contexts": [
{
"type": "personal",
"id": "usr_surface_fixture",
"label": "Personal",
"slug": null,
"role": "account",
"permissions": [],
"resources": []
}
]
}
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
Revoked work membership leaves a personal context with no workspace grants. The decision reflects only the disclosed fixture state; resolve live identifiers and runtime authority separately.
First-party context-RBAC credential retains its Alpha organization boundary
Input · payload.json:
{
"app_id": "app_topolo_chat"
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Surface session retrieved",
"data": {
"account_id": "usr_surface_fixture",
"surface_session": {
"version": 1,
"appId": "app_topolo_chat",
"contexts": [
{
"type": "personal",
"id": "usr_surface_fixture",
"label": "Personal",
"slug": null,
"role": "account",
"permissions": [],
"resources": []
},
{
"type": "organization",
"id": "org_surface_alpha",
"label": "Alpha fixture",
"slug": "alpha-fixture",
"role": "member",
"permissions": [
"direct_messages:read"
],
"resources": [
{
"type": "workspace",
"id": "ws_surface_alpha",
"label": "Alpha workspace",
"slug": "alpha-workspace",
"isDefault": true,
"accessLevel": "read_write"
}
]
}
]
}
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
First-party context-RBAC credential retains its Alpha organization boundary. The decision reflects only the disclosed fixture state; resolve live identifiers and runtime authority separately.
Live browser session and refresh record with matching existing CSRF nonce
Input · payload.json:
{
"app_id": "app_topolo_chat"
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Surface session retrieved",
"data": {
"account_id": "usr_surface_fixture",
"surface_session": {
"version": 1,
"appId": "app_topolo_chat",
"contexts": [
{
"type": "personal",
"id": "usr_surface_fixture",
"label": "Personal",
"slug": null,
"role": "account",
"permissions": [],
"resources": []
},
{
"type": "organization",
"id": "org_surface_alpha",
"label": "Alpha fixture",
"slug": "alpha-fixture",
"role": "member",
"permissions": [
"direct_messages:read"
],
"resources": [
{
"type": "workspace",
"id": "ws_surface_alpha",
"label": "Alpha workspace",
"slug": "alpha-workspace",
"isDefault": true,
"accessLevel": "read_write"
}
]
}
]
},
"csrf_token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
Live browser session and refresh record with matching existing CSRF nonce. The decision reflects only the disclosed fixture state; resolve live identifiers and runtime authority separately.
Verify the result
-
Read surface_sessions.get with the same app_id and credential. Match account_id and the application; each workspace must remain within the returned context.
-
Projection metadata grants neither messaging entitlement nor conversation membership. Resource operations must recheck current authorisation.
Errors and recovery
An API key cannot substitute for a human source credential
Input:
{
"app_id": "app_topolo_chat"
}
Captured local refusal · HTTP 403:
{
"success": false,
"error": {
"message": "A human sign-in is required",
"code": "FORBIDDEN",
"details": null,
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
Token version predates current account revocation
Input:
{
"app_id": "app_topolo_chat"
}
Captured local refusal · HTTP 401:
{
"success": false,
"error": {
"message": "Invalid or revoked account session",
"code": "AUTH_ERROR",
"details": null,
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
Unverified account without a work context has no available Chat surface
Input:
{
"app_id": "app_topolo_chat"
}
Captured local refusal · HTTP 403:
{
"success": false,
"error": {
"message": "User does not have access to this surface",
"code": "FORBIDDEN",
"details": null,
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
Canonical-looking identifier is not a registered application
Input:
{
"app_id": "app_unknown_fixture"
}
Captured local refusal · HTTP 400:
{
"success": false,
"error": {
"message": "app_id is not registered",
"code": "VALIDATION_ERROR",
"details": {
"app_id": true
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
An organization selector cannot widen or change the credential
Input:
{
"app_id": "app_topolo_chat",
"orgId": "org_surface_beta"
}
Captured local refusal · HTTP 400:
{
"success": false,
"error": {
"message": "Supply one registered app_id only",
"code": "VALIDATION_ERROR",
"details": {
"app_id": true
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
Unavailable workspace policy is an error, not an empty grant
Input:
{
"app_id": "app_topolo_chat"
}
Captured local refusal · HTTP 503:
{
"success": false,
"error": {
"message": "Account surface is temporarily unavailable",
"code": "SURFACE_UNAVAILABLE",
"details": null,
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
Revoked browser refresh record cannot renew or recover sign-in
Input:
{
"app_id": "app_topolo_chat"
}
Captured local refusal · HTTP 401:
{
"success": false,
"error": {
"message": "Browser sign-in revoked or expired",
"code": "AUTH_ERROR",
"details": null,
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
Duplicate application query is rejected
Input:
{
"app_id": "app_topolo_chat"
}
Captured local refusal · HTTP 400:
{
"success": false,
"error": {
"message": "Supply one registered app_id only",
"code": "VALIDATION_ERROR",
"details": {
"app_id": true
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
-
AUTH_ERROR(HTTP 401): Sign in normally after expiry or revocation. A stale refresh credential cannot recover a session. -
FORBIDDEN(HTTP 403): Use a first-party human credential for the requested surface. Cookie creation requires the matching CSRF token from the credentialed surface read. Do not switch context to bypass denial. -
VALIDATION_ERROR(HTTP 400): Discover the application and supply only app_id. A surface token cannot mint another surface token. -
SURFACE_UNAVAILABLE(HTTP 503): Retry the same request when Auth is available; do not infer an access grant from failure.
Tooling error categories
CLI/MCP may separately report authentication_required, permission_denied, rate_limited, invalid_input or dependency_unavailable. These are tooling/catalog categories; preserve the underlying handler code and status shown above when deciding recovery. Do not assume a handler emitted a tooling category.
Recovery boundary
Revoked memberships disappear on the next read; a retained personal context is not work access. The browser verification nonce does not extend or recover a sign-in.
Evidence
Existing isolated handlers; no live session, credential, membership, entitlement or provider was changed.
Actual dependencies: HTTP response serialization and strict input validation; Account identity, token-version and CSRF policy checks; Surface projection and TTL issuer calculation; Portable entitlement SQL evaluated by SQLite.
Simulated dependencies: Access/refresh credential verification and synthetic unusable signing output; Registry, hydrated identity, workspace and permission repositories; Seat-policy decision; minimal entitlement schema is not the full migration database; Fixed clock and deliberately synthetic records.
These captures prove existing handler serialization and selected policy branches with disclosed simulations. They do not prove live signing, production grants, multi-D1 consistency or a real cookie/JWT authentication journey. No business credential operation was executed.