Compare commits
4 Commits
05ae81d641
...
8b80afbd60
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b80afbd60 | |||
| 8255665349 | |||
| 2fc3b66c07 | |||
| 9e7103f613 |
@@ -12,7 +12,8 @@ ENABLED_MODULES=tenancy,organizations,identity,access,admin,dashboard,policy,aud
|
||||
|
||||
CELERY_ENABLED=true
|
||||
REDIS_URL=redis://127.0.0.1:6379/0
|
||||
CELERY_QUEUES=send_email,append_sent,default
|
||||
CELERY_QUEUES=send_email,append_sent,notifications,calendar,default
|
||||
CALENDAR_OUTBOX_TERMINAL_RETENTION_DAYS=90
|
||||
|
||||
CORS_ORIGINS=https://govoplan.example.org
|
||||
AUTH_COOKIE_SECURE=true
|
||||
|
||||
@@ -16,7 +16,8 @@ DATABASE_URL=postgresql+psycopg://govoplan:govoplan-dev@127.0.0.1:55433/govoplan
|
||||
GOVOPLAN_DATABASE_URL_PGTOOLS=postgresql://govoplan:govoplan-dev@127.0.0.1:55433/govoplan
|
||||
REDIS_URL=redis://127.0.0.1:56379/0
|
||||
CELERY_ENABLED=true
|
||||
CELERY_QUEUES=send_email,append_sent,default
|
||||
CELERY_QUEUES=send_email,append_sent,notifications,calendar,default
|
||||
CALENDAR_OUTBOX_TERMINAL_RETENTION_DAYS=90
|
||||
|
||||
ENABLED_MODULES=tenancy,organizations,identity,access,admin,dashboard,policy,audit,campaigns,files,mail,calendar,docs,ops
|
||||
CORS_ORIGINS=http://127.0.0.1:5173,http://localhost:5173
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Production-Like Development Profile
|
||||
|
||||
This profile runs the shared services that production depends on while keeping
|
||||
API, worker, and WebUI code in the editable local repositories.
|
||||
API, worker, scheduler, and WebUI code in the editable local repositories.
|
||||
|
||||
It provides:
|
||||
|
||||
@@ -10,6 +10,7 @@ It provides:
|
||||
- explicit `ENABLED_MODULES`
|
||||
- local durable file storage under `runtime/production-like/files`
|
||||
- a Celery worker process using the same queues as the API
|
||||
- a Celery beat process for durable retry and recovery schedules
|
||||
|
||||
Start it from the meta repository:
|
||||
|
||||
@@ -37,7 +38,7 @@ password changes:
|
||||
cp dev/production-like/.env.example dev/production-like/.env
|
||||
```
|
||||
|
||||
The API and worker use:
|
||||
The API, worker, and scheduler use:
|
||||
|
||||
```text
|
||||
DATABASE_URL=postgresql+psycopg://govoplan:govoplan-dev@127.0.0.1:55433/govoplan
|
||||
@@ -45,7 +46,7 @@ REDIS_URL=redis://127.0.0.1:56379/0
|
||||
CELERY_ENABLED=true
|
||||
```
|
||||
|
||||
Stop the launched API/WebUI/worker with `Ctrl+C`. The PostgreSQL and Redis
|
||||
Stop the launched API/WebUI/worker/scheduler with `Ctrl+C`. The PostgreSQL and Redis
|
||||
containers keep running by default so the next launch is fast. To stop them too:
|
||||
|
||||
```bash
|
||||
|
||||
349
docs/CAPABILITY_AND_INFRASTRUCTURE_FIT.md
Normal file
349
docs/CAPABILITY_AND_INFRASTRUCTURE_FIT.md
Normal file
@@ -0,0 +1,349 @@
|
||||
# GovOPlaN Capability and IT-Infrastructure Fit Assessment
|
||||
|
||||
## Assessment record
|
||||
|
||||
| Field | Value |
|
||||
| --- | --- |
|
||||
| Assessment ID | `campaign-reference-2026-07-20` |
|
||||
| Schema | `govoplan.fit-assessment/0.1.0` |
|
||||
| Assessed on | 2026-07-20 |
|
||||
| Product snapshot | Untagged workspace at meta commit `05ae81d64195`; this is not a release artifact |
|
||||
| Configuration basis | Root `.env.example` and the production-like development profile |
|
||||
| Scope | Campaign-centric internal pilot and small-production candidate |
|
||||
| Explicitly postponed | Workflow and workflow-driven user stories |
|
||||
| Machine-readable companion | [`capability-fit-current.json`](capability-fit-current.json) |
|
||||
| Input schema | [`capability-fit.schema.json`](capability-fit.schema.json) |
|
||||
|
||||
This is a fit assessment, not a production approval or security certification.
|
||||
It deliberately does not infer implementation from a repository, issue, or
|
||||
manifest existing. A conclusion needs code plus a route/contract, test,
|
||||
operational drill, configured example, or explicit evidence that the capability
|
||||
is absent.
|
||||
|
||||
The checkout contained unrelated uncommitted work when this assessment was
|
||||
made. A dirty repository is recorded below, but local-only changes do not count
|
||||
as an integrated release capability. Tests run against the dirty workspace are
|
||||
useful implementation evidence and are labelled as such; they do not turn the
|
||||
workspace into a reproducible release.
|
||||
|
||||
## Controlled status vocabulary
|
||||
|
||||
| Status | Meaning |
|
||||
| --- | --- |
|
||||
| `verified` | The stated capability is implemented and directly exercised by evidence appropriate to the stated scope. Conditions and target-environment proof may still remain. |
|
||||
| `available_unconfigured` | An implementation and supporting evidence exist, but the target endpoint, credentials, policy, or deployment component has not been configured and exercised. |
|
||||
| `partial` | A useful subset exists, but one or more material parts of the stated journey or operational requirement are missing or unproved. |
|
||||
| `scaffold` | Contracts, models, routes, or UI structure exist, but the end-to-end capability is not yet usable. |
|
||||
| `external_system` | GovOPlaN expects the deployment or another system to supply this capability; integration requirements must still be assessed. |
|
||||
| `planned` | The capability is represented only by a concept, backlog item, or design direction. |
|
||||
| `not_fit` | Evidence shows that the current composition cannot meet the stated requirement. |
|
||||
| `not_assessed` | The requirement or target environment is not sufficiently known to reach a conclusion. |
|
||||
|
||||
Status alone is not enough. Every row also states its evidence scope and
|
||||
conditions. For example, a unit-tested SMTP adapter is
|
||||
`available_unconfigured`, not `verified` for an organization's mail system.
|
||||
|
||||
## Executive conclusion
|
||||
|
||||
GovOPlaN is a credible candidate for a controlled, Campaign-centric internal
|
||||
pilot using local accounts, PostgreSQL, durable single-node file storage, and a
|
||||
non-production SMTP/IMAP service. The module contract, Campaign authoring and
|
||||
validation paths, managed attachments, mail-profile boundary, local audit
|
||||
records, and operator status surface all have direct code/test evidence.
|
||||
|
||||
It is not yet possible to call the current workspace a supported small-production
|
||||
distribution. The production-like profile intentionally runs only PostgreSQL
|
||||
and Redis in containers; API, WebUI, worker, and scheduler processes still run
|
||||
from editable source trees. A target deployment must supply TLS termination,
|
||||
process supervision, secret injection, monitoring, backup storage, and recovery
|
||||
procedures. The open [Core backup/restore issue #29](https://git.add-ideas.de/add-ideas/govoplan-core/issues/29)
|
||||
is a production gate. Identity federation, external audit export, and a tested
|
||||
disaster-recovery plan are also not complete.
|
||||
|
||||
The current recommendation is therefore:
|
||||
|
||||
- **Pilot:** fit with conditions and a bounded proof of concept.
|
||||
- **Small production:** partial fit; do not approve until the proof checks and
|
||||
operational gates below pass against a clean, pinned release candidate.
|
||||
- **Workflow:** planned and postponed; it is not part of either recommended
|
||||
composition in this assessment.
|
||||
|
||||
## Pinned composition
|
||||
|
||||
The configured reference composition comes from the meta repository's
|
||||
`ENABLED_MODULES`. Module versions come from the actual manifests. `Dirty`
|
||||
means that repository had uncommitted changes at assessment time.
|
||||
|
||||
| Module | Repository commit | Manifest version | Dirty | Role in this assessment |
|
||||
| --- | --- | ---: | :---: | --- |
|
||||
| Core runtime | `govoplan-core@e6f7c45f0a95` | server `0.3.0` | yes | API, registry, migration orchestration, shared WebUI, sessions and kernel contracts |
|
||||
| `tenancy` | `govoplan-tenancy@1dde03854733` | 0.1.8 | no | tenant context and lifecycle |
|
||||
| `organizations` | `govoplan-organizations@45cda1a33f18` | 0.1.8 | no | organization model |
|
||||
| `identity` | `govoplan-identity@7a1710af896f` | 0.1.8 | yes | normalized internal identity directory |
|
||||
| `access` | `govoplan-access@ab07075a679b` | 0.1.8 | yes | local authentication, sessions, API keys and RBAC |
|
||||
| `admin` | `govoplan-admin@c9e1fb287f50` | 0.1.8 | no | administration surfaces |
|
||||
| `dashboard` | `govoplan-dashboard@a315a7c62b1d` | 0.1.8 | no | module-aware home surface |
|
||||
| `policy` | `govoplan-policy@2511fbb5a864` | 0.1.8 | no | policy explanation/configuration boundary |
|
||||
| `audit` | `govoplan-audit@5e4f84a789ea` | 0.1.8 | no | database audit records and retrying audit outbox |
|
||||
| `campaigns` | `govoplan-campaign@2e593b7fa412` | 0.1.8 | yes | Campaign authoring, build, delivery control and reporting |
|
||||
| `files` | `govoplan-files@f3210234d35a` | 0.1.8 | yes | managed files and Campaign attachments |
|
||||
| `mail` | `govoplan-mail@b0337b2d261a` | 0.1.8 | yes | SMTP/IMAP profiles and transports |
|
||||
| `calendar` | `govoplan-calendar@371a00aff51c` | 0.1.8 | yes | optional calendar; not needed by the Campaign pilot |
|
||||
| `docs` | `govoplan-docs@f2ade1d62475` | 0.1.8 | yes | configured-system documentation |
|
||||
| `ops` | `govoplan-ops@341773a4ff8a` | 0.1.8 | no | readiness and deployment-profile visibility |
|
||||
|
||||
No tagged release or configuration package is pinned. That is a reproducibility
|
||||
gap, not a harmless omission. The static contract scan found 43 interface
|
||||
contracts, 29 providers, and no contract errors in this workspace. This proves
|
||||
the scanned manifest graph is internally consistent; it does not prove the
|
||||
behavior of every repository in that graph.
|
||||
|
||||
`govoplan-addresses@f19350e65d76` (manifest 0.1.8, dirty) is an optional extension
|
||||
for reusable recipient sources. It is not enabled in the pinned root profile and
|
||||
must be added explicitly when the pilot needs address lists or CardDAV.
|
||||
|
||||
## Recommended scenarios
|
||||
|
||||
### Campaign pilot
|
||||
|
||||
Use one internal tenant or office, controlled operators, local GovOPlaN accounts,
|
||||
and non-critical recipient volumes. Enable:
|
||||
|
||||
```text
|
||||
tenancy,organizations,identity,access,admin,dashboard,policy,audit,campaigns,files,mail,docs,ops
|
||||
```
|
||||
|
||||
Add `addresses` only when reusable address books/lists or CardDAV are in scope.
|
||||
Leave Calendar and Workflow out unless the pilot has an explicit journey for
|
||||
them. The minimum topology is one supervised API process, one built WebUI, one
|
||||
PostgreSQL database, durable local file storage, and one Redis/Celery worker when
|
||||
asynchronous delivery is enabled. Use a dedicated non-production SMTP/IMAP
|
||||
account and a restricted recipient allow-list.
|
||||
|
||||
### Small-production candidate
|
||||
|
||||
Use a reverse proxy/TLS endpoint, built WebUI assets, separately supervised API
|
||||
and worker processes, PostgreSQL with measured backup/restore, Redis with
|
||||
persistence, and durable shared or object storage. Run one scheduler only when a
|
||||
selected module needs scheduled recovery. Multiple scheduler replicas require
|
||||
leader election or an external lock, which is not established by this report.
|
||||
|
||||
This topology is a recommendation from the [Ops scalability profiles](https://git.add-ideas.de/add-ideas/govoplan-ops/src/branch/main/docs/SCALABILITY_PROFILES.md),
|
||||
not a currently shipped production Compose/Kubernetes/systemd package.
|
||||
|
||||
## Functional capability matrix
|
||||
|
||||
| Capability | Status | Evidence and scope | Conditions, gaps, or exclusions |
|
||||
| --- | --- | --- | --- |
|
||||
| Module-aware API/WebUI composition | `verified` | Core registry tests cover installed manifests, route contribution, missing modules, and module permutations; the static contract scan passed. | The pinned workspace is dirty and untagged; repeat on a clean release candidate. |
|
||||
| Local tenants, accounts, sessions, API keys and RBAC | `verified` | Access/tenancy manifests, auth dependency tests, cookie/CSRF API smoke tests, and role/permission contracts. | External identity providers are not included in this conclusion. |
|
||||
| Campaign draft authoring, validation, recipient import, build, execution snapshot and mock send | `verified` | Core API smoke tests exercise create/validate/build/mock-send, frozen delivery configuration, policy gates, job deltas and reconciliation; Campaign-focused tests passed in this workspace. | Current Campaign UI/code also contains substantial unintegrated WIP; usability and release integration need separate acceptance. |
|
||||
| Managed Campaign attachments and local file storage | `verified` | Files capability/route tests, Campaign attachment-build tests, and local-storage backend code. | The deployment must provide a durable path and include files in database/storage backup plans. |
|
||||
| SMTP send, IMAP append and mailbox/profile policy | `available_unconfigured` | Mail adapters, encrypted profile model, helper tests, Campaign mail-policy smoke tests, and a GreenMail-oriented runbook/testbed. | No target mail server, TLS chain, throttling, sender policy, bounce/reply process, or real delivery receipt was exercised here. |
|
||||
| Delivery retry, uncertainty and reconciliation | `partial` | Campaign API smoke tests include worker-loss/outcome-unknown reconciliation and frozen job evidence. | A target-provider failure drill and operational alerting are still required; local Campaign audit-proof work is not release-integrated. |
|
||||
| Reusable address lists and Campaign recipient-source integration | `available_unconfigured` | Address list/recipient capability and Campaign optional lookup tests passed; manifests expose optional interfaces. | `addresses` is not in the pinned profile. Configure permissions and data governance before use. |
|
||||
| CardDAV address synchronization | `available_unconfigured` | Discovery, preview/conflict, two-way create/update/delete and disconnect tests passed in the current Addresses workspace. | Requires target-server interoperability, credentials, CA/TLS, rate-limit, conflict and restore drills. |
|
||||
| File connectors (WebDAV/Nextcloud/Seafile/SMB/S3 import) | `partial` | Provider descriptors and browse/import helper tests exist; S3 connector tests passed. | Coverage varies by provider and optional dependency. No target content system was exercised; connector egress and provenance policy need review. |
|
||||
| Local audit log and governed-event retry outbox | `verified` | Audit module contract plus enqueue/dispatch/failure-for-retry tests passed. | Central audit/SIEM export, retention enforcement and operational monitoring are not verified. |
|
||||
| Configured-system documentation and Ops status pages | `verified` | Docs/Ops manifests contribute protected routes and WebUI packages; Ops code checks database, Redis, workers, storage and deployment-security settings. | This does not replace external monitoring or a target runbook. |
|
||||
| Calendar/CalDAV integration | `partial` | Calendar storage/sync tests exist; durable external-write outbox, worker recovery and retention are local WIP in this snapshot. | Not required for the Campaign pilot and must not be treated as release-integrated yet. Bulk synchronized-calendar migration semantics remain separate work. |
|
||||
| External LDAP/AD, OIDC/SAML or SCIM identity integration | `scaffold` | IDM owns normalized assignment APIs and documents connector boundaries. | Provider connectors, login callback flow and target directory reconciliation are not an implemented end-to-end capability. Use local accounts for this pilot. |
|
||||
| Export-control/embargo-list screening | `planned` | Product-level [GovOPlaN #12](https://git.add-ideas.de/add-ideas/govoplan/issues/12) defines the consumer-independent user story. | No screening provider, list provenance, matching policy, review flow or legal evidence exists in this composition. |
|
||||
| Workflow-driven journeys and views | `planned` | Workflow contracts/concepts exist outside this assessment. | Explicitly postponed. Do not include Workflow in pilot or production claims from this report. |
|
||||
|
||||
## Infrastructure matrix
|
||||
|
||||
| Component | Status | Current evidence | Target requirement / gap |
|
||||
| --- | --- | --- | --- |
|
||||
| WebUI and API | `verified` | FastAPI app, module routes, shared WebUI host, health endpoint, dev smoke and module-permutation tests. | Build immutable, matching frontend/backend artifacts and supervise them; no production image/service bundle is supplied here. |
|
||||
| Background workers | `available_unconfigured` | Celery app, Campaign queues, Redis configuration and production-like launcher. | Run target broker/worker heartbeat and failure drills; split queues when provider limits or load justify it. |
|
||||
| Scheduler | `partial` | A separately launched Celery beat process and Calendar recovery schedule exist in local WIP. | Keep single-instance until leader election/locking is proved; add process supervision and missed-schedule alerts. |
|
||||
| PostgreSQL | `verified` | Production target in settings/operator docs, migration tracks and a disposable integration-check harness. | Target HA, patching, connection limits, WAL/archive policy and restore time are external deployment decisions. |
|
||||
| Redis/queues | `available_unconfigured` | Redis-backed Celery configuration, health ping and append-only production-like container. | Target availability, persistence, eviction, authentication/TLS and queue-loss behavior were not assessed. |
|
||||
| Local file storage | `verified` | Local backend, configured root, fallback-root tests and Ops writability check. | Suitable only for a durable single-node/shared path with backup; it blocks independent API scaling when node-local. |
|
||||
| S3-compatible object storage | `partial` | S3 backend and connector code plus mocked browse/import tests. | Exercise the chosen service, credentials, CA, versioning, lifecycle, multipart/size behavior, restore and consistency expectations. |
|
||||
| Reverse proxy and TLS | `external_system` | Core validates explicit CORS and secure-cookie posture; Ops reports unsafe production settings. | Deployment must provide certificates, proxy/header policy, request limits, logs and renewal monitoring. |
|
||||
| Local identity and authorization | `verified` | Password/session/API-key/RBAC capabilities and tests. | Establish account lifecycle, MFA expectation, protected bootstrap and break-glass procedure. |
|
||||
| Federated identity | `scaffold` | IDM boundary and assignment APIs. | Select and implement/test the actual OIDC/SAML/LDAP/SCIM path before requiring federation. |
|
||||
| Application secret encryption | `verified` | Stable `MASTER_KEY_B64` contract and encrypted mail-credential paths. | Rotation and loss-recovery procedure need target validation. |
|
||||
| Secret store and injection | `external_system` | Environment/file references are supported and templates avoid populated secrets. | Choose Vault/KMS/Kubernetes/systemd/environment mechanism, restrict access, rotate credentials and prevent secret exposure in logs/backups. |
|
||||
| SMTP/IMAP and other connectors | `available_unconfigured` | Protocol adapters and development testbeds. | Target endpoints, egress, DNS, CA, throttling, service accounts and data-processing terms remain environment-specific. |
|
||||
| Health/readiness | `verified` | `/health`, protected `/health/details`, and Ops checks for DB, Redis, workers, storage, maintenance and cookie/CORS posture. | Add external probes and distinguish liveness from dependency readiness for the chosen orchestrator. |
|
||||
| Metrics, logs and alerting | `partial` | Correlation IDs, slow-request/query metrics in logs, worker inspection and operator status are implemented. | No bundled metrics exporter, log collector, dashboards, queue-depth alerts, pager route or SLO is verified. |
|
||||
| Audit | `partial` | Local audit tables and retry outbox are verified. | Retention, tamper-evident export, privileged access review and SIEM integration are unproved. |
|
||||
| Backup and restore | `partial` | Operator guide and installer hooks describe `pg_dump`/`pg_restore`; SQLite and simulated installer rollback drills exist. | [Core #29](https://git.add-ideas.de/add-ideas/govoplan-core/issues/29) remains open. No target PostgreSQL + files + secrets restore drill or measured RTO/RPO exists. |
|
||||
| Disaster recovery | `not_assessed` | The Ops guide asks for RPO/RTO and restore drills. | No agreed RPO/RTO, off-site copy, failover topology, dependency recovery order, communications plan or exercise evidence was supplied. |
|
||||
|
||||
The scalability and sizing documentation delivered the documentation portions
|
||||
of [Core #217](https://git.add-ideas.de/add-ideas/govoplan-core/issues/217) and
|
||||
[Core #219](https://git.add-ideas.de/add-ideas/govoplan-core/issues/219).
|
||||
[Core #28](https://git.add-ideas.de/add-ideas/govoplan-core/issues/28) records the
|
||||
operator-documentation slice. These closed tickets are evidence of documented
|
||||
models, not evidence that an organization's production environment has passed
|
||||
them.
|
||||
|
||||
## Trust, data-flow and network boundaries
|
||||
|
||||
| Boundary / flow | Data and trust | Required controls |
|
||||
| --- | --- | --- |
|
||||
| Browser -> reverse proxy -> WebUI/API | Session and CSRF cookies, campaign content, recipient personal data and managed files cross the public/client boundary. | HTTPS, exact origins, secure cookies, request/body limits, tenant/RBAC enforcement, security headers and access logs. |
|
||||
| API -> PostgreSQL | Tenants, identities, permissions, campaign drafts/snapshots/jobs, connector metadata and audit evidence enter the primary trusted data store. | Dedicated DB identity, encrypted transport where networked, least privilege, migration control, backup/restore and retention. |
|
||||
| API/worker -> file/object storage | Campaign attachments and generated evidence may contain personal or confidential content. | Private buckets/paths, encryption, scoped credentials, malware/content policy where required, lifecycle and coordinated restore. |
|
||||
| API -> Redis -> worker | Queue messages and job identifiers cross from request processing to an asynchronous trust zone. PostgreSQL remains the durable business-state authority. | Private/authenticated broker, bounded payloads, idempotent claims, queue monitoring and worker isolation. |
|
||||
| Worker -> SMTP/IMAP | Recipient addresses, message bodies and attachments leave GovOPlaN; IMAP append stores a sent copy externally. | Approved service account, TLS/CA policy, recipient/sender policy, rate limits, outcome reconciliation and disclosure/legal basis. |
|
||||
| Connector worker -> CardDAV/WebDAV/Seafile/SMB/S3/CalDAV | Address data, files or calendars cross an organizational/system boundary in both directions depending on connector mode. | Explicit direction, scoped credentials, endpoint allow-list, provenance, conflict policy, retry/reconciliation and target interoperability test. |
|
||||
| Operator -> installer/catalog/migration plane | A highly privileged process can mutate packages, schemas and desired module state. | Separate operator identity, signed/pinned catalogs, maintenance mode, immutable run records, backups, rollback checks and restricted network access. |
|
||||
| API/audit -> monitoring or SIEM | Operational metadata and potentially personal audit context may leave GovOPlaN. | Data minimization, retention/access policy, authenticated transport, integrity and documented processor/location. No sink is verified today. |
|
||||
|
||||
Typical network requirements are inbound HTTPS to the deployment proxy and
|
||||
private connectivity from API/workers to PostgreSQL and Redis. Outbound access
|
||||
may be required to SMTP submission, IMAP, HTTPS-based connectors/object storage,
|
||||
DNS, NTP, certificate validation, monitoring and the signed module catalog.
|
||||
Ports and destinations must come from the selected infrastructure; common
|
||||
defaults such as PostgreSQL 5432, Redis 6379, SMTP 465/587 and IMAP 993 are not
|
||||
an allow-list.
|
||||
|
||||
## Known assumptions, gaps and risks
|
||||
|
||||
Facts:
|
||||
|
||||
- The production-like profile is a development validation composition, not a
|
||||
production deployment artifact.
|
||||
- The assessed workspace is untagged and several key repositories are dirty.
|
||||
- Workflow is postponed.
|
||||
- The default composition does not enable Addresses.
|
||||
- Health/readiness checks exist; an external monitoring stack does not.
|
||||
|
||||
Assumptions that require confirmation:
|
||||
|
||||
- The pilot can use local accounts and one internal tenant/office.
|
||||
- A controlled non-production SMTP/IMAP account and safe recipients are
|
||||
available.
|
||||
- Campaign volume is below the measured limits of a single worker and database.
|
||||
- Local durable storage is acceptable for the pilot and all recipient data has
|
||||
an approved legal basis and retention policy.
|
||||
|
||||
Highest risks:
|
||||
|
||||
1. A dirty, untagged workspace cannot be reproduced or promoted safely.
|
||||
2. Real SMTP/IMAP behavior, throttling and ambiguous outcomes have not been
|
||||
proven against the target provider.
|
||||
3. Backup/restore and disaster recovery are not demonstrated across database,
|
||||
files, keys and deployment configuration.
|
||||
4. External identity, monitoring, secret-store and reverse-proxy controls are
|
||||
deployment gaps rather than GovOPlaN-delivered components.
|
||||
5. Local Campaign and Calendar WIP can look complete in the checkout while
|
||||
remaining absent from the remote release baseline.
|
||||
6. Data classification, retention, recipient consent/legal basis and external
|
||||
disclosure rules are not assessed for a concrete organization.
|
||||
|
||||
## Proof checks before promotion
|
||||
|
||||
1. Create a clean release candidate that pins every module/package and WebUI
|
||||
artifact; rerun the contract, module-permutation and focused test gates.
|
||||
2. Run a target-like Campaign from import through validation, attachment build,
|
||||
queue, SMTP acceptance, IMAP append, reporting and audit using safe data.
|
||||
3. Drill transient SMTP failure, accepted-but-local-commit-lost uncertainty,
|
||||
worker restart, Redis interruption and manual reconciliation without a
|
||||
duplicate send.
|
||||
4. Restore PostgreSQL, managed files, configuration and encrypted credentials
|
||||
into an isolated environment; measure RPO and RTO.
|
||||
5. Validate proxy/TLS, CORS, cookies, headers, body limits, account bootstrap,
|
||||
maintenance access and secret redaction.
|
||||
6. Measure representative recipient/file volume, queue age, database growth,
|
||||
send rate and provider throttling; set capacity and alert thresholds.
|
||||
7. Confirm audit/retention/privacy/legal requirements and any SIEM or archive
|
||||
export before using production personal data.
|
||||
|
||||
## Reusable assessment questionnaire
|
||||
|
||||
Answers should contain no secrets and no unnecessary personal data. Each answer
|
||||
must be marked `answered`, `assumed`, `not_applicable`, or `not_assessed` and may
|
||||
link evidence.
|
||||
|
||||
### Scope and outcomes
|
||||
|
||||
- What outcome and reference journey must GovOPlaN support?
|
||||
- Which users, roles, tenants, organization units and delegated functions take
|
||||
part?
|
||||
- Which journey steps are mandatory, optional, manual, external, or explicitly
|
||||
postponed?
|
||||
- What constitutes pilot success and production acceptance?
|
||||
|
||||
### Data, privacy, records and policy
|
||||
|
||||
- Which data classes enter database, files, messages, calendars, addresses,
|
||||
logs and audit evidence?
|
||||
- What are the legal basis, purpose, minimization, access, residency, retention,
|
||||
deletion, archive and legal-hold requirements?
|
||||
- Which external systems/processors receive data, and in which jurisdictions?
|
||||
- Which decisions require four-eyes approval, explainability or immutable
|
||||
evidence?
|
||||
|
||||
### Identity and integrations
|
||||
|
||||
- Are local accounts acceptable, or are OIDC, SAML, LDAP/AD or SCIM mandatory?
|
||||
- What are the MFA, joiner/mover/leaver, service-account and break-glass rules?
|
||||
- Which SMTP/IMAP, file/DMS, CardDAV/CalDAV, ERP, API or event endpoints are in
|
||||
scope? Record protocol/version, direction, auth, CA, rate limit and owner.
|
||||
- Which integrations may be unavailable, and what degraded/manual behavior is
|
||||
acceptable?
|
||||
|
||||
### Workload and growth
|
||||
|
||||
- Tenants, named/active/concurrent users and peak requests?
|
||||
- Campaigns per period, recipients per Campaign, send window, attachment sizes,
|
||||
import size and retry peak?
|
||||
- Managed files, database and audit volume now and over the retention window?
|
||||
- Connector batches, queue depth/age, scheduled jobs and external rate limits?
|
||||
|
||||
### Availability, hosting and operations
|
||||
|
||||
- Required service hours, planned maintenance, availability, RPO and RTO?
|
||||
- Hosting, network zones, egress/proxy/DNS/NTP/CA, data-residency and
|
||||
air-gap constraints?
|
||||
- Who operates PostgreSQL, Redis, storage, TLS, identity, secrets, monitoring,
|
||||
backups and incident response?
|
||||
- What deployment, patch, migration, rollback, restore and DR drills must pass?
|
||||
|
||||
### Procurement and decisions
|
||||
|
||||
- Required open-source/license, support, accessibility, security, certification,
|
||||
interoperability and procurement conditions?
|
||||
- Which requirements are blockers, accepted risks, residual risks or later
|
||||
roadmap work?
|
||||
- Who owns each decision, evidence item and next review date?
|
||||
|
||||
For every capability and infrastructure conclusion, record the requirement,
|
||||
status from the controlled vocabulary, evidence scope, evidence links,
|
||||
assumptions, gaps, risks, recommendation and proof check. Reassessment must pin a
|
||||
new composition and review any row whose code, evidence, configuration or target
|
||||
requirement changed.
|
||||
|
||||
## Evidence used in this slice
|
||||
|
||||
- [Production-like profile](../dev/production-like/README.md) and
|
||||
[Compose dependencies](../dev/production-like/docker-compose.yml)
|
||||
- [Module contracts and install boundaries](MODULE_CONTRACTS_AND_INSTALLS.md)
|
||||
- [Core deployment operator guide](https://git.add-ideas.de/add-ideas/govoplan-core/src/branch/main/docs/DEPLOYMENT_OPERATOR_GUIDE.md)
|
||||
- [Ops scalability profiles](https://git.add-ideas.de/add-ideas/govoplan-ops/src/branch/main/docs/SCALABILITY_PROFILES.md)
|
||||
- Actual module manifests in the pinned repositories and the static contract
|
||||
checker in this meta repository
|
||||
- Core module-system/API smoke/auth/install-config tests, plus focused Campaign,
|
||||
Files, Mail, Audit and Addresses tests
|
||||
- [Campaign delivery runbook](https://git.add-ideas.de/add-ideas/govoplan-campaign/src/branch/main/docs/CAMPAIGN_DELIVERY_RUNBOOK.md)
|
||||
|
||||
Checks run for this first slice against the current workspace:
|
||||
|
||||
- static manifest/interface contract scan: 43 contracts, 29 providers, no issues
|
||||
- selected Core module-composition, auth/CSRF, health, Campaign journey,
|
||||
reconciliation and install-configuration tests: 14 passed
|
||||
- Campaign tests: 14 passed
|
||||
- Files tests: 14 passed
|
||||
- Mail tests: 22 passed
|
||||
- Audit tests: 5 passed
|
||||
- Addresses tests: 14 passed (one non-failing SQLite resource warning)
|
||||
- JSON Schema validation of the machine-readable assessment: passed
|
||||
|
||||
These checks are evidence for the rows above; they are not a substitute for the
|
||||
clean-release and target-environment proof checks.
|
||||
@@ -3,6 +3,11 @@
|
||||
GovOPlaN modules should choose their page layout by the kind of work the user is
|
||||
doing, not by the repository that owns the feature.
|
||||
|
||||
These concise layout choices are one canonical input to the broader
|
||||
[`INTERFACE_PATTERN_LANGUAGE.md`](INTERFACE_PATTERN_LANGUAGE.md). The current
|
||||
route and rollout evidence lives in
|
||||
[`INTERFACE_SURFACE_INVENTORY.md`](INTERFACE_SURFACE_INVENTORY.md).
|
||||
|
||||
## Structured Data Directories
|
||||
|
||||
Use a full-available-space workspace for structured data directories: files,
|
||||
@@ -41,6 +46,9 @@ Principles:
|
||||
summaries, and dashboard widgets.
|
||||
- Collapsible panels and segmented controls are appropriate when a dense
|
||||
configuration area needs controlled disclosure.
|
||||
- A collapsible card whose sole content is a table gives that table the full
|
||||
available card body; avoid nested cards, duplicate padding, inner max-widths,
|
||||
and nested scrolling.
|
||||
- Avoid forcing workflow/configuration pages into a file-explorer style unless
|
||||
the primary interaction is genuinely directory browsing.
|
||||
|
||||
|
||||
@@ -140,6 +140,7 @@ Use one `type/*` label:
|
||||
|
||||
- `type/bug`
|
||||
- `type/feature`
|
||||
- `type/user-story`
|
||||
- `type/task`
|
||||
- `type/debt`
|
||||
- `type/docs`
|
||||
|
||||
392
docs/INTERFACE_PATTERN_LANGUAGE.md
Normal file
392
docs/INTERFACE_PATTERN_LANGUAGE.md
Normal file
@@ -0,0 +1,392 @@
|
||||
# GovOPlaN Interface Pattern Language
|
||||
|
||||
This document is the cross-repository pattern language for GovOPlaN user
|
||||
interfaces. It turns the existing ethical doctrine, binding UI/UX decisions,
|
||||
layout principles, and module boundary into a common composition and review
|
||||
grammar. It does not replace those sources.
|
||||
|
||||
The companion [interface surface inventory](INTERFACE_SURFACE_INVENTORY.md)
|
||||
records which surfaces the current code contributes and where each surface
|
||||
enters the rollout.
|
||||
|
||||
## Source Of Truth And Precedence
|
||||
|
||||
Use the narrowest owning document when changing a rule:
|
||||
|
||||
1. `govoplan-core/docs/INTERFACE_ETHICS_AND_DESIGN_DOCTRINE.md` owns why a
|
||||
consequential interface must preserve context, decision, consequence,
|
||||
responsibility, contestability, and traceability.
|
||||
2. `govoplan-core/docs/UI_UX_DECISION_LEDGER.md` owns accepted product decisions
|
||||
such as progressive disclosure, adaptive forms, blocker language, guided
|
||||
operations, and the platform theme contract.
|
||||
3. `docs/FRONTEND_LAYOUT_PRINCIPLES.md` owns the high-level choice between a
|
||||
full-space structured-data workspace and a heading/menu/card workflow or
|
||||
configuration surface.
|
||||
4. `govoplan-core/docs/MODULE_ARCHITECTURE.md` owns the shell, route, navigation,
|
||||
UI-capability, and shared-component boundaries.
|
||||
5. This document owns the common pattern names, placement grammar, wording and
|
||||
state conventions, focused-view composition, and definition of done across
|
||||
those sources.
|
||||
|
||||
If two rules appear to conflict, do not create a third local convention. Record
|
||||
the conflict in the owning decision ledger, resolve it there, and update the
|
||||
affected patterns and surfaces together.
|
||||
|
||||
## Product Contract
|
||||
|
||||
GovOPlaN should feel calm because it shows what is relevant to the task, not
|
||||
because it hides authority, risk, or evidence. Every surface follows these
|
||||
rules:
|
||||
|
||||
- Start with the user's current object and task.
|
||||
- Show common actions before advanced controls.
|
||||
- Keep context, status, problems, and the next action spatially connected.
|
||||
- Make consequential effects explicit before execution and observed effects
|
||||
inspectable afterwards.
|
||||
- Treat permissions, policy, privacy, and module availability as behavior, not
|
||||
decoration.
|
||||
- Keep optional modules optional. Compose through core route and UI-capability
|
||||
contracts, never sibling-private components.
|
||||
- Preserve a stable way back to the containing object and the broader system.
|
||||
- Do not let navigation, selection, or a view switch imply consent.
|
||||
|
||||
## Surface Archetypes
|
||||
|
||||
Choose an archetype from the task, then specialize it for the domain. A route
|
||||
may contain more than one bounded archetype, but it should have one dominant
|
||||
one.
|
||||
|
||||
| Archetype | Use when | Standard anatomy | Do not use when |
|
||||
| --- | --- | --- | --- |
|
||||
| Directory or explorer | Users browse hierarchical collections such as files, mailboxes, calendars, addresses, or records. | Collection/source pane, collection actions, filter in the pane it affects, main list/content pane, optional detail pane. | The content is a set of unrelated settings or workflow stages. |
|
||||
| List-detail workspace | Users repeatedly find objects, inspect one, and act without losing list context. | Search/filter/list, persistent selected-object context, detail/actions, stable selection and URL. | A single guided operation is the primary task. |
|
||||
| Focused task view | Only a bounded composition is needed to complete one task. | Task identity and reason, selected object, necessary module regions/actions, progress or status, obvious exit to the full system. | Hiding a surface would obscure a consequence, blocker, or required evidence. |
|
||||
| Create or edit | Users change one coherent object state. | Adaptive typed form, field-level validation, advanced section, save/cancel, unsaved-change guard. | Discovery-heavy setup or a broad consequential change needs staged review. |
|
||||
| Guided setup or import | The user must discover, upload, map, test, or preflight before a safe result exists. | Named steps, current progress, preserved inputs, validation/problem list, review, resumable completion where work is durable. | An ordinary edit can be understood as one coherent form. |
|
||||
| Review or decision | A person must inspect evidence and deliberately approve, reject, send, publish, or otherwise commit. | Decision context, evidence/problems, consequence and reversibility, authority/provenance, explicit action, resulting record. | The interaction is passive inspection. |
|
||||
| Monitoring, progress, or report | Users observe asynchronous or aggregate state and intervene when needed. | Summary, filters, durable job/item state, last update, retry/reconcile/intervention, detail and evidence. | A toast is sufficient for a short, non-durable local action. |
|
||||
| Administration or configuration | Users compare and configure separate concerns. | Heading and scope, grouped subnavigation, overview/list plus selected details, adaptive editor or guided risky operation, effective policy and source. | The primary task is browsing one structured object space. |
|
||||
| Dashboard | Users need a task-oriented starting point across modules. | Prioritized actionable widgets, scoped status, clear destination per widget, explicit refresh/staleness. | It merely duplicates every module navigation item or metric. |
|
||||
| Public service or entry | An unauthenticated or external participant starts or resumes a service. | Service identity, eligibility/context, privacy and evidence expectations, accessible form/task, save/resume or handoff. | The actor is performing internal administration. |
|
||||
|
||||
## Placement Grammar
|
||||
|
||||
### Shell And Navigation
|
||||
|
||||
- The global title bar and rail belong to core. A module contributes routes,
|
||||
navigation metadata, and explicit UI capabilities; it does not reproduce the
|
||||
shell.
|
||||
- Global navigation answers "which service area?" Local subnavigation answers
|
||||
"which stable facet of this object or area?" A progress indicator answers
|
||||
"where am I in this operation?" Do not use those three controls
|
||||
interchangeably.
|
||||
- Keep the current tenant, actor, object, and selected version or scope stable
|
||||
across local navigation. Guard unsaved work before navigation.
|
||||
- Permission and capability filtering happens before view composition. A
|
||||
missing menu item is not evidence that an actor lacks backend access, and a
|
||||
visible item is never authorization by itself.
|
||||
- Route, selection, panel, and view changes must not execute consequential
|
||||
actions.
|
||||
|
||||
### Page And Workspace
|
||||
|
||||
- Structured directories use the full available content space and persistent
|
||||
panes. They do not add a decorative heading row that reduces working height.
|
||||
- Workflow, configuration, dashboard, and explanatory pages may use a heading.
|
||||
The heading names the task or scoped object and contains only route-level
|
||||
actions.
|
||||
- Put filters beside the list or pane they affect. Put bulk actions immediately
|
||||
above or beside the current selection. Put object actions with the object
|
||||
detail, not in the global title bar.
|
||||
- Full-page create and edit surfaces put their persistent action cluster in the
|
||||
upper-right of the page heading. `Discard` comes before `Save …`, with the
|
||||
primary save action at the far right. Keep both controls in the same place
|
||||
across validation, loading, and saved states; guard unsaved work when the
|
||||
user discards or navigates away.
|
||||
- A page or panel has one visually primary action for its current state. Put
|
||||
secondary actions beside it. Separate destructive actions and name their real
|
||||
effect.
|
||||
- Dialog actions use a stable footer: cancel/back first, then the primary action
|
||||
at the end. Header and footer stay fixed while long bodies scroll.
|
||||
- Use cards for independent groups, summaries, and settings blocks. Do not wrap
|
||||
every region in a card or nest cards merely to create spacing.
|
||||
- When a collapsible card contains one table and no other content, the table
|
||||
uses the card's full available width and body height. The card/table region
|
||||
owns overflow; do not add an inner max-width, decorative wrapper, duplicate
|
||||
padding, or nested scroll container that reduces the working area.
|
||||
- Row actions in tables are icon-only controls in a stable rightmost action
|
||||
column. Order them by intent: inspect/open, edit, copy/duplicate,
|
||||
transfer/share/download, retry/restore, then remove/delete last. Omit actions
|
||||
that do not apply without closing the gap or changing the relative order.
|
||||
Every icon has a translated accessible name and matching tooltip. Separate
|
||||
destructive actions visually, and use a named confirmation/review surface
|
||||
when the consequence cannot be understood from the icon and row context.
|
||||
- Transient feedback should not shift the workspace. Durable failures, partial
|
||||
results, and blockers remain attached to the affected item or operation.
|
||||
|
||||
### Detail And Explanation
|
||||
|
||||
- Keep the selected object's identity and material status visible while its
|
||||
detail changes.
|
||||
- Short field help sits with the label. Longer "Why?", policy source,
|
||||
diagnostics, or provenance belongs in an expandable area, detail panel, or
|
||||
review step.
|
||||
- Empty space is not an error. An empty state states what is empty, why that can
|
||||
happen, and the permitted next action. Do not show creation actions to actors
|
||||
who cannot create.
|
||||
|
||||
## Visual Grammar
|
||||
|
||||
- Core owns the appearance contract and shared CSS tokens. Modules use core
|
||||
colors, spacing, radii, shadows, focus treatment, status colors, and disabled
|
||||
treatment; module CSS may specialize layout only.
|
||||
- Establish hierarchy through spacing, typography, grouping, and placement
|
||||
before adding borders or color.
|
||||
- Color never carries status or required action alone. Pair it with text and,
|
||||
where useful, an icon.
|
||||
- Icons support recognition but do not replace accessible names. Use the core
|
||||
icon-name mapping for navigation.
|
||||
- Keep list columns, tree indentation, headers, dialog dimensions, and action
|
||||
positions stable as content changes.
|
||||
- Density is a user preference, not a license to remove labels, focus targets,
|
||||
explanations, or consequences.
|
||||
- Respect system/light/dark themes and reduced-motion preferences through the
|
||||
core contract. Do not build module-local theme systems.
|
||||
|
||||
## Wording Grammar
|
||||
|
||||
Use the same noun for the same domain object in navigation, headings, fields,
|
||||
actions, states, API-facing explanations, and documentation. Prefer the most
|
||||
specific user-facing noun: "Recipients" rather than "Data", "Delivery job"
|
||||
rather than "Process", and "Mail profile" rather than "Configuration" when
|
||||
that is what the user is acting on.
|
||||
|
||||
Actions use a verb plus the object or consequence:
|
||||
|
||||
- Prefer `Save campaign`, `Review messages`, `Queue delivery`, `Retry failed
|
||||
deliveries`, or `Delete calendar`.
|
||||
- Avoid `Submit`, `OK`, `Continue`, or `Execute` when a more precise action is
|
||||
available.
|
||||
- Use `Continue` only when it advances a reversible guided flow without
|
||||
committing the final effect.
|
||||
- Do not say `Undo` when the system can only cancel future work, create a
|
||||
correction, supersede a record, or request retraction.
|
||||
|
||||
State text describes observed state, not optimism. Use stable shared terms where
|
||||
they fit: `Draft`, `Ready for review`, `Blocked`, `Queued`, `Running`,
|
||||
`Retry scheduled`, `Partially completed`, `Completed`, `Failed`, and
|
||||
`Cancelled`. Domain-specific states may refine these terms but should not give a
|
||||
shared term a contradictory meaning.
|
||||
|
||||
Blocked and failed actions use the structured language from DUE-005:
|
||||
|
||||
- what is unavailable or failed
|
||||
- why, in plain language
|
||||
- what must happen next
|
||||
- who can do it
|
||||
- where to go
|
||||
- optional technical details behind deliberate disclosure
|
||||
|
||||
Errors should identify the affected object and whether saved state or external
|
||||
effects may already exist. Never expose raw exception text as the only user
|
||||
message.
|
||||
|
||||
## State Contract
|
||||
|
||||
Every surface implements the states it can reach; it does not render a blank
|
||||
region while waiting or collapse distinct outcomes into a generic error.
|
||||
|
||||
| State | Required treatment |
|
||||
| --- | --- |
|
||||
| Loading | Keep the stable shell and context visible. Name what is loading; preserve usable prior data when safe. |
|
||||
| Empty | State the scope and reason, then show only permitted next actions. |
|
||||
| Validation problem | Attach the problem to the field/item and provide a navigable summary when problems span regions or steps. |
|
||||
| Permission denied | Name the unavailable action or object, the required actor/role where safe, and a valid exit. Do not leak protected data. |
|
||||
| Capability unavailable | Distinguish not installed, disabled, not configured, unhealthy, and not permitted when the actor may know. Give the responsible actor and target. |
|
||||
| Offline or unreachable | Preserve local context and unsaved input, show last-known/stale state, and offer a safe retry. Do not present network absence as an authentication failure. |
|
||||
| Stale or conflicting | Show which data changed, preserve both values where feasible, and offer reload, merge, or explicit overwrite according to policy. |
|
||||
| Partial result | Show completed and incomplete effects separately. Never label a partial operation successful without qualification. |
|
||||
| Asynchronous work | Show durable job identity, queued/running/retry/block/final state, last update, progress if meaningful, and leave/return behavior. |
|
||||
| Success | State the resulting object/effect and provide its evidence or destination. Use a transient toast only when the result is already visible and durable elsewhere. |
|
||||
| Destructive or corrective action | Preview scope, downstream effects, reversibility limit, evidence, and required confirmation or approval. |
|
||||
|
||||
Long-running or external work must expose retry and reconciliation as observable
|
||||
states. The UI must not imply that a request and its external effect were one
|
||||
atomic success when an outbox, worker, or remote system sits between them.
|
||||
|
||||
## Consequence And Provenance
|
||||
|
||||
Before an action affects records, rights, policy, retention, communications,
|
||||
money, external systems, or workflow state, its action surface must answer the
|
||||
decision-surface questions in the interface doctrine. At minimum show:
|
||||
|
||||
- affected object and scope
|
||||
- acting identity or system actor and relevant authority
|
||||
- immediate and possible downstream effects
|
||||
- whether the operation is reversible, cancellable, corrective, or final
|
||||
- blockers and their resolution path
|
||||
- audit/evidence that will be created
|
||||
- effective policy or configuration source when it changes the decision
|
||||
|
||||
After execution, users must be able to reach the command/job, observed effects,
|
||||
policy result, failures, retries, reconciliation outcome, actor, time, and source
|
||||
data that explain the result. Provenance may be quiet by default, but it must not
|
||||
be absent.
|
||||
|
||||
Privacy follows the same rule: lists, previews, logs, notifications, and
|
||||
diagnostics show only the personal or secret data needed for the actor's task.
|
||||
Redaction must be explicit enough that users do not mistake a redacted value for
|
||||
missing source data.
|
||||
|
||||
## Focused Views
|
||||
|
||||
A focused view is a declarative UI composition for a task. It selects the
|
||||
routes, local regions, navigation entries, and actions relevant to that task
|
||||
after installed-module, capability, permission, and policy filtering. It does
|
||||
not change backend authorization or domain state.
|
||||
|
||||
A view definition must be able to explain:
|
||||
|
||||
- its stable identifier, label, and task purpose
|
||||
- the current object/scope and default destination
|
||||
- included navigation and contributed regions/actions, with deterministic order
|
||||
- the visible escape to the containing module and full system
|
||||
- why the view is active and how the user may switch when switching is allowed
|
||||
- what happens to unsaved work when entering, leaving, or switching views
|
||||
|
||||
Focused views follow these invariants:
|
||||
|
||||
- Do not hide a blocker, material consequence, provenance, or required review
|
||||
merely to make the screen quieter.
|
||||
- Preserve the global tenant/actor context and provide an obvious exit.
|
||||
- Filter unavailable contributions without leaving broken separators, empty
|
||||
groups, or dead destinations.
|
||||
- A manual or automatic switch is navigation, not consent. Guard unsaved work
|
||||
and never execute a domain action as a side effect.
|
||||
- Display why a non-manual default was selected, for example a role or task
|
||||
default, without exposing protected policy details.
|
||||
- Treat an unknown or invalid view as a recoverable fallback to the normal
|
||||
module surface.
|
||||
|
||||
When more than one source proposes a focused view, use this precedence:
|
||||
|
||||
1. a manual view pinned for the current user session
|
||||
2. a current-task suggestion, including a future workflow-step suggestion
|
||||
3. the user's saved default
|
||||
4. the role or tenant default
|
||||
5. the normal full interface
|
||||
|
||||
Show the active source and an escape to the full interface. A task or workflow
|
||||
suggestion is never an authorization change and never locks the user into the
|
||||
composition; tenant policy may constrain which views are selectable, but it
|
||||
must not hide required evidence or remove that escape. Workflow implementation
|
||||
is explicitly postponed and is not a prerequisite for defining, manually
|
||||
selecting, testing, or piloting focused views. A future workflow module may
|
||||
request a view through a core contract; it must not own the view composition
|
||||
implementation.
|
||||
|
||||
## Accessibility And Responsive Contract
|
||||
|
||||
- Every action is reachable and operable by keyboard in a logical order.
|
||||
- Use semantic headings, landmarks, labels, tables/lists, and native controls
|
||||
before adding ARIA. Icon-only controls need stable accessible names.
|
||||
- Focus is visible. Dialogs trap focus, announce their name, and return focus to
|
||||
the control that opened them. Validation moves or links focus to the first
|
||||
relevant problem without losing the problem summary.
|
||||
- Loading, saved, failed, queued, progress, and externally updated states are
|
||||
announced without repeatedly interrupting the user.
|
||||
- Disabled primary actions need a focusable explanation; a pointer-only tooltip
|
||||
is insufficient.
|
||||
- Do not rely on color, hover, drag-and-drop, pointer precision, or animation as
|
||||
the only interaction. Provide keyboard and explicit-control equivalents.
|
||||
- At narrow widths and high zoom, preserve task order and action access. Collapse
|
||||
secondary panes into an explicit drawer/step and never move a destructive
|
||||
action into the primary position.
|
||||
- Honor reduced motion. Avoid motion that implies progress when the operation is
|
||||
merely waiting.
|
||||
- Truncation has an accessible full-value path. Personal or secret values remain
|
||||
redacted according to permission and policy in that path.
|
||||
|
||||
## Component Ownership
|
||||
|
||||
Core already exports shell, navigation, access-boundary, form, dialog, loading,
|
||||
status, policy/provenance, blocker, review, table, tree, message-display, and
|
||||
unsaved-change primitives. Reuse them when their contract fits.
|
||||
|
||||
Do not promote a component only because two screens look similar. Promote it to
|
||||
`@govoplan/core-webui` after a second consumer or a clear platform contract has
|
||||
proved shared behavior, accessibility, state, and extension needs. Modules own
|
||||
domain composition, wording, and policy semantics; core owns generic contracts
|
||||
and appearance.
|
||||
|
||||
## Test Expectations
|
||||
|
||||
For every changed surface, select tests from each applicable layer:
|
||||
|
||||
- route and permission tests: module enabled/disabled permutations, route guard,
|
||||
contribution filtering, fallback, and direct-link behavior
|
||||
- behavior tests: primary task, validation, unsaved-change guard, confirmation,
|
||||
retry/reconcile, partial result, and leave/return behavior
|
||||
- accessibility tests: semantic names/roles, keyboard order, focus entry/return,
|
||||
live-state announcements, and non-color status meaning
|
||||
- state tests: loading, empty, denied, capability-missing, stale/conflict,
|
||||
offline, partial, success, and destructive/corrective outcomes as applicable
|
||||
- composition tests: absent optional module, duplicate/unknown contribution,
|
||||
deterministic ordering, and focused-view fallback
|
||||
- presentation checks: supported widths/zoom, light/dark/system theme, reduced
|
||||
motion, comfortable/compact density, and long translated text
|
||||
- i18n checks: user-facing strings owned by the rendering package and structural
|
||||
audits passing
|
||||
- visual regression: useful for geometry and hierarchy after behavior and
|
||||
accessibility assertions exist; never the only evidence
|
||||
|
||||
If the current harness cannot automate a required check, record the gap and the
|
||||
manual evidence in the owning issue. "Not tested" is an inventory state, not a
|
||||
reason to infer that a pattern is satisfied.
|
||||
|
||||
## Definition Of Done For A Surface
|
||||
|
||||
- The dominant task and archetype are recorded in the inventory.
|
||||
- Placement, action hierarchy, wording, and every reachable state follow this
|
||||
pattern language or an explicit ledger exception.
|
||||
- Permission, capability, privacy, and redaction behavior are verified.
|
||||
- Consequence, reversibility, authority, evidence, and provenance are present
|
||||
where applicable.
|
||||
- Keyboard, focus, announcement, responsive, theme, density, motion, and i18n
|
||||
behavior are covered in proportion to the surface.
|
||||
- Optional modules remain optional and no sibling-private UI import was added.
|
||||
- Behavioral/accessibility evidence is linked from the rollout matrix and issue.
|
||||
- Configured-system help can reach the applicable pattern or reference topic
|
||||
when [Docs #15](https://git.add-ideas.de/add-ideas/govoplan-docs/issues/15)
|
||||
supplies that experience.
|
||||
|
||||
## First Pilot: Campaign
|
||||
|
||||
[Campaign #74](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/74)
|
||||
is the first full-domain audit and migration. It should prove patterns before
|
||||
generic extraction:
|
||||
|
||||
- [#59](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/59) and
|
||||
[#73](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/73): stable,
|
||||
accessible preview and attachment-detail overlays
|
||||
- [#63](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/63): review
|
||||
stages, outcomes, blockers, and intervention vocabulary
|
||||
- [#62](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/62): explicit
|
||||
synchronous/asynchronous send mode and durable delivery progress
|
||||
- [#65](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/65): one
|
||||
coherent report filtering and count-affordance model
|
||||
- [#35](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/35): guided
|
||||
first-campaign entry
|
||||
|
||||
These slices do not depend on the Workflow runtime. Campaign's current
|
||||
domain-owned review/send state is enough to prove layout, wording, focused-view,
|
||||
progress, intervention, and evidence patterns.
|
||||
|
||||
## Revision Procedure
|
||||
|
||||
1. Record a changed product decision in the core UI/UX decision ledger.
|
||||
2. Update the relevant pattern here without copying the full owning doctrine.
|
||||
3. Update the surface inventory and rollout owner/issues.
|
||||
4. Change shared components only where the proven contract belongs to core.
|
||||
5. Migrate and test affected module surfaces.
|
||||
6. Publish configured-system pattern/reference help through the Docs module.
|
||||
236
docs/INTERFACE_SURFACE_INVENTORY.md
Normal file
236
docs/INTERFACE_SURFACE_INVENTORY.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# GovOPlaN Interface Surface Inventory And Rollout
|
||||
|
||||
This is the initial evidence inventory for the product-wide interface pattern
|
||||
language. It records code contributions, not an assertion that every listed
|
||||
surface is complete, enabled in a deployment, usable, or compliant.
|
||||
|
||||
The applicable design contract is
|
||||
[`INTERFACE_PATTERN_LANGUAGE.md`](INTERFACE_PATTERN_LANGUAGE.md).
|
||||
|
||||
## Snapshot And Method
|
||||
|
||||
Snapshot date: 2026-07-20.
|
||||
|
||||
Evidence was read from tracked Git `HEAD` in the local GovOPlaN checkouts:
|
||||
|
||||
- core routes and fallback behavior in `govoplan-core/webui/src/App.tsx`
|
||||
- every present `govoplan-*/webui/src/module.ts`
|
||||
- the matching backend `src/*/backend/manifest.py`
|
||||
- named UI capabilities and contribution identifiers in each `module.ts`
|
||||
- Campaign nested routes in its tracked `CampaignWorkspace.tsx` and
|
||||
`SectionSidebar.tsx`
|
||||
|
||||
Tracked `HEAD` is used as the integrated baseline. Dirty worktree changes are
|
||||
not treated as delivered behavior. One material exception is called out in the
|
||||
Campaign inventory: local WIP folds the tracked `recipient-data` surface into
|
||||
`recipients`, but that change is not yet part of the baseline.
|
||||
|
||||
Runtime visibility remains conditional on the module being packaged and
|
||||
enabled, server metadata, installed optional capabilities, the authenticated
|
||||
actor, tenant context, route permission guards, and inner-surface permission
|
||||
checks. A route in this inventory therefore means "the code contributes this
|
||||
route when its module is active", not "every user sees it".
|
||||
|
||||
Inventory states:
|
||||
|
||||
- **Contributed**: a route or named UI capability exists in tracked source.
|
||||
- **Metadata gap**: frontend runtime source contributes a route but the backend
|
||||
manifest does not describe the same route/navigation surface.
|
||||
- **Unreviewed**: the surface has not yet completed the pattern, state,
|
||||
accessibility, privacy, and consequence audit. This is the default unless an
|
||||
issue supplies verification evidence.
|
||||
- **Pilot**: the surface is in the Campaign-first rollout.
|
||||
|
||||
## Core Shell Surfaces
|
||||
|
||||
| Surface | Owner and code evidence | Audience/access evidence | Primary task and target archetype | Audit / rollout |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Public landing and login | `govoplan-core` `PublicLandingPage`; rendered while no authenticated principal exists | Unauthenticated; maintenance and backend-reachability context are shell inputs | Understand the service and authenticate; public entry | Unreviewed; later public-entry audit |
|
||||
| Session/bootstrap state | `govoplan-core` `App.tsx` and `AppShell` | All browser sessions during bootstrap | Understand that session/platform state is loading; state contract | Unreviewed; core shell |
|
||||
| `/` authenticated redirect | `govoplan-core` chooses the first visible navigation destination | Authenticated; result depends on visible nav contributions | Enter the actor's first accessible service area; navigation behavior, not a content page | Unreviewed; focused-view/default-route work must preserve this fallback |
|
||||
| `/dashboard` fallback | `govoplan-core` `DashboardPage` only when the Dashboard module is absent | Authenticated; no route-specific scope in core | Cross-module starting point; dashboard | Unreviewed; compare with module dashboard before shared changes |
|
||||
| `/settings` | `govoplan-core` `SettingsPage` | Authenticated; contributed sections and integrations filter internally | Profile, UI/workspace preference, local connection, and user-scoped integration settings; configuration | Unreviewed; Core #225 program |
|
||||
| Shell chrome | `AppShell`, `Titlebar`, `IconRail`, `BreadcrumbBar`, `HelpMenu`, language menu, unsaved-change provider | Public/authenticated variants; nav filtered later | Tenant/actor context, global navigation, help, language, session and maintenance state | Unreviewed; platform-owned prerequisite for focused views |
|
||||
|
||||
## Direct Module Route Contributions
|
||||
|
||||
The access guard column reports only the route-level declaration in
|
||||
`module.ts`. Inner APIs and controls may impose additional checks.
|
||||
|
||||
| Route | Owner / render evidence | Route-level access evidence | Primary task | Target archetype | Status / priority |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `/admin` | `govoplan-access` `AdminPage` | Any core `adminReadScopes` | Administer system and tenant concerns assembled from module sections | Administration/configuration | Contributed; unreviewed; P1 under [Core #225](https://git.add-ideas.de/add-ideas/govoplan-core/issues/225) |
|
||||
| `/address-book` | `govoplan-addresses` `AddressBookPage` | `addresses:contact:read` | Browse and manage contacts, address books, and lists | Directory/list-detail | Contributed; unreviewed; P2 after Campaign |
|
||||
| `/calendar` | `govoplan-calendar` `CalendarPage` | `calendar:event:read` | Browse calendars/events and act on calendar data | Directory/list-detail | Contributed; metadata gap; unreviewed; P2 after Campaign |
|
||||
| `/campaigns` | `govoplan-campaign` `CampaignListPage` | `campaigns:campaign:read` | Find, compare, create, and open campaigns | List-detail entry | Pilot; P1 [Campaign #74](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/74) |
|
||||
| `/campaigns/:campaignId/*` | `govoplan-campaign` `CampaignResourceRoute` and `CampaignWorkspace` | `campaigns:campaign:read`, plus resource probe | Configure, review, send, and inspect one campaign/version | List-detail workspace containing edit, review, monitoring, and evidence surfaces | Pilot; P1 Campaign #74 |
|
||||
| `/operator` | `govoplan-campaign` `OperatorQueuePage` | Any campaign queue/review/send scope declared by the module | Monitor and intervene in campaign jobs | Monitoring/work queue | Pilot; P1 Campaign #74 |
|
||||
| `/reports` | `govoplan-campaign` inline `ReportsPage` | `campaigns:report:read` | Reach campaign reporting; current component identifies itself as prepared for later functionality | Reporting | Pilot inventory; implementation maturity explicitly incomplete; P2 after campaign report pilot |
|
||||
| `/templates` | `govoplan-campaign` `TemplatesPage` | No route guard declared in `module.ts` | Browse/manage campaign templates | Directory/list-detail | Pilot audit; permission intent must be verified; P2 |
|
||||
| `/dashboard` | `govoplan-dashboard` `DashboardPage` | No route-specific scope | Assemble module-provided actionable widgets | Dashboard | Contributed; unreviewed; P2 |
|
||||
| `/docs` | `govoplan-docs` `DocsPage` | Docs read or system/tenant settings read scopes | Read configured, available, and evidence-aware documentation | Documentation directory/reference | Contributed; unreviewed; P1 [Docs #15](https://git.add-ideas.de/add-ideas/govoplan-docs/issues/15) after initial pattern content |
|
||||
| `/files` | `govoplan-files` `FilesPage` | `files:file:read` | Browse folders/files and perform managed-file work | Directory/explorer | Contributed; metadata gap; unreviewed; P2 after Campaign |
|
||||
| `/idm` | `govoplan-idm` `IdmPage` | Any IDM assignment/write or organization function-assign scope | Inspect and govern identity/function assignments | List-detail/configuration | Contributed; unreviewed; P2 |
|
||||
| `/mail` | `govoplan-mail` `MailboxPage` | `mail:mailbox:read` | Browse mailboxes and messages | Directory/list-detail | Contributed; metadata gap; unreviewed; P2 after Campaign |
|
||||
| `/notifications` | `govoplan-notifications` `NotificationCenterPage` | `notifications:notification:read` | Inspect and acknowledge notification state | List-detail/inbox | Contributed without a nav item or backend frontend metadata; navigation intent unknown; P2 discovery |
|
||||
| `/ops` | `govoplan-ops` `OpsPage` | Ops read or system/tenant settings read scopes | Inspect runtime health and readiness | Monitoring | Contributed; unreviewed; P2 |
|
||||
| `/organizations` | `govoplan-organizations` `OrganizationsPage` | Organization model/unit/function or admin settings read scopes | Model and inspect organizational structures/functions | Directory/list-detail | Contributed; unreviewed; P2 |
|
||||
| `/scheduling` | `govoplan-scheduling` `SchedulingPage` | `scheduling:schedule:read` | Plan and decide scheduling requests and availability | List-detail/guided decision | Contributed; metadata gap; unreviewed; P2 |
|
||||
|
||||
## Manifest And Runtime Route Alignment
|
||||
|
||||
Backend route metadata lets operators, Docs, release tooling, and remote bundle
|
||||
loading reason about the configured interface without executing module UI code.
|
||||
`module.ts` remains the executable local route/render source. Missing metadata
|
||||
is recorded here as an evidence gap; this inventory does not infer whether each
|
||||
gap is intentional.
|
||||
|
||||
| Module | `module.ts` routes | Backend manifest frontend routes | Backend nav alignment | Result |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Access | `/admin` | `/admin` | Aligned | Described |
|
||||
| Addresses | `/address-book` | `/address-book` | Aligned | Described |
|
||||
| Admin | No direct route; `admin.sections` | None | Not applicable | Composed surface |
|
||||
| Audit | No direct route; `admin.sections` | None | Not applicable | Composed surface |
|
||||
| Calendar | `/calendar` | None | `/calendar` nav exists | Metadata gap |
|
||||
| Campaign | Five routes | None | Four top-level nav items exist | Metadata gap; wildcard resource route is also undescribed |
|
||||
| Dashboard | `/dashboard` | `/dashboard` | Aligned | Described |
|
||||
| Docs | `/docs` | `/docs` | Aligned | Described |
|
||||
| Files | `/files` | None | `/files` nav exists | Metadata gap |
|
||||
| IDM | `/idm` | `/idm` | Aligned | Described |
|
||||
| Mail | `/mail` | None | `/mail` nav exists | Metadata gap |
|
||||
| Notifications | `/notifications` | No frontend metadata | No nav item | Metadata and discovery gap |
|
||||
| Ops | `/ops` | `/ops` | Aligned | Described |
|
||||
| Organizations | `/organizations` | `/organizations` | Aligned | Described |
|
||||
| Policy | No direct route; `admin.sections` | None | Not applicable | Composed surface |
|
||||
| Scheduling | `/scheduling` | None | `/scheduling` nav exists | Metadata gap |
|
||||
|
||||
Before a release claims a complete configured-system route inventory, add a
|
||||
contract check or explicit exceptions so executable routes and manifest
|
||||
metadata cannot silently diverge.
|
||||
|
||||
## Composed Surfaces And Extension Points
|
||||
|
||||
These surfaces are active only when the host and contributing modules are
|
||||
enabled and the actor passes the declared filters.
|
||||
|
||||
| Host surface | Contributor and evidence | Contributed regions/actions | Pattern implication | Audit |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `/admin` | Access host (`AdminPage`) | System tenants/users/roles, tenant users/groups/roles/API keys/settings, function-role mappings, user/group mail and file connector scopes | One stable admin information architecture must contain both host-owned and contributed sections | Unreviewed; P1 Core #225 |
|
||||
| `/admin` | `govoplan-admin` `admin.sections` | Overview; system settings; configuration changes; configuration packages; role/group templates; module management | Configuration, guided operations, review/preflight, consequence | In progress under Core #225; surface-level evidence still needed |
|
||||
| `/admin` | `govoplan-audit` `admin.sections` | System audit; tenant audit | Evidence/provenance and reporting | Unreviewed |
|
||||
| `/admin` | `govoplan-files` `admin.sections` and `files.connectors` | System and tenant file connections plus scoped connector managers used by Access | Adaptive configuration, discovery/test, policy and credentials | First migration family in Core #225; verification incomplete in this inventory |
|
||||
| `/admin` | `govoplan-organizations` `admin.sections` | Tenant organization settings | Configuration/list-detail | Unreviewed |
|
||||
| `/admin` | `govoplan-policy` `admin.sections` | System, tenant, group, and user retention | Effective value, source/provenance, consequential configuration | Unreviewed; Core #225 phase 4 |
|
||||
| `/admin` and `/settings` | `govoplan-mail` `mail.profiles` | System/tenant/group/user mail profile and policy managers | Same server/credential/policy grammar as file connectors | Unreviewed; Core #225 mail migration |
|
||||
| `/settings` | Core host | Profile; interface; workspace; local connection | Personal configuration with adaptive forms and immediate feedback | Unreviewed |
|
||||
| `/settings` | Files and Mail named capabilities | User-scoped file connections and mail profiles/policy | Optional integration regions disappear cleanly when capability absent | Unreviewed |
|
||||
| `/settings` | `govoplan-notifications` `settings.sections` | Notification preferences | Personal configuration | Unreviewed |
|
||||
| `/dashboard` | Dashboard host and `dashboard.widgets` | Installed-modules widget; Ops health widget when Ops contributes it | Widget ordering, staleness, permissions, destination behavior | Unreviewed |
|
||||
| `/organizations` | IDM `organizations.functionActions` | Action leading to assignment view filtered by IDM scopes | Cross-module context action through explicit capability | Unreviewed |
|
||||
| Campaign attachments/import | Files `files.fileExplorer` | Folder tree, managed chooser, file listing/pattern resolution/sharing | Optional domain composition without sibling-private imports | Pilot audit under Campaign #74 |
|
||||
| Campaign review/send | Mail runtime `mail.devMailbox` | Mock-mail verification when backend advertises runtime capability | Optional review stage with unavailable/optional states | Pilot audit under Campaign #63/#62 |
|
||||
|
||||
Other named capability exports (`files.connectors`, `organizations.functionPicker`,
|
||||
and mail profile validation) are contracts consumed inside the composed surfaces
|
||||
above; they are not independent routes.
|
||||
|
||||
## Campaign Pilot Surface Map
|
||||
|
||||
Campaign is detailed first because it exercises almost every archetype. The
|
||||
tracked baseline still contains a dedicated `recipient-data` section. The dirty
|
||||
local WIP redirects that path into `recipients` and removes it from the sidebar;
|
||||
do not mark that consolidation delivered until
|
||||
[Campaign #67](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/67)
|
||||
is integrated or the issue state is corrected.
|
||||
|
||||
Campaign already consumes core primitives including `ModuleSubnav`, `Card`,
|
||||
`PageTitle`, `Button`, `LoadingFrame`, `DismissibleAlert`, `FormField`,
|
||||
`StatusBadge`, `MetricCard`, `Dialog`, `ConfirmDialog`, `FileDropZone`,
|
||||
`MessageDisplayPanel`, policy components, access/module capabilities, and
|
||||
unsaved-navigation guards. Reuse alone does not prove that the composition or
|
||||
states satisfy the pattern.
|
||||
|
||||
| Surface / code evidence | Primary task | Target pattern | Material consequence/state | Known issue / rollout |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Campaign list (`CampaignListPage`) | Find, compare, create, open | List-detail entry | Campaign lifecycle/status and creation | Audit in [#74](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/74); guided entry [#35](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/35) |
|
||||
| Overview (`CampaignOverviewPage`) | Understand/edit campaign identity, version, access, lifecycle | Object overview plus adaptive edit | Lock/archive/delete/access changes need real consequence and reversibility wording | #74; integrate/reconcile #67 before migration claims |
|
||||
| Fields (`CampaignFieldsPage`) | Define recipient/template field schema | Structured editor | Schema changes can invalidate recipient/template data | #74 audit |
|
||||
| Attachments/files (`AttachmentsDataPage`, `AttachmentRulesOverlay`) | Select sources and attachment/ZIP rules | Directory chooser plus adaptive rule editor | Missing or mismatched files affect built messages | #74; attachment-detail [#59](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/59) |
|
||||
| Recipients (`RecipientDataPage`) | Select/import/map/edit recipients and per-recipient values/files | Import/mapping plus list-detail editor | Personal data, validation, bulk activation, file links | #74; guided entry #35 |
|
||||
| Recipient data (`RecipientDetailsPage` in tracked baseline) | Inspect/edit a dedicated recipient-data view | List-detail editor | Personal data and send eligibility | Local WIP removes this separate surface; #67 integration state must decide baseline |
|
||||
| Template (`TemplateDataPage`, placeholder/expression dialogs) | Author subject/body and preview substitutions | Adaptive editor plus stable preview | Generated communication content and unresolved expressions | #74; stable overlay [#73](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/73) |
|
||||
| Mail settings (`MailSettingsPage` settings view) | Select/configure campaign mail transport | Adaptive configuration | Credentials, SMTP/IMAP destinations, test outcomes | #74; align with Core #225 mail pattern |
|
||||
| Campaign settings (`GlobalSettingsPage` settings view) | Configure campaign behavior | Adaptive configuration | Can alter validation/build/send behavior | #74 audit |
|
||||
| Mail policy (`MailSettingsPage` policy view) | Inspect/override effective mail policy | Effective policy/provenance editor | Inheritance and locks affect allowed delivery | #74; Core #225 policy pattern |
|
||||
| Campaign policy (`GlobalSettingsPage` policy view) | Inspect/override campaign policy | Effective policy/provenance editor | Inheritance, actor authority, and blocked edits | #74; Core #225 policy pattern |
|
||||
| Review/send (`ReviewSendPage`) | Validate, build, mock-test, confirm/send, inspect results | Guided review/decision plus durable progress | External communication, partial effects, retries, evidence | Intervention vocabulary [#63](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/63); sync/async progress [#62](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/62) |
|
||||
| Message and attachment detail overlays | Inspect one built/mock message and its attachment links | Stable detail/review dialog | Personal data, exact outbound content, reviewed state | Implement/verify [#59](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/59) and [#73](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/73) together |
|
||||
| Campaign report (`CampaignReportPage`) | Filter and inspect delivery outcomes | Reporting/list-detail | Partial, failed, skipped, SMTP/IMAP outcomes and retries | Filtering [#65](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/65), dependent on [Core #263](https://git.add-ideas.de/add-ideas/govoplan-core/issues/263) |
|
||||
| Audit (`CampaignAuditPage`) | Inspect campaign evidence/history | Provenance timeline/report | Actor/action/effect trace | #74 audit |
|
||||
| JSON (`CampaignJsonView`) | Inspect expert representation | Advanced diagnostics/reference | Raw data may contain personal/configuration values; not a primary editor | #74 privacy/redaction audit |
|
||||
| Create wizard (`CreateWizard`) | Seed a campaign through basics, sender, fields, recipients, template, attachments, review, send | Guided setup | Current steps mix creation and later consequential delivery; completion semantics need audit | Guided first campaign [#35](https://git.add-ideas.de/add-ideas/govoplan-campaign/issues/35) |
|
||||
| Review/send wizard routes | Alternate guided review/send shells | Guided review | Tracked routes exist; implementation relationship to `ReviewSendPage` must be established, not guessed | #74 inventory decision |
|
||||
| Operator queue (`OperatorQueuePage`) | Monitor jobs and intervene | Monitoring/work queue | Retry/pause/reconcile and system actor/effect evidence | #74, then #62 vocabulary |
|
||||
| Top-level reports placeholder | Enter cross-campaign reports | Reporting | Component explicitly says functionality is prepared for later passes | Keep marked incomplete; do not infer parity with per-campaign report |
|
||||
| Templates route (`TemplatesPage`) | Browse template records | Directory/list-detail | Template availability and later generated outputs | #74 audit; verify missing route guard intent |
|
||||
|
||||
The five review stages currently named in code are `Validate and inspect`,
|
||||
`Build and review`, `Mock send and verify`, `Confirm and send`, and `Delivery
|
||||
results`. Campaign #63 owns the intervention and status vocabulary; Workflow is
|
||||
not required to define or implement it.
|
||||
|
||||
## Repositories Without A WebUI Route Contribution
|
||||
|
||||
The following local repositories contain a backend manifest but no
|
||||
`webui/src/module.ts` at this snapshot:
|
||||
|
||||
`govoplan-approvals`, `govoplan-assets`, `govoplan-booking`,
|
||||
`govoplan-certificates`, `govoplan-committee`, `govoplan-consultation`,
|
||||
`govoplan-contracts`, `govoplan-dist-lists`, `govoplan-evaluation`,
|
||||
`govoplan-facilities`, `govoplan-forms-runtime`, `govoplan-grants`,
|
||||
`govoplan-helpdesk`, `govoplan-identity`, `govoplan-inspections`,
|
||||
`govoplan-issue-reporting`, `govoplan-learning`, `govoplan-permits`,
|
||||
`govoplan-poll`, `govoplan-procurement`, `govoplan-records`,
|
||||
`govoplan-resources`, `govoplan-rest`, `govoplan-risk-compliance`,
|
||||
`govoplan-soap`, `govoplan-tenancy`, and `govoplan-transparency`.
|
||||
|
||||
This is only negative route evidence. It does not classify the backend module's
|
||||
maturity or decide that it needs a WebUI. Connector-only, capability-only, or
|
||||
backend-only modules may remain intentionally headless.
|
||||
|
||||
## Rollout Matrix
|
||||
|
||||
| Order | Scope | Current evidence | Target | Owner / issue | Verification gate | Status |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| 0 | Product grammar and route inventory | Doctrine, ledger, layout rules, module contract, current route sources | One reconciled pattern language and evidence inventory | Meta [#11](https://git.add-ideas.de/add-ideas/govoplan/issues/11) | Docs links/diff checks; issue/wiki sync after integration | Initial slice in this document |
|
||||
| 1 | Campaign baseline integration | Closed work and local WIP can differ from tracked baseline | Integrated, testable baseline before migration claims | Campaign #67 and tracker cleanup | Clean scoped diff, behavior tests, build, issue evidence | Must precede claiming Campaign migration complete |
|
||||
| 2 | Campaign previews/details | Existing message/attachment overlays and known overflow/geometry issues | Stable header/body/footer, accessible long-content detail | Campaign #59 and #73 | Keyboard/focus/scroll behavior, long content, responsive and translated text | P1 ready |
|
||||
| 3 | Campaign review/interventions | Five domain-owned stages with unresolved intervention language | Clear stages, outcomes, blockers, next actor/action, reviewed evidence | Campaign #63 | State matrix behavior/accessibility tests and agreed vocabulary | P1 needs product wording decision |
|
||||
| 4 | Campaign send/progress | Synchronous/asynchronous behavior is not explicit enough | Pre-send mode/consequence plus durable leave/return progress, retry and reconciliation | Campaign #62 | Sync and async behavior, partial/failure/retry, reload/return tests | P1 ready after stage vocabulary |
|
||||
| 5 | Campaign report filtering | Duplicate/inconsistent filter models are reported | One shared status/list/filter/count model | Campaign #65 and Core #263 | Query/filter behavior, keyboard, counts, large result set | P1 blocked on shared DataGrid direction |
|
||||
| 6 | Guided first campaign | Existing wizard routes and ordinary workspace overlap | Task-oriented entry that hands off clearly to normal editing/review | Campaign #35 | First-run flow, resume/back, validation, optional modules, no implicit send | P1 after core pilot patterns stabilize |
|
||||
| 7 | Prove/extract generic primitives | Core already exports many primitives; Campaign composition still unreviewed | Extract only contracts with a second consumer or clear platform ownership | Core #225 plus bounded follow-ups | Core behavior/accessibility tests and module-permutation tests | After Campaign proof |
|
||||
| 8 | Configured-system pattern help | Docs route and classification exist | Role/config-aware pattern and route/field/blocker help | Docs #15 | Topic grouping, audience filtering, stable links/anchors | P1 after initial pattern IDs stabilize |
|
||||
| 9 | Admin/configuration family | Phase inventory and connector primitives exist in the ledger | Apply the pattern to files, mail, policy, retention, packages, modules, API keys, settings | Core #225 and module children | Per-surface state/accessibility/consequence evidence | Parallel where independent of Campaign shared decisions |
|
||||
| 10 | Remaining direct routes | Routes are contributed; most are unreviewed | Per-module bounded audit and migration plan | New module issues derived from this inventory | Applicable definition-of-done gates | P2 after Campaign, not a bulk rewrite |
|
||||
| 11 | Manifest/runtime alignment | Several executable routes are absent from manifest metadata | Declared alignment or explicit validated exception | Core contract issue to create | Automated manifest/module route check and configured Docs verification | Discovery follow-up |
|
||||
|
||||
Workflow/user-story implementation is postponed. It is not on the critical path
|
||||
for rows 0 through 10. Focused views can be specified, manually selected, and
|
||||
tested through core composition contracts; a later workflow step may become one
|
||||
activation source without changing the proven surface patterns.
|
||||
|
||||
## Inventory Maintenance
|
||||
|
||||
When a route, nav item, named UI capability, host section, or Campaign workspace
|
||||
surface changes:
|
||||
|
||||
1. Update the owner, evidence, task, archetype, and consequence here.
|
||||
2. Link the implementation issue and verification evidence.
|
||||
3. Keep "unreviewed" until state, permission/privacy, consequence/provenance,
|
||||
accessibility, responsive, theme, i18n, and applicable async behavior have
|
||||
been checked.
|
||||
4. Re-scan both `module.ts` and the backend manifest; do not infer one from the
|
||||
other.
|
||||
5. Recreate the inventory from a clean release lockfile before using it as
|
||||
release evidence.
|
||||
968
docs/capability-fit-current.json
Normal file
968
docs/capability-fit-current.json
Normal file
@@ -0,0 +1,968 @@
|
||||
{
|
||||
"$schema": "./capability-fit.schema.json",
|
||||
"schema_version": "0.1.0",
|
||||
"assessment_id": "campaign-reference-2026-07-20",
|
||||
"assessed_at": "2026-07-20",
|
||||
"scope": {
|
||||
"title": "Campaign-centric internal pilot and small-production candidate",
|
||||
"reference_journeys": [
|
||||
"Internal operator authors, validates, builds, queues, sends and reconciles an email Campaign with managed attachments",
|
||||
"Operator inspects delivery and audit evidence"
|
||||
],
|
||||
"postponed": [
|
||||
"Workflow and workflow-driven user stories"
|
||||
]
|
||||
},
|
||||
"release": {
|
||||
"kind": "workspace_snapshot",
|
||||
"ref": "workspace-2026-07-20",
|
||||
"meta_commit": "05ae81d64195",
|
||||
"reproducible": false,
|
||||
"configuration_packages": [],
|
||||
"notes": [
|
||||
"The snapshot is untagged.",
|
||||
"Dirty repositories are recorded and local-only work is not treated as release-integrated."
|
||||
]
|
||||
},
|
||||
"composition": [
|
||||
{
|
||||
"module_id": "core",
|
||||
"repository": "govoplan-core",
|
||||
"commit": "e6f7c45f0a95",
|
||||
"manifest_version": "server-0.3.0",
|
||||
"enabled": true,
|
||||
"dirty": true,
|
||||
"role": "API, registry, migrations, sessions, kernel contracts and shared WebUI"
|
||||
},
|
||||
{
|
||||
"module_id": "tenancy",
|
||||
"repository": "govoplan-tenancy",
|
||||
"commit": "1dde03854733",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": false,
|
||||
"role": "Tenant context and lifecycle"
|
||||
},
|
||||
{
|
||||
"module_id": "organizations",
|
||||
"repository": "govoplan-organizations",
|
||||
"commit": "45cda1a33f18",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": false,
|
||||
"role": "Organization model"
|
||||
},
|
||||
{
|
||||
"module_id": "identity",
|
||||
"repository": "govoplan-identity",
|
||||
"commit": "7a1710af896f",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": true,
|
||||
"role": "Normalized internal identity directory"
|
||||
},
|
||||
{
|
||||
"module_id": "access",
|
||||
"repository": "govoplan-access",
|
||||
"commit": "ab07075a679b",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": true,
|
||||
"role": "Local authentication, sessions, API keys and RBAC"
|
||||
},
|
||||
{
|
||||
"module_id": "admin",
|
||||
"repository": "govoplan-admin",
|
||||
"commit": "c9e1fb287f50",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": false,
|
||||
"role": "Administration surfaces"
|
||||
},
|
||||
{
|
||||
"module_id": "dashboard",
|
||||
"repository": "govoplan-dashboard",
|
||||
"commit": "a315a7c62b1d",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": false,
|
||||
"role": "Module-aware home surface"
|
||||
},
|
||||
{
|
||||
"module_id": "policy",
|
||||
"repository": "govoplan-policy",
|
||||
"commit": "2511fbb5a864",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": false,
|
||||
"role": "Policy explanation and configuration boundary"
|
||||
},
|
||||
{
|
||||
"module_id": "audit",
|
||||
"repository": "govoplan-audit",
|
||||
"commit": "5e4f84a789ea",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": false,
|
||||
"role": "Database audit records and retrying audit outbox"
|
||||
},
|
||||
{
|
||||
"module_id": "campaigns",
|
||||
"repository": "govoplan-campaign",
|
||||
"commit": "2e593b7fa412",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": true,
|
||||
"role": "Campaign authoring, build, delivery control and reporting"
|
||||
},
|
||||
{
|
||||
"module_id": "files",
|
||||
"repository": "govoplan-files",
|
||||
"commit": "f3210234d35a",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": true,
|
||||
"role": "Managed files and Campaign attachments"
|
||||
},
|
||||
{
|
||||
"module_id": "mail",
|
||||
"repository": "govoplan-mail",
|
||||
"commit": "b0337b2d261a",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": true,
|
||||
"role": "SMTP and IMAP profiles and transports"
|
||||
},
|
||||
{
|
||||
"module_id": "calendar",
|
||||
"repository": "govoplan-calendar",
|
||||
"commit": "371a00aff51c",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": true,
|
||||
"role": "Optional calendar outside the Campaign pilot minimum"
|
||||
},
|
||||
{
|
||||
"module_id": "docs",
|
||||
"repository": "govoplan-docs",
|
||||
"commit": "f2ade1d62475",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": true,
|
||||
"role": "Configured-system documentation"
|
||||
},
|
||||
{
|
||||
"module_id": "ops",
|
||||
"repository": "govoplan-ops",
|
||||
"commit": "341773a4ff8a",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": true,
|
||||
"dirty": false,
|
||||
"role": "Readiness and deployment-profile visibility"
|
||||
},
|
||||
{
|
||||
"module_id": "addresses",
|
||||
"repository": "govoplan-addresses",
|
||||
"commit": "f19350e65d76",
|
||||
"manifest_version": "0.1.8",
|
||||
"enabled": false,
|
||||
"dirty": true,
|
||||
"role": "Optional reusable recipient sources and CardDAV"
|
||||
}
|
||||
],
|
||||
"deployment_profile": {
|
||||
"id": "production-like-dev",
|
||||
"status": "partial",
|
||||
"description": "PostgreSQL and Redis run in containers while API, WebUI, worker and scheduler run from editable source trees.",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "configuration",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan/dev/production-like/docker-compose.yml"
|
||||
},
|
||||
{
|
||||
"kind": "documentation",
|
||||
"scope": "documented_model",
|
||||
"locator": "govoplan/dev/production-like/README.md"
|
||||
}
|
||||
]
|
||||
},
|
||||
"questionnaire": {
|
||||
"scope_outcomes": [
|
||||
{
|
||||
"id": "outcome.reference_journey",
|
||||
"question": "Which journey is assessed?",
|
||||
"state": "answered",
|
||||
"answer": "An internal operator authors, validates, builds, queues, sends and reconciles a Campaign with managed attachments.",
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"id": "outcome.workflow",
|
||||
"question": "Is Workflow in scope?",
|
||||
"state": "answered",
|
||||
"answer": "No; Workflow is planned and explicitly postponed.",
|
||||
"evidence": []
|
||||
}
|
||||
],
|
||||
"data_policy": [
|
||||
{
|
||||
"id": "data.classification",
|
||||
"question": "Which data classes and legal bases apply?",
|
||||
"state": "not_assessed",
|
||||
"answer": null,
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"id": "data.retention",
|
||||
"question": "What retention, deletion, archive and legal-hold rules apply?",
|
||||
"state": "not_assessed",
|
||||
"answer": null,
|
||||
"evidence": []
|
||||
}
|
||||
],
|
||||
"identity_integrations": [
|
||||
{
|
||||
"id": "identity.pilot",
|
||||
"question": "May the pilot use local GovOPlaN accounts?",
|
||||
"state": "assumed",
|
||||
"answer": "Yes; federation is outside the verified composition.",
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"id": "integration.mail",
|
||||
"question": "Which target SMTP/IMAP service and policy apply?",
|
||||
"state": "not_assessed",
|
||||
"answer": null,
|
||||
"evidence": []
|
||||
}
|
||||
],
|
||||
"workload_growth": [
|
||||
{
|
||||
"id": "workload.campaign",
|
||||
"question": "What are Campaign frequency, recipients per Campaign, send window, import size and attachment volume?",
|
||||
"state": "not_assessed",
|
||||
"answer": null,
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"id": "workload.platform",
|
||||
"question": "What are tenant, user, concurrency, file, database, queue and audit growth assumptions?",
|
||||
"state": "not_assessed",
|
||||
"answer": null,
|
||||
"evidence": []
|
||||
}
|
||||
],
|
||||
"availability_operations": [
|
||||
{
|
||||
"id": "availability.rto_rpo",
|
||||
"question": "What availability, RPO and RTO are required?",
|
||||
"state": "not_assessed",
|
||||
"answer": null,
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"id": "operations.ownership",
|
||||
"question": "Who operates database, queue, storage, TLS, secrets, monitoring, backup and incident response?",
|
||||
"state": "not_assessed",
|
||||
"answer": null,
|
||||
"evidence": []
|
||||
}
|
||||
],
|
||||
"procurement_decisions": [
|
||||
{
|
||||
"id": "procurement.constraints",
|
||||
"question": "Which licensing, accessibility, security, certification, support and procurement conditions are mandatory?",
|
||||
"state": "not_assessed",
|
||||
"answer": null,
|
||||
"evidence": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"capabilities": [
|
||||
{
|
||||
"id": "platform.composition",
|
||||
"requirement": "Compose enabled backend and WebUI modules without hard optional-module dependencies.",
|
||||
"status": "verified",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan-core/tests/test_module_system.py"
|
||||
},
|
||||
{
|
||||
"kind": "contract",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan/tools/checks/check-contracts.py",
|
||||
"note": "43 contracts, 29 providers, no issues"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Repeat checks on a clean pinned release candidate."
|
||||
],
|
||||
"gaps": [
|
||||
"The current snapshot is dirty and untagged."
|
||||
],
|
||||
"risks": [
|
||||
"A working module graph can still be unreproducible."
|
||||
],
|
||||
"recommendation": "Use the minimal Campaign composition and pin all artifacts before promotion.",
|
||||
"proof_check": "Run contract, migration, API and WebUI module-permutation gates on the release candidate."
|
||||
},
|
||||
{
|
||||
"id": "access.local",
|
||||
"requirement": "Provide tenant-scoped local accounts, sessions, API keys and RBAC.",
|
||||
"status": "verified",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan-access/tests/test_auth_dependencies.py"
|
||||
},
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan-core/tests/test_api_smoke.py#cookie-session-csrf"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Pilot accepts local accounts."
|
||||
],
|
||||
"gaps": [
|
||||
"MFA and federated lifecycle are not part of this conclusion."
|
||||
],
|
||||
"risks": [
|
||||
"Manual account lifecycle may not satisfy production identity policy."
|
||||
],
|
||||
"recommendation": "Use controlled local pilot accounts and define break-glass/bootstrap rules.",
|
||||
"proof_check": "Exercise joiner, role change, suspension and protected-owner recovery."
|
||||
},
|
||||
{
|
||||
"id": "campaign.journey",
|
||||
"requirement": "Author, validate, build, queue, send, reconcile and report a Campaign with frozen execution evidence.",
|
||||
"status": "verified",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan-core/tests/test_api_smoke.py#campaign-create-validate-build-mock-send"
|
||||
},
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan-campaign/tests",
|
||||
"note": "14 tests passed"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"This verifies implementation paths, not target-provider delivery."
|
||||
],
|
||||
"gaps": [
|
||||
"Substantial Campaign UI/code WIP is not release-integrated."
|
||||
],
|
||||
"risks": [
|
||||
"Local WIP can make the checkout look more complete than the release baseline."
|
||||
],
|
||||
"recommendation": "Integrate and retest Campaign work before usability or production acceptance.",
|
||||
"proof_check": "Run the complete journey with safe data and the target-like mail service."
|
||||
},
|
||||
{
|
||||
"id": "files.managed_attachments",
|
||||
"requirement": "Store and resolve managed Campaign attachments on durable storage.",
|
||||
"status": "verified",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan-files/tests",
|
||||
"note": "14 tests passed"
|
||||
},
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan-campaign/tests/test_attachment_building.py"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Deployment provides a durable storage root."
|
||||
],
|
||||
"gaps": [
|
||||
"Target backup and restore are not verified."
|
||||
],
|
||||
"risks": [
|
||||
"Node-local storage prevents safe independent API scaling."
|
||||
],
|
||||
"recommendation": "Use durable local storage for the pilot and assess object/shared storage before scaling.",
|
||||
"proof_check": "Back up and restore files together with database references."
|
||||
},
|
||||
{
|
||||
"id": "mail.smtp_imap",
|
||||
"requirement": "Send Campaign mail through SMTP and optionally append sent messages through IMAP.",
|
||||
"status": "available_unconfigured",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan-mail/tests",
|
||||
"note": "22 tests passed"
|
||||
},
|
||||
{
|
||||
"kind": "documentation",
|
||||
"scope": "documented_model",
|
||||
"locator": "govoplan-campaign/docs/CAMPAIGN_DELIVERY_RUNBOOK.md"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Use a dedicated non-production service account and safe recipients."
|
||||
],
|
||||
"gaps": [
|
||||
"No target provider, TLS chain, throttling or bounce/reply process was exercised."
|
||||
],
|
||||
"risks": [
|
||||
"Ambiguous provider outcomes can cause duplicate-send risk if reconciled incorrectly."
|
||||
],
|
||||
"recommendation": "Run target-like interoperability and failure drills before production use.",
|
||||
"proof_check": "Prove SMTP acceptance, IMAP append, throttling and outcome reconciliation."
|
||||
},
|
||||
{
|
||||
"id": "addresses.recipient_sources",
|
||||
"requirement": "Select reusable address lists as Campaign recipient sources.",
|
||||
"status": "available_unconfigured",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan-addresses/tests",
|
||||
"note": "14 tests passed"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Enable the Addresses module explicitly."
|
||||
],
|
||||
"gaps": [
|
||||
"Addresses is disabled in the pinned root profile."
|
||||
],
|
||||
"risks": [
|
||||
"Recipient governance may differ between source data and frozen Campaign evidence."
|
||||
],
|
||||
"recommendation": "Enable only when reusable lists are a pilot requirement.",
|
||||
"proof_check": "Build a Campaign from a source list and verify immutable recipient provenance."
|
||||
},
|
||||
{
|
||||
"id": "audit.local",
|
||||
"requirement": "Retain tenant/system audit evidence and retry governed audit events.",
|
||||
"status": "verified",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan-audit/tests",
|
||||
"note": "5 tests passed"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Conclusion covers local database evidence only."
|
||||
],
|
||||
"gaps": [
|
||||
"No central sink, retention enforcement or tamper-evident archive is verified."
|
||||
],
|
||||
"risks": [
|
||||
"Local audit evidence may not satisfy organizational records or SIEM requirements."
|
||||
],
|
||||
"recommendation": "Define retention and export requirements before production approval.",
|
||||
"proof_check": "Exercise privileged-event review, retention and any required external export."
|
||||
},
|
||||
{
|
||||
"id": "identity.federation",
|
||||
"requirement": "Integrate external LDAP/AD, OIDC/SAML or SCIM identity infrastructure.",
|
||||
"status": "scaffold",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "documentation",
|
||||
"scope": "documented_model",
|
||||
"locator": "govoplan-idm/README.md"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"gaps": [
|
||||
"No end-to-end provider connector or federated login is verified."
|
||||
],
|
||||
"risks": [
|
||||
"Federation-dependent organizations cannot use the current pilot composition without extra implementation."
|
||||
],
|
||||
"recommendation": "Use local pilot accounts or assess and implement the selected provider path.",
|
||||
"proof_check": "Run provider metadata, login/provisioning, deprovisioning and failure tests."
|
||||
},
|
||||
{
|
||||
"id": "compliance.export_control",
|
||||
"requirement": "Screen persons and organizations against embargo/sanctions lists with review evidence.",
|
||||
"status": "planned",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "issue",
|
||||
"scope": "documented_model",
|
||||
"locator": "https://git.add-ideas.de/add-ideas/govoplan/issues/12"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"gaps": [
|
||||
"No provider, list provenance, match policy, review flow or legal evidence exists."
|
||||
],
|
||||
"risks": [
|
||||
"The current composition must not be represented as performing export-control screening."
|
||||
],
|
||||
"recommendation": "Keep outside pilot claims until the user story is implemented and legally validated.",
|
||||
"proof_check": "Validate list ingestion, versioning, matching, false-positive review and audit evidence."
|
||||
},
|
||||
{
|
||||
"id": "workflow",
|
||||
"requirement": "Orchestrate the journey through Workflow.",
|
||||
"status": "planned",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "observation",
|
||||
"scope": "documented_model",
|
||||
"locator": "Assessment scope",
|
||||
"note": "Explicitly postponed"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"gaps": [
|
||||
"Workflow is outside this assessment."
|
||||
],
|
||||
"risks": [
|
||||
"Including it would overstate the assessed composition."
|
||||
],
|
||||
"recommendation": "Do not enable or claim Workflow for this reference pilot.",
|
||||
"proof_check": "Reassess in a later Workflow-focused composition."
|
||||
}
|
||||
],
|
||||
"infrastructure": [
|
||||
{
|
||||
"id": "runtime.web_api",
|
||||
"requirement": "Serve matching WebUI and API artifacts with health endpoints.",
|
||||
"status": "verified",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan-core/tests/test_module_system.py"
|
||||
},
|
||||
{
|
||||
"kind": "route",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan-core/src/govoplan_core/server/fastapi.py#/health"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Build immutable matching artifacts for promotion."
|
||||
],
|
||||
"gaps": [
|
||||
"No production image or service bundle is supplied by the profile."
|
||||
],
|
||||
"risks": [
|
||||
"Editable source processes are unsuitable as a production artifact."
|
||||
],
|
||||
"recommendation": "Package and supervise WebUI/API from one release candidate.",
|
||||
"proof_check": "Deploy the built artifacts and run health/module-route checks."
|
||||
},
|
||||
{
|
||||
"id": "runtime.worker",
|
||||
"requirement": "Run durable asynchronous Campaign jobs.",
|
||||
"status": "available_unconfigured",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "configuration",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan/tools/launch/launch-production-like-dev.sh"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Redis and a supervised worker are required when Celery is enabled."
|
||||
],
|
||||
"gaps": [
|
||||
"Target heartbeat, restart and queue-age alerting are not proved."
|
||||
],
|
||||
"risks": [
|
||||
"Queued work can stall silently without monitoring."
|
||||
],
|
||||
"recommendation": "Start one worker for the pilot and split queues only after measurement.",
|
||||
"proof_check": "Interrupt and restart a worker while preserving job/reconciliation safety."
|
||||
},
|
||||
{
|
||||
"id": "runtime.scheduler",
|
||||
"requirement": "Run periodic recovery and cleanup safely.",
|
||||
"status": "partial",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan-core/tests/test_calendar_outbox_worker.py"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Relevant Calendar work is local WIP."
|
||||
],
|
||||
"gaps": [
|
||||
"No distributed leader election or target supervision is established."
|
||||
],
|
||||
"risks": [
|
||||
"Multiple schedulers can duplicate periodic dispatch without locking."
|
||||
],
|
||||
"recommendation": "Omit from the Campaign-only pilot or run one supervised instance.",
|
||||
"proof_check": "Prove missed-schedule recovery and single-leader behavior."
|
||||
},
|
||||
{
|
||||
"id": "data.postgresql",
|
||||
"requirement": "Persist application state in PostgreSQL with explicit migrations.",
|
||||
"status": "verified",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "configuration",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan/dev/postgres"
|
||||
},
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan/tools/checks/postgres-integration-check.py"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Target database remains deployment-owned."
|
||||
],
|
||||
"gaps": [
|
||||
"HA, patching, WAL policy and capacity are not assessed."
|
||||
],
|
||||
"risks": [
|
||||
"A single unprotected database is a system-wide failure point."
|
||||
],
|
||||
"recommendation": "Use managed or dedicated PostgreSQL with explicit migration and backup controls.",
|
||||
"proof_check": "Run migrations and restore a target-like database."
|
||||
},
|
||||
{
|
||||
"id": "queue.redis",
|
||||
"requirement": "Provide the Celery broker and queue persistence.",
|
||||
"status": "available_unconfigured",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "configuration",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan/dev/production-like/docker-compose.yml#redis"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"gaps": [
|
||||
"Authentication, TLS, eviction, HA and queue-loss policy are not assessed."
|
||||
],
|
||||
"risks": [
|
||||
"Broker loss or eviction can delay work even when database business state survives."
|
||||
],
|
||||
"recommendation": "Configure private persistent Redis and monitor queue age/depth.",
|
||||
"proof_check": "Exercise broker interruption and worker recovery."
|
||||
},
|
||||
{
|
||||
"id": "storage.local",
|
||||
"requirement": "Persist managed files on a durable single-node/shared path.",
|
||||
"status": "verified",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "contract",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan-files/src/govoplan_files/backend/storage/backends.py"
|
||||
}
|
||||
],
|
||||
"conditions": [
|
||||
"Path is durable, private, writable and backed up."
|
||||
],
|
||||
"gaps": [
|
||||
"Node-local storage cannot support independent API replicas."
|
||||
],
|
||||
"risks": [
|
||||
"Files can be lost or become inconsistent with database state."
|
||||
],
|
||||
"recommendation": "Use for a bounded pilot only with coordinated backup.",
|
||||
"proof_check": "Restore files and verify all database references."
|
||||
},
|
||||
{
|
||||
"id": "storage.object",
|
||||
"requirement": "Use S3-compatible storage for independently scalable file persistence.",
|
||||
"status": "partial",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "test",
|
||||
"scope": "current_workspace",
|
||||
"locator": "govoplan-files/tests/test_connector_providers.py"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"gaps": [
|
||||
"No chosen target service or storage-backend interoperability drill."
|
||||
],
|
||||
"risks": [
|
||||
"Provider semantics, CA or lifecycle mismatch can break file access/retention."
|
||||
],
|
||||
"recommendation": "Select and exercise the target object store before horizontal scaling.",
|
||||
"proof_check": "Upload, retrieve, version, back up and restore representative objects."
|
||||
},
|
||||
{
|
||||
"id": "edge.proxy_tls",
|
||||
"requirement": "Terminate HTTPS and enforce proxy/security policy.",
|
||||
"status": "external_system",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "route",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan-ops/src/govoplan_ops/backend/api/v1/routes.py#deployment-security"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"gaps": [
|
||||
"No proxy, certificates, renewal, header or request-limit configuration is shipped here."
|
||||
],
|
||||
"risks": [
|
||||
"Incorrect proxy/cookie/CORS configuration can expose sessions or block legitimate use."
|
||||
],
|
||||
"recommendation": "Supply and monitor the edge through the target platform.",
|
||||
"proof_check": "Run external TLS/header/cookie/CORS and upload-limit tests."
|
||||
},
|
||||
{
|
||||
"id": "security.secret_store",
|
||||
"requirement": "Inject and rotate master, database, mail and connector secrets.",
|
||||
"status": "external_system",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "configuration",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan/.env.example"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"gaps": [
|
||||
"No target secret manager or rotation drill is selected."
|
||||
],
|
||||
"risks": [
|
||||
"Loss of the master key makes encrypted credentials unavailable; leakage compromises connectors."
|
||||
],
|
||||
"recommendation": "Use target-native secret injection and document rotation/recovery.",
|
||||
"proof_check": "Rotate a non-production credential and recover from a protected backup."
|
||||
},
|
||||
{
|
||||
"id": "operations.monitoring",
|
||||
"requirement": "Detect API, database, worker, queue, storage and delivery degradation.",
|
||||
"status": "partial",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "route",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan-ops/src/govoplan_ops/backend/api/v1/routes.py#/ops/readiness"
|
||||
},
|
||||
{
|
||||
"kind": "contract",
|
||||
"scope": "committed_source",
|
||||
"locator": "govoplan-core/src/govoplan_core/server/fastapi.py#slow-request-logging"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"gaps": [
|
||||
"No metrics exporter, log collector, dashboards, alert routes or SLO is verified."
|
||||
],
|
||||
"risks": [
|
||||
"Failures and queue backlog can remain unnoticed."
|
||||
],
|
||||
"recommendation": "Integrate external monitoring before small production.",
|
||||
"proof_check": "Trigger each readiness/delivery failure and verify an actionable alert."
|
||||
},
|
||||
{
|
||||
"id": "operations.backup_restore",
|
||||
"requirement": "Back up and restore database, files, configuration and keys as a coherent service.",
|
||||
"status": "partial",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "documentation",
|
||||
"scope": "documented_model",
|
||||
"locator": "govoplan-core/docs/DEPLOYMENT_OPERATOR_GUIDE.md"
|
||||
},
|
||||
{
|
||||
"kind": "issue",
|
||||
"scope": "documented_model",
|
||||
"locator": "https://git.add-ideas.de/add-ideas/govoplan-core/issues/29"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"gaps": [
|
||||
"No target full-service restore drill or measured RPO/RTO exists."
|
||||
],
|
||||
"risks": [
|
||||
"Partial restore can produce missing files, unusable secrets or inconsistent evidence."
|
||||
],
|
||||
"recommendation": "Treat Core #29 and a target restore drill as a production gate.",
|
||||
"proof_check": "Restore the whole service into an isolated environment and measure it."
|
||||
},
|
||||
{
|
||||
"id": "operations.disaster_recovery",
|
||||
"requirement": "Recover the service after site or dependency loss within agreed RPO/RTO.",
|
||||
"status": "not_assessed",
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "absence",
|
||||
"scope": "current_workspace",
|
||||
"locator": "No target DR plan or exercise evidence supplied"
|
||||
}
|
||||
],
|
||||
"conditions": [],
|
||||
"gaps": [
|
||||
"RPO/RTO, off-site copies, recovery order, failover, communications and exercise schedule are unknown."
|
||||
],
|
||||
"risks": [
|
||||
"Service and evidence may be unrecoverable after a major incident."
|
||||
],
|
||||
"recommendation": "Define and exercise DR before any availability commitment.",
|
||||
"proof_check": "Run a documented end-to-end recovery exercise."
|
||||
}
|
||||
],
|
||||
"data_flows": [
|
||||
{
|
||||
"id": "browser.api",
|
||||
"from": "User browser",
|
||||
"to": "Reverse proxy and GovOPlaN WebUI/API",
|
||||
"data": [
|
||||
"Session and CSRF cookies",
|
||||
"Campaign content",
|
||||
"Recipient personal data",
|
||||
"Managed files"
|
||||
],
|
||||
"trust_boundary": "Client/public to application",
|
||||
"controls": [
|
||||
"HTTPS",
|
||||
"Exact CORS origins",
|
||||
"Secure cookies",
|
||||
"Tenant and RBAC enforcement",
|
||||
"Request limits"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "api.database",
|
||||
"from": "GovOPlaN API and workers",
|
||||
"to": "PostgreSQL",
|
||||
"data": [
|
||||
"Tenant and identity records",
|
||||
"Campaign drafts, snapshots and jobs",
|
||||
"Connector metadata",
|
||||
"Audit evidence"
|
||||
],
|
||||
"trust_boundary": "Application to primary state store",
|
||||
"controls": [
|
||||
"Dedicated database identity",
|
||||
"Private or encrypted transport",
|
||||
"Migrations",
|
||||
"Backup and retention"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "api.queue.worker",
|
||||
"from": "GovOPlaN API",
|
||||
"to": "Redis and Celery worker",
|
||||
"data": [
|
||||
"Job identifiers",
|
||||
"Queue routing and retry metadata"
|
||||
],
|
||||
"trust_boundary": "Request plane to asynchronous processing plane",
|
||||
"controls": [
|
||||
"Private authenticated broker",
|
||||
"Bounded payloads",
|
||||
"Idempotent claims",
|
||||
"Queue monitoring"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "worker.mail",
|
||||
"from": "GovOPlaN Campaign worker",
|
||||
"to": "External SMTP and IMAP services",
|
||||
"data": [
|
||||
"Recipient addresses",
|
||||
"Message bodies",
|
||||
"Attachments",
|
||||
"Sent-message copy"
|
||||
],
|
||||
"trust_boundary": "GovOPlaN to external communication provider",
|
||||
"controls": [
|
||||
"Scoped service account",
|
||||
"TLS and CA policy",
|
||||
"Sender and recipient policy",
|
||||
"Rate limits",
|
||||
"Outcome reconciliation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "worker.connectors",
|
||||
"from": "GovOPlaN connector worker",
|
||||
"to": "External address, file, object or calendar service",
|
||||
"data": [
|
||||
"Addresses",
|
||||
"Files and provenance",
|
||||
"Calendar resources"
|
||||
],
|
||||
"trust_boundary": "GovOPlaN to organizational/external content systems",
|
||||
"controls": [
|
||||
"Explicit sync direction",
|
||||
"Scoped credentials",
|
||||
"Endpoint allow-list",
|
||||
"Provenance",
|
||||
"Conflict and reconciliation policy"
|
||||
]
|
||||
}
|
||||
],
|
||||
"assumptions": [
|
||||
"The pilot can use local accounts and one internal tenant or office.",
|
||||
"A dedicated non-production SMTP/IMAP account and safe recipients are available.",
|
||||
"Pilot load fits one API and one worker until measured otherwise.",
|
||||
"Durable local storage is acceptable for the pilot."
|
||||
],
|
||||
"open_questions": [
|
||||
"What are the target organization's data classes, legal bases, retention and external-disclosure rules?",
|
||||
"Which identity, mail, file, address and monitoring systems are mandatory?",
|
||||
"What are Campaign volume, concurrency, growth, availability, RPO and RTO?",
|
||||
"Who owns each external runtime component and operational control?",
|
||||
"Which accessibility, security, support and procurement constraints are mandatory?"
|
||||
],
|
||||
"risks": [
|
||||
{
|
||||
"id": "risk.reproducibility",
|
||||
"statement": "The dirty, untagged workspace cannot be reproduced as a release.",
|
||||
"impact": "Uncertain deployed behavior and unsafe promotion or rollback.",
|
||||
"treatment": "Integrate scoped work and create a clean pinned release candidate.",
|
||||
"owner": null,
|
||||
"residual_risk": "Module and environment differences still require release-environment verification."
|
||||
},
|
||||
{
|
||||
"id": "risk.delivery_provider",
|
||||
"statement": "Target SMTP/IMAP behavior and failure modes are unproved.",
|
||||
"impact": "Failed, delayed or duplicate communication and incomplete evidence.",
|
||||
"treatment": "Run target-like interoperability, throttling and uncertainty drills.",
|
||||
"owner": null,
|
||||
"residual_risk": "External provider outages and ambiguous outcomes remain operational risks."
|
||||
},
|
||||
{
|
||||
"id": "risk.recovery",
|
||||
"statement": "Backup/restore and disaster recovery are not demonstrated across all state and keys.",
|
||||
"impact": "Irrecoverable or inconsistent service after loss.",
|
||||
"treatment": "Complete Core #29 and an isolated full-service restore/DR exercise.",
|
||||
"owner": null,
|
||||
"residual_risk": "Recovery time and data loss remain bounded by the selected external infrastructure."
|
||||
}
|
||||
],
|
||||
"recommendations": [
|
||||
"Proceed only with a controlled internal Campaign pilot after the bounded proof checks pass.",
|
||||
"Use the minimal composition and enable Addresses only for an explicit reusable-recipient journey.",
|
||||
"Do not claim Workflow, export-control screening, identity federation or production DR as implemented.",
|
||||
"Treat a clean release candidate, target mail proof, monitoring and coherent restore drill as production gates."
|
||||
],
|
||||
"proof_checks": [
|
||||
"Pin and build a clean matching backend/WebUI release candidate and rerun cross-repository gates.",
|
||||
"Run a safe target-like Campaign through SMTP acceptance, IMAP append, reporting and audit.",
|
||||
"Drill worker, Redis and ambiguous-delivery failures without duplicate sends.",
|
||||
"Restore PostgreSQL, managed files, configuration and encrypted credentials and measure RPO/RTO.",
|
||||
"Validate proxy/TLS, cookies/CORS, account bootstrap, secret redaction, monitoring and alert delivery.",
|
||||
"Measure representative Campaign/file/queue/database load and external throttling."
|
||||
]
|
||||
}
|
||||
298
docs/capability-fit.schema.json
Normal file
298
docs/capability-fit.schema.json
Normal file
@@ -0,0 +1,298 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://git.add-ideas.de/add-ideas/govoplan/src/branch/main/docs/capability-fit.schema.json",
|
||||
"title": "GovOPlaN capability and infrastructure fit assessment",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"schema_version",
|
||||
"assessment_id",
|
||||
"assessed_at",
|
||||
"scope",
|
||||
"release",
|
||||
"composition",
|
||||
"deployment_profile",
|
||||
"questionnaire",
|
||||
"capabilities",
|
||||
"infrastructure",
|
||||
"data_flows",
|
||||
"assumptions",
|
||||
"open_questions",
|
||||
"risks",
|
||||
"recommendations",
|
||||
"proof_checks"
|
||||
],
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"type": "string",
|
||||
"format": "uri-reference"
|
||||
},
|
||||
"schema_version": {
|
||||
"const": "0.1.0"
|
||||
},
|
||||
"assessment_id": {
|
||||
"$ref": "#/$defs/non_empty_string"
|
||||
},
|
||||
"assessed_at": {
|
||||
"type": "string",
|
||||
"format": "date"
|
||||
},
|
||||
"scope": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["title", "reference_journeys", "postponed"],
|
||||
"properties": {
|
||||
"title": { "$ref": "#/$defs/non_empty_string" },
|
||||
"reference_journeys": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/non_empty_string" }
|
||||
},
|
||||
"postponed": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/non_empty_string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"release": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["kind", "ref", "meta_commit", "reproducible", "configuration_packages"],
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": ["tagged_release", "release_candidate", "workspace_snapshot"]
|
||||
},
|
||||
"ref": { "$ref": "#/$defs/non_empty_string" },
|
||||
"meta_commit": { "$ref": "#/$defs/non_empty_string" },
|
||||
"reproducible": { "type": "boolean" },
|
||||
"configuration_packages": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/non_empty_string" }
|
||||
},
|
||||
"notes": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/non_empty_string" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"composition": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/module" }
|
||||
},
|
||||
"deployment_profile": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["id", "status", "description", "evidence"],
|
||||
"properties": {
|
||||
"id": { "$ref": "#/$defs/non_empty_string" },
|
||||
"status": { "$ref": "#/$defs/status" },
|
||||
"description": { "$ref": "#/$defs/non_empty_string" },
|
||||
"evidence": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/evidence" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"questionnaire": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"scope_outcomes",
|
||||
"data_policy",
|
||||
"identity_integrations",
|
||||
"workload_growth",
|
||||
"availability_operations",
|
||||
"procurement_decisions"
|
||||
],
|
||||
"properties": {
|
||||
"scope_outcomes": { "$ref": "#/$defs/answers" },
|
||||
"data_policy": { "$ref": "#/$defs/answers" },
|
||||
"identity_integrations": { "$ref": "#/$defs/answers" },
|
||||
"workload_growth": { "$ref": "#/$defs/answers" },
|
||||
"availability_operations": { "$ref": "#/$defs/answers" },
|
||||
"procurement_decisions": { "$ref": "#/$defs/answers" }
|
||||
}
|
||||
},
|
||||
"capabilities": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/assessed_item" }
|
||||
},
|
||||
"infrastructure": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/assessed_item" }
|
||||
},
|
||||
"data_flows": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": { "$ref": "#/$defs/data_flow" }
|
||||
},
|
||||
"assumptions": { "$ref": "#/$defs/string_list" },
|
||||
"open_questions": { "$ref": "#/$defs/string_list" },
|
||||
"risks": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/risk" }
|
||||
},
|
||||
"recommendations": { "$ref": "#/$defs/string_list" },
|
||||
"proof_checks": { "$ref": "#/$defs/string_list" }
|
||||
},
|
||||
"$defs": {
|
||||
"non_empty_string": {
|
||||
"type": "string",
|
||||
"minLength": 1
|
||||
},
|
||||
"string_list": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/non_empty_string" }
|
||||
},
|
||||
"status": {
|
||||
"enum": [
|
||||
"verified",
|
||||
"available_unconfigured",
|
||||
"partial",
|
||||
"scaffold",
|
||||
"external_system",
|
||||
"planned",
|
||||
"not_fit",
|
||||
"not_assessed"
|
||||
]
|
||||
},
|
||||
"evidence": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["kind", "scope", "locator"],
|
||||
"properties": {
|
||||
"kind": {
|
||||
"enum": [
|
||||
"test",
|
||||
"route",
|
||||
"contract",
|
||||
"drill",
|
||||
"documentation",
|
||||
"configuration",
|
||||
"issue",
|
||||
"absence",
|
||||
"observation"
|
||||
]
|
||||
},
|
||||
"scope": {
|
||||
"enum": [
|
||||
"committed_source",
|
||||
"current_workspace",
|
||||
"documented_model",
|
||||
"target_environment"
|
||||
]
|
||||
},
|
||||
"locator": { "$ref": "#/$defs/non_empty_string" },
|
||||
"note": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"module": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"module_id",
|
||||
"repository",
|
||||
"commit",
|
||||
"manifest_version",
|
||||
"enabled",
|
||||
"dirty",
|
||||
"role"
|
||||
],
|
||||
"properties": {
|
||||
"module_id": { "$ref": "#/$defs/non_empty_string" },
|
||||
"repository": { "$ref": "#/$defs/non_empty_string" },
|
||||
"commit": {
|
||||
"type": "string",
|
||||
"pattern": "^[0-9a-f]{7,40}$"
|
||||
},
|
||||
"manifest_version": { "$ref": "#/$defs/non_empty_string" },
|
||||
"enabled": { "type": "boolean" },
|
||||
"dirty": { "type": "boolean" },
|
||||
"role": { "$ref": "#/$defs/non_empty_string" }
|
||||
}
|
||||
},
|
||||
"answers": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/answer" }
|
||||
},
|
||||
"answer": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["id", "question", "state", "answer", "evidence"],
|
||||
"properties": {
|
||||
"id": { "$ref": "#/$defs/non_empty_string" },
|
||||
"question": { "$ref": "#/$defs/non_empty_string" },
|
||||
"state": {
|
||||
"enum": ["answered", "assumed", "not_applicable", "not_assessed"]
|
||||
},
|
||||
"answer": {
|
||||
"type": ["string", "array", "null"],
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"evidence": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/evidence" }
|
||||
}
|
||||
}
|
||||
},
|
||||
"assessed_item": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"id",
|
||||
"requirement",
|
||||
"status",
|
||||
"evidence",
|
||||
"conditions",
|
||||
"gaps",
|
||||
"risks",
|
||||
"recommendation",
|
||||
"proof_check"
|
||||
],
|
||||
"properties": {
|
||||
"id": { "$ref": "#/$defs/non_empty_string" },
|
||||
"requirement": { "$ref": "#/$defs/non_empty_string" },
|
||||
"status": { "$ref": "#/$defs/status" },
|
||||
"evidence": {
|
||||
"type": "array",
|
||||
"items": { "$ref": "#/$defs/evidence" }
|
||||
},
|
||||
"conditions": { "$ref": "#/$defs/string_list" },
|
||||
"gaps": { "$ref": "#/$defs/string_list" },
|
||||
"risks": { "$ref": "#/$defs/string_list" },
|
||||
"recommendation": { "type": "string" },
|
||||
"proof_check": { "type": "string" }
|
||||
}
|
||||
},
|
||||
"data_flow": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["id", "from", "to", "data", "trust_boundary", "controls"],
|
||||
"properties": {
|
||||
"id": { "$ref": "#/$defs/non_empty_string" },
|
||||
"from": { "$ref": "#/$defs/non_empty_string" },
|
||||
"to": { "$ref": "#/$defs/non_empty_string" },
|
||||
"data": { "$ref": "#/$defs/string_list" },
|
||||
"trust_boundary": { "$ref": "#/$defs/non_empty_string" },
|
||||
"controls": { "$ref": "#/$defs/string_list" }
|
||||
}
|
||||
},
|
||||
"risk": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["id", "statement", "impact", "treatment", "owner", "residual_risk"],
|
||||
"properties": {
|
||||
"id": { "$ref": "#/$defs/non_empty_string" },
|
||||
"statement": { "$ref": "#/$defs/non_empty_string" },
|
||||
"impact": { "$ref": "#/$defs/non_empty_string" },
|
||||
"treatment": { "$ref": "#/$defs/non_empty_string" },
|
||||
"owner": { "type": ["string", "null"] },
|
||||
"residual_risk": { "$ref": "#/$defs/non_empty_string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,12 @@
|
||||
"description": "New user-visible behavior or platform capability.",
|
||||
"exclusive": true
|
||||
},
|
||||
{
|
||||
"name": "type/user-story",
|
||||
"color": "1d76db",
|
||||
"description": "End-to-end user journey or real-world process story used to steer product slices.",
|
||||
"exclusive": true
|
||||
},
|
||||
{
|
||||
"name": "type/task",
|
||||
"color": "1d76db",
|
||||
|
||||
@@ -27,12 +27,14 @@ STOP_DEPENDENCIES_ON_EXIT="${GOVOPLAN_STOP_PROFILE_DEPENDENCIES_ON_EXIT:-0}"
|
||||
LOG_DIR="$META_ROOT/runtime/production-like/logs"
|
||||
BACKEND_LOG="$LOG_DIR/backend.log"
|
||||
WORKER_LOG="$LOG_DIR/worker.log"
|
||||
BEAT_LOG="$LOG_DIR/beat.log"
|
||||
FRONTEND_LOG="$LOG_DIR/frontend.log"
|
||||
BACKEND_URL="http://$BACKEND_HOST:$BACKEND_PORT"
|
||||
FRONTEND_URL="http://$FRONTEND_HOST:$FRONTEND_PORT"
|
||||
|
||||
backend_pid=""
|
||||
worker_pid=""
|
||||
beat_pid=""
|
||||
frontend_pid=""
|
||||
|
||||
fail() {
|
||||
@@ -54,7 +56,7 @@ export DATABASE_URL="${DATABASE_URL:-${GOVOPLAN_PRODUCTION_LIKE_DATABASE_URL:-po
|
||||
export GOVOPLAN_DATABASE_URL_PGTOOLS="${GOVOPLAN_DATABASE_URL_PGTOOLS:-${GOVOPLAN_PRODUCTION_LIKE_DATABASE_URL_PGTOOLS:-postgresql://govoplan:govoplan-dev@127.0.0.1:55433/govoplan}}"
|
||||
export REDIS_URL="${REDIS_URL:-${GOVOPLAN_PRODUCTION_LIKE_REDIS_URL:-redis://127.0.0.1:56379/0}}"
|
||||
export CELERY_ENABLED="${CELERY_ENABLED:-true}"
|
||||
export CELERY_QUEUES="${CELERY_QUEUES:-send_email,append_sent,default}"
|
||||
export CELERY_QUEUES="${CELERY_QUEUES:-send_email,append_sent,notifications,calendar,default}"
|
||||
export FILE_STORAGE_BACKEND="${FILE_STORAGE_BACKEND:-local}"
|
||||
export FILE_STORAGE_LOCAL_ROOT="${FILE_STORAGE_LOCAL_ROOT:-$META_ROOT/runtime/production-like/files}"
|
||||
export DEV_AUTO_MIGRATE_ENABLED="${DEV_AUTO_MIGRATE_ENABLED:-false}"
|
||||
@@ -146,6 +148,9 @@ cleanup() {
|
||||
if [ -n "${worker_pid:-}" ] && kill -0 "$worker_pid" 2>/dev/null; then
|
||||
kill "$worker_pid" 2>/dev/null || true
|
||||
fi
|
||||
if [ -n "${beat_pid:-}" ] && kill -0 "$beat_pid" 2>/dev/null; then
|
||||
kill "$beat_pid" 2>/dev/null || true
|
||||
fi
|
||||
if [ "$STOP_DEPENDENCIES_ON_EXIT" = "1" ]; then
|
||||
compose down >/dev/null 2>&1 || true
|
||||
fi
|
||||
@@ -160,6 +165,7 @@ trap cleanup EXIT INT TERM
|
||||
mkdir -p "$LOG_DIR" "$FILE_STORAGE_LOCAL_ROOT"
|
||||
: > "$BACKEND_LOG"
|
||||
: > "$WORKER_LOG"
|
||||
: > "$BEAT_LOG"
|
||||
: > "$FRONTEND_LOG"
|
||||
|
||||
port_is_free "$BACKEND_HOST" "$BACKEND_PORT" || fail "$BACKEND_URL is already in use"
|
||||
@@ -200,6 +206,14 @@ printf 'Starting Celery worker for queues %s\n' "$CELERY_QUEUES"
|
||||
) >"$WORKER_LOG" 2>&1 &
|
||||
worker_pid="$!"
|
||||
|
||||
printf 'Starting Celery beat for durable recovery schedules\n'
|
||||
(
|
||||
cd "$ROOT"
|
||||
"$PYTHON" -m celery -A govoplan_core.celery_app:celery beat \
|
||||
--loglevel INFO
|
||||
) >"$BEAT_LOG" 2>&1 &
|
||||
beat_pid="$!"
|
||||
|
||||
printf 'Starting GovOPlaN WebUI at %s\n' "$FRONTEND_URL"
|
||||
(
|
||||
cd "$WEBUI_ROOT"
|
||||
@@ -235,10 +249,11 @@ Files: $FILE_STORAGE_LOCAL_ROOT
|
||||
Logs:
|
||||
Backend: $BACKEND_LOG
|
||||
Worker: $WORKER_LOG
|
||||
Beat: $BEAT_LOG
|
||||
WebUI: $FRONTEND_LOG
|
||||
|
||||
Docker dependencies remain running after Ctrl+C unless GOVOPLAN_STOP_PROFILE_DEPENDENCIES_ON_EXIT=1.
|
||||
Press Ctrl+C to stop API, worker, and WebUI.
|
||||
Press Ctrl+C to stop API, worker, beat, and WebUI.
|
||||
EOF
|
||||
|
||||
wait
|
||||
|
||||
@@ -19,7 +19,7 @@ usage() {
|
||||
Usage: tools/launch/production-like-dev.sh <command> [--yes]
|
||||
|
||||
Commands:
|
||||
start Start the production-like API, worker, WebUI, PostgreSQL, and Redis profile.
|
||||
start Start the production-like API, worker, scheduler, WebUI, PostgreSQL, and Redis profile.
|
||||
stop Stop PostgreSQL and Redis profile containers.
|
||||
status Show profile container status and validate the effective environment.
|
||||
seed Run migrations and seed development data against the profile database.
|
||||
@@ -27,7 +27,7 @@ Commands:
|
||||
validate-config Validate the profile environment only.
|
||||
|
||||
The start command delegates to tools/launch/launch-production-like-dev.sh. Stop/reset
|
||||
operate on Docker dependencies; API/WebUI/worker processes started by the
|
||||
operate on Docker dependencies; API/WebUI/worker/scheduler processes started by the
|
||||
launcher are stopped with Ctrl+C in that launcher terminal.
|
||||
EOF
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user