New usage_events table, separate from audit_log - see the model docstring for why. Verified: applies and downgrades cleanly on SQLite, and the postgresql-dialect --sql render has no risky defaults (the BL-027 class of defect). No app wiring yet - that's T11.2.
47 lines
1.9 KiB
Python
47 lines
1.9 KiB
Python
"""usage events (CR-019, wave 11)
|
|
|
|
Append-only navigation/session activity, separate from audit_log on purpose —
|
|
see the UsageEvent docstring in server/models.py. Retention is indefinite by
|
|
decision (docs/waves/decisions-2026-09-17.md); nothing here schedules a purge.
|
|
|
|
Revision ID: 8e2cb3003f8a
|
|
Revises: 1d60a608bb51
|
|
Create Date: 2026-09-23 00:00:00.000000
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision = '8e2cb3003f8a'
|
|
down_revision = '1d60a608bb51'
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table('usage_events',
|
|
sa.Column('id', sa.String(length=40), nullable=False),
|
|
sa.Column('at', sa.DateTime(timezone=True), nullable=False),
|
|
sa.Column('username', sa.String(length=200), nullable=False),
|
|
sa.Column('project_id', sa.String(length=40), nullable=True),
|
|
sa.Column('tool', sa.String(length=40), nullable=False),
|
|
sa.Column('event', sa.String(length=40), nullable=False),
|
|
sa.Column('detail', sa.JSON(), nullable=False),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
op.create_index(op.f('ix_usage_events_at'), 'usage_events', ['at'], unique=False)
|
|
op.create_index(op.f('ix_usage_events_username'), 'usage_events', ['username'], unique=False)
|
|
op.create_index(op.f('ix_usage_events_project_id'), 'usage_events', ['project_id'], unique=False)
|
|
op.create_index(op.f('ix_usage_events_tool'), 'usage_events', ['tool'], unique=False)
|
|
op.create_index(op.f('ix_usage_events_event'), 'usage_events', ['event'], unique=False)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index(op.f('ix_usage_events_event'), table_name='usage_events')
|
|
op.drop_index(op.f('ix_usage_events_tool'), table_name='usage_events')
|
|
op.drop_index(op.f('ix_usage_events_project_id'), table_name='usage_events')
|
|
op.drop_index(op.f('ix_usage_events_username'), table_name='usage_events')
|
|
op.drop_index(op.f('ix_usage_events_at'), table_name='usage_events')
|
|
op.drop_table('usage_events')
|