Aug 26 - Enhance security 4
CI / Python lint (flake8) (push) Has been cancelled
CI / Python syntax check (push) Has been cancelled
CI / Alembic migration chain (push) Has been cancelled
CI / JavaScript syntax check (push) Has been cancelled
CI / Pytest (push) Has been cancelled
CI / Build extension zip (push) Has been cancelled

This commit is contained in:
2026-08-26 14:19:25 -04:00
parent cc216b0d98
commit b84a6d9245
11 changed files with 546 additions and 33 deletions
@@ -0,0 +1,49 @@
"""add vault retrieval tracking to emergency_access
Revision ID: l2m3n4o5p6q7
Revises: k1l2m3n4o5p6
Create Date: 2026-08-26 00:00:00.000000
Makes emergency-vault retrieval visible to the grantor.
Previously GET /api/emergency/<id>/vault neither changed the record nor recorded
anything the grantor could see: the audit entry was written under the *grantee's*
user_id, and /api/auth/audit-log filters by user_id, so it never appeared in the
grantor's own log. Combined with the status never advancing past 'pending', a
grantee could re-fetch the snapshot indefinitely with nothing surfacing to the
person whose vault it was.
vault_retrieved_at — when the snapshot was FIRST retrieved (NULL = never)
vault_retrieval_count — how many times, so repeated access is visible
Retrieval is deliberately NOT blocked after the first time: the whole premise of
emergency access is that the grantor may be unable to re-provision, and a browser
crash mid-import must not permanently strand the grantee. The wait period remains
the gate; these columns plus the dual audit entries make use of that access
auditable, and the grantor can still revoke with DELETE at any point.
"""
from alembic import op
import sqlalchemy as sa
revision = 'l2m3n4o5p6q7'
down_revision = 'k1l2m3n4o5p6'
branch_labels = None
depends_on = None
def upgrade():
op.add_column(
'emergency_access',
sa.Column('vault_retrieved_at', sa.DateTime, nullable=True),
)
op.add_column(
'emergency_access',
sa.Column('vault_retrieval_count', sa.Integer,
nullable=False, server_default='0'),
)
def downgrade():
op.drop_column('emergency_access', 'vault_retrieval_count')
op.drop_column('emergency_access', 'vault_retrieved_at')