Merge remote-tracking branch 'origin/master' into feat/totp-two-factor-auth

# Conflicts:
#	uv.lock
This commit is contained in:
TyperBody
2026-09-25 14:31:03 +08:00
32 changed files with 2540 additions and 62 deletions
@@ -0,0 +1,40 @@
"""Add private management-assistant conversations."""
import sqlalchemy as sa
from alembic import op
revision = '0025_assistant_conversations'
down_revision = '0024_passkey_credentials'
branch_labels = None
depends_on = None
def upgrade() -> None:
conn = op.get_bind()
if 'assistant_conversations' not in sa.inspect(conn).get_table_names():
op.create_table(
'assistant_conversations',
sa.Column('uuid', sa.String(36), primary_key=True),
sa.Column(
'workspace_uuid', sa.String(36), sa.ForeignKey('workspaces.uuid', ondelete='CASCADE'), nullable=False
),
sa.Column('account_uuid', sa.String(36), sa.ForeignKey('users.uuid', ondelete='CASCADE'), nullable=False),
sa.Column('revision', sa.Integer, nullable=False, server_default='0'),
sa.Column('status', sa.String(20), nullable=False, server_default='ready'),
sa.Column('messages', sa.JSON, nullable=False),
sa.Column('error', sa.Text),
sa.Column('model_name', sa.String(255)),
sa.Column('model_uuid', sa.String(36)),
sa.Column('updated_at', sa.DateTime, nullable=False, server_default=sa.func.now()),
)
if conn.dialect.name == 'postgresql':
op.execute('ALTER TABLE assistant_conversations ENABLE ROW LEVEL SECURITY')
op.execute('ALTER TABLE assistant_conversations FORCE ROW LEVEL SECURITY')
op.execute('DROP POLICY IF EXISTS langbot_workspace_isolation ON assistant_conversations')
op.execute("""CREATE POLICY langbot_workspace_isolation ON assistant_conversations
USING (workspace_uuid::text = NULLIF(current_setting('langbot.workspace_uuid', true), ''))
WITH CHECK (workspace_uuid::text = NULLIF(current_setting('langbot.workspace_uuid', true), ''))""")
def downgrade() -> None:
op.drop_table('assistant_conversations')
@@ -0,0 +1,25 @@
"""Join the workspace assistant conversations branch with the released chain.
Revision ID: 0030_merge_assistant
Revises: 0029_merge_rag_identity, 0025_assistant_conversations
The assistant conversation tables ship independently of the released schema
chain. Both parents are already published, so this revision only joins the
graph; Alembic applies the missing branch before this no-op merge. The
identifier is kept within the 32 character limit enforced by the migration
graph test.
"""
revision = '0030_merge_assistant'
down_revision = ('0029_merge_rag_identity', '0025_assistant_conversations')
branch_labels = None
depends_on = None
def upgrade() -> None:
pass
def downgrade() -> None:
# Only unmerge the revision graph; neither branch's schema/data is removed.
pass
@@ -0,0 +1,30 @@
"""Join the TOTP credential branch with the workspace assistant branch.
Revision ID: 0031_merge_totp_assistant
Revises: 0030_merge_assistant, 0030_merge_totp_into_release
Both ``0030`` merge revisions were authored independently: the release/master
line converged on ``0030_merge_assistant`` while the TOTP two-factor feature
branch converged on ``0030_merge_totp_into_release``. Integrating them leaves
Alembic with two heads, so this revision rejoins the graph and lets a single
``upgrade head`` apply both the TOTP credential tables and the workspace
assistant conversation tables.
Schemas and data are untouched; only the revision graph is joined.
"""
from __future__ import annotations
revision = '0031_merge_totp_assistant'
down_revision = ('0030_merge_assistant', '0030_merge_totp_into_release')
branch_labels = None
depends_on = None
def upgrade() -> None:
pass
def downgrade() -> None:
# Unmerge the graph only; retain both branches' schemas and user data.
pass
+1
View File
@@ -57,6 +57,7 @@ _ALEMBIC_TENANT_TABLES = {
'workspace_execution_states',
'support_admin_temporary_sessions',
'workspace_metadata',
'assistant_conversations',
'api_keys',
'agents',
'bots',
@@ -45,6 +45,7 @@ TENANT_TABLE_COLUMNS: dict[str, str] = {
'workspace_execution_states': 'workspace_uuid',
'support_admin_temporary_sessions': 'workspace_uuid',
'workspace_metadata': 'workspace_uuid',
'assistant_conversations': 'workspace_uuid',
'api_keys': 'workspace_uuid',
'agents': 'workspace_uuid',
'bots': 'workspace_uuid',