Release v0.1.7
All checks were successful
Dependency Audit / dependency-audit (push) Successful in 1m35s
All checks were successful
Dependency Audit / dependency-audit (push) Successful in 1m35s
This commit is contained in:
@@ -133,13 +133,12 @@ Access:
|
||||
|
||||
Tenancy:
|
||||
|
||||
- `tenancy.tenant.created`
|
||||
- `tenancy.tenant.updated`
|
||||
- `tenancy.tenant.suspended`
|
||||
- `tenancy.tenant.reactivated`
|
||||
- `tenancy.tenant.delete_requested`
|
||||
- `tenancy.tenant.delete_blocked`
|
||||
- `tenancy.tenant.deleted`
|
||||
- `tenant.created`
|
||||
- `tenant.updated`
|
||||
- `tenant.suspended`
|
||||
- `tenant.resumed`
|
||||
- `tenant.deletion_requested`
|
||||
- `tenant.erasure_completed`
|
||||
|
||||
Policy:
|
||||
|
||||
|
||||
@@ -458,6 +458,17 @@ routers and live module activation fail fast if two routers register the same
|
||||
HTTP method and path. That keeps OpenAPI output and FastAPI route order from
|
||||
silently masking a module collision.
|
||||
|
||||
Tenant deletion and cleanup use the registry-owned delete-veto contract. A
|
||||
module that owns tenant-bound data may declare `delete_veto_providers` on its
|
||||
manifest for resource types such as `tenant` or `group`. Providers receive
|
||||
`(session, tenant_id, resource_id)` and should return `DeleteVetoIssue`, an
|
||||
iterable of `DeleteVetoIssue`, or `None`; older exception-based providers are
|
||||
still treated as blocking vetoes. Core attributes each issue to the provider
|
||||
module and adds resource context before the tenancy module exposes the issues
|
||||
through the deletion plan. `blocker` issues prevent destructive or retire
|
||||
operations, `warning` issues explain retained data, and `info` issues document
|
||||
non-blocking lifecycle facts.
|
||||
|
||||
## Database And Migrations
|
||||
|
||||
Core owns the database/session lifecycle. Modules access the database through core session dependencies and register their models/migrations through their manifest.
|
||||
@@ -492,13 +503,34 @@ against the configured offline license before adding the entry to the install
|
||||
plan. Catalog entries may also declare `migration_safety` as `automatic`,
|
||||
`requires_review`, `forward_only`, or `destructive`; forward-only and
|
||||
destructive entries require explicit operator acknowledgement in the install
|
||||
plan before installer preflight allows activation.
|
||||
plan before installer preflight allows activation. Forward-only and destructive
|
||||
catalog entries must also declare a tested recovery path. Catalog update entries
|
||||
can define direct-update windows with `current_version_min` and
|
||||
`current_version_max_exclusive`, mark intermediate `bridge_release` targets, and
|
||||
explicitly opt into reviewed downgrade or same-version package-refresh plans.
|
||||
Module migration order can be declared with `migration_after` and
|
||||
`migration_before` in manifests or release catalogs; installer preflight turns
|
||||
that metadata, module dependencies, and named interface relationships into an
|
||||
ordered migration plan.
|
||||
|
||||
Modules that need live-data work outside Alembic schema revisions may declare
|
||||
`migration_tasks` on `MigrationSpec`. This is deliberately narrower than a
|
||||
general lifecycle hook system. Each task has a stable `task_id`, one of four
|
||||
phases (`pre_migration_check`, `pre_migration_prepare`,
|
||||
`post_migration_backfill`, `post_migration_verify`), a short operator-facing
|
||||
summary, a task version, safety metadata, and an idempotent executor. Installer
|
||||
preflight blocks non-idempotent tasks, forward-only/destructive tasks without
|
||||
operator acknowledgement, and installed manifest tasks that have no executor.
|
||||
Catalog task metadata is surfaced before activation as pending because the
|
||||
executor can only be verified after the package is installed.
|
||||
|
||||
Modules should provide:
|
||||
|
||||
- pinned backend and WebUI package refs for official catalog entries
|
||||
- module dependency metadata for catalog target-state planning
|
||||
- migration-safety metadata for catalog update planning
|
||||
- migration task metadata when live-data checks, preparation, backfills, or
|
||||
verification must run around Alembic
|
||||
- compatibility metadata in the module manifest
|
||||
- named interface contracts in the manifest and catalog entry when the module
|
||||
provides or consumes cross-module APIs
|
||||
@@ -984,13 +1016,19 @@ The package install-plan API records operator intent only:
|
||||
- `POST /api/v1/admin/system/modules/install-plan/catalog/{module_id}` saves
|
||||
a planned install or update row from a validated catalog entry. Installed
|
||||
modules are planned as updates. Catalog signature and approved-channel policy
|
||||
are enforced before the row is saved. The saved plan row can also carry a
|
||||
are enforced before the row is saved. When the selected catalog row requires
|
||||
companion dependency or interface-provider updates, the endpoint adds those
|
||||
rows to the plan automatically. The saved plan row can also carry a
|
||||
data-safety acknowledgement used by preflight for forward-only or destructive
|
||||
catalog entries.
|
||||
- Install-plan preflight returns a structured `target_plan` summary so the
|
||||
admin UI can show current version, target version, package refs,
|
||||
migration-safety level, and acknowledgement state without requiring JSON
|
||||
editing.
|
||||
migration-safety level, update-window and bridge metadata, recovery metadata,
|
||||
and acknowledgement state without requiring JSON editing.
|
||||
- Install-plan preflight also returns a structured `migration_plan` summary with
|
||||
target enabled modules and ordered module migration steps. When the installer
|
||||
runs with migration enabled, the database migration command receives that
|
||||
target module set and ordered module list.
|
||||
- `POST /api/v1/admin/system/modules/{module_id}/uninstall-plan` saves a
|
||||
planned non-destructive uninstall row for an installed module after it has
|
||||
been disabled. The Python distribution name is resolved from the installed
|
||||
|
||||
@@ -111,10 +111,12 @@ scripts/push-release-tag.sh --version 0.1.6
|
||||
`ModuleManifest` objects while writing catalog entries. When a manifest is
|
||||
available, the catalog entry uses the manifest version, points package refs at
|
||||
`v<manifest.version>`, and copies `provides_interfaces` /
|
||||
`requires_interfaces` from the manifest. If a manifest cannot be discovered,
|
||||
the entry falls back to the release version passed with `--version` and omits
|
||||
interface metadata. This keeps the catalog aligned with independently
|
||||
versioned module packages instead of relying on a hardcoded compatibility table.
|
||||
`requires_interfaces` from the manifest. It also copies module migration order
|
||||
and `migration_tasks` metadata when present. If a manifest cannot be
|
||||
discovered, the entry falls back to the release version passed with `--version`
|
||||
and omits interface and migration-task metadata. This keeps the catalog aligned
|
||||
with independently versioned module packages instead of relying on a hardcoded
|
||||
compatibility table.
|
||||
|
||||
The script also includes GovOPlaN roadmap/scaffold module repositories that do
|
||||
not yet have package metadata. Those repositories are committed, tagged, and
|
||||
@@ -211,6 +213,21 @@ Each module entry can declare:
|
||||
or `destructive`
|
||||
- `migration_notes`, operator-facing data/migration guidance for review,
|
||||
forward-only, or destructive changes
|
||||
- `migration_after` and `migration_before`, explicit module ids used to order
|
||||
module-owned migration heads when a release needs a live-data sequencing rule
|
||||
- `migration_tasks`, constrained live-data tasks that run around Alembic
|
||||
migration phases. Each task declares `task_id`, `phase`, `summary`,
|
||||
`task_version`, `safety`, `idempotent`, and optionally `timeout_seconds`.
|
||||
The allowed phases are `pre_migration_check`, `pre_migration_prepare`,
|
||||
`post_migration_backfill`, and `post_migration_verify`.
|
||||
- `current_version_min` and `current_version_max_exclusive`, the installed
|
||||
version window from which this catalog target may be applied directly
|
||||
- `bridge_release` and `bridge_notes`, marking a target as an intermediate
|
||||
compatibility release in a staged update path
|
||||
- `allow_downgrade` and `allow_same_version`, explicit opt-ins for reviewed
|
||||
rollback or package-refresh plans
|
||||
- `recovery_tested` and `recovery_notes`, documenting the rehearsal for
|
||||
forward-only or destructive data changes
|
||||
- `provides_interfaces`, named interface contracts exported by this module
|
||||
- `requires_interfaces`, named interface contracts and version ranges required
|
||||
by this module
|
||||
@@ -282,8 +299,18 @@ Catalog provenance changes preflight severity:
|
||||
block activation before the installer runs
|
||||
- selected catalog entries whose target dependencies are neither installed nor
|
||||
planned block activation before the installer runs
|
||||
- catalog update targets older than the installed module version block unless
|
||||
the catalog entry declares `allow_downgrade: true`
|
||||
- catalog update targets equal to the installed module version block unless the
|
||||
catalog entry declares `allow_same_version: true`
|
||||
- catalog update targets with a `current_version_min` /
|
||||
`current_version_max_exclusive` window block when the installed version is
|
||||
outside that window; publish and apply a bridge release instead
|
||||
- catalog entries marked `forward_only` or `destructive` block activation until
|
||||
the plan row has an explicit data-safety acknowledgement
|
||||
- catalog entries marked `forward_only` or `destructive` also block unless the
|
||||
catalog entry declares `recovery_tested: true` and either the catalog entry or
|
||||
operator plan row contains recovery notes
|
||||
- catalog entries marked `destructive` also require catalog migration notes or
|
||||
operator notes describing the cleanup or retirement plan
|
||||
|
||||
@@ -298,12 +325,37 @@ activate the resulting set together.
|
||||
Install-plan rows support explicit `install`, `update`, and `uninstall`
|
||||
actions. Catalog planning writes `update` when the module is already installed.
|
||||
Preflight resolves the target set from installed manifests plus the planned
|
||||
catalog entries. Unplanned catalog entries are not treated as installed; when
|
||||
they would satisfy a missing dependency or named interface, preflight blocks
|
||||
activation with a companion-update issue so the operator can add them to the
|
||||
same plan. The preflight response also includes a structured `target_plan`
|
||||
summary with each planned module's action, current version, catalog target
|
||||
version, package refs, migration-safety level, and acknowledgement state.
|
||||
catalog entries. Unplanned catalog entries are not treated as installed. When a
|
||||
catalog entry would satisfy a missing dependency or named interface, preflight
|
||||
blocks activation with a companion-update issue; the admin catalog planner adds
|
||||
those companion rows automatically when it can resolve them from the current
|
||||
catalog. The preflight response also includes a structured `target_plan` summary
|
||||
with each planned module's action, current version, catalog target version,
|
||||
package refs, migration-safety level, current-version update window, bridge
|
||||
metadata, recovery metadata, and acknowledgement state.
|
||||
|
||||
Database migrations are planned against that same target module set. When the
|
||||
installer is run with `--migrate`, it calls `govoplan_core.commands.init_db`
|
||||
with the target enabled modules rather than the pre-update startup module list,
|
||||
so newly installed module migration directories are discovered before
|
||||
activation. Preflight also returns a structured migration plan. Its step order is
|
||||
derived from:
|
||||
|
||||
- manifest and catalog `migration_after` / `migration_before` declarations
|
||||
- module dependencies and optional dependencies when both modules are in the
|
||||
target plan
|
||||
- named interface provider/consumer relationships when both sides are in the
|
||||
target plan
|
||||
|
||||
Preflight blocks cycles in that ordering graph. It also blocks non-idempotent
|
||||
module migration tasks, forward-only/destructive tasks without operator
|
||||
acknowledgement, and installed manifest tasks that declare no executor.
|
||||
Catalog-only task executors are marked as pending because they can only be
|
||||
confirmed after the target package is installed. The migrator runs pre-migration
|
||||
tasks, upgrades the ordered module heads first, finishes with Alembic `heads`,
|
||||
and then runs post-migration tasks, so Alembic's revision graph remains
|
||||
authoritative while GovOPlaN still gives operators a module-aware live-data
|
||||
order.
|
||||
|
||||
This avoids circular "upgrade A first / upgrade B first" traps: named interface
|
||||
requirements are solved against the target set, not against each intermediate
|
||||
@@ -330,15 +382,20 @@ modules with registered migrations as `requires_review` by default. Release
|
||||
authors should keep that value for ordinary reversible migrations, raise it to
|
||||
`forward_only` when database rollback requires restoring a snapshot, and raise
|
||||
it to `destructive` when the update removes or irreversibly rewrites persisted
|
||||
data. The admin install-plan UI exposes the safety level and lets operators
|
||||
record an explicit acknowledgement; preflight keeps acknowledged
|
||||
forward-only/destructive changes visible as warnings.
|
||||
data. Forward-only and destructive entries must include `recovery_tested: true`
|
||||
and recovery notes after a verified restore or forward-recovery rehearsal. The
|
||||
admin install-plan UI exposes the safety level and lets operators record an
|
||||
explicit acknowledgement; preflight keeps acknowledged forward-only/destructive
|
||||
changes visible as warnings.
|
||||
|
||||
In practice, circular dependencies are avoided by designing interfaces with
|
||||
compatibility windows and by publishing bridge releases. A bridge release keeps
|
||||
the old interface while introducing the new one, allowing dependent modules to
|
||||
move first; a later release can retire the old interface after every dependent
|
||||
module has a compatible target version.
|
||||
module has a compatible target version. Use `current_version_min` and
|
||||
`current_version_max_exclusive` to make those direct-update windows explicit in
|
||||
the catalog, and set `bridge_release: true` on intermediate targets that exist
|
||||
primarily to carry installations safely across a compatibility gap.
|
||||
|
||||
Trusted catalog keys are configured locally:
|
||||
|
||||
|
||||
@@ -1,4 +1,100 @@
|
||||
{
|
||||
"version": 1,
|
||||
"releases": []
|
||||
"releases": [
|
||||
{
|
||||
"heads": [
|
||||
{
|
||||
"owner": "govoplan-campaign",
|
||||
"revision": "2c3d4e5f7081"
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-mail",
|
||||
"revision": "3d4e5f708192"
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-core",
|
||||
"revision": "4f2a9c8e7b6d"
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-identity",
|
||||
"revision": "5c6d7e8f9a10"
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-organizations",
|
||||
"revision": "6d7e8f9a0b1c"
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-idm",
|
||||
"revision": "8f9a0b1c2d3e"
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-calendar",
|
||||
"revision": "9e0f1a2b3c4d"
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-files",
|
||||
"revision": "a7b8c9d0e1f3"
|
||||
}
|
||||
],
|
||||
"owner_heads": [
|
||||
{
|
||||
"owner": "govoplan-access",
|
||||
"revisions": [
|
||||
"4a5b6c7d8e9f"
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-calendar",
|
||||
"revisions": [
|
||||
"9e0f1a2b3c4d"
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-campaign",
|
||||
"revisions": [
|
||||
"2c3d4e5f7081"
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-core",
|
||||
"revisions": [
|
||||
"4f2a9c8e7b6d"
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-files",
|
||||
"revisions": [
|
||||
"a7b8c9d0e1f3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-identity",
|
||||
"revisions": [
|
||||
"5c6d7e8f9a10"
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-idm",
|
||||
"revisions": [
|
||||
"8f9a0b1c2d3e"
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-mail",
|
||||
"revisions": [
|
||||
"3d4e5f708192"
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "govoplan-organizations",
|
||||
"revisions": [
|
||||
"6d7e8f9a0b1c"
|
||||
]
|
||||
}
|
||||
],
|
||||
"recorded_at": "2026-07-11T00:19:07Z",
|
||||
"release": "0.1.7",
|
||||
"squash_policy": "reviewed-manual"
|
||||
}
|
||||
],
|
||||
"version": 1
|
||||
}
|
||||
|
||||
@@ -15,6 +15,29 @@
|
||||
"python_ref": "govoplan-files @ git+ssh://git@git.add-ideas.de/add-ideas/govoplan-files.git@v0.1.4",
|
||||
"webui_package": "@govoplan/files-webui",
|
||||
"webui_ref": "git+ssh://git@git.add-ideas.de/add-ideas/govoplan-files.git#v0.1.4",
|
||||
"migration_safety": "forward_only",
|
||||
"migration_notes": "Database rollback requires restoring the pre-update snapshot.",
|
||||
"migration_after": ["access"],
|
||||
"migration_before": ["campaigns"],
|
||||
"migration_tasks": [
|
||||
{
|
||||
"task_id": "backfill_spaces",
|
||||
"phase": "post_migration_backfill",
|
||||
"summary": "Backfill file spaces after the schema migration.",
|
||||
"task_version": "1",
|
||||
"safety": "forward_only",
|
||||
"idempotent": true,
|
||||
"timeout_seconds": 300
|
||||
}
|
||||
],
|
||||
"current_version_min": "0.1.0",
|
||||
"current_version_max_exclusive": "0.2.0",
|
||||
"bridge_release": true,
|
||||
"bridge_notes": "Keeps the 0.1.x campaign attachment interface while introducing the 0.2.x contract.",
|
||||
"allow_downgrade": false,
|
||||
"allow_same_version": false,
|
||||
"recovery_tested": true,
|
||||
"recovery_notes": "Snapshot restore and forward recovery were rehearsed on the release candidate dataset.",
|
||||
"provides_interfaces": [
|
||||
{
|
||||
"name": "files.campaign_attachments",
|
||||
|
||||
Reference in New Issue
Block a user