The version in pyproject.toml was static, while releases are derived from
conventional commits and tagged by CI. The first release after packaging was
cut as v0.4.0 while the file still declared 0.3.0, so the Python package and
the Nix store path both understated the release.
The version cannot be set by hand in the pull request that causes a release:
it is computed from the commit messages and is only known inside the release
job. So the release job now writes it into pyproject.toml, commits it as
chore(release), and tags that commit.
Neither push re-triggers the workflow -- it listens on main only for the
image-affecting paths, and pyproject.toml is not one of them -- and the
chore(release) subject produces no bump of its own on the next run. The branch
push is ordered before the tag push so a rejected push cannot leave a tag
pointing at a commit that is not on main.
pyproject.toml is bumped to 0.4.0 here to correct the current state; from the
next release onward CI maintains it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
## What
- `pyproject.toml` — setuptools metadata with a `legacy-email-proxy` console script. Runtime dependencies are read dynamically from `requirements.txt`, so the Docker build and the package cannot drift apart.
- `proxy_server.run()` — a synchronous entry point for that console script; `main` is a coroutine and cannot be referenced by one. The `__main__` path behaves as before.
- `flake.nix` / `package.nix` — the package, `overlays.default`, a dev shell, and `checks`. The pytest suite runs as part of the build.
- `module.nix` — a NixOS module: `services.legacy-email-proxy` with freeform `settings` (environment variables) and a separate `environmentFile` for credentials, so secrets stay out of the Nix store. Runs under `DynamicUser`, takes `CAP_NET_BIND_SERVICE` only while a listener is on a privileged port, and opens no firewall ports.
- README: pip install, Nix usage, and a NixOS service example.
## Why
The proxy could only be consumed as a container. Anyone deploying it on NixOS had to vendor a package definition into their own configuration — which is exactly what happened downstream, and is now deleted there in favour of this.
## Not in scope
- The `Dockerfile` and its CI workflow are untouched.
- No Nix job in CI; the runner has no Nix. The build is reproducible locally with `nix flake check`.
- `version` is static and tracks the latest tag (`0.3.0`); bump it with the tag.
## Verification
- `nix flake check` — package builds, 14 tests pass inside the build.
- Consumed from a downstream NixOS host with `--override-input`: the unit's `ExecStart` resolves to the module's own build, and that flake's checks pass too.
---------
Co-authored-by: Emma Thorpe <emma.thorpe@citrix.com>
Reviewed-on: #16