Topolo Docs Topolo Platform
Open workspace

Delete user passkey

Delete the exact target user credential record after verifying alternate sign-in; existing sessions and authenticator data are unchanged.

Outcome

Delete the exact target user credential record after verifying alternate sign-in; existing sessions and authenticator data are unchanged.

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.

  • Review the validated plan and intended effect before confirmation. Passkey deletion can remove the last passkey; verify an alternate working sign-in method first. Presence and lockout flags do not prove successful authentication. 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_passkeys.delete --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

FieldRequiredMeaning
userIdYesExisting 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.
passkeyIdYesInternal credential row id from user_passkeys.list credentials[].id for this exact user, not credentialId, which is the WebAuthn credential identifier. Verify a separate usable sign-in method before approving removal of a sole passkey.

Effects

  • Deletes only the stored credential belonging to the selected user; keeps unrelated users/credentials.

  • Sole-passkey removal is permitted. Audit/lifecycle notification failures are nonfatal; physical authenticator data and existing Auth sessions are unchanged.

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.

The handler checks the stored credential belongs to the selected user and deletes by row id plus user id. data.userId/passkeyId/deleted acknowledge that exact row. A known foreign credential is refused, and repeated deletion is NOT_FOUND. It can delete the sole passkey without proving another sign-in route exists; verify an alternate working method before confirming.

Deleting the Auth record does not erase the credential from the physical authenticator, unlink external providers, disable TOTP, revoke existing Auth sessions or change the password. Lifecycle notification and audit are nonfatal; success does not prove an alert was delivered. The fixture has unconfigured notifications and forbids live fetch.

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.

Self deletes exactly its selected stored passkey; notification is unconfigured

Input · payload.json:

{
  "userId": "usr_self",
  "passkeyId": "passkey_first"
}

CLI:

topolo actions validate app_topolo_auth.user_passkeys.delete --data @payload.json --json
topolo actions plan app_topolo_auth.user_passkeys.delete --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_passkeys.delete --data @payload.json --confirm --json

MCP call after validation and plan review:

{
  "tool": "topolo_call_action",
  "arguments": {
    "actionId": "app_topolo_auth.user_passkeys.delete",
    "input": {
      "userId": "usr_self",
      "passkeyId": "passkey_first"
    },
    "confirm": true
  }
}

Captured local handler response · HTTP 200:

{
  "success": true,
  "message": "Passkey deleted successfully",
  "data": {
    "userId": "usr_self",
    "passkeyId": "passkey_first",
    "deleted": true
  },
  "timestamp": "2026-10-02T00:00:00.000Z"
}

Administrator may delete the sole managed-user passkey; alternate sign-in needs separate proof

Input · payload.json:

{
  "userId": "usr_managed",
  "passkeyId": "passkey_managed"
}

CLI:

topolo actions validate app_topolo_auth.user_passkeys.delete --data @payload.json --json
topolo actions plan app_topolo_auth.user_passkeys.delete --data @payload.json --confirm --json
topolo actions call app_topolo_auth.user_passkeys.delete --data @payload.json --confirm --json

MCP call after validation and plan review:

{
  "tool": "topolo_call_action",
  "arguments": {
    "actionId": "app_topolo_auth.user_passkeys.delete",
    "input": {
      "userId": "usr_managed",
      "passkeyId": "passkey_managed"
    },
    "confirm": true
  }
}

Captured local handler response · HTTP 200:

{
  "success": true,
  "message": "Passkey deleted successfully",
  "data": {
    "userId": "usr_managed",
    "passkeyId": "passkey_managed",
    "deleted": true
  },
  "timestamp": "2026-10-02T00:00:00.000Z"
}

Verify the result

  • Read user_passkeys.list for the same user and require the acknowledged id to be absent while unrelated credentials remain. Independently check security status with passkeyError null.

  • Verify the removed credential can no longer establish a new session through the actual WebAuthn ceremony, and that the approved alternate sign-in method works. Verify any notification delivery independently; deletion success alone proves neither.

Errors and recovery

A known foreign credential cannot be deleted through a self target

Captured local refusal · HTTP 401:

{
  "input": {
    "userId": "usr_self",
    "passkeyId": "passkey_foreign"
  },
  "response": {
    "success": false,
    "error": {
      "message": "Credential does not belong to the specified user",
      "code": "AUTH_ERROR",
      "details": null,
      "timestamp": "2026-10-02T00:00:00.000Z"
    }
  }
}

Repeated deletion reports missing credential

Captured local refusal · HTTP 404:

{
  "input": {
    "userId": "usr_self",
    "passkeyId": "passkey_first"
  },
  "response": {
    "success": false,
    "error": {
      "message": "Passkey credential not found",
      "code": "NOT_FOUND",
      "details": null,
      "timestamp": "2026-10-02T00:00:00.000Z"
    }
  }
}

Foreign user deletion is denied before credential lookup

Captured local refusal · HTTP 401:

{
  "input": {
    "userId": "usr_foreign",
    "passkeyId": "passkey_foreign"
  },
  "response": {
    "success": false,
    "error": {
      "message": "Access denied: You can only delete your own passkeys",
      "code": "AUTH_ERROR",
      "details": null,
      "timestamp": "2026-10-02T00:00:00.000Z"
    }
  }
}

Missing delete target is not provisioned

Captured local refusal · HTTP 404:

{
  "input": {
    "userId": "usr_missing",
    "passkeyId": "passkey_foreign"
  },
  "response": {
    "success": false,
    "error": {
      "message": "User not found",
      "code": "NOT_FOUND",
      "details": null,
      "timestamp": "2026-10-02T00:00:00.000Z"
    }
  }
}

Anonymous credential deletion is refused

Captured local refusal · HTTP 401:

{
  "input": {
    "userId": "usr_self",
    "passkeyId": "passkey_second"
  },
  "response": {
    "success": false,
    "error": {
      "message": "Access token required",
      "code": "AUTH_ERROR",
      "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.

  • 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

No un-delete operation restores the original credential. Re-registration requires the user/authenticator browser ceremony and a separately approved registration begin/complete workflow. Never recreate a row from copied public-key/counter data. After an unknown outcome list current credentials before reviewing a retry; keep an alternate working sign-in route.

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.