--- title: "1.15.0 — Bootstrap provisioning end to end, messaging management, fleet drift" description: "django-mojo 1.15.0 takes an empty AWS account to a serving, HTTPS-enabled deployment with a first admin login link — eight prompts, then init/apply/configure/admin — and makes email and SMS first-class citizens of the admin portal: dashboard rows, management pages, connection tests, and test sends d…" date: "2026-08-19" tags: ["release"] canonical: "https://django-mojo.sitesmojo.com/changelog/1-15-0/" --- django-mojo 1.15.0 takes an empty AWS account to a serving, HTTPS-enabled deployment with a first admin login link — eight prompts, then init/apply/configure/admin — and makes email and SMS first-class citizens of the admin portal: dashboard rows, management pages, connection tests, and test sends diagnosed in plain words instead of a 500. A daily fleet-drift scan now compares what is actually serving against the recorded topology. Two upgrade notes matter: a populated Twilio from-number on a phone config, previously ignored, is now honored; and password-reset links now survive their first click. ### Added - Bootstrap provisioning CLI: `python -m mojo.deploy.provision init|apply|status|configure|admin`. Eight prompts write a committed environment file; `apply` shows a counted and priced preview, requires a typed `yes`, and converges an empty AWS account in about three idempotent, create-only runs — the tooling never deletes, revokes, or replaces, and a dry run makes zero mutating calls. - Provisioned nodes self-provision in two stages, `configure` publishes the application config and converges every node over SSH (finishing HTTPS with a rate-limit-safe certificate sequence on single-node environments), and `admin` creates the first superuser and prints a single-use login link. - `create_user --login-link`: creates the user with a discarded random password and prints a password-reset link instead — usable over SSH where there is no terminal to type a password at. - Fleet drift scanner: a daily, read-only comparison of what is actually serving in AWS against the recorded topology, surfaced on the incident health strip. Notify-only by design, files nothing when credentials are unavailable, and every finding says what it is, what it costs, and what a person should do. - Admin portal, Messaging → Email: SES domains with a live per-domain "Check now" diagnosed in plain words (sandbox, DKIM pending, unverified, receiving incomplete), mailbox management with system/domain default controls, and a test send. - Admin portal, Messaging → Text messages: the system SMS provider (Twilio, AWS SNS, or the Mojo relay) with secrets shown as presence-only state rows, a zero-side-effect connection test, group overrides listed read-only, and a test SMS with an explicit real-cost confirm. - Dashboard rows for Email and Text messages in the Software section — absent when unconfigured, and deliberately unable to turn the availability headline red. - System Setup gains two readiness sections: a read-only view of the provisioned infrastructure topology (zero AWS calls unless a committed environment file exists), and the WebApp serving destination. - Zero-config managed-domain onboarding: the WebApp serving destination is now derived (explicit override, else the platform's own base URL) instead of requiring a setting up front, and app creation refuses cleanly — before creating anything or moving money — on an installation that cannot serve yet. - New admin endpoints for email (summary, test send, set default mailbox) and SMS (summary, save/test/send). A test email send always answers 200 with a structured, plain-words error — never a 500 — including for an unverified domain or an outbound-disabled mailbox. ### Changed - Saving the system SMS configuration through the admin portal requires a literal superuser, verifies the provider credentials before writing, holds a concurrency token so a stale editor cannot silently clobber a newer save, and files an audit event. That row routes every OTP, MFA, and password-reset text on the installation. - Connection-test results no longer contain raw provider exception text — a stable error code with a plain-words diagnosis, with the raw text kept in server logs. Test mode is reported as its own state ("provider not contacted"), never as OK. - Exactly one system-default mailbox is now enforced under a row lock by a single shared writer, and any default-flag change made through the API is audited with the acting user. - Activity evidence for capability-gated admins no longer masks secret-named values on screen — the API already served those admins the raw data, so the mask only obstructed incident review. ### Fixed - Password-reset links failed on their first click for anyone without a session: the bot-challenge redirect dropped the token, so the admin "send reset link" feature was effectively broken for every recipient. The link now works first click. - Fixing the CloudWatch alarm allowlist from the portal silently dropped a file-configured topic from the effective allowlist — alarm deliveries then 403'd while the alarms kept billing. The two configuration planes now merge, and the union is self-healing. - The WebApp wizard rendered manual-DNS instructions for domains the platform writes itself, and swallowed address-step errors; it now auto-advances the address step and surfaces real errors with a retry. - Activity evidence display truncated deep fields of real data ("[depth limit]") and the Copy button copied the truncated render; display caps are now stack-protection only and Copy hands over the raw stored value. - Config sync installed the runtime config file readable only by its writer, not by the web app it configures. - A phone config storing exactly one of the two Twilio credentials now fails the send with a configuration error instead of silently mixing config and settings credentials — the mix Twilio rejects as a foreign from-number. ### Upgrade notes - Installations with a populated Twilio from-number on a phone config change sending behavior on upgrade: that number is now used (it was previously ignored in favor of the deployment setting), and when both Twilio credentials are also stored on the config, those credentials are used with it. Review any phone config whose from-number differs from the deployment's `TWILIO_NUMBER` before upgrading. - Test mode on a phone config does not stop real sends — it only affects the connection test. The portal now says so plainly; making the flag suppress sends is tracked as follow-up work.