Release v0.1.8

This commit is contained in:
2026-07-11 16:49:03 +02:00
parent 213157aca1
commit 39c081c4fb
12 changed files with 237 additions and 46 deletions

View File

@@ -86,7 +86,7 @@ def _organization_directory(context: ModuleContext) -> object:
manifest = ModuleManifest(
id="organizations",
name="Organizations",
version="0.1.7",
version="0.1.8",
required_capabilities=(CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR),
optional_dependencies=("tenancy", "access", "audit", "policy"),
permissions=PERMISSIONS,

View File

@@ -0,0 +1 @@
"""Organizations Alembic revisions."""

View File

@@ -0,0 +1,187 @@
"""v0.1.7 organizations baseline
Revision ID: 6d7e8f9a0b1c
Revises: None
Create Date: 2026-07-11 00:00:00.000000
"""
from __future__ import annotations
from alembic import op
import sqlalchemy as sa
revision = '6d7e8f9a0b1c'
down_revision = None
branch_labels = None
depends_on = '4f2a9c8e7b6d'
def upgrade() -> None:
op.create_table('organizations_structures',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('tenant_id', sa.String(length=36), nullable=False),
sa.Column('slug', sa.String(length=100), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('structure_kind', sa.String(length=30), nullable=False),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('settings', sa.JSON(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.PrimaryKeyConstraint('id', name=op.f('pk_organizations_structures')),
sa.UniqueConstraint('tenant_id', 'slug', name='uq_organizations_structures_tenant_slug')
)
op.create_index(op.f('ix_organizations_structures_tenant_id'), 'organizations_structures', ['tenant_id'], unique=False)
op.create_table('organizations_tenant_settings',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('tenant_id', sa.String(length=36), nullable=False),
sa.Column('allow_tenant_model_customization', sa.Boolean(), nullable=False),
sa.Column('require_model_change_requests', sa.Boolean(), nullable=False),
sa.Column('audit_detail_level', sa.String(length=30), nullable=False),
sa.Column('change_retention_days', sa.Integer(), nullable=True),
sa.Column('settings', sa.JSON(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.PrimaryKeyConstraint('id', name=op.f('pk_organizations_tenant_settings')),
sa.UniqueConstraint('tenant_id', name='uq_organizations_tenant_settings_tenant')
)
op.create_index(op.f('ix_organizations_tenant_settings_tenant_id'), 'organizations_tenant_settings', ['tenant_id'], unique=False)
op.create_table('organizations_unit_types',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('tenant_id', sa.String(length=36), nullable=False),
sa.Column('slug', sa.String(length=100), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('settings', sa.JSON(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.PrimaryKeyConstraint('id', name=op.f('pk_organizations_unit_types')),
sa.UniqueConstraint('tenant_id', 'slug', name='uq_organizations_unit_types_tenant_slug')
)
op.create_index(op.f('ix_organizations_unit_types_tenant_id'), 'organizations_unit_types', ['tenant_id'], unique=False)
op.create_table('organizations_function_types',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('tenant_id', sa.String(length=36), nullable=False),
sa.Column('slug', sa.String(length=100), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('organization_unit_type_id', sa.String(length=36), nullable=True),
sa.Column('delegable', sa.Boolean(), nullable=False),
sa.Column('act_in_place_allowed', sa.Boolean(), nullable=False),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('settings', sa.JSON(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['organization_unit_type_id'], ['organizations_unit_types.id'], name=op.f('fk_organizations_function_types_organization_unit_type_id_organizations_unit_types'), ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id', name=op.f('pk_organizations_function_types')),
sa.UniqueConstraint('tenant_id', 'slug', name='uq_organizations_function_types_tenant_slug')
)
op.create_index(op.f('ix_organizations_function_types_organization_unit_type_id'), 'organizations_function_types', ['organization_unit_type_id'], unique=False)
op.create_index(op.f('ix_organizations_function_types_tenant_id'), 'organizations_function_types', ['tenant_id'], unique=False)
op.create_table('organizations_relation_types',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('tenant_id', sa.String(length=36), nullable=False),
sa.Column('structure_id', sa.String(length=36), nullable=True),
sa.Column('slug', sa.String(length=100), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('source_unit_type_id', sa.String(length=36), nullable=True),
sa.Column('target_unit_type_id', sa.String(length=36), nullable=True),
sa.Column('is_hierarchical', sa.Boolean(), nullable=False),
sa.Column('allow_cycles', sa.Boolean(), nullable=False),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('settings', sa.JSON(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['source_unit_type_id'], ['organizations_unit_types.id'], name=op.f('fk_organizations_relation_types_source_unit_type_id_organizations_unit_types'), ondelete='SET NULL'),
sa.ForeignKeyConstraint(['structure_id'], ['organizations_structures.id'], name=op.f('fk_organizations_relation_types_structure_id_organizations_structures'), ondelete='SET NULL'),
sa.ForeignKeyConstraint(['target_unit_type_id'], ['organizations_unit_types.id'], name=op.f('fk_organizations_relation_types_target_unit_type_id_organizations_unit_types'), ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id', name=op.f('pk_organizations_relation_types')),
sa.UniqueConstraint('tenant_id', 'slug', name='uq_organizations_relation_types_tenant_slug')
)
op.create_index(op.f('ix_organizations_relation_types_source_unit_type_id'), 'organizations_relation_types', ['source_unit_type_id'], unique=False)
op.create_index('ix_organizations_relation_types_structure', 'organizations_relation_types', ['tenant_id', 'structure_id'], unique=False)
op.create_index(op.f('ix_organizations_relation_types_structure_id'), 'organizations_relation_types', ['structure_id'], unique=False)
op.create_index(op.f('ix_organizations_relation_types_target_unit_type_id'), 'organizations_relation_types', ['target_unit_type_id'], unique=False)
op.create_index(op.f('ix_organizations_relation_types_tenant_id'), 'organizations_relation_types', ['tenant_id'], unique=False)
op.create_table('organizations_units',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('tenant_id', sa.String(length=36), nullable=False),
sa.Column('unit_type_id', sa.String(length=36), nullable=True),
sa.Column('parent_id', sa.String(length=36), nullable=True),
sa.Column('slug', sa.String(length=100), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('settings', sa.JSON(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['parent_id'], ['organizations_units.id'], name=op.f('fk_organizations_units_parent_id_organizations_units'), ondelete='SET NULL'),
sa.ForeignKeyConstraint(['unit_type_id'], ['organizations_unit_types.id'], name=op.f('fk_organizations_units_unit_type_id_organizations_unit_types'), ondelete='SET NULL'),
sa.PrimaryKeyConstraint('id', name=op.f('pk_organizations_units')),
sa.UniqueConstraint('tenant_id', 'slug', name='uq_organizations_units_tenant_slug')
)
op.create_index(op.f('ix_organizations_units_parent_id'), 'organizations_units', ['parent_id'], unique=False)
op.create_index(op.f('ix_organizations_units_tenant_id'), 'organizations_units', ['tenant_id'], unique=False)
op.create_index(op.f('ix_organizations_units_unit_type_id'), 'organizations_units', ['unit_type_id'], unique=False)
op.create_table('organizations_functions',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('tenant_id', sa.String(length=36), nullable=False),
sa.Column('function_type_id', sa.String(length=36), nullable=True),
sa.Column('organization_unit_id', sa.String(length=36), nullable=False),
sa.Column('slug', sa.String(length=100), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('delegable', sa.Boolean(), nullable=False),
sa.Column('act_in_place_allowed', sa.Boolean(), nullable=False),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('settings', sa.JSON(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['function_type_id'], ['organizations_function_types.id'], name=op.f('fk_organizations_functions_function_type_id_organizations_function_types'), ondelete='SET NULL'),
sa.ForeignKeyConstraint(['organization_unit_id'], ['organizations_units.id'], name=op.f('fk_organizations_functions_organization_unit_id_organizations_units'), ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id', name=op.f('pk_organizations_functions')),
sa.UniqueConstraint('tenant_id', 'organization_unit_id', 'slug', name='uq_organizations_functions_tenant_unit_slug')
)
op.create_index(op.f('ix_organizations_functions_function_type_id'), 'organizations_functions', ['function_type_id'], unique=False)
op.create_index(op.f('ix_organizations_functions_organization_unit_id'), 'organizations_functions', ['organization_unit_id'], unique=False)
op.create_index(op.f('ix_organizations_functions_tenant_id'), 'organizations_functions', ['tenant_id'], unique=False)
op.create_table('organizations_relations',
sa.Column('id', sa.String(length=36), nullable=False),
sa.Column('tenant_id', sa.String(length=36), nullable=False),
sa.Column('structure_id', sa.String(length=36), nullable=False),
sa.Column('relation_type_id', sa.String(length=36), nullable=False),
sa.Column('source_unit_id', sa.String(length=36), nullable=False),
sa.Column('target_unit_id', sa.String(length=36), nullable=False),
sa.Column('valid_from', sa.DateTime(timezone=True), nullable=True),
sa.Column('valid_until', sa.DateTime(timezone=True), nullable=True),
sa.Column('is_active', sa.Boolean(), nullable=False),
sa.Column('settings', sa.JSON(), nullable=False),
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=False),
sa.ForeignKeyConstraint(['relation_type_id'], ['organizations_relation_types.id'], name=op.f('fk_organizations_relations_relation_type_id_organizations_relation_types'), ondelete='CASCADE'),
sa.ForeignKeyConstraint(['source_unit_id'], ['organizations_units.id'], name=op.f('fk_organizations_relations_source_unit_id_organizations_units'), ondelete='CASCADE'),
sa.ForeignKeyConstraint(['structure_id'], ['organizations_structures.id'], name=op.f('fk_organizations_relations_structure_id_organizations_structures'), ondelete='CASCADE'),
sa.ForeignKeyConstraint(['target_unit_id'], ['organizations_units.id'], name=op.f('fk_organizations_relations_target_unit_id_organizations_units'), ondelete='CASCADE'),
sa.PrimaryKeyConstraint('id', name=op.f('pk_organizations_relations')),
sa.UniqueConstraint('tenant_id', 'structure_id', 'relation_type_id', 'source_unit_id', 'target_unit_id', name='uq_organizations_relations_edge')
)
op.create_index(op.f('ix_organizations_relations_relation_type_id'), 'organizations_relations', ['relation_type_id'], unique=False)
op.create_index(op.f('ix_organizations_relations_source_unit_id'), 'organizations_relations', ['source_unit_id'], unique=False)
op.create_index(op.f('ix_organizations_relations_structure_id'), 'organizations_relations', ['structure_id'], unique=False)
op.create_index('ix_organizations_relations_structure_source', 'organizations_relations', ['tenant_id', 'structure_id', 'source_unit_id'], unique=False)
op.create_index('ix_organizations_relations_structure_target', 'organizations_relations', ['tenant_id', 'structure_id', 'target_unit_id'], unique=False)
op.create_index(op.f('ix_organizations_relations_target_unit_id'), 'organizations_relations', ['target_unit_id'], unique=False)
op.create_index(op.f('ix_organizations_relations_tenant_id'), 'organizations_relations', ['tenant_id'], unique=False)
def downgrade() -> None:
op.drop_table('organizations_relations')
op.drop_table('organizations_functions')
op.drop_table('organizations_units')
op.drop_table('organizations_relation_types')
op.drop_table('organizations_function_types')
op.drop_table('organizations_unit_types')
op.drop_table('organizations_tenant_settings')
op.drop_table('organizations_structures')