457 lines
18 KiB
Markdown
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.
|