Files
govoplan-core/docs/ACCESS_EXTRACTION_PLAN.md
2026-07-07 16:00:38 +02:00

18 KiB

GovOPlaN Access Extraction Plan

Backlog state migrated to Gitea issues on 2026-07-06. Keep this document as durable extraction context and architecture notes. Track active tasks, decisions, blockers, and implementation state in add-ideas/govoplan-core issues with module/access and source/backlog-import.

This plan describes how to extract access, authentication, RBAC, and related administration behavior from the current compatibility core into a dedicated govoplan-access platform module.

The goal is not to make access optional in every real deployment. The goal is to make ownership explicit: the kernel composes modules and exposes contracts; govoplan-access owns identity, sessions, API keys, roles, groups, and access administration.

Current Inventory

Existing Access Module Seed

govoplan-access contains the extracted module-shaped seed package under src/govoplan_access/backend. govoplan-core keeps compatibility import shims under src/govoplan_core/access:

  • manifest.py declares ModuleManifest(id="access").
  • db/models.py defines access-owned model candidates.
  • auth/principals.py, auth/roles.py, and auth/tokens.py contain auth helper concepts.
  • permissions/definitions.py, permissions/evaluator.py, and permissions/registry.py contain permission catalogue/evaluation concepts.
  • tenancy/datastore.py contains early tenancy access helpers.

This seed package is now the starting point for the access module, but it is not yet the full live source of truth for the running product.

Live Compatibility Ownership In Core

The active implementation still uses core-owned models and services:

  • src/govoplan_core/db/models.py
    • Account
    • Tenant
    • User
    • Group
    • Role
    • SystemSettings
    • GovernanceTemplate
    • GovernanceTemplateAssignment
    • SystemRoleAssignment
    • UserGroupMembership
    • UserRoleAssignment
    • GroupRoleAssignment
    • ApiKey
    • AuthSession
    • AuditLog
  • src/govoplan_core/auth/dependencies.py
  • src/govoplan_core/security/api_keys.py
  • src/govoplan_core/security/permissions.py
  • src/govoplan_core/security/sessions.py
  • src/govoplan_core/security/passwords.py
  • src/govoplan_core/security/secrets.py
  • src/govoplan_core/security/module_permissions.py
  • src/govoplan_core/admin/service.py
  • src/govoplan_core/admin/governance.py
  • src/govoplan_core/api/v1/auth.py
  • src/govoplan_core/api/v1/admin.py
  • src/govoplan_core/api/v1/admin_schemas.py
  • src/govoplan_core/api/v1/audit.py
  • src/govoplan_core/db/bootstrap.py

Core still hosts the generic login/settings shell and shared WebUI primitives. The legacy administration page has moved to the govoplan-access WebUI package and is contributed as the /admin route by the access module. Individual admin panels can now be split further into access, admin, tenancy, policy, and audit WebUI contributions without changing the core shell route wiring again.

Current Module Consumers

Feature modules no longer import core auth dependency wrappers or access-owned ORM models. Backend routers import the access-published FastAPI dependency API from govoplan_access.backend.auth.dependencies; runtime cooperation uses kernel capabilities such as access.directory, campaigns.access, campaigns.mailPolicyContext, and campaigns.deliveryTasks.

Target Ownership

Kernel

The kernel keeps only platform composition and stable contracts:

  • module discovery and registry validation
  • route aggregation
  • migration orchestration
  • database engine/session lifecycle
  • permission catalogue aggregation
  • capability registry
  • event/command envelopes
  • dependency injection hooks
  • health and diagnostics
  • compatibility facades while modules migrate

The kernel should not own account, tenant, role, group, session, or API-key semantics.

govoplan-access

govoplan-access owns:

  • accounts
  • authentication routes
  • session lifecycle
  • API keys
  • users
  • groups and memberships
  • roles and assignments
  • principal resolution
  • permission evaluation
  • access administration routes
  • access administration WebUI contributions
  • access-related migrations
  • access permissions and role templates

Later Platform Modules

Some current access-adjacent behavior can remain in access initially, but should have clean seams for later extraction:

  • govoplan-tenancy: tenants, tenant lifecycle, tenant switching, tenant metadata, tenant settings boundaries.
  • govoplan-policy: hierarchical policy/effective policy resolution and provenance display contracts.
  • govoplan-audit: audit log storage, audit routes, retention hooks, evidence exports.
  • govoplan-admin: generic administration shell contributions if they are not owned by access/tenancy/policy/audit directly.

Kernel Contracts To Stabilize First

Before moving live code, define contracts that feature modules can depend on without importing access ORM models:

  • PrincipalResolver
    • resolves the current actor from a request/session/API key.
    • returns a stable DTO, not an ORM model.
  • AccessDirectory
    • resolves users, groups, memberships, and display labels by stable IDs.
    • supports batch lookups for grids and policy screens.
  • TenantResolver
    • resolves current tenant context and tenant metadata by stable ID.
  • PermissionEvaluator
    • evaluates required scopes for a principal and resource.
  • ResourceAccessProvider
    • lets modules register resource ACL behavior without importing each other.
  • SecretProvider
    • encrypts/decrypts named secrets without tying consumers to access models.
  • AuditSink
    • records audit events without importing audit storage models.

DTOs should be small and serializable:

  • PrincipalRef
  • AccountRef
  • TenantRef
  • UserRef
  • GroupRef
  • RoleRef

Extraction Stages

Stage 0: Baseline Safeguards

Status: started.

  • Document the kernel/platform module model.
  • Add dependency-boundary checks.
  • Add backend module permutation startup tests.
  • Inventory access/auth/RBAC imports.
  • Draft this extraction plan.

Acceptance criteria:

  • scripts/check_dependency_boundaries.py passes.
  • backend module permutation tests start every supported module combination.
  • current direct imports are tracked as explicit transitional debt.

Stage 1: Contract Definitions

Add kernel-owned protocols and DTOs for access-related interaction.

Tasks:

  • Add protocol definitions under a kernel contract package.
  • Add registry/capability names for access services.
  • Keep existing core dependency functions as compatibility wrappers.
  • Make wrappers resolve through capabilities when govoplan-access is present.
  • Add tests for missing-capability behavior and clear error messages.

Acceptance criteria:

  • Feature modules can receive principal/tenant/group/user references without importing access ORM models.
  • Existing routes continue to work through compatibility wrappers.

Stage 2: Create govoplan-access

Create the new repository/package and move the access seed package into it.

Tasks:

  • Create package metadata and entry points for govoplan-access.
  • Move govoplan_core/access implementation into the new package.
  • Publish ModuleManifest(id="access").
  • Register access permissions, role templates, routers, and migrations.
  • Add compatibility imports in core where needed.
  • Add release/dev dependency entries in core.

Acceptance criteria:

  • govoplan-core + govoplan-access starts through normal module discovery.
  • govoplan-core compatibility imports still work during transition.
  • access manifest, migrations, and route contributions are discovered by core.

Stage 3: Move Live Models And Migrations

Move active identity/access models out of govoplan_core.db.models.

Current state: the stable table naming strategy is to keep legacy table names and move SQLAlchemy class definitions under their platform owners. The old govoplan_core.db.models compatibility re-export has been removed; callers must import module-owned models or use kernel capabilities. The earlier access_* candidate tables are not active metadata.

Current table ownership:

  • govoplan-tenancy: tenants
  • govoplan-access: accounts, tenant memberships in users, groups, roles, role/group assignment tables, api_keys, and auth_sessions
  • govoplan-admin: governance templates and assignments
  • govoplan-audit: audit log
  • govoplan-core: system settings

Tasks:

  • Decide the stable table naming strategy.
  • Map legacy model names to access-owned model classes.
  • Keep database table names where possible to avoid data migration churn.
  • Add Alembic migration metadata owned by the platform module owners.
  • Remove core model compatibility aliases after callers moved to module-owned imports.
  • Update bootstrap/create-all compatibility paths.

Acceptance criteria:

  • Existing development databases migrate without data loss.
  • New databases initialize with module-owned metadata.
  • Core no longer owns or re-exports live account/user/group/role/session/API-key model definitions.

Stage 4: Move Auth Routes And Dependencies

Move authentication, sessions, API keys, and principal dependencies.

Tasks:

  • Move /api/v1/auth/* implementation to access.
  • Move session/API-key services to access.
  • Keep core route compatibility only if required by clients.
  • Replace feature-module imports of core auth dependencies with the access-published FastAPI dependency API.
  • Add tests for login, session refresh, tenant selection, API-key auth, and missing access capability failures.

Acceptance criteria:

  • Auth behavior works through the access module.
  • Feature modules do not import access internals except the published govoplan_access.backend.auth.dependencies dependency API used by FastAPI routers.
  • Core can explain startup failure clearly if auth-required routes are enabled without the access capability.

Stage 5: Move Admin And WebUI Contributions

Move access administration UI/API ownership into modules.

Tasks:

  • Move users, groups, roles, API keys, and access settings pages into govoplan-access.
  • Move tenant-specific pages to govoplan-tenancy when that module exists, or keep them temporarily in access with clear boundaries.
  • Move overview, system settings, and governance-template panels into govoplan-admin.
  • Register admin navigation and admin sections through module contributions.
  • Keep core shell, layout, route rendering, and generic components only.

Acceptance criteria:

  • Core WebUI shell renders admin/access pages from module contributions.
  • Core does not import access page components directly.
  • Module nav and route metadata remain serializable.
  • The access admin shell consumes module-owned admin.sections capability contributions without importing sibling module panels.

Stage 6: Decouple Feature Modules

Remove direct ORM/model imports from files, mail, and campaign.

Tasks:

  • Replace Group, Tenant, User, and UserGroupMembership imports with directory/capability lookups.
  • Replace direct cross-module cleanup/count queries with registered providers, events, or module-owned API contracts.
  • Replace mail-profile ownership resolution with stable owner references.
  • Replace campaign/file access checks with resource ACL provider contracts.

Acceptance criteria:

  • govoplan-files, govoplan-mail, and govoplan-campaign do not import access implementation modules or sibling feature modules.
  • Dependency-boundary allowlist stays empty after each replacement.

Stage 7: Remove Compatibility Debt

Finalize the split.

Tasks:

  • Remove obsolete core compatibility aliases.
  • Keep the dependency-boundary checker allowlist empty.
  • Update release dependency docs.
  • Update operator migration notes.
  • Add full module permutation tests including access-present and access-absent behavior.

Acceptance criteria:

  • Core is a composition kernel.
  • Access behavior is owned by govoplan-access.
  • Feature modules communicate through kernel contracts, capabilities, events, and their own APIs.

Immediate Backlog

  • Document kernel/platform module model.
  • Add dependency-boundary check.
  • Add backend permutation startup smoke checks.
  • Inventory access/auth/RBAC import debt.
  • Draft access extraction plan.
  • Define kernel access DTOs and protocols.
  • Add access capability registry names.
  • Register live access directory and tenant resolver capability implementations backed by the current compatibility tables.
  • Register an access tenant-provisioner capability so tenancy can seed access-owned default roles without importing access service internals.
  • Replace govoplan-files direct user/group/tenant model imports with the access.directory capability for group membership and share-target checks.
  • Replace govoplan-files direct campaign model imports with the campaigns.access capability for campaign share/existence checks.
  • Replace govoplan-mail direct user/group/tenant model imports with mail-owned policy storage plus access-directory validation and legacy-read fallback.
  • Replace govoplan-mail direct campaign model imports with the campaigns.mailPolicyContext capability for campaign-scoped mail policy and owner context.
  • Replace govoplan-campaign runtime user/group/tenant model imports with access-directory lookups and string-based ORM relationships.
  • Create govoplan-access repository workspace and issue workflow scaffold.
  • Create govoplan-access repository/package skeleton.
  • Move govoplan_core/access seed package into govoplan-access.
  • Add compatibility wrappers in core for old import paths.
  • Route existing auth dependency wrappers through access principal/evaluator capabilities.
  • Move FastAPI auth dependency wrappers out of core and into govoplan-access.
  • Move session, API-key, and password helper services into govoplan-access.
  • Move interactive auth/session routes behind access module manifest.
  • Move legacy admin/API-key routes behind access module manifest.
  • Move access-owned legacy admin service helpers into govoplan-access.
  • Move governance-template CRUD helpers and routes into govoplan-admin.
  • Move governance-template materialization of access-owned groups and roles behind the access.governanceMaterializer capability.
  • Replace legacy access-to-files/campaign admin lookups with module tenant-summary and group-delete veto providers.
  • Split legacy admin route contribution across govoplan-admin, govoplan-tenancy, govoplan-policy, govoplan-audit, and govoplan-access route slices.
  • Move legacy admin route-handler ownership out of the access compatibility router into access, admin, tenancy, policy, and audit module routers.
  • Move shared system-settings, tenant-governance, slug/error, and tenant-count helpers out of access internals into core settings/tenancy helpers used by the split platform route modules.
  • Move campaign schema routes into the campaign route contribution.
  • Move development mailbox routes into the mail route contribution.
  • Replace core Celery direct campaign/mail imports with the campaigns.deliveryTasks capability.
  • Replace core retention direct campaign queries with campaigns.policyContext and campaigns.retention capabilities.
  • Replace core create_all feature-model imports with module registry metadata discovery.
  • Remove transitional boundary checker allowlist entries.
  • Move live legacy model definitions out of core and into govoplan-access while preserving existing table names.
  • Split the transitional access-owned legacy model graph further into tenancy, audit, admin, access, and core settings ownership.
  • Reverse the tenancy/access dependency direction so govoplan-access depends on govoplan-tenancy, and the registry inserts tenancy before access.
  • Replace tenancy-to-access default role seeding with an access tenant-provisioner capability.
  • Replace tenancy-to-access owner candidate and owner membership handling with the access tenant-provisioner capability.
  • Replace admin overview counts and audit actor lookup/filtering with the access.administration capability.
  • Replace feature-module direct user/group/tenant model imports.
    • govoplan-files
    • govoplan-mail
    • govoplan-campaign
  • Replace files/mail/campaign direct cross-module SQL lookups with provider/capability contracts.
  • Move access admin WebUI pages to module route contributions.
  • Move generic admin-owned WebUI panels into govoplan-admin and register them through the admin.sections UI capability.
  • Remove transitional boundary checker allowlist entries as each contract lands.
  • Remove old core import shims for access models, access routes, admin service helpers, and access-owned security services.
  • Move campaign-scoped mail policy ownership fully behind an API/event workflow if direct synchronous capability calls become too tight for later deployment boundaries.

Open Decisions

  • Is govoplan-access required for any authenticated deployment, while core-only remains a diagnostics/settings shell?
  • Tenant models live in govoplan-tenancy; govoplan-access depends on tenancy for authenticated platform composition.
  • Historical table names remain stable for painless migrations.
  • Should secret encryption remain a kernel primitive or become an access-owned capability?
  • Audit log storage lives in govoplan-audit; policy provenance can build on that module boundary.
  • How long should core keep compatibility route paths for existing clients?

Verification

Use the following checks while extracting access:

cd /mnt/DATA/git/govoplan-core
./.venv/bin/python scripts/check_dependency_boundaries.py
./.venv/bin/python -m unittest tests.test_module_system

For each removed dependency-boundary exception, add or update a focused test that proves the replacement contract starts without the old direct import.