Sync wiki from project files

2026-07-13 18:09:26 +02:00
parent 43fc6f1c67
commit f4d1ab1b99
4 changed files with 499 additions and 0 deletions

9
Codex-Project-Index.md Normal file

@@ -0,0 +1,9 @@
# govoplan-addresses Project Wiki Index
<!-- codex-wiki-sync:index -->
This page is generated from repository and product-directory project files.
- [Repo-README](Repo-README) - `/mnt/DATA/git/govoplan-addresses/README.md`
- [Repo-docs-ADDRESS-MODULE-ARCHITECTURE](Repo-docs-ADDRESS-MODULE-ARCHITECTURE) - `/mnt/DATA/git/govoplan-addresses/docs/ADDRESS_MODULE_ARCHITECTURE.md`
- [Repo-docs-IMPLEMENTATION-PLAN](Repo-docs-IMPLEMENTATION-PLAN) - `/mnt/DATA/git/govoplan-addresses/docs/IMPLEMENTATION_PLAN.md`

96
Repo-README.md Normal file

@@ -0,0 +1,96 @@
<!-- codex-wiki-sync:6cd57fdf439d1c9624bb2acf -->
> Mirrored from `/mnt/DATA/git/govoplan-addresses/README.md`.
> Origin: `repository`.
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
---
# GovOPlaN Addresses
<!-- govoplan-repository-type:start -->
**Repository type:** module (domain).
<!-- govoplan-repository-type:end -->
`govoplan-addresses` is the reusable address and recipient-source module. It
owns long-lived address directories and makes them available to campaigns,
mail, forms, reporting, portal, and postbox modules 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 also supports classical address lists: reusable groupings of
contacts or specific contact methods within one address book. Broader
operational `Verteiler` with mixed users, identities, groups, functions, raw
recipients, and nested lists belong in `govoplan-dist-lists`.
## Boundary
`govoplan-addresses` owns:
- Adrema-style person, organization, household, and postal-address records
- reusable email address lists and postal-letter recipient views
- segments and reusable recipient-source definitions
- 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
- operational distribution lists/`Verteiler` with mixed recipient types
## First Capabilities
The module exposes three 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.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.
Consumers must store their own immutable snapshot when they need historical
evidence. The addresses module remains the owner of the reusable source, not of
the consumer's historical records. 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.
## Design Documents
- [Address module architecture](docs/ADDRESS_MODULE_ARCHITECTURE.md)
- [Implementation plan](docs/IMPLEMENTATION_PLAN.md)

@@ -0,0 +1,179 @@
<!-- codex-wiki-sync:7efc8433978627bec4341e52 -->
> Mirrored from `/mnt/DATA/git/govoplan-addresses/docs/ADDRESS_MODULE_ARCHITECTURE.md`.
> Origin: `repository`.
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
---
# GovOPlaN Addresses Module Architecture
## Decision
`govoplan-addresses` owns reusable contact and recipient-source data. Campaigns,
mail, scheduling, portal, postbox, forms, reporting, and other modules consume
address data through core-mediated capabilities and APIs, not by importing
address-module internals.
The implementation reference for contact data is vCard. CardDAV is the primary
address-book sync protocol. LDAP/Active Directory, Exchange/Microsoft 365,
Google Contacts, CSV/XLSX, LDIF, and batch vCard import/export are connector
targets layered on top of the same local model and sync contracts.
## Ownership
`govoplan-addresses` owns:
- scoped address books
- contacts, organizations, households, and postal/email/phone address data
- vCard import/export and vCard-compatible field mapping
- reusable recipient sources and classical address lists
- contact tags, categories, communication preferences, consent, and legal basis
- deduplication, merge, address quality checks, and suppression lists
- contact provenance, audit history, soft delete, and restore
- external-source bindings, sync state, conflicts, and read-only source markers
It does not own:
- campaign-local recipient snapshots and evidence
- mail transport, mailbox access, or delivery queues
- calendar events or iCalendar event storage
- global identity authentication or authorization decisions
- organization structure or internal function assignments
- operational distribution lists/`Verteiler` with mixed users, identities,
groups, functions, roles, raw recipients, and nested lists
## Scopes
Address books can live in these scopes:
- `user`: personal address books and remembered contacts
- `group`: team/shared address books
- `tenant`: tenant-wide directories and approved shared lists
- `system`: platform-wide public/shared directories where policy allows it
The scope determines visibility, default permissions, sync credentials, and
whether downstream modules may reuse or mutate entries.
## Data Model Principles
The canonical model should preserve enough vCard semantics to round-trip common
fields:
- name components and formatted names
- nicknames and display names
- email addresses, phone numbers, postal addresses, URLs, notes, categories
- organizations, titles, roles, departments, and relationships
- birthday/anniversary where allowed by policy
- photos/avatars where storage and privacy policy allow them
- calendar or scheduling addresses where present
- source IDs, revisions, ETags, sync tokens, and provenance
The model should support both normalized query fields and a preserved original
representation for import/export and conflict handling.
The local baseline implements scoped address books, contacts, normalized
email/phone/postal-address tables, tags, source kind/reference fields,
first-class source payload/revision fields, and provenance JSON. Imported
vCards preserve raw source payload and revision metadata for audit/debugging
and later conflict workflows. External sync conflict tables and resolution UI
remain part of the sync milestones.
## Capabilities
The first stable capabilities are:
- `addresses.recipient_source`: return immutable recipient snapshots for
campaigns, forms, reporting, and other send/build workflows.
- `addresses.lookup`: provide read-only lookup and autocomplete for mail,
campaign, scheduling, postbox, portal, and case workflows.
- `addresses.contact_writer`: provide address-book-scoped write target decisions
and contact creation for local or otherwise writable sources.
Capabilities use DTOs and source IDs. Consumers must not receive ORM objects or
write address tables directly. Consumers that need historical evidence must
store their own immutable snapshot with source ID, source revision, and
provenance; they must not treat live address records as historical evidence.
`addresses.recipient_source` exposes both complete address books and classical
address lists. Address-book sources use `addresses:address_book:<id>`.
Address-list sources use `addresses:address_list:<id>` and include the
address-list entry ID in each recipient's provenance. The current snapshot DTO
is email-recipient oriented; postal-only list entries are valid address-list
members but are skipped by the email recipient-source path until postal
recipient DTOs are added.
The writer capability is intentionally address-book specific. It answers
whether the current principal may perform an operation such as `create_contact`,
`update_contact`, or `delete_contact` against a concrete address book. The
decision payload includes:
- `allowed`
- stable `reason`
- user-facing `message`
- required scopes
- source kind
- read-only state
- scope and tenant provenance
Policy modules or connector sync state may later add inputs to this decision,
but consumers must continue to call the address capability/API instead of
importing policy logic or address services directly. Disabled or read-only UI
actions should surface the returned `message` on hover.
## Sync Model
Every synced address book should track:
- connector type and external account/source
- external address-book ID and display name
- local address-book scope
- sync direction: read-only, one-way import, one-way export, two-way
- sync token, ETag/revision, last successful sync, last attempted sync
- deleted markers/tombstones
- conflict status and resolution decision
- connector diagnostics and rate-limit/backoff state
Sync conflict UX must show the local value, remote value, source, timestamp, and
available action. Silent overwrite is not acceptable.
## Connector Direction
Implement connectors in this order:
1. vCard import/export and batch import.
2. CardDAV address books.
3. LDAP/Active Directory read-only directories.
4. Exchange/Microsoft 365 and Google Contacts.
5. CSV/XLSX/LDIF import mapping profiles.
Connector runtime behavior should reuse shared connector concepts where useful:
configured endpoints, credentials, dry-run, diagnostics, rate limits, and audit
events.
## Cross-Module Integration
Campaigns should consume `addresses.recipient_source` through the platform
registry and freeze snapshots into campaign versions. Mail should consume
`addresses.lookup` for autocomplete and `addresses.contact_writer` for "add
contact" workflows. Scheduling should use lookup for attendees and organizers.
Portal, postbox, cases, forms, and reporting should link to contact records by
stable IDs while keeping their own domain evidence. Cross-module UI must hide
write actions when no writable target exists, or show the writer decision
message when a disabled action remains visible for context.
Operational distribution lists belong in `govoplan-dist-lists`. They may later
consume address lists as one entry type, but they own mixed recipient expansion
for users, identities, organization units, groups, functions, roles, raw
recipients, and nested lists. Workflow and Tasks own `Umlauf` execution state;
distribution lists define who is included, not how work circulates.
## Deferred Work
The following are valuable but not required for the first functional milestone:
- automatic deduplication and merge suggestions
- two-way sync conflict UI
- Microsoft/Google connectors
- household and relationship editing
- advanced consent-policy automation
- contact activity timeline across all modules

@@ -0,0 +1,215 @@
<!-- codex-wiki-sync:dde972bdd14557a46f93b5a5 -->
> Mirrored from `/mnt/DATA/git/govoplan-addresses/docs/IMPLEMENTATION_PLAN.md`.
> Origin: `repository`.
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
---
# GovOPlaN Addresses Implementation Plan
## Milestone 1: Functional Local Address Books
Goal: make `govoplan-addresses` useful without external sync.
Primary issue: `govoplan-addresses#3`.
Status: implemented. The persistent backend, router, migration, permissions,
role templates, lookup endpoint, restore support, multi-value contact editor,
and first WebUI are in place.
Tasks:
- [x] add backend tables and migrations for address books, contacts, contact
methods, postal addresses, tags, and provenance
- [x] add permissions and role templates for viewing and managing address books
- [x] implement address-book CRUD API
- [x] implement contact CRUD API
- [x] implement scoped WebUI views for user, group, tenant, and system books
- [x] support soft delete
- [x] add restore API/UI for soft-deleted address books and contacts
- [x] expose read-only contact lookup for the WebUI
Exit criteria:
- [x] an admin can create tenant/system books
- [x] a user can create a personal book and contacts
- [x] address data survives restart and appears in the address-book UI
- [x] disabled or read-only actions explain why they are unavailable
## Milestone 2: vCard Foundation
Goal: make the model standards-based before adding sync.
Primary issue: `govoplan-addresses#4`.
Status: implemented. The module can import and export common vCard fields for
local books, preserves imported raw vCard payload and revision metadata in
first-class source fields, reports field/card import issues, and has round-trip
and partial-import tests. Full two-way connector conflict resolution remains in
the sync milestones.
Tasks:
- [x] define vCard-compatible DTOs
- [x] preserve original imported vCard data and normalized query fields
- [x] import `.vcf` files into a selected address book
- [x] export contacts/address books as vCard
- [x] add validation for common vCard fields
- [x] add tests for round-trip import/export of names, emails, phones, postal
addresses, organization fields, notes, categories, and URLs
- [x] add field/card validation messages for batch import
- [x] promote original payload and revision handling into first-class contact
source fields
Exit criteria:
- [x] common vCard files can be imported and exported without losing core fields
- [x] normalized search fields are populated during import
- [x] invalid entries produce field-level actionable validation messages
## Milestone 3: Core Capabilities
Goal: allow other modules to use addresses without dependencies.
Primary issue: `govoplan-addresses#5`.
Tasks:
- [x] implement `addresses.lookup`
- [x] implement `addresses.recipient_source`
- [x] define immutable recipient snapshot DTOs
- [x] expose source provenance in capability responses
- [x] expose classical address lists as `addresses.recipient_source` sources
- [x] add module presence/capability tests
- [x] document consumer rules for campaign, mail, scheduling, portal, postbox, and
reporting
Exit criteria:
- [x] campaign can request a recipient source via core-mediated capability
- [x] mail/scheduling can request autocomplete candidates via core-mediated lookup
- [x] consumers do not import `govoplan_addresses`
## Milestone 4: Campaign Integration
Goal: replace campaign-local reusable address concepts with address-module
sources.
Primary issue: `govoplan-campaign#55`.
Tasks:
- [x] add campaign recipient-source picker when `addresses.recipient_source` exists
- [x] snapshot selected address-source rows into the campaign version
- [x] store source ID, revision, and provenance in campaign evidence
- [x] show stale-source warnings when an address source changed after selection
- [x] keep campaign import for one-off local recipient data
- [x] define classical address lists as reusable address-domain sources
- [ ] add address-list selection and management UI in addresses/campaign
- [ ] define segments/dynamic filters before exposing them as campaign sources
Exit criteria:
- [x] campaign works without addresses installed
- [x] campaign offers address-source selection when addresses is installed
- [x] built campaigns remain auditable after source contacts change
## Milestone 5: Mail And Scheduling Integration
Goal: make contacts visible where users naturally need them.
Primary issues: `govoplan-mail#13` and `govoplan-scheduling#2`.
Tasks:
- [x] add mail recipient/autocomplete integration through `addresses.lookup`
at API/capability level; visible compose UI reuse follows when mail
compose exists
- [x] expose `addresses.contact_writer` for explicit address-book write
decisions, required scopes, read-only/source reasons, and provenance
- [ ] add "add sender/contact" actions in consuming UIs by using
`addresses.contact_writer`
- [x] add scheduling attendee/organizer lookup integration
- [x] preserve module independence when addresses is absent
Exit criteria:
- [x] mail and scheduling build without addresses installed
- [x] when addresses is installed, lookup improves recipient/attendee entry
- [x] address write decisions expose why actions are unavailable for read-only
sources, deleted books, missing scopes, or unsupported operations
- [ ] consuming UI write actions are hidden or explained with the
`addresses.contact_writer` decision payload
## Milestone 6: Sync Infrastructure
Goal: prepare external address books without committing to all connectors at
once.
Primary issue: `govoplan-addresses#6`.
Tasks:
- add address-source connector configuration
- add sync state, ETags, revisions, tokens, tombstones, and conflict records
- add sync diagnostics and audit events
- support read-only and writable source flags
- add dry-run and preview for connector changes
Exit criteria:
- a connector can report planned creates/updates/deletes before applying them
- sync failures are visible in the UI
- conflicts are persisted and do not silently overwrite data
## Milestone 7: CardDAV
Goal: implement the first real standards-based sync connector.
Primary issue: `govoplan-addresses#7`.
Tasks:
- add CardDAV account/address-book discovery
- sync vCard resources into scoped address books
- support read-only and writable CardDAV books where the server allows it
- handle ETag changes, deletes, and conflicts
- add connection test and diagnostics
Exit criteria:
- a CardDAV source can be connected, synced, inspected, and disconnected
- contacts can be refreshed without duplicating entries
- conflict and permission states are visible to the user
## Milestone 8: Additional Connectors And Advanced Address Features
Goal: expand beyond CardDAV after the model and sync engine are stable.
Primary issues: `govoplan-addresses#8`, `govoplan-addresses#9`,
`govoplan-addresses#10`, and `govoplan-connectors#8`.
Tasks:
- LDAP/Active Directory read-only directory connector
- Exchange/Microsoft 365 contacts connector
- Google Contacts connector
- CSV/XLSX/LDIF import mapping profiles
- classical address-list UI and static/dynamic address-domain segments
- operational distribution lists move to `govoplan-dist-lists`
- consent, legal-basis, suppression, and communication preferences
- deduplication and merge workflow
- address quality checks and normalization
- relationship/household/organization editing
Exit criteria:
- each connector or advanced feature can be enabled independently
- users can understand where data came from and whether they may edit it
- downstream modules can safely use contacts without owning them
## First Implementation Recommendation
Start with Milestone 1 and enough of Milestone 2 to define the data model
correctly. Do not start CardDAV before the local vCard-compatible storage and
API are stable.