Base Camp — GET <dashboard_path>/base-camp, the SES connection/setup page.
Renders the connection-config form (region + credentials mode + optional static keys), a provisioning action, the SES sending quota, and the list of sending identities with their DKIM/DNS status.
Missing credentials is a normal state
Every SES call can return {:error, :missing_credentials} — this is the
expected steady state for a fresh install with no AWS credentials. It never
crashes mount/handle_event/handle_async; instead the quota and
identity sections render a "Set up camp" onboarding empty state (copy
"Connect your SES credentials to start tracking sightings.") while the
connection-config form — which never touches AWS — stays fully usable so an
operator can enter credentials in the first place.
Webhook base URL
SES.provision/1 needs a full, publicly-reachable webhook URL, but neither
Source nor the app config has a field to store the host's public base URL.
So we take it as a plain form field ("Webhook base URL") kept only in socket
assigns for the session, and build the full path as
base_url <> @dashboard_path <> "/webhooks/sns/" <> source.webhook_token.
Persisting this would need a new Source field (a follow-up — source.ex
is out of this file's territory).