Files
govoplan-addresses/README.md
T

6.6 KiB

GovOPlaN Addresses

Repository type: module (domain).

govoplan-addresses is the reusable address and recipient-source module. It owns long-lived address directories and contact points and makes them available to consumers through platform capabilities.

The campaign module may import campaign-local recipient tables, but reusable address management belongs here.

Current State

Milestone 1 is implemented. The module now owns persistent local address books and contact CRUD under /api/v1/addresses, contributes /address-book to the WebUI, and registers address permissions, role templates, database migrations, tenant summaries, and uninstall guards.

The first UI supports user, group, tenant, and system-scoped address books, multi-value contact methods, soft deletion, restore, read-only lookup/search, and vCard import/export for common contact fields. Imported vCards preserve source payload and revision metadata for later sync/conflict work.

The backend and WebUI also support classical address lists: reusable groupings of contacts or specific contact methods within one address book. Campaigns can import address books and address lists through the core-mediated addresses.recipient_source capability without importing address-module internals. Broader operational Verteiler with mixed users, identities, groups, functions, raw recipients, and nested lists belong in govoplan-dist-lists.

The backend now also contains connector-neutral sync infrastructure. Address books can be bound to external sources, sync attempts can record status, tokens, ETags, revisions, diagnostics, tombstones, and conflicts, and read-only or one-way-import sources make the owning address book read-only for normal write paths. CardDAV discovery, source binding, dry-run preview, inbound vCard sync, outbound create/update/delete for writable CardDAV sources, diagnostics, tombstones, conflict persistence, source disconnect/delete UX, and a first sync inspection UI are implemented. The conflict review UI compares stored local and remote field payloads, can apply a stored remote vCard payload, and supports manual per-field local/remote merge choices.

API-managed CardDAV credentials are encrypted inside the source record. Source deletion physically removes that credential material and records a non-secret audit event in the same database transaction; destructive module retirement audits every remaining credential before the owning tables are dropped. Legacy external references are detached but are never sent to a secret provider for deletion because Addresses cannot prove that it owns them.

Boundary

govoplan-addresses owns:

  • scoped address books, vCard-compatible contacts, and postal/email/phone contact points
  • classical address-only lists and recipient-source views
  • consent, legal-basis, and communication-preference metadata
  • deduplication, merge, and address quality workflows
  • import/export of reusable address directories
  • source provenance and change history

It must not own:

  • campaign-local recipient snapshots
  • delivery queues or send attempts
  • SMTP/IMAP transport
  • file storage
  • global identity authentication or RBAC evaluation
  • typed IDM groups, identity relationships, organization structures, or effective function assignments
  • operational distribution lists/Verteiler with mixed recipient types

First Capabilities

The module exposes four core-mediated capabilities:

  • addresses.lookup: read-only contact/recipient lookup for autocomplete.
  • addresses.recipient_source: immutable recipient snapshots for campaign, reporting, mail-build, forms, portal, and postbox workflows.
  • addresses.contact_writer: address-book-scoped write decisions and contact creation for local or otherwise writable sources.
  • addresses.contact_point_resolution: purpose-aware, channel-neutral resolution and immutable snapshots for email, postal, internal-mail, and portal targets.

addresses.recipient_source returns:

  • source id and display label
  • normalized recipient rows
  • email recipient fields
  • source update marker
  • provenance fields suitable for audit and campaign reports

Recipient sources currently include complete address books and classical address lists. Address-list source IDs use addresses:address_list:<id> and preserve the address-list entry ID in recipient provenance. Address-list entries may point at a whole contact, a concrete email address, or a concrete postal address. Email-oriented consumers snapshot email targets and whole-contact entries with a usable email address; postal-only entries remain valid list members for later postal/document workflows.

Legacy addresses.recipient_source consumers must store their own immutable snapshot when they need historical evidence. Channel-neutral consumers may use the dedicated freeze operation described below. The addresses module remains the owner of reusable sources; domain consumers remain responsible for linking their own records to snapshot evidence. Consumers must resolve these capabilities through the platform registry and must not import address ORM/service internals.

addresses.contact_writer returns an explicit decision before a consumer shows or executes write actions: allowed/blocked, reason, user-facing message, required scopes, source kind, read-only state, and provenance. The decision is address-book specific; broader policy modules may later contribute to the same decision path, but consumers should not import or duplicate policy logic.

For channel-neutral consumers, addresses.contact_point_resolution supersedes the email-only shape without removing it. It accepts local contact IDs and stable provider references such as idm:identity:<id>, applies an effective date, communication purpose, address purpose, fallback rule, locale, and domestic/international postal formatting, and returns candidates plus excluded targets with stable reason codes. Bounded previews are live. A frozen snapshot stores the complete values, source and governance revisions, provenance, and a deterministic hash in Addresses so later contact edits cannot rewrite evidence.

The corresponding HTTP API is available below /api/v1/addresses:

  • POST /contact-points/resolve
  • POST /contact-point-sources/preview
  • POST /contact-point-snapshots
  • GET /contact-point-snapshots/{snapshot_id}

Design Documents