Skip to content

Passport suspension (temp hold): add 'suspended' status between active and revoked, reversible by admin #112

Description

@leocagli

Context

Currently passports are either active or permanently revoked. There is no intermediate state for temporary suspension — e.g. when an agent is under investigation or a payment dispute is open. A suspended status lets admins freeze a passport without permanently revoking it.

What to implement

Status addition

Add 'suspended' to the passport status union:

type PassportStatus = 'active' | 'revoked' | 'expired' | 'suspended'

Routes

  • POST /api/protocol/passport/[id]/suspend — set status to suspended; body: { reason: string }
  • POST /api/protocol/passport/[id]/unsuspend — set status back to active; body: { reason: string }

Both require admin auth. Both fire an audit log entry (issue #108) and a webhook event (passport.suspended / passport.unsuspended).

Authorization check

Any endpoint that validates a passport (spending, verification) must treat suspended as a denial — same as revoked, but with a distinct error code passport_suspended.

Acceptance criteria

  • POST /suspend → status becomes 'suspended'; subsequent spend attempts → 403 with code 'passport_suspended'
  • POST /unsuspend → status becomes 'active'; spend works again
  • Cannot unsuspend a revoked or expired passport (400)
  • Audit log entries for both actions
  • Unit tests: active → suspend → verify denied; unsuspend → verify allowed

🎁 Evidencia visual = reward extra

  • Si tu PR incluye video demo o capturas de pantalla mostrando la funcionalidad pedida funcionando end-to-end, va a ser considerado para rewards de GrantFox en esta issue. No es obligatorio, pero suma mucho para la evaluación.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions