Files
govoplan-postbox/docs/POSTBOX_CONCEPT.md
T

22 KiB

Postbox Concept

Purpose

GovOPlaN Postbox provides in-platform postboxes that are addressable containers for messages, files, workflow evidence, and operational handoff. They can be used internally, exposed through portals, and connected to campaign workflows.

The key distinction from a mailbox is ownership. A mailbox is usually bound to a login, user credential, or external mail account. A GovOPlaN postbox is a durable communication and content-access container bound to institutional context: primarily a function in an organizational unit, and where explicitly needed a role, process, portal, campaign, or service responsibility. It may look like an inbox for a message task or like a vault for content shared with the current holders of that responsibility; neither form is owned by one account.

The strategic target is a policy-selectable administrative postbox. The current implementation offers unencrypted content, an institution-managed Encryption envelope, and a strict external E2EE boundary. E2EE messages contain only an external ciphertext reference, signed-manifest reference, wrapped recipient keys, and a verified plaintext digest; an approved producer or client owns the actual cryptographic operation and private-key custody. GovOPlaN cannot decrypt that profile. The institution-managed envelope remains server-readable by authorized institutional key holders. Subjects, routing, participants, and attachment references remain visible in every profile. The cross-module target architecture is recorded in govoplan-core/docs/POSTBOX_E2EE_ARCHITECTURE.md.

Function-Organization-Bound Access

The primary access pattern is a postbox linked to an organizational unit and one or more institutional functions. A person can access that postbox while their identity/account has an effective matching function assignment in that organizational unit and their account may perform the requested Postbox action. Opening a function postbox does not require mapping the function to an RBAC role.

Example:

  • Organizational unit: District Office North
  • Required function: Case Clerk
  • Postbox: District Office North / Case Clerk Intake

Any identity/account currently holding the Case Clerk function for District Office North can see the postbox if it also satisfies the generic Postbox permission and applicable policy. When the function assignment or delegation is removed or expires, access disappears without moving messages or reassigning a mailbox.

The postbox exists independently of its holders. It remains addressable while the function is vacant and may accept durable deliveries according to policy; the UI must then show that no current human holder can open or act on the content. Assigning one or several incumbents grants access in their explicit function context. It does not transfer ownership of the container or rewrite its history.

This makes postboxes useful for responsibilities that outlive individuals:

  • intake desks
  • function-based service queues
  • campaign sender or response desks
  • portal message inboxes for organizational responsibilities
  • file or evidence drops linked to a function in an organization

Incumbency, hand-over, and delegation

  • Zero, one, or several people may hold a function at the same time.
  • A postbox can remain vacant without being deleted, redirected to a personal account, or losing content.
  • A new assignment can grant access to the function's permitted history through a current key epoch. Which historical epochs a new incumbent receives is an explicit postbox policy, not an accidental consequence of account creation.
  • A delegation is a time-bounded access grant in the represented function context. Expiry removes future platform key access and action authority; it cannot destroy plaintext or exports already obtained.
  • Hand-over and revocation rotate the function/postbox key epoch. Per-content data keys should normally be rewrapped; policy may require content re-encryption for a stronger rotation event.
  • Stored content is not silently substituted or overwritten. A correction, replacement, or new version is a new linked object with provenance while the previous signed/ciphertext manifest remains governed by retention policy.

Directory And Authorization Model

The normalized ownership boundary is:

  • Organizations owns units, structures, function types, and concrete functions.
  • Identity owns identities and account links.
  • IDM owns effective identity-to-function assignments, validity, delegation, acting-for context, and assignment lifecycle facts.
  • Core/Access authorizes generic Postbox actions.
  • Postbox owns templates, stable addresses, containers, messages, routing, visibility decisions, grouping preferences, and retention.

The Postbox module stores postbox bindings and postbox-specific decisions, but it must not duplicate identity, organization, assignment, hierarchy, or RBAC resolution.

The minimum authorization inputs are:

  • postbox id
  • tenant id
  • organizational unit id
  • required function id or function type id
  • actor identity id
  • current effective function assignments, delegations, and acting context from IDM
  • generic Postbox permissions from Core/Access
  • optional explicit administrative grants for postbox administration

The expected result is a narrow access decision:

  • can discover
  • can read
  • can send or reply
  • can attach or link files
  • can administer bindings

Access changes must be auditable because a person can gain or lose postbox visibility through function-assignment changes rather than direct postbox membership edits.

Runtime integration must use the kernel capabilities:

  • identity.directory to resolve identities and account links.
  • idm.directory to resolve effective function assignments.
  • organizations.directory to resolve function, function-type, unit, and hierarchy facts.
  • the Core/Access permission evaluator for generic Postbox actions.
  • access explanation/audit contracts to attach permission and acting-context provenance where available.

Postbox must not import Identity, IDM, Organizations, or Access ORM models. Acting-in-place access requires an explicit selected acting context. A function assignment is an organizational responsibility fact; it does not grant unrelated application permissions.

Templates And Stable Addresses

A reusable Postbox template can target a function type and an organization scope, such as a unit type, structure, or subtree. Postbox resolves a stable unit-specific address from the tenant, template revision, concrete unit, concrete function, and optional case/service context.

Subtree scope is explicit about the Organizations structure and may restrict the hierarchical relation types used within that structure. It does not infer scope from the legacy parent_id when an administrator creates or revises a template. This prevents an administrative, reporting, and project hierarchy from being confused when they contain the same units.

Before saving a draft, administrators can run a read-only impact preview. It uses the same scope, function matching, address rendering, and incumbent rules as materialization and reports ready targets, already materialized addresses, vacancies, collisions, cycles, depth limits, and ambiguous paths. The preview does not create a template, address, Postbox, or delivery. A large result is bounded in the UI while its aggregate counts remain visible.

Addresses should be resolved lazily and idempotently rather than eagerly creating empty containers for every unit. They remain durable through vacancy and reassignment. A delivery snapshots the template revision and normalized organization/function references so later hierarchy changes do not rewrite history.

Exact postboxes remain useful for exceptional responsibilities that do not belong to a reusable function type.

Unified Inbox Projections

A user with several functions can group selected visible postboxes into named unified inbox views and keep other responsibilities separate. Grouping is a query projection only. It never merges source containers, messages, read or acknowledgement state, retention, encryption keys, or audit evidence.

The optional Tasks module may aggregate available unread Postbox messages into the common work inbox. This is a current, permission-rechecked projection of a personal read receipt, not a copied task or message. Reading the message in Postbox removes the projection; Postbox remains authoritative for content, access, acknowledgement, reply, retention, and evidence.

Grouping summaries calculate total and unread counts over the currently visible source Postboxes in one tenant-bounded query. Hidden sources retained for later reassignment do not leak counts into the projection.

Every item and action continues to show the source function, unit, postbox, assignment/delegation context, and classification. Policy may require some postboxes to remain separate.

Hierarchy Routing

Hierarchy behavior is disabled by default. The system distinguishes:

  • a linked copy delivered to a parent function postbox
  • attention or escalation metadata sent to a parent responsibility
  • shared visibility over the original message

These have different privacy, retention, acknowledgement, and audit effects and must not be treated as synonyms.

The first production slice should implement explicit linked-copy routing with a selected structure, target function mapping, maximum depth, stop condition, classification gate, loop protection, and delivery-time route snapshot. Organization changes do not retroactively expose old messages.

Vacancy is a visible delivery/attention state rather than an automatic grant to an unrelated personal account. Policy may trigger a bounded escalation after a delay.

The implemented policy keeps the three semantics separate:

  • linked_copy can target the nearest matching ancestor or every bounded matching ancestor in one selected structure.
  • attention currently supports delayed vacancy escalation over the remaining delivery-time target snapshot.
  • shared_visibility remains explicitly disabled until its access and encryption semantics are implemented.

Routing is off unless an immutable template revision enables it and supplies a target template, target function type, producer allowlist, classification allowlist, depth, and structure. Optional relation, stop-unit, stop-unit-type, expiry, and maximum-retention gates narrow the route further. The dry-run API returns blocked and unavailable candidates without materializing addresses. Delivery materializes only frozen candidates, stores path-edge provenance, and creates source-preserving copies with independent read and acknowledgement receipts.

Campaign Distribution

Campaign can use Postbox as an explicit delivery channel through postbox.delivery. A campaign may select Mail, Postbox, both, or a configured fallback order for a target. It must never switch channels silently.

Validation and build preview stable function/unit/context destinations, vacancies, hierarchy-copy effects, classifications, and duplicates. Delivery uses idempotency keys and returns per-target evidence. Postbox owns acceptance, routing, message state, read/acknowledgement state, and postbox ids; Campaign owns campaign preparation, jobs, recipient reports, and channel-attempt evidence.

Domain Objects

The initial domain model should stay small:

  • PostboxTemplate and immutable revisions: reusable function/scope configuration.
  • PostboxAddress: the stable tenant/function/unit/context destination.
  • Postbox: the addressable container, materialized when needed.
  • PostboxBinding: the binding to organization, role, portal, campaign, service, or explicit context.
  • PostboxMessage: a platform-native message or message reference.
  • PostboxParticipant: normalized sender, recipient, author, or actor reference.
  • PostboxAttachmentRef: reference to a file, evidence item, generated campaign artifact, or external attachment.
  • PostboxDelivery and PostboxRoute: idempotent producer acceptance and linked copy/escalation provenance.
  • PostboxGrouping: a per-user source-preserving inbox projection.
  • PostboxAccessEvent: auditable record of access-affecting changes and sensitive actions.

Messages and files should be linked by stable ids and typed references. The postbox module should not import file, mail, or campaign internals.

Capability Boundaries

Postbox should expose narrow capabilities through core:

  • postbox.directory: find postboxes visible to an actor.
  • postbox.access: answer access decisions for a postbox/action pair.
  • postbox.messages: create, list, and read postbox messages through DTOs.
  • postbox.delivery: accept messages or delivery artifacts from other modules.
  • postbox.evidence: link durable evidence references without owning the evidence store.

Optional consumers:

  • Campaign can use postboxes for function-targeted delivery, sender context, reply intake, review queues, and access to campaign artifacts.
  • Files can expose file references to a postbox when the actor has effective source-postbox access.
  • Portal can show portal-facing postboxes without owning the postbox access model.
  • Mail can bridge external mailbox delivery into postboxes when configured, without making postboxes mailbox-bound.

Operational Rules

  • Current function assignment and delegation state controls current access.
  • Historical message records remain durable even when no current person holds the function; vacancy is a visible attention/access state, not a missing postbox.
  • Multiple incumbents receive independent device-bound key grants and remain distinguishable in access and action evidence.
  • Delegation start, expiry, withdrawal, key grant, and key-epoch rotation are separate auditable events.
  • Administration of bindings should require explicit postbox administration permission plus access/RBAC authority for the target organization.
  • Sensitive access decisions and binding changes should emit audit events.
  • Retention rules should be postbox-owned but able to reference campaign, file, and portal provenance.
  • Expiry, withdrawal, and retraction UI must distinguish future access control from already fetched or decrypted plaintext.
  • Message metadata should preserve room for ciphertext manifests, wrapped keys, key epochs, recipient device references, and external capability tokens even before full E2EE ships.

Retention, Audit, And Privacy

Postbox retention is owned by the postbox module because postbox messages are platform-native communication records, not mailbox folders and not ordinary file shares. Retention policies may reference provenance from campaign, file, portal, mail, or workflow modules, but those modules should pass stable ids and typed evidence references through capabilities instead of giving postbox direct access to their internals.

The postbox module should emit audit events for:

  • postbox creation, archival, and destructive retirement
  • binding creation, changes, expiry, and removal
  • sensitive access checks when an actor gains or loses visibility
  • message creation, read/download of sensitive content, attachment linking, and delivery handoff
  • retention holds, retention expiry, export, and destruction decisions

Privacy behavior must separate current access from historical evidence. Losing a function assignment or generic Postbox permission removes future visibility, but it does not rewrite the fact that a person previously accessed a message or that a message existed. Deletion and destructive retention actions must preserve legally required audit/evidence records while removing or redacting content according to the effective policy.

When E2EE is enabled later, retention and audit metadata must remain operable without decrypting message content. UI copy should be honest: expiry, withdrawal, or revocation can prevent future platform access, but it cannot guarantee removal of plaintext already fetched, exported, printed, or delivered outside the platform.

Migration And Compatibility Ownership

Postbox-owned tables, DTOs, migrations, and capability names belong in govoplan-postbox. Core may temporarily contain compatibility imports or legacy migration references only when needed to keep existing installations upgradable while code is being extracted.

Compatibility code must be narrow and documented:

  • new postbox behavior is implemented in govoplan-postbox
  • old import paths may re-export postbox DTOs or helpers during a transition, but must not become active owners of postbox logic
  • migrations that move tables to postbox ownership must preserve existing data and have explicit downgrade/retirement notes
  • optional integrations with campaign, files, portal, or mail remain capability contracts, not direct imports

Once supported release migrations have crossed the compatibility window, legacy core import aliases and old table ownership comments should be removed through a normal cleanup issue.

First Implementation Shape

The first implementation should define the backend manifest, permissions, DTOs, and migrations before building rich UI. A minimal API can then support directory lookup, access checks, message creation, message listing, and binding administration.

The WebUI should start as an administration and inbox surface:

  • postbox directory
  • function-bound access explanation
  • message list and message detail
  • template and binding editor for organization/function links
  • audit-visible administrative actions

Campaign, files, portal, and mail behavior should arrive as optional integrations after the core postbox model is stable.

Configurable content-protection profiles

An exact Postbox or template revision selects one profile. The administration surface recommends the managed profile and requires its vault explicitly; the API retains the legacy plaintext default when an older integration omits these new fields so an upgrade cannot make an unavailable Encryption module block existing automation.

  • server_envelope_v1 is the recommended standard. New local message bodies are encrypted through the optional encryption.content_cipher capability, stored in body_ciphertext, and linked to an owner-bound envelope in the institution's selected vault. Authorized reads ask that capability to open the exact tenant, message, and envelope tuple. Missing Encryption, unavailable or destroyed keys, tampering, and resource mismatch fail closed.
  • external_e2ee_v1 is a server-blind storage contract. Clear bodies are rejected. A producer must provide a ciphertext reference, signed manifest, wrapped recipient keys for the current key epoch, and sha256 content digest. The server retains and authorizes those artifacts but has no private key with which to decrypt them.
  • plaintext_v1 stores the body without content encryption. It remains available for deployments that explicitly choose transport and infrastructure controls only.

No profile hides operational metadata. Subjects, senders, participants, routing, timestamps, classifications, attachment references, receipts, retention state, and access evidence remain server-visible. Native browser or device enrollment, private-key custody, offline recovery, and independently reviewed cryptographic clients are not bundled by Postbox; an institution that selects E2EE must provide and govern that client/provider boundary.

Protection and hand-over policy

Each Postbox snapshots policy for the choices that cannot safely be inferred:

  • a new incumbent sees all retained history, content since assignment, or a bounded look-back period;
  • ordinary and compromise rotations select key rewrapping or full content re-encryption;
  • recovery, hand-over, emergency access, export, and destruction name the required user-consent, institutional key-holder, or dual-control authority and quorum;
  • external retrieval requires strong identity, email plus a one-time code, or may be disabled; and
  • vacancy escalation is always metadata-only and never gives an unrelated personal account content access.

The defaults are deliberately conservative: history since assignment, ordinary rewrapping, re-encryption after compromise, two-person institutional recovery, dual-control hand-over/emergency/export/destruction, strong external identity, and metadata-only vacancy escalation. These are product defaults, not hard-coded policy decisions; administrators can change them per template or exact Postbox.

Governed profile transitions

A profile change increments the Postbox key epoch and applies immediately to new messages. The administrator chooses whether retained history stays under its existing profile or is migrated. Every transition records an idempotency key, source and target profiles/vaults, user-consent and/or institutional authorization evidence, quorum, reason, immutable configuration snapshot, message digests, and per-message outcome.

Plaintext-to-managed and managed-to-plaintext migrations can complete through the configured Encryption capability. Managed decrypt, export, and re-encryption operations are also written to the Encryption migration ledger; old envelopes are not merely orphaned. A transition to or from E2EE pauses each historical message until an approved external client supplies the ciphertext or plaintext transform and evidence. Postbox checks the immutable SHA-256 digest before committing the new representation. Leaving E2EE requires user-consent evidence; changing institution-managed history requires institutional key-holder evidence; dual control can require both. Previously viewed, copied, printed, or exported cleartext cannot be recalled and must be acknowledged.

Database recovery of managed messages requires Postbox and Encryption tables from the same consistency point plus the provider/deployment key. Recovery of E2EE content additionally depends on the institution's external private-key custody and client procedures.