- 迁移 6:character(生命周期六态检查约束、起源、现实人物治理标记、道体基线、内驱力)+ character_version(baseline/first_statement/drive_revision/reforging/persona_candidate 五类不可变版本与审核态) - 创建:手动与随缘(确定性词库组合,同种子同候选、一次一个——不是抽卡);现实人物治理(已故拒绝、未声明授权拒绝) - 启镜(draft→active + 首个 baseline 版本)与初照自陈(候选→确认归真并入道体) - 生命周期端点:静修/归藏/复照(归档可恢复、复照不抹历史)+ 死亡两步确认(7 天冷静期可撤销、未满确认 422);非法状态迁移 422 - 铸魂(显式 confirm 强确认,直接更新道体)与人格候选(pending→审核批准才并入道体,不静默覆盖) - 内驱力编辑:写当前值并落 drive_revision 版本(可追溯,ADR-018) - 测试 52 项全绿(+8):状态机全路径、随缘确定性、现实人物三例、铸魂确认、候选审核与重复审核 409、跨域 fail-closed
70 lines
3.7 KiB
Python
70 lines
3.7 KiB
Python
"""角色与版本链
|
|
|
|
Revision ID: 6292e21950cc
|
|
Revises: 8f48659a83f6
|
|
Create Date: 2026-09-10 18:08:36.628784
|
|
|
|
"""
|
|
from collections.abc import Sequence
|
|
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
from alembic import op
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision: str = '6292e21950cc'
|
|
down_revision: str | Sequence[str] | None = '8f48659a83f6'
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
"""Upgrade schema."""
|
|
# ### commands auto generated by Alembic - please adjust! ###
|
|
op.create_table('character',
|
|
sa.Column('id', sa.String(), nullable=False),
|
|
sa.Column('personal_domain_id', sa.String(), nullable=False),
|
|
sa.Column('name', sa.String(), nullable=False),
|
|
sa.Column('status', sa.String(), nullable=False),
|
|
sa.Column('origin', sa.String(), nullable=False),
|
|
sa.Column('based_on_real_person', sa.Boolean(), nullable=False),
|
|
sa.Column('real_person_attested', sa.Boolean(), nullable=False),
|
|
sa.Column('identity_baseline', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
|
sa.Column('drives', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
|
sa.Column('current_version_id', sa.String(), nullable=True),
|
|
sa.Column('death_requested_at', sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.CheckConstraint("origin IN ('original', 'serendipity', 'template', 'import', 'fork')", name=op.f('ck_character_origin_values')),
|
|
sa.CheckConstraint("status IN ('draft', 'active', 'resting', 'archived', 'death_pending', 'deceased')", name=op.f('ck_character_status_values')),
|
|
sa.ForeignKeyConstraint(['current_version_id'], ['character_version.id'], name=op.f('fk_character_character_version'), ondelete='set null', use_alter=True),
|
|
sa.ForeignKeyConstraint(['personal_domain_id'], ['personal_domain.id'], name=op.f('fk_character_personal_domain'), ondelete='cascade'),
|
|
sa.PrimaryKeyConstraint('id', name=op.f('pk_character'))
|
|
)
|
|
op.create_index(op.f('ix_character_personal_domain_id'), 'character', ['personal_domain_id'], unique=False)
|
|
op.create_table('character_version',
|
|
sa.Column('id', sa.String(), nullable=False),
|
|
sa.Column('character_id', sa.String(), nullable=False),
|
|
sa.Column('kind', sa.String(), nullable=False),
|
|
sa.Column('status', sa.String(), nullable=False),
|
|
sa.Column('payload', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.CheckConstraint("kind IN ('baseline', 'first_statement', 'drive_revision', 'reforging', 'persona_candidate')", name=op.f('ck_character_version_kind_values')),
|
|
sa.CheckConstraint("status IN ('pending', 'approved', 'rejected')", name=op.f('ck_character_version_status_values')),
|
|
sa.ForeignKeyConstraint(['character_id'], ['character.id'], name=op.f('fk_character_version_character'), ondelete='cascade'),
|
|
sa.PrimaryKeyConstraint('id', name=op.f('pk_character_version'))
|
|
)
|
|
op.create_index(op.f('ix_character_version_character_id'), 'character_version', ['character_id'], unique=False)
|
|
# ### end Alembic commands ###
|
|
|
|
|
|
def downgrade() -> None:
|
|
"""Downgrade schema."""
|
|
# ### commands auto generated by Alembic - please adjust! ###
|
|
op.drop_index(op.f('ix_character_version_character_id'), table_name='character_version')
|
|
op.drop_table('character_version')
|
|
op.drop_index(op.f('ix_character_personal_domain_id'), table_name='character')
|
|
op.drop_table('character')
|
|
# ### end Alembic commands ###
|