Outcome
Check whether the active verified human account has an explicit current application entitlement through any live organization membership, independent of selected context. Grants no resource or conversation access.
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.me.application_entitlement.get --detail --json
Input fields
| Field | Required | Meaning |
|---|---|---|
appId | Yes | Canonical application id from application discovery. Does not select another account or organization. |
Interpret the response
This input is appId, unlike app_id on surface session actions. It reads only the verified human account. appId is not an account or organization selector; duplicate queries and extra selectors are rejected.
data.accountId and data.appId identify the self-only decision. identityVerified, entitled and reason distinguish verification_required, active_entitlement and no_active_entitlement. evaluatedAt is the observation time. A successful false decision is HTTP 200; it neither removes history nor changes membership.
Portable entitlement evaluates current active organization memberships, enabled unexpired application grants and current seat policy independently of the selected browser/credential context. It exposes no organization billing or membership rows. It grants no workspace data, conversation membership or consent; protected operations must separately check those boundaries.
An organization API key, agent or service identity is refused. Expired/revoked account identity is HTTP 401. Store or seat-policy failure is HTTP 503 ENTITLEMENT_UNAVAILABLE, never an inferred positive or negative decision. The read is private, no-store and creates no reusable authorization token.
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.me.application_entitlement.get --data @payload.json --json
topolo actions plan app_topolo_auth.me.application_entitlement.get --data @payload.json --json
topolo actions call app_topolo_auth.me.application_entitlement.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.me.application_entitlement.get",
"input": {
"appId": "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.
Live entitlement is portable across selected context and exposes no organization details
Input · payload.json:
{
"appId": "app_topolo_chat"
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Account entitlement retrieved",
"data": {
"accountId": "usr_entitlement_fixture",
"appId": "app_topolo_chat",
"identityVerified": true,
"entitled": true,
"reason": "active_entitlement",
"evaluatedAt": "2026-10-05T00:00:00.000Z"
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
Live entitlement is portable across selected context and exposes no organization details. The decision reflects only the disclosed fixture state; resolve live identifiers and runtime authority separately.
No live membership is a successful negative entitlement decision
Input · payload.json:
{
"appId": "app_topolo_chat"
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Account entitlement retrieved",
"data": {
"accountId": "usr_entitlement_fixture",
"appId": "app_topolo_chat",
"identityVerified": true,
"entitled": false,
"reason": "no_active_entitlement",
"evaluatedAt": "2026-10-05T00:00:00.000Z"
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
No live membership is a successful negative entitlement decision. The decision reflects only the disclosed fixture state; resolve live identifiers and runtime authority separately.
Unverified account requires verification before entitlement
Input · payload.json:
{
"appId": "app_topolo_chat"
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Account entitlement retrieved",
"data": {
"accountId": "usr_entitlement_fixture",
"appId": "app_topolo_chat",
"identityVerified": false,
"entitled": false,
"reason": "verification_required",
"evaluatedAt": "2026-10-05T00:00:00.000Z"
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
Unverified account requires verification before entitlement. The decision reflects only the disclosed fixture state; resolve live identifiers and runtime authority separately.
Expired application grant is not active entitlement
Input · payload.json:
{
"appId": "app_topolo_chat"
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Account entitlement retrieved",
"data": {
"accountId": "usr_entitlement_fixture",
"appId": "app_topolo_chat",
"identityVerified": true,
"entitled": false,
"reason": "no_active_entitlement",
"evaluatedAt": "2026-10-05T00:00:00.000Z"
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
Expired application grant is not active entitlement. The decision reflects only the disclosed fixture state; resolve live identifiers and runtime authority separately.
Current seat policy denies the otherwise active organization grant
Input · payload.json:
{
"appId": "app_topolo_chat"
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "Account entitlement retrieved",
"data": {
"accountId": "usr_entitlement_fixture",
"appId": "app_topolo_chat",
"identityVerified": true,
"entitled": false,
"reason": "no_active_entitlement",
"evaluatedAt": "2026-10-05T00:00:00.000Z"
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
Current seat policy denies the otherwise active organization grant. The decision reflects only the disclosed fixture state; resolve live identifiers and runtime authority separately.
Verify the result
-
Match data.accountId to the authenticated account and data.appId to the discovered application.
-
Use entitled only for the portable application entitlement decision; independently verify resource membership and conversation consent. Re-evaluate on each protected operation; this is not a reusable authorization token.
Errors and recovery
Unavailable seat policy produces an unavailable decision
Input:
{
"appId": "app_topolo_chat"
}
Captured local refusal · HTTP 503:
{
"success": false,
"error": {
"message": "Account entitlement is temporarily unavailable",
"code": "ENTITLEMENT_UNAVAILABLE",
"details": null,
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
Revoked account token is refused
Input:
{
"appId": "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"
}
}
Service principal cannot inspect personal entitlement
Input:
{
"appId": "app_topolo_chat"
}
Captured local refusal · HTTP 403:
{
"success": false,
"error": {
"message": "A human account is required",
"code": "FORBIDDEN",
"details": null,
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
Organization selector is rejected before identity lookup
Input:
{
"appId": "app_topolo_chat",
"orgId": "org_entitlement_fixture"
}
Captured local refusal · HTTP 400:
{
"success": false,
"error": {
"message": "Supply one canonical appId only",
"code": "VALIDATION_ERROR",
"details": {
"appId": true
},
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
Organization API key cannot inspect personal entitlement
Input:
{
"appId": "app_topolo_chat"
}
Captured local refusal · HTTP 403:
{
"success": false,
"error": {
"message": "A human account session is required",
"code": "FORBIDDEN",
"details": null,
"timestamp": "2026-10-05T00:00:00.000Z"
}
}
-
AUTH_ERROR(HTTP 401): Use normal authentication after an expired, revoked or inactive account session. -
FORBIDDEN(HTTP 403): Use a first-party human account session. Organization API keys, agents and service credentials cannot inspect personal entitlement. -
VALIDATION_ERROR(HTTP 400): Supply only a discovered appId; arbitrary account, organization and duplicate query selectors are rejected. -
ENTITLEMENT_UNAVAILABLE(HTTP 503): Preserve the failure and retry this same read; never treat an unavailable decision as entitled.
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
Read-only. A false result does not delete history or restore a blocked relationship. Resolve verification or entitlement through published account and commercial actions; do not switch credential context to bypass denial.
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.