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

457 lines
18 KiB
Markdown

# 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:
- [x] Decide the stable table naming strategy.
- [x] Map legacy model names to access-owned model classes.
- [x] Keep database table names where possible to avoid data migration churn.
- [x] Add Alembic migration metadata owned by the platform module owners.
- [x] Remove core model compatibility aliases after callers moved to
module-owned imports.
- [x] 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:
- [x] 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.
- [x] Move overview, system settings, and governance-template panels into
`govoplan-admin`.
- [x] Register admin navigation and admin sections through module
contributions.
- [x] 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
- [x] Document kernel/platform module model.
- [x] Add dependency-boundary check.
- [x] Add backend permutation startup smoke checks.
- [x] Inventory access/auth/RBAC import debt.
- [x] Draft access extraction plan.
- [x] Define kernel access DTOs and protocols.
- [x] Add access capability registry names.
- [x] Register live access directory and tenant resolver capability
implementations backed by the current compatibility tables.
- [x] Register an access tenant-provisioner capability so tenancy can seed
access-owned default roles without importing access service internals.
- [x] Replace `govoplan-files` direct user/group/tenant model imports with the
`access.directory` capability for group membership and share-target checks.
- [x] Replace `govoplan-files` direct campaign model imports with the
`campaigns.access` capability for campaign share/existence checks.
- [x] Replace `govoplan-mail` direct user/group/tenant model imports with
mail-owned policy storage plus access-directory validation and legacy-read
fallback.
- [x] Replace `govoplan-mail` direct campaign model imports with the
`campaigns.mailPolicyContext` capability for campaign-scoped mail policy and
owner context.
- [x] Replace `govoplan-campaign` runtime user/group/tenant model imports with
access-directory lookups and string-based ORM relationships.
- [x] Create `govoplan-access` repository workspace and issue workflow scaffold.
- [x] Create `govoplan-access` repository/package skeleton.
- [x] Move `govoplan_core/access` seed package into `govoplan-access`.
- [x] Add compatibility wrappers in core for old import paths.
- [x] Route existing auth dependency wrappers through access principal/evaluator capabilities.
- [x] Move FastAPI auth dependency wrappers out of core and into
`govoplan-access`.
- [x] Move session, API-key, and password helper services into `govoplan-access`.
- [x] Move interactive auth/session routes behind access module manifest.
- [x] Move legacy admin/API-key routes behind access module manifest.
- [x] Move access-owned legacy admin service helpers into `govoplan-access`.
- [x] Move governance-template CRUD helpers and routes into `govoplan-admin`.
- [x] Move governance-template materialization of access-owned groups and roles
behind the `access.governanceMaterializer` capability.
- [x] Replace legacy access-to-files/campaign admin lookups with module
tenant-summary and group-delete veto providers.
- [x] Split legacy admin route contribution across `govoplan-admin`,
`govoplan-tenancy`, `govoplan-policy`, `govoplan-audit`, and
`govoplan-access` route slices.
- [x] Move legacy admin route-handler ownership out of the access compatibility
router into access, admin, tenancy, policy, and audit module routers.
- [x] 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.
- [x] Move campaign schema routes into the campaign route contribution.
- [x] Move development mailbox routes into the mail route contribution.
- [x] Replace core Celery direct campaign/mail imports with the
`campaigns.deliveryTasks` capability.
- [x] Replace core retention direct campaign queries with
`campaigns.policyContext` and `campaigns.retention` capabilities.
- [x] Replace core `create_all` feature-model imports with module registry
metadata discovery.
- [x] Remove transitional boundary checker allowlist entries.
- [x] Move live legacy model definitions out of core and into
`govoplan-access` while preserving existing table names.
- [x] Split the transitional access-owned legacy model graph further into
tenancy, audit, admin, access, and core settings ownership.
- [x] Reverse the tenancy/access dependency direction so `govoplan-access`
depends on `govoplan-tenancy`, and the registry inserts tenancy before access.
- [x] Replace tenancy-to-access default role seeding with an access
tenant-provisioner capability.
- [x] Replace tenancy-to-access owner candidate and owner membership handling
with the access tenant-provisioner capability.
- [x] Replace admin overview counts and audit actor lookup/filtering with the
`access.administration` capability.
- [x] Replace feature-module direct user/group/tenant model imports.
- [x] `govoplan-files`
- [x] `govoplan-mail`
- [x] `govoplan-campaign`
- [x] Replace files/mail/campaign direct cross-module SQL lookups with
provider/capability contracts.
- [x] Move access admin WebUI pages to module route contributions.
- [x] Move generic admin-owned WebUI panels into `govoplan-admin` and register
them through the `admin.sections` UI capability.
- [x] Remove transitional boundary checker allowlist entries as each contract
lands.
- [x] 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:
```bash
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.