diff --git a/README.md b/README.md index 0af97e1..e58c7a7 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,21 @@ mailboxes: - `ano@produktor.io` - `postmaster@produktor.io` - `postman@produktor.io` -- `wheregroup@produktor.io` — incubator mailbox (issue #251): nobody logs in; - legacy `.eml` corpus is imported via `doveadm import` by the ETL connector. +- `andriy.oblivantsev@wheregroup.com` — incubator mailbox of the гдеgroup + period (issue #252): the owner's **historical address**, not an abstract + source box. Nobody logs in; legacy `.eml` corpus is imported via doveadm by + the ETL connector (`bin/mail/incubator.go`, 2dph), routed to + `Sent`/`INBOX`/`INBOX/Unmatched` by the recipient headers. +- `wheregroup@produktor.io` — superseded A1 pilot box (abstract "source" + model, issue #251): its 1000 imported messages are migrated to + `andriy.oblivantsev@wheregroup.com` and the account is then deleted (issue + #252). Listed until deletion; `user-patches.sh` skips owners that are no + longer in `postfix-accounts.cf`. Passwords live in `.env` (`INFO_PASSWORD`, `ANDRIY_PASSWORD`; `ano@` uses -`GATOR_MAIL_PASS` in the gator repo `.env`; `wheregroup@` uses -`WHEGROUP_PASSWORD`, random — no interactive login). Do not commit `.env`. +`GATOR_MAIL_PASS` in the gator repo `.env`; `andriy.oblivantsev@wheregroup.com` +uses `ANDRIY_WG_PASSWORD`, random — no interactive login; `wheregroup@` uses +`WHEGROUP_PASSWORD`). Do not commit `.env`. ## Web UI (Roundcube) @@ -75,21 +84,24 @@ changedetector (`check-for-changes.sh`, polls every 2 s) picks up the edited Dovecot. No mail is lost, no container recreation. ```bash -# 1. random password for the new source mailbox (stored in .env only) +# 1. random password for the new historical-address mailbox (stored in .env only) PW=$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 32) -printf 'WHEGROUP_PASSWORD=%s\n' "$PW" >> .env # never commit .env +printf 'ANDRIY_WG_PASSWORD=%s\n' "$PW" >> .env # never commit .env -# 2. add the account — password is read from stdin, never from argv/ps +# 2. add the account — password is read from stdin, never from argv/ps. +# DMS accepts any virtual user: the domain need not be serviced by +# mail.produktor.io (verified live with wheregroup.com, issue #252) — the +# account only serves IMAP/doveadm, no inbound delivery. printf '%s\n%s\n' "$PW" "$PW" | - docker exec -i mailserver setup email add wheregroup@produktor.io + docker exec -i mailserver setup email add andriy.oblivantsev@wheregroup.com # 3. changedetector applies within ~5 s; verify -docker exec mailserver doveadm user wheregroup@produktor.io +docker exec mailserver doveadm user andriy.oblivantsev@wheregroup.com # 4. give the fresh mailbox an INBOX (a brand-new owner has none — without it # `doveadm mailbox list -u ` is empty and user-patches.sh cannot # record any share), then apply the shared/ACL policy -docker exec mailserver doveadm mailbox create -u wheregroup@produktor.io INBOX +docker exec mailserver doveadm mailbox create -u andriy.oblivantsev@wheregroup.com INBOX docker exec mailserver /bin/bash /tmp/docker-mailserver/user-patches.sh ``` @@ -107,11 +119,13 @@ right sets for `info@`: - **production owners** (`ano@`, `andriy.oblivantsev@`, `postmaster@`): read-only — `lookup read` (issue #79); -- **incubator owners** (`wheregroup@produktor.io`, later `gmail_lenovo@`, - `tb-*`/`pst-*`): read **and delete** — `lookup read delete expunge - write-deleted` (issue #251). The owner never logs in; mail arrives via - `doveadm import`. Deleting a message in Roundcube = filter/exclusion from - the corpus (auto-sync, epic B), so the delete button must work in `Shared/`. +- **incubator owners** (one account per historical address of the owner: + `andriy.oblivantsev@wheregroup.com` for the гдеgroup period; later + `eslider@gmail.com`, `...@viscreation.de`, ...): read **and delete** — + `lookup read delete expunge write-deleted` (issue #251). The owner never + logs in; mail arrives via `doveadm import`. Deleting a message in + Roundcube = filter/exclusion from the corpus (auto-sync, epic B), so the + delete button must work in `Shared/`. Verified on live: `write-deleted` is sufficient for the `\Deleted` flag Roundcube sets (no extra `write` right needed), `expunge` is also what Dovecot MOVE needs on the source side when Roundcube moves a deleted message diff --git a/config/user-patches.sh b/config/user-patches.sh index ea32184..e91ea1a 100755 --- a/config/user-patches.sh +++ b/config/user-patches.sh @@ -3,11 +3,18 @@ # two owner classes (issue #79, issue #251 / epic #250): # - production owners (ano@, andriy.oblivantsev@, postmaster@): read-only # (`lookup read`) — one login in Roundcube covers the whole account list; -# - incubator owners (wheregroup@produktor.io; future sources like -# gmail_lenovo@, tb-*/pst-*): read + delete (`lookup read delete expunge +# - incubator owners: read + delete (`lookup read delete expunge # write-deleted`) — the mailbox owner never logs in, mail is imported via # doveadm; deleting a message in Roundcube = filter/exclusion from the # corpus (autosync, epic B). +# Incubator model (corrected 2026-09-02, issue #252): the incubator mailbox IS +# the owner's HISTORICAL ADDRESS per period, not an abstract "source" mailbox. +# The wheregroup period = andriy.oblivantsev@wheregroup.com; later periods get +# their own account (eslider@gmail.com, ...@viscreation.de, ...). +# wheregroup@produktor.io stays listed as the superseded A1 pilot box until +# its 1000 messages are migrated and the account is deleted — grant_share +# skips owners that are not (yet) in postfix-accounts.cf, so a deleted account +# is a silent no-op. # DMS runs this only on the FIRST start of each container instance (plain # `docker compose restart` skips the setup step by design — /CONTAINER_START # marker), so it must stay idempotent. ACLs, the shared dict and subscriptions @@ -31,7 +38,7 @@ chmod 0770 "${SHARED_DB_DIR}" # when Roundcube moves a deleted message to Trash. READER='info@produktor.io' PRODUCTION_OWNERS='ano@produktor.io andriy.oblivantsev@produktor.io postmaster@produktor.io' -INCUBATOR_OWNERS='wheregroup@produktor.io' +INCUBATOR_OWNERS='andriy.oblivantsev@wheregroup.com wheregroup@produktor.io' grant_share() { # $1=owner, remaining=right names local owner=$1