Skip to content

Implement WebAuthn-gated grant approval flow #69

@helixclaw

Description

@helixclaw

Summary

Wire the WebAuthn assertion into the grant approval flow so that approvals require successful biometric/passkey verification via the approval web UI.

Context

This is the core Phase 3 value: instead of approving via Discord reactions, the operator clicks a link, performs a WebAuthn assertion (Face ID, Touch ID, etc.), and the server issues the grant only after successful verification.

Acceptance Criteria

  • Server approval endpoints:
    • POST /api/approve/:requestId — requires valid WebAuthn assertion in request body
    • POST /api/deny/:requestId — requires valid CSRF token (no WebAuthn needed for deny)
  • Approval flow:
    1. Client creates request → server sends notification with approval link
    2. Operator clicks link → approval web UI loads
    3. Operator clicks "Approve" → WebAuthn assertion prompt
    4. Assertion verified → grant created + signed (JWS) → request status = approved
    5. Client polls and receives signed grant
  • Server policy config: approval.requireWebAuthn: boolean (default: false)
    • When true: only WebAuthn-verified approvals are accepted
    • When false: both Discord reactions and WebAuthn are valid (backward compatible)
  • Approval token: one-time use, expires in 10 minutes, tied to specific requestId
  • Audit: approval events logged with credential ID, timestamp, request details
  • Integration tests: full flow with mocked WebAuthn (simulated assertion)

Dependencies

Scope Boundaries

  • Does NOT replace Discord notifications (they now include a link instead of / in addition to reaction-based approval)
  • Does NOT change client-side injection logic

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions