No description
  • Python 92.7%
  • Shell 7.3%
Find a file
Josh Quinlan 61f6075728
v0.3.0: effect encryption-at-rest via Stalwart /api/account/crypto
Encryption-at-rest was inert: it wrote LDAP attrs and relied on a Stalwart
[storage.encryption] config block that does not exist, so mail was stored in
plaintext. At-rest is per-user state inside Stalwart, set via POST
/api/account/crypto. New provapi/stalwart.py acts as the authenticated caller
over the master mechanism; /me and operator PGP/at-rest endpoints now push the
effective state to Stalwart before persisting intent to the directory.

Also map malformed local-part/domain ValueError to 422 instead of 500.
2026-06-25 03:54:07 +01:00
cli Initial release: extract albient-provisioning-api from albient.mailstack 2026-06-24 22:44:48 +01:00
docs Initial release: extract albient-provisioning-api from albient.mailstack 2026-06-24 22:44:48 +01:00
provapi v0.3.0: effect encryption-at-rest via Stalwart /api/account/crypto 2026-06-25 03:54:07 +01:00
.gitignore Initial release: extract albient-provisioning-api from albient.mailstack 2026-06-24 22:44:48 +01:00
CHANGELOG.md v0.3.0: effect encryption-at-rest via Stalwart /api/account/crypto 2026-06-25 03:54:07 +01:00
gen_openapi.py Initial release: extract albient-provisioning-api from albient.mailstack 2026-06-24 22:44:48 +01:00
LICENSE Initial release: extract albient-provisioning-api from albient.mailstack 2026-06-24 22:44:48 +01:00
pyproject.toml v0.3.0: effect encryption-at-rest via Stalwart /api/account/crypto 2026-06-25 03:54:07 +01:00
README.md Initial release: extract albient-provisioning-api from albient.mailstack 2026-06-24 22:44:48 +01:00
requirements.txt v0.2.1: PGP UID email guardrail on key upload (gpg/python-gnupg), force override 2026-06-25 01:15:49 +01:00
run.py Initial release: extract albient-provisioning-api from albient.mailstack 2026-06-24 22:44:48 +01:00

albient-provisioning-api

The mailstack provisioning API — a FastAPI service that is the single write-path into 389-DS for the Albient mail platform, plus the Zitadel identity sync that keeps the directory in step with the IdP.

What it does

  • Domains / mailboxes / aliases CRUD against 389-DS (mailstackPerson schema), role-scoped by bearer token (admin / operator / billing / readonly).
  • App-passwords — per-mailbox application passwords for IMAP/SMTP clients.
  • Quota / tier / PGP / encrypt-at-rest management.
  • Zitadel push sync (POST /webhooks/zitadel) — HMAC-verified Actions v2 webhook that materialises, updates, suspends, renames, and deletes mailboxes to match the Zitadel user (source of truth). State is derived from the live user.state.
  • DSAR export/erase and an append-only audit log.
  • Idempotent writes (Idempotency-Key) and a generated OpenAPI spec.

Layout

provapi/            FastAPI app package (app, auth, config, directory, models, audit)
run.py              uvicorn entrypoint
gen_openapi.py      emits the OpenAPI spec artifact
requirements.txt    pinned runtime deps (deploy venv)
cli/mailstackctl    thin bash CLI over the API
docs/WHMCS_SEAM.md  billing-integration seam notes

Running

python3.12 -m venv venv && . venv/bin/activate
pip install -r requirements.txt
export PROVAPI_CONFIG=/path/to/config.yaml
python run.py

Configuration is a YAML file (see provapi/config.py for the schema): LDAP bind, role→token map, Zitadel issuer + service-account token + webhook signing key.

CLI

export MAILSTACKCTL_API="https://api.mail.example.com/api/v1"
export MAILSTACKCTL_TOKEN="<bearer>"
cli/mailstackctl mailbox add alice@example.com --quota 5G --tier standard

Deployment

In the Albient stack this service is deployed by the albient.mailstack.provisioning_api Ansible role, which checks out a pinned tag of this repository, builds the venv, renders the config + systemd unit, and installs the CLI. The service itself has no dependency on Ansible.

License

Copyright © Albient. All rights reserved. See LICENSE.