docs: mark Novi-Mailman Bridge POC complete and update notes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-03-17 18:17:18 -04:00
parent 6b25cf9c6d
commit 950e34cabd

View File

@@ -37,23 +37,16 @@
- SQLAlchemy 2.0 is likely the easier migration (additive, legacy mode available). - SQLAlchemy 2.0 is likely the easier migration (additive, legacy mode available).
- Pydantic v2 touches every model definition — do this second. - Pydantic v2 touches every model definition — do this second.
- Current pins: `pydantic==1.*`, `SQLAlchemy==1.4.52` — intentional, do not remove until migration is done. - Current pins: `pydantic==1.*`, `SQLAlchemy==1.4.52` — intentional, do not remove until migration is done.
- [~] **Novi-Mailman Bridge:** Synchronization between Novi AMS and Mailman 3. - [x] **Novi-Mailman Bridge:** Cron-based mirror sync between Novi AMS and Mailman 3**POC complete 2026-03-17**.
- Files: `app/methods/e_novi_mailman_methods.py`, `app/routers/api_v3_actions_e_novi_mailman.py` - Files: `app/methods/e_novi_mailman_methods.py`, `app/routers/api_v3_actions_e_novi_mailman.py`
- Registered at `/v3/action/e_novi_mailman/` - Registered at `/v3/action/e_novi_mailman/`
- **Confirmed from IDAA Jitsi code:** - **Confirmed Novi API shape:** No flat member list. Fetch via `/groups/{guid}/members` → UUIDs, then `/customers/{uuid}` for full record. Fields: `Email`, `FirstName`, `LastName`, `Active` (bool), `UnsubscribeFromEmails` (bool). Emails may contain spaces instead of `+` — sanitized with `.replace(' ', '+')`.
- Auth: `Authorization: Basic {api_key}` (Base64-encoded key stored in `data_store`) - **Credentials:** All in IDAA site `cfg_json` (`id_random='58_gJESdlUh'`, site id=17). Keys: `novi_api_root_url`, `novi_idaa_api_key`, `mailman_base_url`, `mailman_username`, `mailman_password`, `novi_mailman_sync` (array).
- Novi member fields are PascalCase: `Email`, `FirstName`, `LastName`, `Name` - **Mailman 3 REST API:** `https://lists.idaa.org/mailman-api` (Nginx proxy → `127.0.0.1:8008` → Docker container). Roster: `/3.1/lists/{list_id_dot}/roster/member`.
- Individual member lookup: `GET /customers/{uuid}` - **Sync logic:** Full mirror — subscribe Novi-only addresses, unsubscribe Mailman-only addresses. Respects `Active=false` and `UnsubscribeFromEmails=true`.
- Group member list: `GET /groups/{guid}/members?pageSize=200` (returns `Results` or `Members` key) - **Cron target:** `POST /v3/action/e_novi_mailman/sync` — runs all `novi_mailman_sync` mappings.
- Emails may contain spaces instead of `+` — sanitize with `.replace(' ', '+')` - **Webhook approach abandoned** — cron is simpler; Novi webhook payload format is unknown and Novi hasn't been configured to send webhooks.
- **Still needs confirmation:** - **Remaining:** Set production group→list mappings in `cfg_json`, configure cron schedule, rotate Mailman `restadmin` password.
- Bulk member list endpoint (likely `/members` or `/customers`) — hit `/novi/members` route after creds are set to inspect
- `MembershipStatus` field name in bulk response (may be `Status`)
- Webhook `EventType` values and payload shape (check Novi webhook docs)
- **data_store setup required (two records):**
- `novi_api_config``{"api_key": "<base64-key>", "base_url": "https://www.idaa.org/api", "mailman_list_id": "members@yourdomain.org"}`
- `mailman_api_config``{"base_url": "http://<host>:8001", "username": "restadmin", "password": "<password>"}`
- **Outstanding TODO in code:** Webhook HMAC signature verification once Novi webhook secret is known.
- [ ] **Lookup System Batch 2:** Migration of `post_topic`, `user_status`, `file_purpose`. - [ ] **Lookup System Batch 2:** Migration of `post_topic`, `user_status`, `file_purpose`.
- [ ] **Zoom Events Integration:** Implement cron synchronization for OAuth2 ticket retrieval. - [ ] **Zoom Events Integration:** Implement cron synchronization for OAuth2 ticket retrieval.