[Feature] Add Postbox as a governed Campaign delivery channel #81

Open
opened 2026-07-28 18:59:05 +02:00 by zemion · 2 comments
Owner

Outcome

Campaign can deliver a built message to stable organizational function postbox addresses as an alternative or explicit companion to Mail, with per-target evidence, retries, and operator-visible outcomes.

Acceptance criteria

  • Define channel policy per campaign/version/recipient: Mail, Postbox, both, or an explicit fallback order. Never switch channels silently.
  • Select or derive function/unit/context targets through typed directory/address capabilities; Campaign does not import Postbox, IDM, or Organizations internals.
  • During validation/build, resolve and freeze destination refs plus the selected channel policy, while retaining enough provenance to explain function type, unit, template, vacancy, and hierarchy-copy effects.
  • Preview vacant/unavailable/ambiguous targets and duplicate destinations as warnings or blockers according to campaign policy.
  • Commit Postbox deliveries with stable idempotency keys; retries cannot create duplicate messages or hierarchy copies.
  • Preserve Campaign job, recipient, message, attachment/evidence, and channel-attempt relationships without exposing Postbox storage internals.
  • Report accepted, vacant-but-accepted, currently readable, read/acknowledged, failed, retryable, and outcome-unknown separately from SMTP/IMAP states.
  • Mixed-channel campaigns have clear progress and audit evidence; destructive rollback is never implied after a recipient has read/exported content.
  • Work without Postbox installed: authoring remains possible where appropriate, while Postbox channel validation/delivery is unavailable and explained.

Dependencies

## Outcome Campaign can deliver a built message to stable organizational function postbox addresses as an alternative or explicit companion to Mail, with per-target evidence, retries, and operator-visible outcomes. ## Acceptance criteria - Define channel policy per campaign/version/recipient: Mail, Postbox, both, or an explicit fallback order. Never switch channels silently. - Select or derive function/unit/context targets through typed directory/address capabilities; Campaign does not import Postbox, IDM, or Organizations internals. - During validation/build, resolve and freeze destination refs plus the selected channel policy, while retaining enough provenance to explain function type, unit, template, vacancy, and hierarchy-copy effects. - Preview vacant/unavailable/ambiguous targets and duplicate destinations as warnings or blockers according to campaign policy. - Commit Postbox deliveries with stable idempotency keys; retries cannot create duplicate messages or hierarchy copies. - Preserve Campaign job, recipient, message, attachment/evidence, and channel-attempt relationships without exposing Postbox storage internals. - Report accepted, vacant-but-accepted, currently readable, read/acknowledged, failed, retryable, and outcome-unknown separately from SMTP/IMAP states. - Mixed-channel campaigns have clear progress and audit evidence; destructive rollback is never implied after a recipient has read/exported content. - Work without Postbox installed: authoring remains possible where appropriate, while Postbox channel validation/delivery is unavailable and explained. ## Dependencies - [Postbox user story](https://git.add-ideas.de/GovOPlaN/govoplan-postbox/issues/16) - [Postbox delivery capability issue](https://git.add-ideas.de/GovOPlaN/govoplan-postbox/issues/6) - [IDM effective assignments](https://git.add-ideas.de/GovOPlaN/govoplan-idm/issues/5) - [Organizations hierarchy/function types](https://git.add-ideas.de/GovOPlaN/govoplan-organizations/issues/5)
Author
Owner

Codex State: needs-info

The optional capability dependency and typed Campaign adapter are implemented locally; Campaign delivery options now report whether Postbox is active. Full recipient/job/report integration needs a product choice on target cardinality/mapping and channel fallback semantics before its persisted schema is set. The Postbox delivery foundation itself is no longer the blocker.

## Codex State: needs-info The optional capability dependency and typed Campaign adapter are implemented locally; Campaign delivery options now report whether Postbox is active. Full recipient/job/report integration needs a product choice on target cardinality/mapping and channel fallback semantics before its persisted schema is set. The Postbox delivery foundation itself is no longer the blocker.
zemion added
status
needs-info
codex/needs-human
and removed
status
blocked
codex/ready
labels 2026-07-29 00:20:22 +02:00
Author
Owner

Codex State: progress

Summary

  • Resolved the target-cardinality, derivation, and fallback decisions: recipient rows support multiple direct or field-derived Postbox targets, independently or alongside Mail.
  • Implemented optional typed postbox.directory/postbox.delivery integration, build-time target freezing, durable per-target attempts, idempotency, retries, reconciliation, reporting, and Campaign UI controls.
  • Fallback now crosses channels only after confirmed pre-acceptance rejection; accepted or outcome-unknown evidence blocks unsafe fallback, including partial-retry edge cases.

Changed Files

  • src/govoplan_campaign/backend
  • webui/src/features/campaigns
  • src/govoplan_campaign/backend/migrations/versions/f0a1b2c3d4e5_v0115_postbox_delivery.py
  • tests/test_postbox_delivery_orchestration.py
  • tests/test_postbox_target_resolution.py

Verification

  • Campaign pytest: 223 passed
  • Core/Postbox focused composition check: passed, including campaign-only and campaign-with-postbox
  • Core production WebUI build: passed
  • Core devserver migration/startup smoke: passed

Next / Blocked

  • Push and release the coordinated Core, Postbox, and Campaign versions.
  • Still open in the broader issue: expose downstream Postbox readability/read/acknowledgement state in Campaign, and make frozen target provenance prominent in Build/Review.

Suggested status label: status/in-progress

## Codex State: progress ### Summary - Resolved the target-cardinality, derivation, and fallback decisions: recipient rows support multiple direct or field-derived Postbox targets, independently or alongside Mail. - Implemented optional typed postbox.directory/postbox.delivery integration, build-time target freezing, durable per-target attempts, idempotency, retries, reconciliation, reporting, and Campaign UI controls. - Fallback now crosses channels only after confirmed pre-acceptance rejection; accepted or outcome-unknown evidence blocks unsafe fallback, including partial-retry edge cases. ### Changed Files - `src/govoplan_campaign/backend` - `webui/src/features/campaigns` - `src/govoplan_campaign/backend/migrations/versions/f0a1b2c3d4e5_v0115_postbox_delivery.py` - `tests/test_postbox_delivery_orchestration.py` - `tests/test_postbox_target_resolution.py` ### Verification - `Campaign pytest: 223 passed` - `Core/Postbox focused composition check: passed, including campaign-only and campaign-with-postbox` - `Core production WebUI build: passed` - `Core devserver migration/startup smoke: passed` ### Next / Blocked - Push and release the coordinated Core, Postbox, and Campaign versions. - Still open in the broader issue: expose downstream Postbox readability/read/acknowledgement state in Campaign, and make frozen target provenance prominent in Build/Review. Suggested status label: `status/in-progress`
zemion added
status
in-progress
codex/ready
and removed
status
needs-info
codex/needs-human
labels 2026-07-29 02:04:06 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: GovOPlaN/govoplan-campaign#81
No description provided.