This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from importlib.util import module_from_spec, spec_from_file_location
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
_path = (
|
||||||
|
Path(__file__).resolve().parents[1]
|
||||||
|
/ "versions"
|
||||||
|
/ "a36d8e4f9b12_german_reference_locale.py"
|
||||||
|
)
|
||||||
|
_spec = spec_from_file_location("govoplan_german_reference_locale_migration", _path)
|
||||||
|
if _spec is None or _spec.loader is None:
|
||||||
|
raise RuntimeError(f"Unable to load migration implementation from {_path}")
|
||||||
|
_module = module_from_spec(_spec)
|
||||||
|
_spec.loader.exec_module(_module)
|
||||||
|
|
||||||
|
revision = _module.revision
|
||||||
|
down_revision = _module.down_revision
|
||||||
|
branch_labels = _module.branch_labels
|
||||||
|
depends_on = _module.depends_on
|
||||||
|
upgrade = _module.upgrade
|
||||||
|
downgrade = _module.downgrade
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
"""adopt German as the untouched system reference locale
|
||||||
|
|
||||||
|
Revision ID: a36d8e4f9b12
|
||||||
|
Revises: f25c9d3e7a01
|
||||||
|
Create Date: 2026-08-05 00:00:00.000000
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
|
||||||
|
revision = "a36d8e4f9b12"
|
||||||
|
down_revision = "f25c9d3e7a01"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
bind = op.get_bind()
|
||||||
|
if "core_system_settings" not in set(sa.inspect(bind).get_table_names()):
|
||||||
|
return
|
||||||
|
|
||||||
|
settings = sa.table(
|
||||||
|
"core_system_settings",
|
||||||
|
sa.column("id", sa.String),
|
||||||
|
sa.column("default_locale", sa.String),
|
||||||
|
sa.column("created_at", sa.DateTime(timezone=True)),
|
||||||
|
sa.column("updated_at", sa.DateTime(timezone=True)),
|
||||||
|
)
|
||||||
|
bind.execute(
|
||||||
|
settings.update()
|
||||||
|
.where(settings.c.id == "global")
|
||||||
|
.where(settings.c.default_locale == "en")
|
||||||
|
.where(settings.c.created_at == settings.c.updated_at)
|
||||||
|
.values(default_locale="de", updated_at=sa.func.now())
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# Locale selection is user-visible state. A downgrade must not overwrite a
|
||||||
|
# German value that may have been selected explicitly after this migration.
|
||||||
|
pass
|
||||||
@@ -28,6 +28,12 @@ manifest, allowing the shell to link directly to an exact topic when possible.
|
|||||||
Docs still performs the authoritative audience, permission, configured-state,
|
Docs still performs the authoritative audience, permission, configured-state,
|
||||||
and documentation-type filtering.
|
and documentation-type filtering.
|
||||||
|
|
||||||
|
Core also maps explicit route, navigation, settings, and View surface IDs to
|
||||||
|
the module's static user or administrator documentation baseline. This makes a
|
||||||
|
page association complete by default and gives every derived field/action
|
||||||
|
context a useful fallback. Exact `metadata.help_contexts` remain the preferred
|
||||||
|
authoring mechanism for consequential or unfamiliar controls.
|
||||||
|
|
||||||
When there is no exact topic, Docs resolves the page fallback and then the first
|
When there is no exact topic, Docs resolves the page fallback and then the first
|
||||||
visible topic owned by the module. If Docs is unavailable, the shell opens the
|
visible topic owned by the module. If Docs is unavailable, the shell opens the
|
||||||
hosted documentation with the same context parameters.
|
hosted documentation with the same context parameters.
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ operator, and roadmap pages.
|
|||||||
| External references and integration maturity | `EXTERNAL_REFERENCES_AND_INTEGRATION_MATURITY.md` | Stable external identity and cumulative connector maturity; configured source authority is defined by the meta target architecture. |
|
| External references and integration maturity | `EXTERNAL_REFERENCES_AND_INTEGRATION_MATURITY.md` | Stable external identity and cumulative connector maturity; configured source authority is defined by the meta target architecture. |
|
||||||
| Institutional context and governed references | `INSTITUTIONAL_CONTEXT_CONTRACT.md` | Shared temporal, actor/representation, institution, mandate, service, party, decision, evidence, legal-basis, information-governance, presentation, and geo DTO/provider contracts. |
|
| Institutional context and governed references | `INSTITUTIONAL_CONTEXT_CONTRACT.md` | Shared temporal, actor/representation, institution, mandate, service, party, decision, evidence, legal-basis, information-governance, presentation, and geo DTO/provider contracts. |
|
||||||
| Temporal data read context | `TEMPORAL_DATA_CONTEXT.md` | Valid-time and recorded-time titlebar selection, HTTP/cache contract, security boundary, and module-adoption rule. |
|
| Temporal data read context | `TEMPORAL_DATA_CONTEXT.md` | Valid-time and recorded-time titlebar selection, HTTP/cache contract, security boundary, and module-adoption rule. |
|
||||||
|
| Cross-module information governance adoption | `INFORMATION_GOVERNANCE_ADOPTION.md` | Manifest evidence and enforcement rules for temporal browsing, purpose-aware access, retention, and institutional context. |
|
||||||
| Context-sensitive F1 help | `CONTEXTUAL_HELP_CONTRACT.md` | Focus, route, module-manifest documentation contexts, Docs projection, and hosted fallback. |
|
| Context-sensitive F1 help | `CONTEXTUAL_HELP_CONTRACT.md` | Focus, route, module-manifest documentation contexts, Docs projection, and hosted fallback. |
|
||||||
|
| German localization and help quality gate | `LOCALIZATION_AND_HELP_QUALITY.md` | German reference locale, new-installation default, catalog completeness, automatic page associations, and explicit-help review priorities. |
|
||||||
| Postbox E2EE target architecture | `POSTBOX_E2EE_ARCHITECTURE.md` | Strategic encrypted postbox/mailbox model, key ownership, role mailbox semantics, and retraction limits. |
|
| Postbox E2EE target architecture | `POSTBOX_E2EE_ARCHITECTURE.md` | Strategic encrypted postbox/mailbox model, key ownership, role mailbox semantics, and retraction limits. |
|
||||||
| Shared state, runtime coordination, and recovery | `STATE_AND_RECOVERY_CONTRACT.md` | State profiles, object storage, node registration/drain, fenced leases, migration ordering, and recovery evidence. |
|
| Shared state, runtime coordination, and recovery | `STATE_AND_RECOVERY_CONTRACT.md` | State profiles, object storage, node registration/drain, fenced leases, migration ordering, and recovery evidence. |
|
||||||
| Module lifecycle recovery | `MODULE_LIFECYCLE_RECOVERY.md` | Installer/live-graph recovery modes, deployment fence, evidence, retry blocking, and operator reconciliation. |
|
| Module lifecycle recovery | `MODULE_LIFECYCLE_RECOVERY.md` | Installer/live-graph recovery modes, deployment fence, evidence, retry blocking, and operator reconciliation. |
|
||||||
@@ -39,6 +41,8 @@ operator, and roadmap pages.
|
|||||||
| Topic | Canonical document | Notes |
|
| Topic | Canonical document | Notes |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| Product roadmap and module routing | `GOVOPLAN_MASTER_ROADMAP.md` | Product-level sequencing, implementation gates, issue routing, and missing-module decisions. |
|
| Product roadmap and module routing | `GOVOPLAN_MASTER_ROADMAP.md` | Product-level sequencing, implementation gates, issue routing, and missing-module decisions. |
|
||||||
|
| Stable platform ideas | `govoplan/docs/PLATFORM_CORE_IDEAS.md` | Cross-product thesis, canonical distinctions, product experience rule, maturity rule, and decision test. |
|
||||||
|
| Current cross-product reconciliation | `govoplan/docs/STRATEGY_STATUS.md` | The only current prose status source; generated evidence and Gitea remain authoritative inputs. |
|
||||||
| Institutional governance target | `govoplan/docs/INSTITUTIONAL_GOVERNANCE_TARGET_ARCHITECTURE.md` | Cross-product semantic layers, source-authority modes, candidate Mandates/Services/Parties/Decisions boundaries, and migration sequence. |
|
| Institutional governance target | `govoplan/docs/INSTITUTIONAL_GOVERNANCE_TARGET_ARCHITECTURE.md` | Cross-product semantic layers, source-authority modes, candidate Mandates/Services/Parties/Decisions boundaries, and migration sequence. |
|
||||||
| UI/UX decisions | `UI_UX_DECISION_LEDGER.md` | Binding guided-UI decisions, open decisions, impact index, and review checklist. |
|
| UI/UX decisions | `UI_UX_DECISION_LEDGER.md` | Binding guided-UI decisions, open decisions, impact index, and review checklist. |
|
||||||
| Core interface migration | `INTERFACE_PATTERN_MIGRATION.md` | Core-owned settings, credential, retention, lifecycle, and shared-component evidence for the product pattern language. |
|
| Core interface migration | `INTERFACE_PATTERN_MIGRATION.md` | Core-owned settings, credential, retention, lifecycle, and shared-component evidence for the product pattern language. |
|
||||||
|
|||||||
@@ -0,0 +1,131 @@
|
|||||||
|
# Information Governance Adoption
|
||||||
|
|
||||||
|
## Platform Rule
|
||||||
|
|
||||||
|
Temporal browsing, purpose-aware access, retention, and institutional context
|
||||||
|
are platform-wide information-governance dimensions. Every module receives the
|
||||||
|
same contract by default. A module may claim `partial` or `enforced` only with
|
||||||
|
repository-owned object scope, evidence, and limitations; it may claim
|
||||||
|
`not_applicable` only when the dimension genuinely does not apply.
|
||||||
|
|
||||||
|
Historical business data is always authorized under the current security
|
||||||
|
state. No module may use a historical permission, membership, role, function
|
||||||
|
assignment, or policy projection to weaken present-day access.
|
||||||
|
|
||||||
|
Platform-wide adoption is tracked in
|
||||||
|
[GovOPlaN #40](https://git.add-ideas.de/GovOPlaN/govoplan/issues/40), with
|
||||||
|
temporal reads detailed in
|
||||||
|
[GovOPlaN #39](https://git.add-ideas.de/GovOPlaN/govoplan/issues/39).
|
||||||
|
|
||||||
|
## Manifest Declaration
|
||||||
|
|
||||||
|
`ModuleManifest.information_governance` publishes four dimensions:
|
||||||
|
|
||||||
|
- `temporal_browsing`;
|
||||||
|
- `purpose_aware_access`;
|
||||||
|
- `retention`;
|
||||||
|
- `institutional_context`.
|
||||||
|
|
||||||
|
Each dimension declares:
|
||||||
|
|
||||||
|
- adoption: `not_applicable`, `contract_only`, `partial`, or `enforced`;
|
||||||
|
- object types covered;
|
||||||
|
- repository-local test/documentation evidence;
|
||||||
|
- the remaining limitation for `contract_only` or `partial`.
|
||||||
|
|
||||||
|
The default is intentionally `contract_only`. It applies the platform rule
|
||||||
|
without pretending that existing domain queries and effects already enforce
|
||||||
|
it. `reference_ready`, `supported`, and `lts` modules cannot retain an
|
||||||
|
applicable dimension below `enforced`.
|
||||||
|
|
||||||
|
## Read Contract
|
||||||
|
|
||||||
|
For every persistent domain object, the owner classifies the read:
|
||||||
|
|
||||||
|
1. **Current-only:** historical semantics do not exist and the API says so.
|
||||||
|
2. **Valid-time:** select facts effective now or at the requested instant.
|
||||||
|
3. **Bitemporal:** additionally select only revisions known by `recorded_at`.
|
||||||
|
4. **All-validity:** return effective revisions in a bounded history view.
|
||||||
|
|
||||||
|
The Core temporal middleware supplies the request context. Owners apply it in
|
||||||
|
repositories or query helpers, include it in cache keys, return evaluated
|
||||||
|
context, and test current/at/all plus recorded-time boundaries. Search,
|
||||||
|
reporting, exports, selectors, counts, and drill-through must use the same
|
||||||
|
projection as the owning list/detail API.
|
||||||
|
|
||||||
|
## Purpose-Aware Access Contract
|
||||||
|
|
||||||
|
Permission establishes a technical action ceiling. Purpose-aware access asks
|
||||||
|
whether this actor, represented capacity, case/work item, legal basis, and
|
||||||
|
declared use may access this object now.
|
||||||
|
|
||||||
|
- A client-supplied purpose is an assertion, never authority by itself.
|
||||||
|
- The owner or Policy capability validates the purpose and returns explainable
|
||||||
|
provenance.
|
||||||
|
- Sensitive access can require case assignment, mandate, reason capture,
|
||||||
|
approval, or break-glass evidence.
|
||||||
|
- Search, selectors, reporting, exports, background jobs, and connectors apply
|
||||||
|
the same decision.
|
||||||
|
- Audit records the validated purpose identifier and decision reference, not
|
||||||
|
unnecessary content.
|
||||||
|
|
||||||
|
## Retention Contract
|
||||||
|
|
||||||
|
Every persistent object declares an owner, retention class or policy reference,
|
||||||
|
trigger, start instant, hold behavior, review/disposition action, and evidence.
|
||||||
|
Retention is not a generic timestamp deletion job.
|
||||||
|
|
||||||
|
- Domain owners enumerate and execute their own effects through a typed
|
||||||
|
retention provider.
|
||||||
|
- Policy resolves inherited ceilings and simulation.
|
||||||
|
- Records owns record disposition; Files owns byte/object effects; Audit owns
|
||||||
|
audit-detail behavior; external providers declare their own effect and
|
||||||
|
recovery semantics.
|
||||||
|
- Dry-run, legal hold, exact revision, idempotency, outcome unknown,
|
||||||
|
reconciliation, correction, and destruction evidence are mandatory for
|
||||||
|
consequential removal.
|
||||||
|
|
||||||
|
## Institutional Context Contract
|
||||||
|
|
||||||
|
Consequential objects and effects carry the relevant tenant, institution,
|
||||||
|
organization unit, function, mandate/jurisdiction, service/case/work item,
|
||||||
|
party/representation, decision, and record references. Context is minimized to
|
||||||
|
what the operation needs. Organizational membership is not itself permission
|
||||||
|
or mandate.
|
||||||
|
|
||||||
|
Events, automation intents, audit evidence, records, and external effects retain
|
||||||
|
the same governed context envelope or an exact reference to it. Consumers must
|
||||||
|
not reconstruct authority later from mutable current structures.
|
||||||
|
|
||||||
|
## Adoption Order
|
||||||
|
|
||||||
|
1. Inventory every domain list/detail/search/export/effect and classify all
|
||||||
|
four dimensions.
|
||||||
|
2. Migrate institutional owners first: Access, IDM, Organizations, Mandates,
|
||||||
|
Services, Parties, Cases, Approvals, Committee, Decisions, Voting, and
|
||||||
|
Records.
|
||||||
|
3. Migrate communication and content: Addresses, Distribution Lists, Campaign,
|
||||||
|
Postbox, Mail, Calendar, Files, Templates, and Forms Runtime.
|
||||||
|
4. Migrate data projections: Connectors, Datasources, Dataflow, Reporting,
|
||||||
|
Search, Risk Compliance, and Dashboard.
|
||||||
|
5. Migrate workflow/task/background/provider operations and prove that no
|
||||||
|
asynchronous path drops context.
|
||||||
|
6. Advance manifest claims only after owner tests and browser/reference-journey
|
||||||
|
evidence pass.
|
||||||
|
|
||||||
|
The generated platform inventory reports adoption counts and module details.
|
||||||
|
Gitea tracks individual migrations; the declaration is evidence and a maturity
|
||||||
|
gate, not a substitute for implementation.
|
||||||
|
|
||||||
|
## Definition Of Enforced
|
||||||
|
|
||||||
|
A dimension is `enforced` only when:
|
||||||
|
|
||||||
|
- all declared object types and public reads/effects use it;
|
||||||
|
- list/detail/count/search/export/worker behavior is consistent;
|
||||||
|
- cache and pagination semantics cannot cross contexts;
|
||||||
|
- absence, invalid values, and inaccessible referenced context fail safely;
|
||||||
|
- tests cover current, historical, unauthorized, replay, and module-absence
|
||||||
|
combinations appropriate to the dimension;
|
||||||
|
- user/admin documentation explains behavior and limitations;
|
||||||
|
- the manifest cites those tests and docs.
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
# Localization And Contextual Help Quality
|
||||||
|
|
||||||
|
## Reference Language
|
||||||
|
|
||||||
|
German (`de`) is GovOPlaN's first-class reference target. Every translation key
|
||||||
|
used by a shipped WebUI must exist in German and English. German completeness is
|
||||||
|
a release gate; English remains the source-code fallback language so existing
|
||||||
|
literal labels and external developer APIs do not change semantics.
|
||||||
|
|
||||||
|
New installations and tenants default to German. Existing system, tenant, and
|
||||||
|
user preferences are preserved. The available-language and policy model can
|
||||||
|
still select another default or disable a package at the relevant scope.
|
||||||
|
|
||||||
|
Explicit high-risk help content and browser acceptance are tracked in
|
||||||
|
[Core #284](https://git.add-ideas.de/GovOPlaN/govoplan-core/issues/284).
|
||||||
|
|
||||||
|
The platform inventory recognizes both inline locale objects and generated
|
||||||
|
catalogs declared as `const de` / `const en`. Its strict mode requires both
|
||||||
|
locales and reports `de` explicitly as the reference locale.
|
||||||
|
|
||||||
|
## Help Resolution
|
||||||
|
|
||||||
|
Every focusable field and action receives a stable derived F1 identity from the
|
||||||
|
shared shell, even when the component has no dedicated help text. Resolution
|
||||||
|
falls back from field/action to dialog or page and then to the module's visible
|
||||||
|
documentation baseline.
|
||||||
|
|
||||||
|
Backend manifests publish explicit topic associations first. Core additionally
|
||||||
|
associates declared route, navigation, settings, and View surface IDs with the
|
||||||
|
module's static user or administrator documentation baseline. Feature modules
|
||||||
|
should still add exact `metadata.help_contexts` entries for consequential,
|
||||||
|
unfamiliar, policy-controlled, destructive, security-sensitive, or legally
|
||||||
|
meaningful fields and actions.
|
||||||
|
|
||||||
|
The generated `help_review_candidates` list is therefore a content-depth queue,
|
||||||
|
not a list of controls on which F1 cannot work. It should prioritize:
|
||||||
|
|
||||||
|
1. effect, deletion, delivery, retention, disclosure, encryption, and recovery;
|
||||||
|
2. identity, representation, mandate, institutional context, and purpose;
|
||||||
|
3. valid-time versus recorded-time selection;
|
||||||
|
4. provider authority, synchronization, conflict, and outcome unknown;
|
||||||
|
5. fields whose consequences are not evident from their label.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /mnt/DATA/git/govoplan
|
||||||
|
/mnt/DATA/git/govoplan/.venv/bin/python \
|
||||||
|
tools/inventory/platform-interface-inventory.py \
|
||||||
|
--strict --strict-declarations --strict-endpoints
|
||||||
|
```
|
||||||
|
|
||||||
|
The check must report:
|
||||||
|
|
||||||
|
- reference locale `de` present and complete;
|
||||||
|
- no used key missing from `de` or `en`;
|
||||||
|
- every field has a resolvable F1 context;
|
||||||
|
- no duplicate stable IDs;
|
||||||
|
- no undeclared public WebUI surface;
|
||||||
|
- no stale runtime route or endpoint declaration.
|
||||||
@@ -93,10 +93,17 @@ Alembic, and post-migration tasks. The lock is session-scoped and therefore
|
|||||||
released if the migration process dies.
|
released if the migration process dies.
|
||||||
|
|
||||||
Runtime roles run `govoplan_core.commands.wait_for_database`. It waits until
|
Runtime roles run `govoplan_core.commands.wait_for_database`. It waits until
|
||||||
the database has exactly the configured Core/module Alembic heads and never
|
the database has exactly the configured, dependency-resolved Core/module
|
||||||
upgrades schema. This permits a migration Job and runtime Deployments to be
|
Alembic heads and never upgrades schema. Cross-module `depends_on` revisions
|
||||||
|
therefore do not leave runtime roles waiting for a branch marker Alembic has
|
||||||
|
correctly consumed. This permits a migration Job and runtime Deployments to be
|
||||||
submitted together while keeping startup fail-closed.
|
submitted together while keeping startup fail-closed.
|
||||||
|
|
||||||
|
Runtime coordination records the installed `govoplan-core` distribution
|
||||||
|
version for API, worker and scheduler roles. FastAPI/OpenAPI metadata versions
|
||||||
|
are presentation metadata and must not be used as deployable software identity;
|
||||||
|
mixing the two would create a false version-skew readiness failure.
|
||||||
|
|
||||||
## Recovery Ledger
|
## Recovery Ledger
|
||||||
|
|
||||||
`govoplan_core.core.recovery` provides a durable operation and evidence
|
`govoplan_core.core.recovery` provides a durable operation and evidence
|
||||||
|
|||||||
@@ -1065,6 +1065,408 @@
|
|||||||
"release": "0.1.15",
|
"release": "0.1.15",
|
||||||
"squash_policy": "reviewed-manual",
|
"squash_policy": "reviewed-manual",
|
||||||
"track": "release"
|
"track": "release"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"heads": [
|
||||||
|
{
|
||||||
|
"owner": "govoplan-notifications",
|
||||||
|
"revision": "6e2f91ab4c70"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-poll",
|
||||||
|
"revision": "6e7f8a9b0c1d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-dashboard",
|
||||||
|
"revision": "7b9d2f4a6c8e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-voting",
|
||||||
|
"revision": "8b9c0d1e2f3a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-mail",
|
||||||
|
"revision": "93b4c5d6e7f8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-core",
|
||||||
|
"revision": "a36d8e4f9b12"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-forms-runtime",
|
||||||
|
"revision": "a3d5f7b9c1e2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-templates",
|
||||||
|
"revision": "a3f7c9d2e1b4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-organizations",
|
||||||
|
"revision": "a61e4d9c72b8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-mandates",
|
||||||
|
"revision": "a8b1c2d3e4f5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-audit",
|
||||||
|
"revision": "a8d1e4f7b2c5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-approvals",
|
||||||
|
"revision": "a91c4e72b5d8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-policy",
|
||||||
|
"revision": "a9c4e7b2d5f8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-idm",
|
||||||
|
"revision": "b1c2d3e4f5a6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-search",
|
||||||
|
"revision": "b2c3d4e5f607"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-datasources",
|
||||||
|
"revision": "b8d2f5a0c3e7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-views",
|
||||||
|
"revision": "b8e4c1f7a2d9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-risk-compliance",
|
||||||
|
"revision": "b9c0d1e2f3a4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-services",
|
||||||
|
"revision": "b9c2d3e4f5a6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-parties",
|
||||||
|
"revision": "c0d3e4f5a6b7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-identity-trust",
|
||||||
|
"revision": "c3f5a7b9d1e2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-projects",
|
||||||
|
"revision": "c4a1e8f2d6b9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-addresses",
|
||||||
|
"revision": "c5d7e8f9a0b1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-access",
|
||||||
|
"revision": "c7e0a3d6f9b2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-reporting",
|
||||||
|
"revision": "c8d5e2f6a9b3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-scheduling",
|
||||||
|
"revision": "c9d4e7f1a2b3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-decisions",
|
||||||
|
"revision": "d1e4f5a6b7c8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-calendar",
|
||||||
|
"revision": "d24e5f607182"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-committee",
|
||||||
|
"revision": "d8b9f0a1c2e3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-postbox",
|
||||||
|
"revision": "d8e3f6a9b2c5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-campaign",
|
||||||
|
"revision": "e3c8f4a5b6d7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-workflow-engine",
|
||||||
|
"revision": "e4a1f8c2d7b6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-encryption",
|
||||||
|
"revision": "e5b7c9d1f3a4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-dist-lists",
|
||||||
|
"revision": "e7c3a9d1b5f2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-files",
|
||||||
|
"revision": "f1a2b3c4d5e7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-dataflow",
|
||||||
|
"revision": "f6c2a9d4e7b1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-cases",
|
||||||
|
"revision": "f6d3a8b1c4e7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-connectors",
|
||||||
|
"revision": "f7c8d9e0a1b2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"owner_heads": [
|
||||||
|
{
|
||||||
|
"owner": "govoplan-access",
|
||||||
|
"revisions": [
|
||||||
|
"c7e0a3d6f9b2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-addresses",
|
||||||
|
"revisions": [
|
||||||
|
"c5d7e8f9a0b1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-approvals",
|
||||||
|
"revisions": [
|
||||||
|
"a91c4e72b5d8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-audit",
|
||||||
|
"revisions": [
|
||||||
|
"a8d1e4f7b2c5"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-calendar",
|
||||||
|
"revisions": [
|
||||||
|
"d24e5f607182"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-campaign",
|
||||||
|
"revisions": [
|
||||||
|
"e3c8f4a5b6d7"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-cases",
|
||||||
|
"revisions": [
|
||||||
|
"f6d3a8b1c4e7"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-committee",
|
||||||
|
"revisions": [
|
||||||
|
"d8b9f0a1c2e3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-connectors",
|
||||||
|
"revisions": [
|
||||||
|
"f7c8d9e0a1b2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-core",
|
||||||
|
"revisions": [
|
||||||
|
"a36d8e4f9b12"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-dashboard",
|
||||||
|
"revisions": [
|
||||||
|
"7b9d2f4a6c8e"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-dataflow",
|
||||||
|
"revisions": [
|
||||||
|
"f6c2a9d4e7b1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-datasources",
|
||||||
|
"revisions": [
|
||||||
|
"b8d2f5a0c3e7"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-decisions",
|
||||||
|
"revisions": [
|
||||||
|
"d1e4f5a6b7c8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-dist-lists",
|
||||||
|
"revisions": [
|
||||||
|
"e7c3a9d1b5f2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-encryption",
|
||||||
|
"revisions": [
|
||||||
|
"e5b7c9d1f3a4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-files",
|
||||||
|
"revisions": [
|
||||||
|
"f1a2b3c4d5e7"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-forms",
|
||||||
|
"revisions": [
|
||||||
|
"e1f2a3b4c5d6"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-forms-runtime",
|
||||||
|
"revisions": [
|
||||||
|
"a3d5f7b9c1e2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-identity",
|
||||||
|
"revisions": [
|
||||||
|
"5c6d7e8f9a10"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-identity-trust",
|
||||||
|
"revisions": [
|
||||||
|
"c3f5a7b9d1e2"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-idm",
|
||||||
|
"revisions": [
|
||||||
|
"b1c2d3e4f5a6"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-mail",
|
||||||
|
"revisions": [
|
||||||
|
"93b4c5d6e7f8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-mandates",
|
||||||
|
"revisions": [
|
||||||
|
"a8b1c2d3e4f5"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-notifications",
|
||||||
|
"revisions": [
|
||||||
|
"6e2f91ab4c70"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-organizations",
|
||||||
|
"revisions": [
|
||||||
|
"a61e4d9c72b8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-parties",
|
||||||
|
"revisions": [
|
||||||
|
"c0d3e4f5a6b7"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-policy",
|
||||||
|
"revisions": [
|
||||||
|
"a9c4e7b2d5f8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-poll",
|
||||||
|
"revisions": [
|
||||||
|
"6e7f8a9b0c1d"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-postbox",
|
||||||
|
"revisions": [
|
||||||
|
"d8e3f6a9b2c5"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-projects",
|
||||||
|
"revisions": [
|
||||||
|
"c4a1e8f2d6b9"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-reporting",
|
||||||
|
"revisions": [
|
||||||
|
"c8d5e2f6a9b3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-risk-compliance",
|
||||||
|
"revisions": [
|
||||||
|
"b9c0d1e2f3a4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-scheduling",
|
||||||
|
"revisions": [
|
||||||
|
"c9d4e7f1a2b3"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-search",
|
||||||
|
"revisions": [
|
||||||
|
"b2c3d4e5f607"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-services",
|
||||||
|
"revisions": [
|
||||||
|
"b9c2d3e4f5a6"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-templates",
|
||||||
|
"revisions": [
|
||||||
|
"a3f7c9d2e1b4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-views",
|
||||||
|
"revisions": [
|
||||||
|
"b8e4c1f7a2d9"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-voting",
|
||||||
|
"revisions": [
|
||||||
|
"8b9c0d1e2f3a"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"owner": "govoplan-workflow-engine",
|
||||||
|
"revisions": [
|
||||||
|
"e4a1f8c2d7b6"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"recorded_at": "2026-08-05T17:51:25Z",
|
||||||
|
"release": "0.1.16",
|
||||||
|
"squash_policy": "reviewed-manual",
|
||||||
|
"track": "release"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"version": 1
|
"version": 1
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "govoplan-core"
|
name = "govoplan-core"
|
||||||
version = "0.1.15"
|
version = "0.1.16"
|
||||||
description = "Reusable GovOPlaN platform core, access, tenancy, and RBAC components."
|
description = "Reusable GovOPlaN platform core, access, tenancy, and RBAC components."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.12"
|
requires-python = ">=3.12"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class SystemSettings(Base, TimestampMixin):
|
|||||||
__tablename__ = "core_system_settings"
|
__tablename__ = "core_system_settings"
|
||||||
|
|
||||||
id: Mapped[str] = mapped_column(String(36), primary_key=True, default="global")
|
id: Mapped[str] = mapped_column(String(36), primary_key=True, default="global")
|
||||||
default_locale: Mapped[str] = mapped_column(String(20), default="en", nullable=False)
|
default_locale: Mapped[str] = mapped_column(String(20), default="de", nullable=False)
|
||||||
allow_tenant_custom_groups: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
allow_tenant_custom_groups: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
||||||
allow_tenant_custom_roles: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
allow_tenant_custom_roles: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
||||||
allow_tenant_api_keys: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
allow_tenant_api_keys: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False)
|
||||||
@@ -20,4 +20,3 @@ class SystemSettings(Base, TimestampMixin):
|
|||||||
|
|
||||||
|
|
||||||
__all__ = ["SystemSettings"]
|
__all__ = ["SystemSettings"]
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ class TenantInfo(BaseModel):
|
|||||||
slug: str
|
slug: str
|
||||||
name: str
|
name: str
|
||||||
is_active: bool = True
|
is_active: bool = True
|
||||||
default_locale: str = "en"
|
default_locale: str = "de"
|
||||||
enabled_language_codes: list[str] = Field(default_factory=list)
|
enabled_language_codes: list[str] = Field(default_factory=list)
|
||||||
|
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ class AuthProfileResponse(BaseModel):
|
|||||||
active_tenant: TenantInfo
|
active_tenant: TenantInfo
|
||||||
available_languages: list[LanguageInfo] = Field(default_factory=list)
|
available_languages: list[LanguageInfo] = Field(default_factory=list)
|
||||||
enabled_language_codes: list[str] = Field(default_factory=list)
|
enabled_language_codes: list[str] = Field(default_factory=list)
|
||||||
default_language: str = "en"
|
default_language: str = "de"
|
||||||
profile_loaded: bool = True
|
profile_loaded: bool = True
|
||||||
|
|
||||||
|
|
||||||
@@ -239,7 +239,7 @@ class LoginResponse(BaseModel):
|
|||||||
principal: PrincipalContextInfo | None = None
|
principal: PrincipalContextInfo | None = None
|
||||||
available_languages: list[LanguageInfo] = Field(default_factory=list)
|
available_languages: list[LanguageInfo] = Field(default_factory=list)
|
||||||
enabled_language_codes: list[str] = Field(default_factory=list)
|
enabled_language_codes: list[str] = Field(default_factory=list)
|
||||||
default_language: str = "en"
|
default_language: str = "de"
|
||||||
profile_loaded: bool = True
|
profile_loaded: bool = True
|
||||||
roles_loaded: bool = True
|
roles_loaded: bool = True
|
||||||
groups_loaded: bool = True
|
groups_loaded: bool = True
|
||||||
@@ -257,7 +257,7 @@ class MeResponse(BaseModel):
|
|||||||
principal: PrincipalContextInfo | None = None
|
principal: PrincipalContextInfo | None = None
|
||||||
available_languages: list[LanguageInfo] = Field(default_factory=list)
|
available_languages: list[LanguageInfo] = Field(default_factory=list)
|
||||||
enabled_language_codes: list[str] = Field(default_factory=list)
|
enabled_language_codes: list[str] = Field(default_factory=list)
|
||||||
default_language: str = "en"
|
default_language: str = "de"
|
||||||
profile_loaded: bool = True
|
profile_loaded: bool = True
|
||||||
roles_loaded: bool = True
|
roles_loaded: bool = True
|
||||||
groups_loaded: bool = True
|
groups_loaded: bool = True
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ def consume_first_admin_credential(
|
|||||||
tenant = Tenant(
|
tenant = Tenant(
|
||||||
slug=clean_tenant_slug,
|
slug=clean_tenant_slug,
|
||||||
name=clean_tenant_name,
|
name=clean_tenant_name,
|
||||||
default_locale="en",
|
default_locale="de",
|
||||||
settings={},
|
settings={},
|
||||||
is_active=True,
|
is_active=True,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,236 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from dataclasses import dataclass, field
|
||||||
|
from typing import Literal, Mapping, cast
|
||||||
|
|
||||||
|
|
||||||
|
InformationGovernanceAdoption = Literal[
|
||||||
|
"not_applicable",
|
||||||
|
"contract_only",
|
||||||
|
"partial",
|
||||||
|
"enforced",
|
||||||
|
]
|
||||||
|
|
||||||
|
INFORMATION_GOVERNANCE_ADOPTION_ORDER: tuple[InformationGovernanceAdoption, ...] = (
|
||||||
|
"not_applicable",
|
||||||
|
"contract_only",
|
||||||
|
"partial",
|
||||||
|
"enforced",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InformationGovernanceDeclarationError(ValueError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, slots=True)
|
||||||
|
class InformationGovernanceDimension:
|
||||||
|
"""Truthful module-level adoption claim for one cross-cutting dimension."""
|
||||||
|
|
||||||
|
adoption: InformationGovernanceAdoption = "contract_only"
|
||||||
|
object_types: tuple[str, ...] = ()
|
||||||
|
evidence: tuple[str, ...] = ()
|
||||||
|
limitation: str | None = None
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
if self.adoption not in INFORMATION_GOVERNANCE_ADOPTION_ORDER:
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
f"Unsupported information-governance adoption: {self.adoption!r}."
|
||||||
|
)
|
||||||
|
for field_name in ("object_types", "evidence"):
|
||||||
|
values = getattr(self, field_name)
|
||||||
|
if len(values) != len(set(values)) or any(not item.strip() for item in values):
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
f"Information-governance {field_name.replace('_', ' ')} must "
|
||||||
|
"contain unique non-empty values."
|
||||||
|
)
|
||||||
|
if self.adoption == "enforced" and not self.evidence:
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
"An enforced information-governance dimension requires evidence."
|
||||||
|
)
|
||||||
|
if self.adoption in {"partial", "enforced"} and not self.object_types:
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
"Partial and enforced information-governance dimensions must "
|
||||||
|
"name their covered object types."
|
||||||
|
)
|
||||||
|
if self.adoption == "not_applicable" and self.object_types:
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
"A non-applicable information-governance dimension cannot declare object types."
|
||||||
|
)
|
||||||
|
if self.adoption in {"contract_only", "partial"} and not str(
|
||||||
|
self.limitation or ""
|
||||||
|
).strip():
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
"Contract-only and partial adoption must state the current limitation."
|
||||||
|
)
|
||||||
|
|
||||||
|
def to_dict(self) -> dict[str, object]:
|
||||||
|
return {
|
||||||
|
"adoption": self.adoption,
|
||||||
|
"object_types": list(self.object_types),
|
||||||
|
"evidence": list(self.evidence),
|
||||||
|
"limitation": self.limitation,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _contract_only_dimension() -> InformationGovernanceDimension:
|
||||||
|
return InformationGovernanceDimension(
|
||||||
|
adoption="contract_only",
|
||||||
|
limitation=(
|
||||||
|
"The platform contract applies, but module-specific adoption evidence "
|
||||||
|
"has not been declared."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True, slots=True)
|
||||||
|
class ModuleInformationGovernance:
|
||||||
|
"""Cross-cutting data-use requirements and honest adoption evidence."""
|
||||||
|
|
||||||
|
temporal_browsing: InformationGovernanceDimension = field(
|
||||||
|
default_factory=_contract_only_dimension
|
||||||
|
)
|
||||||
|
purpose_aware_access: InformationGovernanceDimension = field(
|
||||||
|
default_factory=_contract_only_dimension
|
||||||
|
)
|
||||||
|
retention: InformationGovernanceDimension = field(
|
||||||
|
default_factory=_contract_only_dimension
|
||||||
|
)
|
||||||
|
institutional_context: InformationGovernanceDimension = field(
|
||||||
|
default_factory=_contract_only_dimension
|
||||||
|
)
|
||||||
|
current_authorization_for_historical_reads: bool = True
|
||||||
|
contract_version: str = "1"
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
if self.contract_version != "1":
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
"Unsupported module information-governance contract version."
|
||||||
|
)
|
||||||
|
if not self.current_authorization_for_historical_reads:
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
"Historical reads must always use current authorization."
|
||||||
|
)
|
||||||
|
for name, dimension in self.dimensions.items():
|
||||||
|
if not isinstance(dimension, InformationGovernanceDimension):
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
f"Information-governance dimension {name!r} has an invalid value."
|
||||||
|
)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dimensions(self) -> Mapping[str, InformationGovernanceDimension]:
|
||||||
|
return {
|
||||||
|
"temporal_browsing": self.temporal_browsing,
|
||||||
|
"purpose_aware_access": self.purpose_aware_access,
|
||||||
|
"retention": self.retention,
|
||||||
|
"institutional_context": self.institutional_context,
|
||||||
|
}
|
||||||
|
|
||||||
|
def to_dict(self) -> dict[str, object]:
|
||||||
|
return {
|
||||||
|
"contract_version": self.contract_version,
|
||||||
|
"current_authorization_for_historical_reads": (
|
||||||
|
self.current_authorization_for_historical_reads
|
||||||
|
),
|
||||||
|
"dimensions": {
|
||||||
|
name: dimension.to_dict()
|
||||||
|
for name, dimension in self.dimensions.items()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def information_governance_from_mapping(
|
||||||
|
value: Mapping[str, object],
|
||||||
|
) -> ModuleInformationGovernance:
|
||||||
|
raw_dimensions = value.get("dimensions")
|
||||||
|
if not isinstance(raw_dimensions, Mapping):
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
"Information-governance dimensions must be an object."
|
||||||
|
)
|
||||||
|
|
||||||
|
def dimension(name: str) -> InformationGovernanceDimension:
|
||||||
|
raw_dimension = raw_dimensions.get(name)
|
||||||
|
if not isinstance(raw_dimension, Mapping):
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
f"Information-governance dimension {name!r} must be an object."
|
||||||
|
)
|
||||||
|
|
||||||
|
def text_tuple(field_name: str) -> tuple[str, ...]:
|
||||||
|
raw_values = raw_dimension.get(field_name, ())
|
||||||
|
if not isinstance(raw_values, (list, tuple)):
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
f"Information-governance {name}.{field_name} must be a list."
|
||||||
|
)
|
||||||
|
if any(not isinstance(item, str) for item in raw_values):
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
f"Information-governance {name}.{field_name} must contain strings."
|
||||||
|
)
|
||||||
|
return tuple(raw_values)
|
||||||
|
|
||||||
|
raw_limitation = raw_dimension.get("limitation")
|
||||||
|
raw_adoption = raw_dimension.get("adoption") or "contract_only"
|
||||||
|
if not isinstance(raw_adoption, str):
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
f"Information-governance {name}.adoption must be a string."
|
||||||
|
)
|
||||||
|
if raw_limitation is not None and not isinstance(raw_limitation, str):
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
f"Information-governance {name}.limitation must be a string."
|
||||||
|
)
|
||||||
|
return InformationGovernanceDimension(
|
||||||
|
adoption=cast(
|
||||||
|
InformationGovernanceAdoption,
|
||||||
|
raw_adoption,
|
||||||
|
),
|
||||||
|
object_types=text_tuple("object_types"),
|
||||||
|
evidence=text_tuple("evidence"),
|
||||||
|
limitation=raw_limitation,
|
||||||
|
)
|
||||||
|
|
||||||
|
current_authorization = value.get(
|
||||||
|
"current_authorization_for_historical_reads",
|
||||||
|
True,
|
||||||
|
)
|
||||||
|
if not isinstance(current_authorization, bool):
|
||||||
|
raise InformationGovernanceDeclarationError(
|
||||||
|
"current_authorization_for_historical_reads must be boolean."
|
||||||
|
)
|
||||||
|
return ModuleInformationGovernance(
|
||||||
|
contract_version=str(value.get("contract_version") or "1"),
|
||||||
|
current_authorization_for_historical_reads=current_authorization,
|
||||||
|
temporal_browsing=dimension("temporal_browsing"),
|
||||||
|
purpose_aware_access=dimension("purpose_aware_access"),
|
||||||
|
retention=dimension("retention"),
|
||||||
|
institutional_context=dimension("institutional_context"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def information_governance_maturity_issues(
|
||||||
|
declaration: ModuleInformationGovernance,
|
||||||
|
*,
|
||||||
|
maturity: str | None,
|
||||||
|
) -> tuple[str, ...]:
|
||||||
|
if maturity not in {"reference_ready", "supported", "lts"}:
|
||||||
|
return ()
|
||||||
|
incomplete = [
|
||||||
|
name
|
||||||
|
for name, dimension in declaration.dimensions.items()
|
||||||
|
if dimension.adoption not in {"not_applicable", "enforced"}
|
||||||
|
]
|
||||||
|
if not incomplete:
|
||||||
|
return ()
|
||||||
|
return (
|
||||||
|
f"Maturity {maturity!r} requires enforced or explicitly non-applicable "
|
||||||
|
"information governance for: " + ", ".join(incomplete),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"INFORMATION_GOVERNANCE_ADOPTION_ORDER",
|
||||||
|
"InformationGovernanceAdoption",
|
||||||
|
"InformationGovernanceDeclarationError",
|
||||||
|
"InformationGovernanceDimension",
|
||||||
|
"ModuleInformationGovernance",
|
||||||
|
"information_governance_from_mapping",
|
||||||
|
"information_governance_maturity_issues",
|
||||||
|
]
|
||||||
@@ -17,6 +17,10 @@ from cryptography.hazmat.primitives import serialization
|
|||||||
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey
|
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey, Ed25519PublicKey
|
||||||
|
|
||||||
from govoplan_core.core.versioning import format_version_range, version_range_is_valid, version_satisfies_range
|
from govoplan_core.core.versioning import format_version_range, version_range_is_valid, version_satisfies_range
|
||||||
|
from govoplan_core.core.information_governance import (
|
||||||
|
information_governance_from_mapping,
|
||||||
|
information_governance_maturity_issues,
|
||||||
|
)
|
||||||
from govoplan_core.core.provider_governance import (
|
from govoplan_core.core.provider_governance import (
|
||||||
external_provider_from_mapping,
|
external_provider_from_mapping,
|
||||||
module_architecture_from_mapping,
|
module_architecture_from_mapping,
|
||||||
@@ -630,6 +634,7 @@ def _normalize_catalog_item(value: Any) -> dict[str, object]:
|
|||||||
"tags": _string_list(value.get("tags")),
|
"tags": _string_list(value.get("tags")),
|
||||||
}
|
}
|
||||||
raw_architecture = value.get("architecture")
|
raw_architecture = value.get("architecture")
|
||||||
|
architecture_maturity: str | None = None
|
||||||
if raw_architecture is not None:
|
if raw_architecture is not None:
|
||||||
if not isinstance(raw_architecture, Mapping):
|
if not isinstance(raw_architecture, Mapping):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
@@ -647,6 +652,27 @@ def _normalize_catalog_item(value: Any) -> dict[str, object]:
|
|||||||
+ "; ".join(issues)
|
+ "; ".join(issues)
|
||||||
)
|
)
|
||||||
item["architecture"] = architecture.to_dict()
|
item["architecture"] = architecture.to_dict()
|
||||||
|
architecture_maturity = architecture.maturity
|
||||||
|
raw_information_governance = value.get("information_governance")
|
||||||
|
if raw_information_governance is not None:
|
||||||
|
if not isinstance(raw_information_governance, Mapping):
|
||||||
|
raise ValueError(
|
||||||
|
"Module package catalog information_governance for "
|
||||||
|
f"{module_id!r} must be an object."
|
||||||
|
)
|
||||||
|
information_governance = information_governance_from_mapping(
|
||||||
|
raw_information_governance
|
||||||
|
)
|
||||||
|
governance_issues = information_governance_maturity_issues(
|
||||||
|
information_governance,
|
||||||
|
maturity=architecture_maturity,
|
||||||
|
)
|
||||||
|
if governance_issues:
|
||||||
|
raise ValueError(
|
||||||
|
"Module package catalog information_governance for "
|
||||||
|
f"{module_id!r} is invalid: " + "; ".join(governance_issues)
|
||||||
|
)
|
||||||
|
item["information_governance"] = information_governance.to_dict()
|
||||||
raw_providers = value.get("external_providers")
|
raw_providers = value.get("external_providers")
|
||||||
if raw_providers is not None:
|
if raw_providers is not None:
|
||||||
if not isinstance(raw_providers, list):
|
if not isinstance(raw_providers, list):
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ from collections.abc import Callable, Iterable, Mapping, Sequence
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import Any, Literal, Protocol, TYPE_CHECKING
|
from typing import Any, Literal, Protocol, TYPE_CHECKING
|
||||||
|
|
||||||
|
from govoplan_core.core.information_governance import ModuleInformationGovernance
|
||||||
from govoplan_core.core.ownership import OwnershipProviderRegistration
|
from govoplan_core.core.ownership import OwnershipProviderRegistration
|
||||||
from govoplan_core.core.provider_governance import (
|
from govoplan_core.core.provider_governance import (
|
||||||
ExternalProviderDeclaration,
|
ExternalProviderDeclaration,
|
||||||
@@ -446,6 +447,9 @@ class ModuleManifest:
|
|||||||
...,
|
...,
|
||||||
] = ()
|
] = ()
|
||||||
architecture: ModuleArchitectureDeclaration | None = None
|
architecture: ModuleArchitectureDeclaration | None = None
|
||||||
|
information_governance: ModuleInformationGovernance = field(
|
||||||
|
default_factory=ModuleInformationGovernance
|
||||||
|
)
|
||||||
external_providers: tuple[ExternalProviderDeclaration, ...] = ()
|
external_providers: tuple[ExternalProviderDeclaration, ...] = ()
|
||||||
external_provider_state_providers: tuple[
|
external_provider_state_providers: tuple[
|
||||||
ExternalProviderStateProviderRegistration,
|
ExternalProviderStateProviderRegistration,
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ from govoplan_core.core.module_entitlements import (
|
|||||||
current_tenant_execution_context,
|
current_tenant_execution_context,
|
||||||
tenant_execution_scope,
|
tenant_execution_scope,
|
||||||
)
|
)
|
||||||
|
from govoplan_core.core.information_governance import (
|
||||||
|
information_governance_maturity_issues,
|
||||||
|
)
|
||||||
from govoplan_core.core.ownership import (
|
from govoplan_core.core.ownership import (
|
||||||
OwnershipProviderRegistration,
|
OwnershipProviderRegistration,
|
||||||
ResourceOwnershipProvider,
|
ResourceOwnershipProvider,
|
||||||
@@ -788,6 +791,13 @@ def _validate_architecture_declarations(manifest: ModuleManifest) -> None:
|
|||||||
raise RegistryError(
|
raise RegistryError(
|
||||||
f"Module {manifest.id!r} architecture declaration: {issue}"
|
f"Module {manifest.id!r} architecture declaration: {issue}"
|
||||||
)
|
)
|
||||||
|
for issue in information_governance_maturity_issues(
|
||||||
|
manifest.information_governance,
|
||||||
|
maturity=architecture.maturity if architecture is not None else None,
|
||||||
|
):
|
||||||
|
raise RegistryError(
|
||||||
|
f"Module {manifest.id!r} information-governance declaration: {issue}"
|
||||||
|
)
|
||||||
|
|
||||||
provider_ids: set[str] = set()
|
provider_ids: set[str] = set()
|
||||||
declared_capabilities = {
|
declared_capabilities = {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ def bootstrap_dev_data(
|
|||||||
) -> BootstrapResult:
|
) -> BootstrapResult:
|
||||||
tenant = session.query(Tenant).filter(Tenant.slug == tenant_slug).one_or_none()
|
tenant = session.query(Tenant).filter(Tenant.slug == tenant_slug).one_or_none()
|
||||||
if tenant is None:
|
if tenant is None:
|
||||||
tenant = Tenant(slug=tenant_slug, name="Default Tenant", default_locale="en", settings={})
|
tenant = Tenant(slug=tenant_slug, name="Default Tenant", default_locale="de", settings={})
|
||||||
session.add(tenant)
|
session.add(tenant)
|
||||||
session.flush()
|
session.flush()
|
||||||
|
|
||||||
|
|||||||
@@ -685,7 +685,10 @@ def configured_migration_heads(
|
|||||||
manifest_factories=manifest_factories,
|
manifest_factories=manifest_factories,
|
||||||
migration_track=migration_track,
|
migration_track=migration_track,
|
||||||
)
|
)
|
||||||
return tuple(sorted(ScriptDirectory.from_config(config).get_heads()))
|
scripts = ScriptDirectory.from_config(config)
|
||||||
|
return tuple(
|
||||||
|
sorted(revision.revision for revision in scripts.get_revisions("heads"))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def database_is_at_configured_heads(
|
def database_is_at_configured_heads(
|
||||||
|
|||||||
@@ -4,10 +4,12 @@ import re
|
|||||||
from typing import Any, Iterable
|
from typing import Any, Iterable
|
||||||
|
|
||||||
I18N_SETTINGS_KEY = "i18n"
|
I18N_SETTINGS_KEY = "i18n"
|
||||||
|
REFERENCE_LANGUAGE_CODE = "de"
|
||||||
|
SOURCE_LANGUAGE_CODE = "en"
|
||||||
|
|
||||||
DEFAULT_LANGUAGE_PACKAGES: tuple[dict[str, str], ...] = (
|
DEFAULT_LANGUAGE_PACKAGES: tuple[dict[str, str], ...] = (
|
||||||
{"code": "en", "label": "English", "native_label": "English"},
|
|
||||||
{"code": "de", "label": "German", "native_label": "Deutsch"},
|
{"code": "de", "label": "German", "native_label": "Deutsch"},
|
||||||
|
{"code": "en", "label": "English", "native_label": "English"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +68,7 @@ def normalize_enabled_language_codes(
|
|||||||
available_languages: Iterable[dict[str, Any]],
|
available_languages: Iterable[dict[str, Any]],
|
||||||
*,
|
*,
|
||||||
default_locale: object = None,
|
default_locale: object = None,
|
||||||
fallback_codes: Iterable[str] = ("en", "de"),
|
fallback_codes: Iterable[str] = (REFERENCE_LANGUAGE_CODE, SOURCE_LANGUAGE_CODE),
|
||||||
) -> list[str]:
|
) -> list[str]:
|
||||||
available_codes = [normalize_language_code(item.get("code")) for item in available_languages if isinstance(item, dict)]
|
available_codes = [normalize_language_code(item.get("code")) for item in available_languages if isinstance(item, dict)]
|
||||||
available = {code for code in available_codes if code}
|
available = {code for code in available_codes if code}
|
||||||
@@ -88,8 +90,10 @@ def normalize_enabled_language_codes(
|
|||||||
|
|
||||||
if enabled:
|
if enabled:
|
||||||
return enabled
|
return enabled
|
||||||
if "en" in available:
|
if REFERENCE_LANGUAGE_CODE in available:
|
||||||
return ["en"]
|
return [REFERENCE_LANGUAGE_CODE]
|
||||||
|
if SOURCE_LANGUAGE_CODE in available:
|
||||||
|
return [SOURCE_LANGUAGE_CODE]
|
||||||
return available_codes[:1]
|
return available_codes[:1]
|
||||||
|
|
||||||
|
|
||||||
@@ -126,7 +130,7 @@ def preferred_language_code(user_settings: dict[str, Any] | None, allowed_codes:
|
|||||||
default = resolve_language_code(default_locale, enabled)
|
default = resolve_language_code(default_locale, enabled)
|
||||||
if default:
|
if default:
|
||||||
return default
|
return default
|
||||||
return enabled[0] if enabled else "en"
|
return enabled[0] if enabled else REFERENCE_LANGUAGE_CODE
|
||||||
|
|
||||||
|
|
||||||
def update_i18n_settings(settings: dict[str, Any] | None, **values: Any) -> dict[str, Any]:
|
def update_i18n_settings(settings: dict[str, Any] | None, **values: Any) -> dict[str, Any]:
|
||||||
@@ -141,10 +145,13 @@ def system_i18n_payload(settings_item: Any | None) -> dict[str, object]:
|
|||||||
settings = getattr(settings_item, "settings", None)
|
settings = getattr(settings_item, "settings", None)
|
||||||
packages = system_language_packages(settings)
|
packages = system_language_packages(settings)
|
||||||
available_codes = [item["code"] for item in packages]
|
available_codes = [item["code"] for item in packages]
|
||||||
default_language = resolve_language_code(getattr(settings_item, "default_locale", None), available_codes) or "en"
|
default_language = (
|
||||||
|
resolve_language_code(getattr(settings_item, "default_locale", None), available_codes)
|
||||||
|
or REFERENCE_LANGUAGE_CODE
|
||||||
|
)
|
||||||
enabled = system_enabled_language_codes(settings, default_locale=default_language)
|
enabled = system_enabled_language_codes(settings, default_locale=default_language)
|
||||||
if default_language not in enabled:
|
if default_language not in enabled:
|
||||||
default_language = enabled[0] if enabled else "en"
|
default_language = enabled[0] if enabled else REFERENCE_LANGUAGE_CODE
|
||||||
return {
|
return {
|
||||||
"available_languages": packages,
|
"available_languages": packages,
|
||||||
"enabled_languages": enabled,
|
"enabled_languages": enabled,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from contextlib import asynccontextmanager
|
from contextlib import asynccontextmanager
|
||||||
|
from importlib.metadata import PackageNotFoundError, version
|
||||||
|
|
||||||
from fastapi import Depends, FastAPI
|
from fastapi import Depends, FastAPI
|
||||||
from fastapi import HTTPException, status
|
from fastapi import HTTPException, status
|
||||||
@@ -20,6 +21,13 @@ from govoplan_core.core.runtime_coordination import (
|
|||||||
from govoplan_core.settings import Settings, settings
|
from govoplan_core.settings import Settings, settings
|
||||||
|
|
||||||
|
|
||||||
|
def _core_distribution_version() -> str:
|
||||||
|
try:
|
||||||
|
return version("govoplan-core")
|
||||||
|
except PackageNotFoundError:
|
||||||
|
return "development"
|
||||||
|
|
||||||
|
|
||||||
def _dev_bootstrap_needs_create_all(database_url: str) -> bool:
|
def _dev_bootstrap_needs_create_all(database_url: str) -> bool:
|
||||||
try:
|
try:
|
||||||
return make_url(database_url).get_backend_name() == "sqlite"
|
return make_url(database_url).get_backend_name() == "sqlite"
|
||||||
@@ -61,7 +69,7 @@ async def lifespan(app: FastAPI):
|
|||||||
)
|
)
|
||||||
runtime_agent = RuntimeNodeAgent(
|
runtime_agent = RuntimeNodeAgent(
|
||||||
settings=settings,
|
settings=settings,
|
||||||
software_version=app.version,
|
software_version=_core_distribution_version(),
|
||||||
module_ids=module_ids,
|
module_ids=module_ids,
|
||||||
metadata={"process": "api"},
|
metadata={"process": "api"},
|
||||||
identity=configured_identity
|
identity=configured_identity
|
||||||
@@ -93,7 +101,7 @@ def register_health_details(
|
|||||||
):
|
):
|
||||||
app.state.govoplan_runtime_identity = runtime_identity(
|
app.state.govoplan_runtime_identity = runtime_identity(
|
||||||
active_settings,
|
active_settings,
|
||||||
software_version=app.version,
|
software_version=_core_distribution_version(),
|
||||||
module_ids=module_ids,
|
module_ids=module_ids,
|
||||||
)
|
)
|
||||||
bind_process_runtime_identity(app.state.govoplan_runtime_identity)
|
bind_process_runtime_identity(app.state.govoplan_runtime_identity)
|
||||||
|
|||||||
@@ -142,14 +142,10 @@ def _frontend_view_surfaces(manifest: ModuleManifest) -> list[dict[str, object]]
|
|||||||
def _documentation_help_contexts(manifest: ModuleManifest) -> list[dict[str, object]]:
|
def _documentation_help_contexts(manifest: ModuleManifest) -> list[dict[str, object]]:
|
||||||
contexts: list[dict[str, object]] = []
|
contexts: list[dict[str, object]] = []
|
||||||
seen: set[str] = set()
|
seen: set[str] = set()
|
||||||
for topic in manifest.documentation:
|
|
||||||
raw_contexts = topic.metadata.get("help_contexts", ())
|
def append_context(context_id: str, topic) -> None:
|
||||||
if isinstance(raw_contexts, str) or not isinstance(raw_contexts, (list, tuple, set)):
|
|
||||||
continue
|
|
||||||
for raw_context in raw_contexts:
|
|
||||||
context_id = str(raw_context).strip()
|
|
||||||
if not context_id or context_id in seen:
|
if not context_id or context_id in seen:
|
||||||
continue
|
return
|
||||||
seen.add(context_id)
|
seen.add(context_id)
|
||||||
contexts.append(
|
contexts.append(
|
||||||
{
|
{
|
||||||
@@ -159,6 +155,45 @@ def _documentation_help_contexts(manifest: ModuleManifest) -> list[dict[str, obj
|
|||||||
"documentation_types": list(topic.documentation_types),
|
"documentation_types": list(topic.documentation_types),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for topic in manifest.documentation:
|
||||||
|
raw_contexts = topic.metadata.get("help_contexts", ())
|
||||||
|
if isinstance(raw_contexts, str) or not isinstance(raw_contexts, (list, tuple, set)):
|
||||||
|
continue
|
||||||
|
for raw_context in raw_contexts:
|
||||||
|
context_id = str(raw_context).strip()
|
||||||
|
append_context(context_id, topic)
|
||||||
|
|
||||||
|
frontend = manifest.frontend
|
||||||
|
if frontend is None or not manifest.documentation:
|
||||||
|
return contexts
|
||||||
|
|
||||||
|
ordered_topics = sorted(manifest.documentation, key=lambda item: (item.order, item.id))
|
||||||
|
|
||||||
|
def baseline_topic(documentation_type: str):
|
||||||
|
return next(
|
||||||
|
(
|
||||||
|
topic
|
||||||
|
for topic in ordered_topics
|
||||||
|
if documentation_type in topic.documentation_types
|
||||||
|
),
|
||||||
|
ordered_topics[0],
|
||||||
|
)
|
||||||
|
|
||||||
|
user_topic = baseline_topic("user")
|
||||||
|
admin_topic = baseline_topic("admin")
|
||||||
|
for route in frontend.routes:
|
||||||
|
if route.surface_id:
|
||||||
|
append_context(route.surface_id, user_topic)
|
||||||
|
for route in frontend.settings_routes:
|
||||||
|
if route.surface_id:
|
||||||
|
append_context(route.surface_id, admin_topic)
|
||||||
|
for item in frontend.nav_items:
|
||||||
|
if item.surface_id:
|
||||||
|
append_context(item.surface_id, user_topic)
|
||||||
|
for surface in frontend.view_surfaces:
|
||||||
|
topic = admin_topic if ".admin." in surface.id else user_topic
|
||||||
|
append_context(surface.id, topic)
|
||||||
return contexts
|
return contexts
|
||||||
|
|
||||||
|
|
||||||
@@ -253,6 +288,7 @@ def create_platform_router(settings: object | None = None) -> APIRouter:
|
|||||||
if manifest.architecture is not None
|
if manifest.architecture is not None
|
||||||
else None
|
else None
|
||||||
),
|
),
|
||||||
|
"information_governance": manifest.information_governance.to_dict(),
|
||||||
"external_providers": [
|
"external_providers": [
|
||||||
declaration.to_dict()
|
declaration.to_dict()
|
||||||
for declaration in manifest.external_providers
|
for declaration in manifest.external_providers
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class Tenant:
|
|||||||
slug: Mapped[str] = mapped_column(String(100), unique=True, nullable=False, index=True)
|
slug: Mapped[str] = mapped_column(String(100), unique=True, nullable=False, index=True)
|
||||||
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
name: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||||
description: Mapped[str | None] = mapped_column(Text)
|
description: Mapped[str | None] = mapped_column(Text)
|
||||||
default_locale: Mapped[str] = mapped_column(String(20), default="en", nullable=False)
|
default_locale: Mapped[str] = mapped_column(String(20), default="de", nullable=False)
|
||||||
settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False)
|
settings: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, nullable=False)
|
||||||
allow_custom_groups: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
allow_custom_groups: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
||||||
allow_custom_roles: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
allow_custom_roles: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
|
||||||
|
|||||||
@@ -184,6 +184,12 @@ class DatabaseMigrationTests(unittest.TestCase):
|
|||||||
system_settings_count = connection.execute(
|
system_settings_count = connection.execute(
|
||||||
text("SELECT COUNT(*) FROM core_system_settings WHERE id = 'global'"),
|
text("SELECT COUNT(*) FROM core_system_settings WHERE id = 'global'"),
|
||||||
).scalar_one()
|
).scalar_one()
|
||||||
|
default_locale = connection.execute(
|
||||||
|
text(
|
||||||
|
"SELECT default_locale FROM core_system_settings "
|
||||||
|
"WHERE id = 'global'"
|
||||||
|
),
|
||||||
|
).scalar_one()
|
||||||
current = database_migration_heads(connection)
|
current = database_migration_heads(connection)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@@ -204,6 +210,7 @@ class DatabaseMigrationTests(unittest.TestCase):
|
|||||||
self.assertIn("file_assets", tables)
|
self.assertIn("file_assets", tables)
|
||||||
self.assertIn("mail_server_profiles", tables)
|
self.assertIn("mail_server_profiles", tables)
|
||||||
self.assertEqual(system_settings_count, 1)
|
self.assertEqual(system_settings_count, 1)
|
||||||
|
self.assertEqual(default_locale, "de")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
role_flags,
|
role_flags,
|
||||||
{"system_owner": True, "system_admin": False, "system_auditor": False},
|
{"system_owner": True, "system_admin": False, "system_auditor": False},
|
||||||
@@ -211,6 +218,42 @@ class DatabaseMigrationTests(unittest.TestCase):
|
|||||||
finally:
|
finally:
|
||||||
engine.dispose()
|
engine.dispose()
|
||||||
|
|
||||||
|
def test_german_reference_migration_preserves_explicit_english(self) -> None:
|
||||||
|
with tempfile.TemporaryDirectory(prefix="govoplan-locale-migration-test-") as directory:
|
||||||
|
database = Path(directory) / "locale.db"
|
||||||
|
url = f"sqlite:///{database}"
|
||||||
|
config = alembic_config(database_url=url, enabled_modules=())
|
||||||
|
command.upgrade(config, "f25c9d3e7a01")
|
||||||
|
|
||||||
|
engine = create_engine(url)
|
||||||
|
try:
|
||||||
|
with engine.begin() as connection:
|
||||||
|
connection.execute(
|
||||||
|
text(
|
||||||
|
"UPDATE core_system_settings "
|
||||||
|
"SET default_locale = 'en', "
|
||||||
|
"updated_at = '2040-01-01 00:00:00' "
|
||||||
|
"WHERE id = 'global'"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
engine.dispose()
|
||||||
|
|
||||||
|
command.upgrade(config, "heads")
|
||||||
|
|
||||||
|
engine = create_engine(url)
|
||||||
|
try:
|
||||||
|
with engine.connect() as connection:
|
||||||
|
default_locale = connection.execute(
|
||||||
|
text(
|
||||||
|
"SELECT default_locale FROM core_system_settings "
|
||||||
|
"WHERE id = 'global'"
|
||||||
|
)
|
||||||
|
).scalar_one()
|
||||||
|
self.assertEqual(default_locale, "en")
|
||||||
|
finally:
|
||||||
|
engine.dispose()
|
||||||
|
|
||||||
def test_default_module_baselines_apply_to_fresh_database(self) -> None:
|
def test_default_module_baselines_apply_to_fresh_database(self) -> None:
|
||||||
with tempfile.TemporaryDirectory(prefix="govoplan-default-baseline-test-") as directory:
|
with tempfile.TemporaryDirectory(prefix="govoplan-default-baseline-test-") as directory:
|
||||||
database = Path(directory) / "default.db"
|
database = Path(directory) / "default.db"
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from govoplan_core.i18n import (
|
||||||
|
REFERENCE_LANGUAGE_CODE,
|
||||||
|
normalize_enabled_language_codes,
|
||||||
|
normalize_language_packages,
|
||||||
|
preferred_language_code,
|
||||||
|
system_i18n_payload,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class I18nReferenceLanguageTests(unittest.TestCase):
|
||||||
|
def test_german_is_the_new_installation_reference_default(self) -> None:
|
||||||
|
packages = normalize_language_packages()
|
||||||
|
|
||||||
|
self.assertEqual("de", REFERENCE_LANGUAGE_CODE)
|
||||||
|
self.assertEqual(["de", "en"], [item["code"] for item in packages])
|
||||||
|
self.assertEqual(
|
||||||
|
["de", "en"],
|
||||||
|
normalize_enabled_language_codes(None, packages),
|
||||||
|
)
|
||||||
|
self.assertEqual("de", system_i18n_payload(None)["default_language"])
|
||||||
|
self.assertEqual("de", preferred_language_code(None, ()))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from govoplan_core.core.information_governance import (
|
||||||
|
InformationGovernanceDeclarationError,
|
||||||
|
InformationGovernanceDimension,
|
||||||
|
ModuleInformationGovernance,
|
||||||
|
information_governance_from_mapping,
|
||||||
|
information_governance_maturity_issues,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class InformationGovernanceTests(unittest.TestCase):
|
||||||
|
def test_default_applies_contract_without_claiming_enforcement(self) -> None:
|
||||||
|
declaration = ModuleInformationGovernance()
|
||||||
|
|
||||||
|
self.assertTrue(declaration.current_authorization_for_historical_reads)
|
||||||
|
self.assertEqual(
|
||||||
|
{"contract_only"},
|
||||||
|
{item.adoption for item in declaration.dimensions.values()},
|
||||||
|
)
|
||||||
|
self.assertEqual("1", declaration.to_dict()["contract_version"])
|
||||||
|
|
||||||
|
def test_enforced_adoption_requires_evidence(self) -> None:
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
InformationGovernanceDeclarationError,
|
||||||
|
"requires evidence",
|
||||||
|
):
|
||||||
|
InformationGovernanceDimension(adoption="enforced")
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
InformationGovernanceDeclarationError,
|
||||||
|
"covered object types",
|
||||||
|
):
|
||||||
|
InformationGovernanceDimension(
|
||||||
|
adoption="enforced",
|
||||||
|
evidence=("tests/test_information_governance.py",),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_catalog_shape_round_trips(self) -> None:
|
||||||
|
declaration = ModuleInformationGovernance()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
declaration,
|
||||||
|
information_governance_from_mapping(declaration.to_dict()),
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_reference_ready_rejects_unproved_dimensions(self) -> None:
|
||||||
|
issues = information_governance_maturity_issues(
|
||||||
|
ModuleInformationGovernance(),
|
||||||
|
maturity="reference_ready",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(1, len(issues))
|
||||||
|
self.assertIn("temporal_browsing", issues[0])
|
||||||
|
self.assertIn("purpose_aware_access", issues[0])
|
||||||
|
self.assertEqual(
|
||||||
|
(),
|
||||||
|
information_governance_maturity_issues(
|
||||||
|
ModuleInformationGovernance(),
|
||||||
|
maturity="vertical_slice",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -106,6 +106,7 @@ from govoplan_core.core.module_package_catalog import (
|
|||||||
sign_module_package_catalog,
|
sign_module_package_catalog,
|
||||||
validate_module_package_catalog,
|
validate_module_package_catalog,
|
||||||
)
|
)
|
||||||
|
from govoplan_core.core.information_governance import ModuleInformationGovernance
|
||||||
from govoplan_core.core.modules import DocumentationTopic, FrontendModule, FrontendRoute, MigrationRetirementPlan, ModuleCompatibility, ModuleMigrationTask, ModuleMigrationTaskContext, ModuleMigrationTaskResult, ModuleUninstallGuardResult, PublicFrontendRoute
|
from govoplan_core.core.modules import DocumentationTopic, FrontendModule, FrontendRoute, MigrationRetirementPlan, ModuleCompatibility, ModuleMigrationTask, ModuleMigrationTaskContext, ModuleMigrationTaskResult, ModuleUninstallGuardResult, PublicFrontendRoute
|
||||||
from govoplan_core.core.module_guards import drop_table_retirement_provider
|
from govoplan_core.core.module_guards import drop_table_retirement_provider
|
||||||
from govoplan_core.core.modules import MigrationSpec, ModuleInterfaceProvider, ModuleInterfaceRequirement, ModuleManifest, PermissionDefinition, RoleTemplate
|
from govoplan_core.core.modules import MigrationSpec, ModuleInterfaceProvider, ModuleInterfaceRequirement, ModuleManifest, PermissionDefinition, RoleTemplate
|
||||||
@@ -119,7 +120,8 @@ from govoplan_core.security.module_permissions import scopes_grant_compatible
|
|||||||
from govoplan_core.security.permissions import scope_grants
|
from govoplan_core.security.permissions import scope_grants
|
||||||
from govoplan_core.server.app import create_app
|
from govoplan_core.server.app import create_app
|
||||||
from govoplan_core.server.config import GovoplanServerConfig
|
from govoplan_core.server.config import GovoplanServerConfig
|
||||||
from govoplan_core.server.platform import create_platform_router
|
from govoplan_core.server.platform import _documentation_help_contexts, create_platform_router
|
||||||
|
from govoplan_core.core.views import ViewSurface
|
||||||
from govoplan_core.server.registry import available_module_manifests, build_platform_registry
|
from govoplan_core.server.registry import available_module_manifests, build_platform_registry
|
||||||
from govoplan_core.server.route_validation import RouteCollisionError
|
from govoplan_core.server.route_validation import RouteCollisionError
|
||||||
from govoplan_core.tenancy.scope import Tenant, create_scope_tables
|
from govoplan_core.tenancy.scope import Tenant, create_scope_tables
|
||||||
@@ -597,6 +599,70 @@ class ModuleSystemTests(unittest.TestCase):
|
|||||||
[item["path"] for item in public_module["frontend"]["public_routes"]],
|
[item["path"] for item in public_module["frontend"]["public_routes"]],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_declared_surfaces_receive_static_documentation_fallbacks(self) -> None:
|
||||||
|
manifest = ModuleManifest(
|
||||||
|
id="example",
|
||||||
|
name="Example",
|
||||||
|
version="test",
|
||||||
|
documentation=(
|
||||||
|
DocumentationTopic(
|
||||||
|
id="example.user",
|
||||||
|
title="Example user guide",
|
||||||
|
summary="User guide.",
|
||||||
|
documentation_types=("user",),
|
||||||
|
order=20,
|
||||||
|
),
|
||||||
|
DocumentationTopic(
|
||||||
|
id="example.admin",
|
||||||
|
title="Example administrator guide",
|
||||||
|
summary="Administrator guide.",
|
||||||
|
documentation_types=("admin",),
|
||||||
|
order=10,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
frontend=FrontendModule(
|
||||||
|
module_id="example",
|
||||||
|
routes=(
|
||||||
|
FrontendRoute(
|
||||||
|
path="/example",
|
||||||
|
component="ExamplePage",
|
||||||
|
surface_id="example.workspace",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
settings_routes=(
|
||||||
|
FrontendRoute(
|
||||||
|
path="/admin?section=example",
|
||||||
|
component="ExampleAdmin",
|
||||||
|
surface_id="example.admin.settings",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
view_surfaces=(
|
||||||
|
ViewSurface(
|
||||||
|
id="example.workspace",
|
||||||
|
module_id="example",
|
||||||
|
kind="route",
|
||||||
|
label="Example workspace",
|
||||||
|
),
|
||||||
|
ViewSurface(
|
||||||
|
id="example.admin.settings",
|
||||||
|
module_id="example",
|
||||||
|
kind="section",
|
||||||
|
label="Example settings",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
contexts = {
|
||||||
|
item["id"]: item for item in _documentation_help_contexts(manifest)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.assertEqual("example.user", contexts["example.workspace"]["topic_id"])
|
||||||
|
self.assertEqual(
|
||||||
|
"example.admin",
|
||||||
|
contexts["example.admin.settings"]["topic_id"],
|
||||||
|
)
|
||||||
|
|
||||||
def test_registry_rejects_duplicate_public_frontend_routes(self) -> None:
|
def test_registry_rejects_duplicate_public_frontend_routes(self) -> None:
|
||||||
registry = PlatformRegistry()
|
registry = PlatformRegistry()
|
||||||
for module_id in ("first", "second"):
|
for module_id in ("first", "second"):
|
||||||
@@ -3300,6 +3366,7 @@ finally:
|
|||||||
"recovery_notes": "Restore rehearsal completed for the release candidate.",
|
"recovery_notes": "Restore rehearsal completed for the release candidate.",
|
||||||
"provides_interfaces": [{"name": "files.spaces", "version": "1.2.0"}],
|
"provides_interfaces": [{"name": "files.spaces", "version": "1.2.0"}],
|
||||||
"requires_interfaces": [{"name": "access.directory", "version_min": "1.0.0", "optional": True}],
|
"requires_interfaces": [{"name": "access.directory", "version_min": "1.0.0", "optional": True}],
|
||||||
|
"information_governance": ModuleInformationGovernance().to_dict(),
|
||||||
"artifact_integrity": {
|
"artifact_integrity": {
|
||||||
"python": {
|
"python": {
|
||||||
"ref": "govoplan-files==0.1.4",
|
"ref": "govoplan-files==0.1.4",
|
||||||
@@ -3345,6 +3412,12 @@ finally:
|
|||||||
[{"name": "access.directory", "optional": True, "version_min": "1.0.0"}],
|
[{"name": "access.directory", "optional": True, "version_min": "1.0.0"}],
|
||||||
catalog[0]["requires_interfaces"],
|
catalog[0]["requires_interfaces"],
|
||||||
)
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
"contract_only",
|
||||||
|
catalog[0]["information_governance"]["dimensions"]["retention"][
|
||||||
|
"adoption"
|
||||||
|
],
|
||||||
|
)
|
||||||
self.assertEqual("0" * 64, catalog[0]["artifact_integrity"]["python"]["sha256"])
|
self.assertEqual("0" * 64, catalog[0]["artifact_integrity"]["python"]["sha256"])
|
||||||
|
|
||||||
validation = validate_module_package_catalog(catalog_path)
|
validation = validate_module_package_catalog(catalog_path)
|
||||||
|
|||||||
@@ -40,6 +40,22 @@ class _Consumer:
|
|||||||
self.added.append(queue)
|
self.added.append(queue)
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_runtime_identity_uses_the_installed_distribution_version(
|
||||||
|
monkeypatch,
|
||||||
|
) -> None:
|
||||||
|
from govoplan_core.server import default_config
|
||||||
|
|
||||||
|
monkeypatch.setattr(
|
||||||
|
default_config,
|
||||||
|
"version",
|
||||||
|
lambda distribution: "0.1.15"
|
||||||
|
if distribution == "govoplan-core"
|
||||||
|
else "unexpected",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert default_config._core_distribution_version() == "0.1.15"
|
||||||
|
|
||||||
|
|
||||||
def test_api_runtime_agent_fails_readiness_on_heartbeat_error() -> None:
|
def test_api_runtime_agent_fails_readiness_on_heartbeat_error() -> None:
|
||||||
agent = RuntimeNodeAgent(
|
agent = RuntimeNodeAgent(
|
||||||
settings=SimpleNamespace(
|
settings=SimpleNamespace(
|
||||||
|
|||||||
@@ -1,12 +1,34 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import patch
|
from types import SimpleNamespace
|
||||||
|
from unittest.mock import MagicMock, patch
|
||||||
|
|
||||||
from govoplan_core.commands.wait_for_database import main
|
from govoplan_core.commands.wait_for_database import main
|
||||||
|
from govoplan_core.db.migrations import configured_migration_heads
|
||||||
|
|
||||||
|
|
||||||
class WaitForDatabaseTests(unittest.TestCase):
|
class WaitForDatabaseTests(unittest.TestCase):
|
||||||
|
def test_configured_heads_resolve_cross_branch_dependencies(self) -> None:
|
||||||
|
scripts = MagicMock()
|
||||||
|
scripts.get_revisions.return_value = (
|
||||||
|
SimpleNamespace(revision="head-b"),
|
||||||
|
SimpleNamespace(revision="head-a"),
|
||||||
|
)
|
||||||
|
|
||||||
|
with (
|
||||||
|
patch("govoplan_core.db.migrations.alembic_config"),
|
||||||
|
patch(
|
||||||
|
"govoplan_core.db.migrations.ScriptDirectory.from_config",
|
||||||
|
return_value=scripts,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
heads = configured_migration_heads("sqlite://")
|
||||||
|
|
||||||
|
self.assertEqual(("head-a", "head-b"), heads)
|
||||||
|
scripts.get_revisions.assert_called_once_with("heads")
|
||||||
|
scripts.get_heads.assert_not_called()
|
||||||
|
|
||||||
def test_waits_until_exact_configured_heads_are_visible(self) -> None:
|
def test_waits_until_exact_configured_heads_are_visible(self) -> None:
|
||||||
with (
|
with (
|
||||||
patch(
|
patch(
|
||||||
|
|||||||
Generated
+76
-76
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@govoplan/core-webui",
|
"name": "@govoplan/core-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@govoplan/core-webui",
|
"name": "@govoplan/core-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@govoplan/access-webui": "file:../../govoplan-access/webui",
|
"@govoplan/access-webui": "file:../../govoplan-access/webui",
|
||||||
"@govoplan/addresses-webui": "file:../../govoplan-addresses/webui",
|
"@govoplan/addresses-webui": "file:../../govoplan-addresses/webui",
|
||||||
@@ -73,12 +73,12 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-access/webui": {
|
"../../govoplan-access/webui": {
|
||||||
"name": "@govoplan/access-webui",
|
"name": "@govoplan/access-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.7.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -92,9 +92,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-addresses/webui": {
|
"../../govoplan-addresses/webui": {
|
||||||
"name": "@govoplan/addresses-webui",
|
"name": "@govoplan/addresses-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -108,12 +108,12 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-admin/webui": {
|
"../../govoplan-admin/webui": {
|
||||||
"name": "@govoplan/admin-webui",
|
"name": "@govoplan/admin-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.7.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -127,9 +127,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-approvals/webui": {
|
"../../govoplan-approvals/webui": {
|
||||||
"name": "@govoplan/approvals-webui",
|
"name": "@govoplan/approvals-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20"
|
"react-dom": ">=19.2.7 <20"
|
||||||
@@ -142,9 +142,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-audit/webui": {
|
"../../govoplan-audit/webui": {
|
||||||
"name": "@govoplan/audit-webui",
|
"name": "@govoplan/audit-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -158,9 +158,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-calendar/webui": {
|
"../../govoplan-calendar/webui": {
|
||||||
"name": "@govoplan/calendar-webui",
|
"name": "@govoplan/calendar-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -177,7 +177,7 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-campaign/webui": {
|
"../../govoplan-campaign/webui": {
|
||||||
"name": "@govoplan/campaign-webui",
|
"name": "@govoplan/campaign-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"read-excel-file": "9.2.0"
|
"read-excel-file": "9.2.0"
|
||||||
},
|
},
|
||||||
@@ -185,7 +185,7 @@
|
|||||||
"typescript": "^5.7.2"
|
"typescript": "^5.7.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -199,9 +199,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-cases/webui": {
|
"../../govoplan-cases/webui": {
|
||||||
"name": "@govoplan/cases-webui",
|
"name": "@govoplan/cases-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -215,9 +215,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-committee/webui": {
|
"../../govoplan-committee/webui": {
|
||||||
"name": "@govoplan/committee-webui",
|
"name": "@govoplan/committee-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -231,9 +231,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-dashboard/webui": {
|
"../../govoplan-dashboard/webui": {
|
||||||
"name": "@govoplan/dashboard-webui",
|
"name": "@govoplan/dashboard-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -247,9 +247,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-dataflow/webui": {
|
"../../govoplan-dataflow/webui": {
|
||||||
"name": "@govoplan/dataflow-webui",
|
"name": "@govoplan/dataflow-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@xyflow/react": "^12.11.2",
|
"@xyflow/react": "^12.11.2",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -265,9 +265,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-datasources/webui": {
|
"../../govoplan-datasources/webui": {
|
||||||
"name": "@govoplan/datasources-webui",
|
"name": "@govoplan/datasources-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -282,9 +282,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-dist-lists/webui": {
|
"../../govoplan-dist-lists/webui": {
|
||||||
"name": "@govoplan/dist-lists-webui",
|
"name": "@govoplan/dist-lists-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -299,9 +299,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-docs/webui": {
|
"../../govoplan-docs/webui": {
|
||||||
"name": "@govoplan/docs-webui",
|
"name": "@govoplan/docs-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -318,9 +318,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-encryption/webui": {
|
"../../govoplan-encryption/webui": {
|
||||||
"name": "@govoplan/encryption-webui",
|
"name": "@govoplan/encryption-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20"
|
"react-dom": ">=19.2.7 <20"
|
||||||
@@ -333,9 +333,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-files/webui": {
|
"../../govoplan-files/webui": {
|
||||||
"name": "@govoplan/files-webui",
|
"name": "@govoplan/files-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -352,9 +352,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-forms-runtime/webui": {
|
"../../govoplan-forms-runtime/webui": {
|
||||||
"name": "@govoplan/forms-runtime-webui",
|
"name": "@govoplan/forms-runtime-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -368,9 +368,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-forms/webui": {
|
"../../govoplan-forms/webui": {
|
||||||
"name": "@govoplan/forms-webui",
|
"name": "@govoplan/forms-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20"
|
"react-dom": ">=19.2.7 <20"
|
||||||
@@ -383,9 +383,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-identity-trust/webui": {
|
"../../govoplan-identity-trust/webui": {
|
||||||
"name": "@govoplan/identity-trust-webui",
|
"name": "@govoplan/identity-trust-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20"
|
"react-dom": ">=19.2.7 <20"
|
||||||
@@ -398,9 +398,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-idm/webui": {
|
"../../govoplan-idm/webui": {
|
||||||
"name": "@govoplan/idm-webui",
|
"name": "@govoplan/idm-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -417,12 +417,12 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-mail/webui": {
|
"../../govoplan-mail/webui": {
|
||||||
"name": "@govoplan/mail-webui",
|
"name": "@govoplan/mail-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^5.7.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -436,9 +436,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-notifications/webui": {
|
"../../govoplan-notifications/webui": {
|
||||||
"name": "@govoplan/notifications-webui",
|
"name": "@govoplan/notifications-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -455,9 +455,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-ops/webui": {
|
"../../govoplan-ops/webui": {
|
||||||
"name": "@govoplan/ops-webui",
|
"name": "@govoplan/ops-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -474,9 +474,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-organizations/webui": {
|
"../../govoplan-organizations/webui": {
|
||||||
"name": "@govoplan/organizations-webui",
|
"name": "@govoplan/organizations-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -493,9 +493,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-policy/webui": {
|
"../../govoplan-policy/webui": {
|
||||||
"name": "@govoplan/policy-webui",
|
"name": "@govoplan/policy-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -509,9 +509,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-portal/webui": {
|
"../../govoplan-portal/webui": {
|
||||||
"name": "@govoplan/portal-webui",
|
"name": "@govoplan/portal-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -525,9 +525,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-postbox/webui": {
|
"../../govoplan-postbox/webui": {
|
||||||
"name": "@govoplan/postbox-webui",
|
"name": "@govoplan/postbox-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -541,9 +541,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-projects/webui": {
|
"../../govoplan-projects/webui": {
|
||||||
"name": "@govoplan/projects-webui",
|
"name": "@govoplan/projects-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -557,9 +557,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-reporting/webui": {
|
"../../govoplan-reporting/webui": {
|
||||||
"name": "@govoplan/reporting-webui",
|
"name": "@govoplan/reporting-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -573,9 +573,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-risk-compliance/webui": {
|
"../../govoplan-risk-compliance/webui": {
|
||||||
"name": "@govoplan/risk-compliance-webui",
|
"name": "@govoplan/risk-compliance-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -589,9 +589,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-scheduling/webui": {
|
"../../govoplan-scheduling/webui": {
|
||||||
"name": "@govoplan/scheduling-webui",
|
"name": "@govoplan/scheduling-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -608,9 +608,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-search/webui": {
|
"../../govoplan-search/webui": {
|
||||||
"name": "@govoplan/search-webui",
|
"name": "@govoplan/search-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -624,9 +624,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-templates/webui": {
|
"../../govoplan-templates/webui": {
|
||||||
"name": "@govoplan/templates-webui",
|
"name": "@govoplan/templates-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -641,9 +641,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-tenancy/webui": {
|
"../../govoplan-tenancy/webui": {
|
||||||
"name": "@govoplan/tenancy-webui",
|
"name": "@govoplan/tenancy-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20"
|
"react-dom": ">=19.2.7 <20"
|
||||||
@@ -656,9 +656,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-views/webui": {
|
"../../govoplan-views/webui": {
|
||||||
"name": "@govoplan/views-webui",
|
"name": "@govoplan/views-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -672,9 +672,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-voting/webui": {
|
"../../govoplan-voting/webui": {
|
||||||
"name": "@govoplan/voting-webui",
|
"name": "@govoplan/voting-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20"
|
"react-dom": ">=19.2.7 <20"
|
||||||
@@ -687,9 +687,9 @@
|
|||||||
},
|
},
|
||||||
"../../govoplan-workflow/webui": {
|
"../../govoplan-workflow/webui": {
|
||||||
"name": "@govoplan/workflow-webui",
|
"name": "@govoplan/workflow-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@xyflow/react": "^12.11.2",
|
"@xyflow/react": "^12.11.2",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
{
|
{
|
||||||
"name": "@govoplan/core-webui",
|
"name": "@govoplan/core-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@govoplan/core-webui",
|
"name": "@govoplan/core-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@govoplan/access-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-access.git#v0.1.15",
|
"@govoplan/access-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-access.git#v0.1.16",
|
||||||
"@govoplan/admin-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-admin.git#v0.1.15",
|
"@govoplan/admin-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-admin.git#v0.1.16",
|
||||||
"@govoplan/audit-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-audit.git#v0.1.15",
|
"@govoplan/audit-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-audit.git#v0.1.16",
|
||||||
"@govoplan/calendar-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-calendar.git#v0.1.15",
|
"@govoplan/calendar-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-calendar.git#v0.1.16",
|
||||||
"@govoplan/campaign-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-campaign.git#v0.1.15",
|
"@govoplan/campaign-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-campaign.git#v0.1.16",
|
||||||
"@govoplan/dashboard-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-dashboard.git#v0.1.15",
|
"@govoplan/dashboard-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-dashboard.git#v0.1.16",
|
||||||
"@govoplan/docs-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-docs.git#v0.1.15",
|
"@govoplan/docs-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-docs.git#v0.1.16",
|
||||||
"@govoplan/files-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-files.git#v0.1.15",
|
"@govoplan/files-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-files.git#v0.1.16",
|
||||||
"@govoplan/idm-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-idm.git#v0.1.15",
|
"@govoplan/idm-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-idm.git#v0.1.16",
|
||||||
"@govoplan/mail-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-mail.git#v0.1.15",
|
"@govoplan/mail-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-mail.git#v0.1.16",
|
||||||
"@govoplan/ops-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-ops.git#v0.1.15",
|
"@govoplan/ops-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-ops.git#v0.1.16",
|
||||||
"@govoplan/organizations-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-organizations.git#v0.1.15",
|
"@govoplan/organizations-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-organizations.git#v0.1.16",
|
||||||
"@govoplan/policy-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-policy.git#v0.1.15",
|
"@govoplan/policy-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-policy.git#v0.1.16",
|
||||||
"@tiptap/core": "^3.29.2",
|
"@tiptap/core": "^3.29.2",
|
||||||
"@tiptap/extension-image": "^3.29.2",
|
"@tiptap/extension-image": "^3.29.2",
|
||||||
"@tiptap/pm": "^3.29.2",
|
"@tiptap/pm": "^3.29.2",
|
||||||
@@ -753,10 +753,10 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/access-webui": {
|
"node_modules/@govoplan/access-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-access.git#794fcf90f8d759eb140d3b5b0a880482912a79be",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-access.git#a7ed28f6a3cf9e3f5f549db9b0e0785910a8c41a",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -769,10 +769,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/admin-webui": {
|
"node_modules/@govoplan/admin-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-admin.git#57e2a34c894e20afa46558b83d167e36a1db26c0",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-admin.git#3842987a4ed2b550a3e3c6932db52fa09995e5b4",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -785,10 +785,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/audit-webui": {
|
"node_modules/@govoplan/audit-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-audit.git#6f095eb56293fa4bc3f3ca5a52d36491c1713b00",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-audit.git#4613b54c06863689eade1012632bd2398d15fef1",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -801,10 +801,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/calendar-webui": {
|
"node_modules/@govoplan/calendar-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-calendar.git#f6faaf196da1891997c5ad7065bbba69aacd018d",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-calendar.git#128c78597edbc6a6fcac844fe1c08b2f9917a872",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -820,13 +820,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/campaign-webui": {
|
"node_modules/@govoplan/campaign-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-campaign.git#ea0efe661f10474e0a8df0bffde75f3a78577f27",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-campaign.git#2db99eaf6a36b433093d37f53cef0125f4b98599",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"read-excel-file": "9.2.0"
|
"read-excel-file": "9.2.0"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -839,10 +839,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/dashboard-webui": {
|
"node_modules/@govoplan/dashboard-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-dashboard.git#c2c7ba8fb2090ea0e6abcb2f3cd46916a9016b1e",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-dashboard.git#77924e7a2c8366be39c9305477e085802a578d0b",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -855,10 +855,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/docs-webui": {
|
"node_modules/@govoplan/docs-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-docs.git#1f5050530589da651a49e8d617bf0825e6332388",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-docs.git#8cbab781bf9126062efc6127c89c7eed308955de",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -874,10 +874,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/files-webui": {
|
"node_modules/@govoplan/files-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-files.git#0293e49defd34a958584c9665ba006d22db497e1",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-files.git#edee29af51fba34c569defc98a977a0ed80c5718",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -893,10 +893,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/idm-webui": {
|
"node_modules/@govoplan/idm-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-idm.git#bd72a3f277ce4f214906e276ee1553f4fd23364d",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-idm.git#6e9393c9c7606e91ced908dceef69fd18cf2abe7",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -912,10 +912,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/mail-webui": {
|
"node_modules/@govoplan/mail-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-mail.git#622f63b4b5fd427128b1a6a9df0ecbe357059d69",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-mail.git#a040de4fe5d9af4a5f434a87d2c5fa8b79e6a818",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -928,10 +928,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/ops-webui": {
|
"node_modules/@govoplan/ops-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-ops.git#ce074044056827f253eaa9bae920136ebdd8ada8",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-ops.git#02e5d91d565bf7d42cc1b550f18e73621a93a6fa",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -947,10 +947,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/organizations-webui": {
|
"node_modules/@govoplan/organizations-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-organizations.git#aab7f25e866b9738390e2d3026e784d3ad9c3a54",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-organizations.git#18e4df348a3cf69602b2d2491e6ae28c26551b59",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"@vitejs/plugin-react": "^5.2.0",
|
"@vitejs/plugin-react": "^5.2.0",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
@@ -966,10 +966,10 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@govoplan/policy-webui": {
|
"node_modules/@govoplan/policy-webui": {
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-policy.git#44d72914aea27a74511fd50f445c450217e3cd5f",
|
"resolved": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-policy.git#107cc3b654b7b97ec441650bcc3bac6a7accc8a0",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@govoplan/core-webui": "^0.1.15",
|
"@govoplan/core-webui": "^0.1.16",
|
||||||
"lucide-react": "^1.23.0",
|
"lucide-react": "^1.23.0",
|
||||||
"react": ">=19.2.7 <20",
|
"react": ">=19.2.7 <20",
|
||||||
"react-dom": ">=19.2.7 <20",
|
"react-dom": ">=19.2.7 <20",
|
||||||
@@ -2059,9 +2059,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.400",
|
"version": "1.5.401",
|
||||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.400.tgz",
|
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.401.tgz",
|
||||||
"integrity": "sha512-96EWDNjM59SYflgeV5Ylsf4EMiq1a25YjCnJH7cxn/AF2H3pILRweaUnoLax0yKHWdpOzY6JKEu45e8irqZIHA==",
|
"integrity": "sha512-H6ViHN68nGYlChEvlIU67fn8O2/tpbWQPwck98yaJmh+08LSvHiydzDQ6oXNccLU3kNRVIRS9A4mA7CG+i6fLQ==",
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
"node_modules/esbuild": {
|
"node_modules/esbuild": {
|
||||||
@@ -2330,9 +2330,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prosemirror-commands": {
|
"node_modules/prosemirror-commands": {
|
||||||
"version": "1.7.1",
|
"version": "1.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.2.tgz",
|
||||||
"integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==",
|
"integrity": "sha512-q6Q6szxqdu9Xd6EcdKsqXghu5nQdZTpB4Q9yd04WRc7/jt763e/rT60Owh0L1GYY+T46o5rD+9lEN36dZS43tw==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"prosemirror-model": "^1.0.0",
|
"prosemirror-model": "^1.0.0",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@govoplan/core-webui",
|
"name": "@govoplan/core-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
|
|||||||
+14
-14
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@govoplan/core-webui",
|
"name": "@govoplan/core-webui",
|
||||||
"version": "0.1.15",
|
"version": "0.1.16",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
@@ -26,19 +26,19 @@
|
|||||||
"preview": "vite preview --host 127.0.0.1 --port 4173"
|
"preview": "vite preview --host 127.0.0.1 --port 4173"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@govoplan/access-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-access.git#v0.1.15",
|
"@govoplan/access-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-access.git#v0.1.16",
|
||||||
"@govoplan/admin-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-admin.git#v0.1.15",
|
"@govoplan/admin-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-admin.git#v0.1.16",
|
||||||
"@govoplan/audit-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-audit.git#v0.1.15",
|
"@govoplan/audit-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-audit.git#v0.1.16",
|
||||||
"@govoplan/calendar-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-calendar.git#v0.1.15",
|
"@govoplan/calendar-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-calendar.git#v0.1.16",
|
||||||
"@govoplan/dashboard-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-dashboard.git#v0.1.15",
|
"@govoplan/dashboard-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-dashboard.git#v0.1.16",
|
||||||
"@govoplan/docs-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-docs.git#v0.1.15",
|
"@govoplan/docs-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-docs.git#v0.1.16",
|
||||||
"@govoplan/files-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-files.git#v0.1.15",
|
"@govoplan/files-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-files.git#v0.1.16",
|
||||||
"@govoplan/idm-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-idm.git#v0.1.15",
|
"@govoplan/idm-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-idm.git#v0.1.16",
|
||||||
"@govoplan/mail-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-mail.git#v0.1.15",
|
"@govoplan/mail-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-mail.git#v0.1.16",
|
||||||
"@govoplan/campaign-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-campaign.git#v0.1.15",
|
"@govoplan/campaign-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-campaign.git#v0.1.16",
|
||||||
"@govoplan/organizations-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-organizations.git#v0.1.15",
|
"@govoplan/organizations-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-organizations.git#v0.1.16",
|
||||||
"@govoplan/ops-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-ops.git#v0.1.15",
|
"@govoplan/ops-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-ops.git#v0.1.16",
|
||||||
"@govoplan/policy-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-policy.git#v0.1.15",
|
"@govoplan/policy-webui": "git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-policy.git#v0.1.16",
|
||||||
"@tiptap/core": "^3.29.2",
|
"@tiptap/core": "^3.29.2",
|
||||||
"@tiptap/extension-image": "^3.29.2",
|
"@tiptap/extension-image": "^3.29.2",
|
||||||
"@tiptap/pm": "^3.29.2",
|
"@tiptap/pm": "^3.29.2",
|
||||||
|
|||||||
+1
-1
@@ -644,7 +644,7 @@ function normalizeAuthInfo(response: AuthPayload): AuthInfo {
|
|||||||
principal,
|
principal,
|
||||||
available_languages: response.available_languages,
|
available_languages: response.available_languages,
|
||||||
enabled_language_codes: profileLoaded ? response.enabled_language_codes ?? activeTenant.enabled_language_codes ?? [] : undefined,
|
enabled_language_codes: profileLoaded ? response.enabled_language_codes ?? activeTenant.enabled_language_codes ?? [] : undefined,
|
||||||
default_language: profileLoaded ? response.default_language ?? user.preferred_language ?? activeTenant.default_locale ?? "en" : undefined,
|
default_language: profileLoaded ? response.default_language ?? user.preferred_language ?? activeTenant.default_locale ?? "de" : undefined,
|
||||||
profile_loaded: profileLoaded,
|
profile_loaded: profileLoaded,
|
||||||
roles_loaded: rolesLoaded,
|
roles_loaded: rolesLoaded,
|
||||||
groups_loaded: groupsLoaded
|
groups_loaded: groupsLoaded
|
||||||
|
|||||||
@@ -32,14 +32,15 @@ type PlatformLanguageProviderProps = {
|
|||||||
|
|
||||||
const STORAGE_KEY = "govoplan.language";
|
const STORAGE_KEY = "govoplan.language";
|
||||||
const PRIMARY_LANGUAGE = "en";
|
const PRIMARY_LANGUAGE = "en";
|
||||||
|
const REFERENCE_LANGUAGE = "de";
|
||||||
const I18N_MESSAGE_SEPARATOR = "::";
|
const I18N_MESSAGE_SEPARATOR = "::";
|
||||||
const TRANSLATABLE_ATTRIBUTES = ["aria-label", "alt", "placeholder", "title"];
|
const TRANSLATABLE_ATTRIBUTES = ["aria-label", "alt", "placeholder", "title"];
|
||||||
const SKIP_TRANSLATION_SELECTOR = "script, style, code, pre, textarea, [data-i18n-skip]";
|
const SKIP_TRANSLATION_SELECTOR = "script, style, code, pre, textarea, [data-i18n-skip]";
|
||||||
const textNodeOriginals = new WeakMap<Text, string>();
|
const textNodeOriginals = new WeakMap<Text, string>();
|
||||||
|
|
||||||
export const DEFAULT_AVAILABLE_LANGUAGES: PlatformLanguage[] = [
|
export const DEFAULT_AVAILABLE_LANGUAGES: PlatformLanguage[] = [
|
||||||
{ code: "en", label: "i18n:govoplan-core.english.649df08a", nativeLabel: "i18n:govoplan-core.language_native_english" },
|
{ code: "de", label: "i18n:govoplan-core.german.da91388c", nativeLabel: "i18n:govoplan-core.language_native_german" },
|
||||||
{ code: "de", label: "i18n:govoplan-core.german.da91388c", nativeLabel: "i18n:govoplan-core.language_native_german" }];
|
{ code: "en", label: "i18n:govoplan-core.english.649df08a", nativeLabel: "i18n:govoplan-core.language_native_english" }];
|
||||||
|
|
||||||
|
|
||||||
export const DEFAULT_TRANSLATIONS: PlatformTranslations = {
|
export const DEFAULT_TRANSLATIONS: PlatformTranslations = {
|
||||||
@@ -186,13 +187,17 @@ function languagesForCodes(languages: PlatformLanguage[], codes?: string[] | nul
|
|||||||
|
|
||||||
function preferredLanguage(languages: PlatformLanguage[], preferred?: string | null): string {
|
function preferredLanguage(languages: PlatformLanguage[], preferred?: string | null): string {
|
||||||
const codes = new Set(languages.map((item) => item.code));
|
const codes = new Set(languages.map((item) => item.code));
|
||||||
const requested = normalizeLanguageCode(preferred ?? storedLanguage() ?? browserLanguage());
|
const requestedValue = preferred ?? storedLanguage() ?? browserLanguage();
|
||||||
|
if (requestedValue) {
|
||||||
|
const requested = normalizeLanguageCode(requestedValue);
|
||||||
if (codes.has(requested)) return requested;
|
if (codes.has(requested)) return requested;
|
||||||
const primary = primaryLanguageCode(requested);
|
const primary = primaryLanguageCode(requested);
|
||||||
const primaryMatch = languages.find((item) => primaryLanguageCode(item.code) === primary);
|
const primaryMatch = languages.find((item) => primaryLanguageCode(item.code) === primary);
|
||||||
if (primaryMatch) return primaryMatch.code;
|
if (primaryMatch) return primaryMatch.code;
|
||||||
|
}
|
||||||
|
if (codes.has(REFERENCE_LANGUAGE)) return REFERENCE_LANGUAGE;
|
||||||
if (codes.has(PRIMARY_LANGUAGE)) return PRIMARY_LANGUAGE;
|
if (codes.has(PRIMARY_LANGUAGE)) return PRIMARY_LANGUAGE;
|
||||||
return languages[0]?.code ?? PRIMARY_LANGUAGE;
|
return languages[0]?.code ?? REFERENCE_LANGUAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
function primaryLanguageCode(value: string): string {
|
function primaryLanguageCode(value: string): string {
|
||||||
|
|||||||
@@ -1124,6 +1124,16 @@ export type PlatformModuleInfo = {
|
|||||||
target_tested_providers: string[];
|
target_tested_providers: string[];
|
||||||
documentation: Record<string, string[]>;
|
documentation: Record<string, string[]>;
|
||||||
} | null;
|
} | null;
|
||||||
|
information_governance?: {
|
||||||
|
contract_version: string;
|
||||||
|
current_authorization_for_historical_reads: boolean;
|
||||||
|
dimensions: Record<string, {
|
||||||
|
adoption: "not_applicable" | "contract_only" | "partial" | "enforced";
|
||||||
|
object_types: string[];
|
||||||
|
evidence: string[];
|
||||||
|
limitation?: string | null;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
external_providers?: Array<{
|
external_providers?: Array<{
|
||||||
contract_version: string;
|
contract_version: string;
|
||||||
id: string;
|
id: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user