"""device_tokens (M8 sync hub, step 2) Revision ID: 0016 Revises: 0015 Create Date: 2026-07-23 Long-lived bearer tokens for native clients (Tauri/Android) to authenticate sync. Only the SHA-256 hash of each token is stored; the plaintext is shown once at creation. Owner-scoped + individually revocable. """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects.postgresql import UUID revision = "0016" down_revision = "0015" branch_labels = None depends_on = None def upgrade() -> None: op.create_table( "device_tokens", sa.Column("id", UUID(as_uuid=True), primary_key=True), sa.Column("user_id", UUID(as_uuid=True), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False), sa.Column("token_hash", sa.Text(), nullable=False, unique=True), sa.Column("name", sa.Text(), nullable=False, server_default=""), sa.Column("created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()), sa.Column("last_used_at", sa.DateTime(timezone=True), nullable=True), ) op.create_index("ix_device_tokens_user", "device_tokens", ["user_id"]) def downgrade() -> None: op.drop_index("ix_device_tokens_user", table_name="device_tokens") op.drop_table("device_tokens")