Overview
Emergency access lets you designate trusted contacts who can request read access to your vault if you become incapacitated, lose your master password, or are otherwise unavailable. The system enforces a configurable waiting period during which you can approve or deny the request. If neither action is taken before the timer expires, access is granted automatically. This is distinct from family vault recovery, which uses Shamir’s Secret Sharing. Emergency access uses a wrapped key model where the access key is pre-encrypted at invite time and released only after authorization.How it works
Status lifecycle
| Status | Description |
|---|---|
pending_invite | Owner sent invite, contact has not accepted yet |
active | Contact accepted the invitation, no access requested |
access_requested | Contact initiated an access request, waiting period running |
access_granted | Access approved (manually or by timeout), 24-hour retrieval window |
access_denied | Owner explicitly denied the request |
access_expired | The 24-hour retrieval window has passed |
revoked | Owner permanently revoked the contact |
Invite flow
Owner adds a trusted contact
The vault owner enters the contact’s email address and configures a waiting period (in hours). A
wrapped_access_key and invite_salt are generated client-side and stored server-side. The invite token hash is computed for secure lookup.Invite email sent
PassAgent sends an email containing a link to
/emergency/{token}. The invite expires after 7 days if not accepted.The contact cannot be the same user as the vault owner. The server explicitly prevents self-invitations to avoid accidental misuse.
Access request flow
Contact requests access
The trusted contact initiates an emergency access request via
POST /api/vault/emergency/request. The record must be in active status.Waiting period begins
The server computes
grant_at = now + wait_hours and transitions the status to access_requested. The vault owner receives a notification.Owner responds (or does not)
The owner can approve or deny the request via
POST /api/vault/emergency/respond. If approved, the status moves to access_granted with a 24-hour retrieval window. If denied, the status becomes access_denied. If the owner takes no action and grant_at passes, access is granted automatically.Key exchange
The wrapped access key model ensures the server never holds the vault’s decryption key in plaintext.invite_salt provides domain separation so each emergency contact relationship uses a unique wrapping context. The wrapped blob is opaque to the server.
Waiting periods
- Short (1-6 hours)
- Medium (24-72 hours)
- Long (7+ days)
Best for close family members where you want fast access in a genuine emergency. The shorter window means less time to react if the request is unauthorized, but the owner still receives an immediate notification.
Owner controls
Revoking a contact
The vault owner can permanently revoke an emergency contact at any time usingDELETE /api/vault/emergency/{id}. This transitions the status to revoked regardless of the current state. A revoked contact cannot request access or be re-activated — a new invitation must be sent.
Updating wait hours
The owner can adjust thewait_hours value for any active contact. The change takes effect on the next access request. An in-progress request retains its original grant_at timestamp.
Rate limiting
All emergency access endpoints enforce rate limits to prevent abuse:| Endpoint | Limit | Window |
|---|---|---|
| Add contact | 5 requests | 60 seconds |
| Request access | 5 requests | 60 seconds |
| Respond (approve/deny) | 5 requests | 60 seconds |
| Accept invite | 5 requests | 60 seconds |
| Revoke contact | 5 requests | 60 seconds |
| Update wait hours | 5 requests | 60 seconds |
Audit logging
Every emergency access action is recorded in the audit log with full context:| Action | Logged metadata |
|---|---|
emergency_contact.add | Contact email, wait hours |
emergency_contact.accept | Vault owner ID |
emergency_access.request | Vault owner ID, wait hours, grant_at |
emergency_access.approve | Contact user ID, contact email |
emergency_access.deny | Contact user ID, contact email |
emergency_access.retrieve_key | Vault owner ID |
emergency_contact.revoke | (none) |
emergency_contact.update | New wait hours |
API endpoints
| Method | Endpoint | Description |
|---|---|---|
GET | /api/vault/emergency | List your emergency contacts (as owner and as contact) |
POST | /api/vault/emergency | Add a new trusted contact |
PATCH | /api/vault/emergency/[id] | Update wait hours for a contact (owner only) |
DELETE | /api/vault/emergency/[id] | Revoke an emergency contact (owner only) |
POST | /api/vault/emergency/accept | Accept an emergency contact invitation |
POST | /api/vault/emergency/request | Request emergency access to a vault |
POST | /api/vault/emergency/respond | Approve or deny an access request (owner only) |
GET | /api/vault/emergency/access | Retrieve the wrapped access key after approval |
Emergency access is a one-way mechanism: the contact receives read access to the owner’s vault. It does not grant the owner access to the contact’s vault, nor does it create a bidirectional trust relationship.