Outcome
Read sanitized security presence/lockout status, creating default security state if missing; passkey count failures are explicit.
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; a credential row id does not authorize a different user.
-
Use authorized identity and user/session discovery. Recovery security data and session/device identifiers must remain inside the caller-approved workflow.
Discover the target
topolo whoami --json
topolo apps --json
topolo actions get app_topolo_auth.user_security.get --detail --json
Use the caller subject or an authorized managed user from discovery. Read user_passkeys.list and copy credentials[].id for that exact user; credentialId is the WebAuthn identifier. Read user_security.get separately and inspect passkeyError.
Input fields
| Field | Required | Meaning |
|---|---|---|
userId | Yes | Existing Auth identity from authorized discovery. These actions allow self or a caller with management authority over that target user. Keep security/device information within the approved workflow. |
Effects
-
Reads security presence/lockout state; when missing, creates the default security row.
-
A failed passkey count is reported as hasPasskeys false plus passkeyError. No MFA or backup-code secret is returned.
Interpret the response
HTTP 200 raw target responses use success/message/data/timestamp; CLI/MCP may wrap or project them. Record timestamps are epoch seconds and the envelope timestamp is ISO text. These handlers prefer the access cookie when present, then Bearer. Fixture identity and target lookup are simulated; stored WebAuthn credentials are unusable and no real browser/authenticator ceremony or sign-in is proven.
Security status reports boolean presence/configuration and selected lockout counters/timestamps, without returning the MFA secret, backup codes, reset token or passkey material. Presence flags do not prove successful MFA authentication. When no security row exists, this GET creates default security state through the repository; readOnly metadata is not a promise of zero storage effects.
hasPasskeys false with a non-null passkeyError means the count lookup failed, not that no credentials exist. Security lookup failures themselves return SERVER_ERROR. Require passkeyError null and separately list credentials before deciding that removal or setup is needed.
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. Deleting a stored passkey does not clear the physical authenticator or existing Auth sessions. An alternate sign-in method and notification delivery require separate verification. Cookies and Bearer tokens must identify the intended principal consistently.
Status read creates missing default security state and reports stored passkey presence
Input · payload.json:
{
"userId": "usr_self"
}
CLI:
topolo actions validate app_topolo_auth.user_security.get --data @payload.json --json
topolo actions plan app_topolo_auth.user_security.get --data @payload.json --json
topolo actions call app_topolo_auth.user_security.get --data @payload.json --json
MCP call after validation and plan review:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.user_security.get",
"input": {
"userId": "usr_self"
}
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "2FA status retrieved",
"data": {
"userId": "usr_self",
"mfa_enabled": false,
"has_mfa_secret": false,
"has_backup_codes": false,
"hasPasskeys": true,
"passkeyError": null,
"security": {
"failed_login_attempts": 0,
"account_locked_until": null,
"created_at": 1790899200,
"updated_at": 1790899200
}
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
userId alias supports self security status
Input · payload.json:
{
"userId": "usr_self"
}
CLI:
topolo actions validate app_topolo_auth.user_security.get --data @payload.json --json
topolo actions plan app_topolo_auth.user_security.get --data @payload.json --json
topolo actions call app_topolo_auth.user_security.get --data @payload.json --json
MCP call after validation and plan review:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.user_security.get",
"input": {
"userId": "usr_self"
}
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "2FA status retrieved",
"data": {
"userId": "usr_self",
"mfa_enabled": false,
"has_mfa_secret": false,
"has_backup_codes": false,
"hasPasskeys": true,
"passkeyError": null,
"security": {
"failed_login_attempts": 0,
"account_locked_until": null,
"created_at": 1790899200,
"updated_at": 1790899200
}
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
Passkey lookup failure is reported as false with passkeyError, not proof of no credentials
Input · payload.json:
{
"userId": "usr_self"
}
CLI:
topolo actions validate app_topolo_auth.user_security.get --data @payload.json --json
topolo actions plan app_topolo_auth.user_security.get --data @payload.json --json
topolo actions call app_topolo_auth.user_security.get --data @payload.json --json
MCP call after validation and plan review:
{
"tool": "topolo_read_action",
"arguments": {
"actionId": "app_topolo_auth.user_security.get",
"input": {
"userId": "usr_self"
}
}
}
Captured local handler response · HTTP 200:
{
"success": true,
"message": "2FA status retrieved",
"data": {
"userId": "usr_self",
"mfa_enabled": false,
"has_mfa_secret": false,
"has_backup_codes": false,
"hasPasskeys": false,
"passkeyError": "Isolated passkey count SQL failure",
"security": {
"failed_login_attempts": 0,
"account_locked_until": null,
"created_at": 1790899200,
"updated_at": 1790899200
}
},
"timestamp": "2026-10-02T00:00:00.000Z"
}
Verify the result
-
Require data.userId to match the intended user. Interpret presence/configuration separately from successful MFA or lockout recovery.
-
Require passkeyError null before treating hasPasskeys as known; independently read user_passkeys.list and verify actual sign-in through the normal approved flow.
Errors and recovery
Foreign organization status is refused
Captured local refusal · HTTP 401:
{
"input": {
"userId": "usr_foreign"
},
"response": {
"success": false,
"error": {
"message": "Access denied: You can only view 2FA status for users in your organization",
"code": "AUTH_ERROR",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Missing status identity returns NOT_FOUND
Captured local refusal · HTTP 404:
{
"input": {
"userId": "usr_missing"
},
"response": {
"success": false,
"error": {
"message": "User not found",
"code": "NOT_FOUND",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Anonymous status read is refused
Captured local refusal · HTTP 401:
{
"input": {
"userId": "usr_self"
},
"response": {
"success": false,
"error": {
"message": "Access token required",
"code": "AUTH_ERROR",
"details": null,
"timestamp": "2026-10-02T00:00:00.000Z"
}
}
}
Published recovery guidance
-
AUTH_ERROR(HTTP 401): Verify the intended identity and cookie/Bearer transport, exact target-user authority and credential ownership. Authenticated authority/ownership denial also uses 401; do not infer OAuth expiry or switch contexts automatically. -
NOT_FOUND(HTTP 404): Refresh authorized user/credential discovery. Missing target or already-deleted credential is not a new successful deletion; do not substitute a WebAuthn credentialId for the internal row id. -
SERVER_ERROR(HTTP 500): Preserve the original error, verify approved authentication and rediscover current credential/security state before reviewing any retry. Do not treat storage failure or passkeyError as proof of zero credentials.
Recovery boundaries
Status discovery may create default security state. Do not delete that state as an inverse of a GET or reset MFA/password automatically. Preserve an unknown passkey count for authorized storage investigation.
Discovery and evidence
This record belongs to app_topolo_auth. Local tests prove real canonical security/passkey SQL, target-user authority and credential ownership with simulated tokens and identity lookup. Stored WebAuthn credentials are unusable and notifications are unconfigured. They do not prove live permissions, authenticator ceremony, successful alternate sign-in, delivered notification, deployment or production completion.