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
50 lines
1.7 KiB
Python
50 lines
1.7 KiB
Python
"""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')
|