Files
hunjing/backend/alembic/versions/010_器谱_设备配对与逐项授契.py
chenxin 2483a25f63 M9:桌面壳与收口——镜匣最小壳、器谱登记、发布证据落位、重写计划功成身退
- 镜匣 desktop/(Tauri v2 最小壳):WebView 承载琉璃镜(frontend/out 或 devUrl);能力桥最小命令(通知);乾坤通道 HMAC 短期凭证构造(与 sandbox/src/auth.rs 验签同算法,密钥仅经 SANDBOX_AUTH_SECRET 环境注入——二进制零平台密钥,静态审计钉死);hard_stop/resume 本地硬急停原子断路(全部通道命令过 ensure_not_halted,本地最高优先级不经云端);tantivy 依赖与 capabilities/ 目录预留;updater 插件位预留;cargo check 通过
- 器谱域 domains/tianzai(迁移 010):devices/device_grants——一次配对(密钥指纹登记)、逐项授契(可授面显式枚举,未知能力键拒)、撤回立即生效、设备撤销连带全部授契失效且不可再授;/devices 器谱 API 组
- 发布收口:release-evidence.md 落位重写期 RW-* 证据包(M0–M9 十里程碑验收自动化套件与结果物);能力矩阵 M9 行收官;rewrite-plan.md 按计划删除(M0–M9 全部完成,能力矩阵与证据台账接棒),全库引用清理
- 验收(test_m9_jingxia 四用例):器谱未授契 403 留痕/撤回即效/设备撤销连带;镜匣零平台密钥(rg 审计源码与配置为空);硬急停语义钉死(通道命令全检查+resume 唯一恢复+HMAC 无密钥不出凭证)
- 五套件终检全绿:后端 349、前端 203、BFF 4、神识 5 包、镜匣 cargo check(2 个预存环境失败历次 HEAD 复验与本周期无关);Compose nginx profile 配置校验通过
2026-08-28 09:35:27 +08:00

122 lines
6.8 KiB
Python

"""器谱_设备配对与逐项授契
Revision ID: 010
Revises: 009
Create Date: 2026-08-28 09:25:57.705846
"""
from typing import Sequence, Union
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision: str = '010'
down_revision: Union[str, Sequence[str], None] = '009'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
"""Upgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('device_grants',
sa.Column('id', sa.String(length=80), nullable=False),
sa.Column('device_id', sa.String(length=80), nullable=False),
sa.Column('owner_scope', sa.String(length=80), nullable=False),
sa.Column('capability', sa.String(length=60), nullable=False),
sa.Column('scope_json', sa.Text(), nullable=False),
sa.Column('status', sa.String(length=20), nullable=False),
sa.Column('granted_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('revoked_at', sa.DateTime(timezone=True), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_device_grants_capability'), 'device_grants', ['capability'], unique=False)
op.create_index(op.f('ix_device_grants_device_id'), 'device_grants', ['device_id'], unique=False)
op.create_index(op.f('ix_device_grants_owner_scope'), 'device_grants', ['owner_scope'], unique=False)
op.create_index(op.f('ix_device_grants_status'), 'device_grants', ['status'], unique=False)
op.create_table('devices',
sa.Column('id', sa.String(length=80), nullable=False),
sa.Column('owner_scope', sa.String(length=80), nullable=False),
sa.Column('kind', sa.String(length=30), nullable=False),
sa.Column('name', sa.String(length=120), nullable=False),
sa.Column('key_fingerprint', sa.String(length=128), nullable=False),
sa.Column('status', sa.String(length=20), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('last_seen_at', sa.DateTime(timezone=True), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_devices_owner_scope'), 'devices', ['owner_scope'], unique=False)
op.create_index(op.f('ix_devices_status'), 'devices', ['status'], unique=False)
op.drop_index(op.f('ix_character_profile_candidates_character_id'), table_name='character_profile_candidates')
op.drop_index(op.f('ix_character_profile_candidates_import_job_id'), table_name='character_profile_candidates')
op.drop_index(op.f('ix_character_profile_candidates_status'), table_name='character_profile_candidates')
op.drop_table('character_profile_candidates')
op.drop_index(op.f('ix_memory_candidates_character_id'), table_name='memory_candidates')
op.drop_index(op.f('ix_memory_candidates_cycle_id'), table_name='memory_candidates')
op.drop_index(op.f('ix_memory_candidates_import_job_id'), table_name='memory_candidates')
op.drop_index(op.f('ix_memory_candidates_status'), table_name='memory_candidates')
op.drop_table('memory_candidates')
# ### end Alembic commands ###
def downgrade() -> None:
"""Downgrade schema."""
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('memory_candidates',
sa.Column('id', sa.VARCHAR(length=80), nullable=False),
sa.Column('character_id', sa.VARCHAR(length=80), nullable=False),
sa.Column('import_job_id', sa.VARCHAR(length=80), nullable=True),
sa.Column('cycle_id', sa.VARCHAR(length=80), nullable=True),
sa.Column('type', sa.VARCHAR(length=60), nullable=False),
sa.Column('title', sa.VARCHAR(length=200), nullable=False),
sa.Column('content', sa.TEXT(), nullable=False),
sa.Column('confidence', sa.FLOAT(), nullable=False),
sa.Column('importance', sa.FLOAT(), nullable=False),
sa.Column('sensitivity', sa.VARCHAR(length=40), nullable=False),
sa.Column('evidence_ids_json', sa.TEXT(), nullable=False),
sa.Column('status', sa.VARCHAR(length=40), nullable=False),
sa.Column('reason', sa.TEXT(), nullable=True),
sa.Column('reviewed_at', sa.DATETIME(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=False),
sa.Column('updated_at', sa.DATETIME(), nullable=False),
sa.ForeignKeyConstraint(['character_id'], ['characters.id'], ),
sa.ForeignKeyConstraint(['cycle_id'], ['big_cycles.id'], ),
sa.ForeignKeyConstraint(['import_job_id'], ['character_import_jobs.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_memory_candidates_status'), 'memory_candidates', ['status'], unique=False)
op.create_index(op.f('ix_memory_candidates_import_job_id'), 'memory_candidates', ['import_job_id'], unique=False)
op.create_index(op.f('ix_memory_candidates_cycle_id'), 'memory_candidates', ['cycle_id'], unique=False)
op.create_index(op.f('ix_memory_candidates_character_id'), 'memory_candidates', ['character_id'], unique=False)
op.create_table('character_profile_candidates',
sa.Column('id', sa.VARCHAR(length=80), nullable=False),
sa.Column('character_id', sa.VARCHAR(length=80), nullable=False),
sa.Column('import_job_id', sa.VARCHAR(length=80), nullable=True),
sa.Column('field', sa.VARCHAR(length=60), nullable=False),
sa.Column('value', sa.TEXT(), nullable=False),
sa.Column('confidence', sa.FLOAT(), nullable=False),
sa.Column('evidence_ids_json', sa.TEXT(), nullable=False),
sa.Column('status', sa.VARCHAR(length=40), nullable=False),
sa.Column('reason', sa.TEXT(), nullable=True),
sa.Column('reviewed_at', sa.DATETIME(), nullable=True),
sa.Column('created_at', sa.DATETIME(), nullable=False),
sa.Column('updated_at', sa.DATETIME(), nullable=False),
sa.ForeignKeyConstraint(['character_id'], ['characters.id'], ),
sa.ForeignKeyConstraint(['import_job_id'], ['character_import_jobs.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_character_profile_candidates_status'), 'character_profile_candidates', ['status'], unique=False)
op.create_index(op.f('ix_character_profile_candidates_import_job_id'), 'character_profile_candidates', ['import_job_id'], unique=False)
op.create_index(op.f('ix_character_profile_candidates_character_id'), 'character_profile_candidates', ['character_id'], unique=False)
op.drop_index(op.f('ix_devices_status'), table_name='devices')
op.drop_index(op.f('ix_devices_owner_scope'), table_name='devices')
op.drop_table('devices')
op.drop_index(op.f('ix_device_grants_status'), table_name='device_grants')
op.drop_index(op.f('ix_device_grants_owner_scope'), table_name='device_grants')
op.drop_index(op.f('ix_device_grants_device_id'), table_name='device_grants')
op.drop_index(op.f('ix_device_grants_capability'), table_name='device_grants')
op.drop_table('device_grants')
# ### end Alembic commands ###