171 lines
5.8 KiB
Markdown
171 lines
5.8 KiB
Markdown
# OpenProject Connector Concept
|
|
|
|
OpenProject is the first proposed concrete connector for
|
|
`govoplan-connectors`. It gives GovOPlaN a public-sector-friendly project and
|
|
work-package integration target without making project management a core
|
|
platform dependency.
|
|
|
|
## Goals
|
|
|
|
- Register OpenProject connection profiles.
|
|
- Test API reachability and authentication without exposing secrets.
|
|
- Read projects, users, statuses, and work packages for linking.
|
|
- Create or update work packages from GovOPlaN tasks/cases/workflows once those
|
|
modules request the capability.
|
|
- Receive or poll changes for external-reference synchronization.
|
|
- Keep all OpenProject-specific client code inside the connector module.
|
|
|
|
## Non-Goals
|
|
|
|
- Replacing a future native GovOPlaN project-management module.
|
|
- Importing workflow, tasks, cases, or access implementation modules directly.
|
|
- Mirroring complete OpenProject project state into GovOPlaN by default.
|
|
- Storing OpenProject tokens outside the platform secret contract.
|
|
|
|
## Profile Fields
|
|
|
|
Candidate profile payload:
|
|
|
|
- `base_url`
|
|
- `api_version`, default `v3`
|
|
- `credential_ref`
|
|
- `verify_tls`
|
|
- `timeout_seconds`
|
|
- `allowed_project_ids`
|
|
- `default_project_id`
|
|
- `webhook_secret_ref`, optional
|
|
- `poll_interval_seconds`, optional
|
|
|
|
## Health Check
|
|
|
|
The connection test should:
|
|
|
|
1. Normalize and validate `base_url`.
|
|
2. Resolve the credential reference.
|
|
3. Call the OpenProject API root or a small read-only endpoint.
|
|
4. Record API version, authenticated principal where available, latency,
|
|
response status, and safe capability hints.
|
|
5. Redact token, Authorization headers, cookies, and any server-provided secret
|
|
fields from diagnostics.
|
|
|
|
## Candidate Capabilities
|
|
|
|
- `connectors.openproject.profileTester`
|
|
- `connectors.openproject.projects`
|
|
- `connectors.openproject.workPackages.read`
|
|
- `connectors.openproject.workPackages.write`
|
|
- `connectors.openproject.webhooks`
|
|
- `connectors.openproject.externalReferences`
|
|
|
|
Domain modules request these through core-mediated capabilities. For example,
|
|
`govoplan-tasks` can publish a task as an OpenProject work package without
|
|
importing OpenProject client code.
|
|
|
|
## Data Boundary Decision
|
|
|
|
OpenProject should be referenced live by default, not mirrored wholesale into
|
|
GovOPlaN. The connector stores stable external references and safe metadata:
|
|
|
|
- profile id and connector type
|
|
- project id and work-package id
|
|
- external URL
|
|
- remote version, ETag, or lock version where available
|
|
- last-seen timestamp and safe status/type labels
|
|
- GovOPlaN trace id for publish or synchronization jobs
|
|
|
|
GovOPlaN should import only the subset needed by a requesting domain module,
|
|
for example a work-package title/status for display, a link-back reference for a
|
|
task, or evidence that a publish operation succeeded. Full project state,
|
|
comments, attachments, membership lists, and custom fields remain remote unless
|
|
a future domain module explicitly owns that synchronization. This keeps cases,
|
|
tasks, workflow, and reporting decoupled from OpenProject while still allowing
|
|
link-out, link-back, selected publish, and selected read views.
|
|
|
|
## Runtime Events
|
|
|
|
- `openproject.profile_tested`
|
|
- `openproject.project_seen`
|
|
- `openproject.work_package_seen`
|
|
- `openproject.work_package_published`
|
|
- `openproject.webhook_received`
|
|
- `openproject.sync_failed`
|
|
|
|
Events should carry GovOPlaN ids, external ids, safe diagnostics, and trace
|
|
context. They must not contain credentials or raw personal data beyond what the
|
|
requesting domain module is authorized to process.
|
|
|
|
## Webhook And Polling Strategy
|
|
|
|
OpenProject supports API and webhook administration. The connector should allow
|
|
both:
|
|
|
|
- Webhook-first when an operator registers a webhook for selected project/work
|
|
package events.
|
|
- Polling fallback for installations where webhooks cannot be exposed.
|
|
|
|
The first implementation can start with manual test plus read-only project/work
|
|
package lookup, then add publishing, then webhook/polling synchronization.
|
|
|
|
## First Implementation Slice
|
|
|
|
1. Add connector type metadata for `openproject`.
|
|
2. Add connection profile CRUD using secret references.
|
|
3. Add a read-only test endpoint.
|
|
4. Add project/work-package lookup DTOs.
|
|
5. Add external-reference storage for linked OpenProject work packages.
|
|
6. Add a WebUI profile page with last-test diagnostics.
|
|
7. Add tests for redaction, unavailable connector behavior, and optional module
|
|
capability discovery.
|
|
|
|
## Minimum DTOs
|
|
|
|
Profile summary:
|
|
|
|
```json
|
|
{
|
|
"id": "openproject-main",
|
|
"connector_type": "openproject",
|
|
"name": "OpenProject",
|
|
"base_url": "https://openproject.example",
|
|
"state": "tested",
|
|
"last_test_at": "2026-07-09T10:00:00Z",
|
|
"last_test_status": "success"
|
|
}
|
|
```
|
|
|
|
External reference:
|
|
|
|
```json
|
|
{
|
|
"connector_type": "openproject",
|
|
"profile_id": "openproject-main",
|
|
"object_type": "work_package",
|
|
"external_id": "1234",
|
|
"external_url": "https://openproject.example/work_packages/1234",
|
|
"version": "etag-or-lock-version",
|
|
"metadata": {
|
|
"project_id": "42"
|
|
}
|
|
}
|
|
```
|
|
|
|
Diagnostics must be redacted and should include only endpoint, version,
|
|
authenticated principal label where safe, latency, status code, and capability
|
|
hints.
|
|
|
|
## First Tests To Add
|
|
|
|
- profile create/update rejects plaintext token fields
|
|
- profile test redacts Authorization, cookies, and token-like response fields
|
|
- lookup capabilities are absent when the connector module is disabled
|
|
- a task/workflow/case module can detect OpenProject capabilities without
|
|
importing connector internals
|
|
- external-reference round-trip stores profile id, object type, external id,
|
|
version/ETag, URL, and safe metadata
|
|
|
|
## Reference Sources
|
|
|
|
- OpenProject API v3 documentation: https://www.openproject.org/docs/api/
|
|
- OpenProject API introduction: https://www.openproject.org/docs/api/introduction/
|
|
- OpenProject API and webhooks administration: https://www.openproject.org/docs/system-admin-guide/api-and-webhooks/
|