A host can pass focusThreadId to select/open a specific conversation — used by the
CRM's global search to jump to the exact thread. Mail switches to Open + selects the
matching item; messenger selects the thread. (Source for the already-published 0.1.6.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a meilisearch service to the dev docker-compose (port 7700, persistent volume)
and MEILI_URL/MEILI_KEY (+ IIOS_CRED_KEY, IIOS_MEDIA_GC_INTERVAL_MS) to .env.example.
Add deploy/meilisearch.yaml — a ready-to-apply k8s Deployment/Service/PVC/Secret for
the ArgoCD prod stack (copy into k8s-pods/services/iios/), with wiring notes for the
iios-service env (MEILI_URL=http://meilisearch:7700, MEILI_KEY from the secret).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New search module: a message index (Meilisearch, MEILI_URL-gated; no-op when unset),
a SearchProjector that indexes on message.sent, and a SearchService whose permission
fence runs server-side — a query only touches the caller's own scope AND the threads
they currently belong to (resolved live from participant rows, so membership changes
reflect immediately). Every conversation kind (chat/mail/sms) is a message with a TEXT
part, so all are searchable through one index. POST /v1/search + /reindex (backfill).
5 fence tests green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SmtpProvider is now scope-aware: it resolves the tenant's own SMTP identity from
the IiosProviderCredential store (providerType SMTP) and sends from it, falling
back to the platform env identity when unset (env fallback applies only to the
platform identity, never a tenant's server). Registered whenever env SMTP OR the
credential store is present; fails closed as NOT_CONFIGURED when neither exists.
Credential endpoints accept SMTP with per-type validation. 18 SMTP tests green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>