From 2fc3b66c0753e010be79f0bc68a28420db2784bf Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Mon, 20 Jul 2026 16:50:06 +0200 Subject: [PATCH] docs: add capability and infrastructure fit assessment --- docs/CAPABILITY_AND_INFRASTRUCTURE_FIT.md | 349 ++++++++ docs/capability-fit-current.json | 968 ++++++++++++++++++++++ docs/capability-fit.schema.json | 298 +++++++ 3 files changed, 1615 insertions(+) create mode 100644 docs/CAPABILITY_AND_INFRASTRUCTURE_FIT.md create mode 100644 docs/capability-fit-current.json create mode 100644 docs/capability-fit.schema.json diff --git a/docs/CAPABILITY_AND_INFRASTRUCTURE_FIT.md b/docs/CAPABILITY_AND_INFRASTRUCTURE_FIT.md new file mode 100644 index 0000000..50af744 --- /dev/null +++ b/docs/CAPABILITY_AND_INFRASTRUCTURE_FIT.md @@ -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. diff --git a/docs/capability-fit-current.json b/docs/capability-fit-current.json new file mode 100644 index 0000000..c80a480 --- /dev/null +++ b/docs/capability-fit-current.json @@ -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." + ] +} diff --git a/docs/capability-fit.schema.json b/docs/capability-fit.schema.json new file mode 100644 index 0000000..114d78b --- /dev/null +++ b/docs/capability-fit.schema.json @@ -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" } + } + } + } +}