Mint short links on piha.lc / beta.piha.li (#12)
Deploy Beta / unit-tests (push) Successful in 21s
Deploy Beta / docker (push) Successful in 24s
Deploy Beta / deploy-beta (push) Successful in 2m4s

## Summary
- Point `SHORTENER_BASE_URL` at `https://piha.lc` (prod) and `https://beta.piha.li` (beta).
- Stop documenting `shortener.aimloperations.com` as the mint host.

Closes #11.

Depends on url_shortening_service serving `/api/` on the short host.

## Test plan
- [ ] Set `SHORTENER_BASE_URL=https://beta.piha.li` and matching token in beta env
- [ ] Compose a campaign SMS and confirm mint hits beta.piha.li (not shortener-beta)
- [ ] Body contains `https://beta.piha.li/<code>`

Reviewed-on: #12
This commit was merged in pull request #12.
This commit is contained in:
2026-08-30 17:27:51 -07:00
parent 2b3f10e784
commit bc7c47a69c
7 changed files with 18 additions and 18 deletions
+2 -2
View File
@@ -79,8 +79,8 @@ SOCIAL_TOKEN_ENCRYPTION_KEY=
OLLAMA_BASE_URL=http://10.0.0.128:11434 OLLAMA_BASE_URL=http://10.0.0.128:11434
OLLAMA_MODEL=llama3.2 OLLAMA_MODEL=llama3.2
# URL shortener (piha.li). Empty locally = long UTM URLs in campaigns. # URL shortener (piha.lc). Empty locally = long UTM URLs in campaigns.
# Call the API host, never https://piha.li (that host only 302s). # Call the short host: POST /api/links/ (Bearer) and recipients GET /<code>.
SHORTENER_BASE_URL= SHORTENER_BASE_URL=
SHORTENER_API_TOKEN= SHORTENER_API_TOKEN=
# Local shortener compose: # Local shortener compose:
+3 -3
View File
@@ -88,10 +88,10 @@ OLLAMA_MODEL=llama3.2
OLLAMA_TIMEOUT_SECONDS=120 OLLAMA_TIMEOUT_SECONDS=120
# URL shortener — mint short links for campaign SMS / email / postcard QR. # URL shortener — mint short links for campaign SMS / email / postcard QR.
# POST /api/links/ on the API host. Recipients hit https://piha.li/<code>. # POST /api/links/ on the same host phones hit. Recipients use https://piha.lc/<code>.
# Token must match SHORTENER_API_TOKENS on url_shortening_service (name:secret). # Token must match SHORTENER_API_TOKENS on url_shortening_service (name:secret).
# Generate: python -c "import secrets; print(secrets.token_urlsafe(32))" # Generate: python -c "import secrets; print(secrets.token_urlsafe(32))"
SHORTENER_BASE_URL=https://shortener.aimloperations.com SHORTENER_BASE_URL=https://piha.lc
SHORTENER_API_TOKEN=monica:replace-me SHORTENER_API_TOKEN=monica:replace-me
# Nominatim address suggest (server-side proxy only; not called from browser) # Nominatim address suggest (server-side proxy only; not called from browser)
@@ -130,5 +130,5 @@ GUNICORN_BIND=0.0.0.0:8000
# OLLAMA_BASE_URL=http://10.0.0.128:11434 # OLLAMA_BASE_URL=http://10.0.0.128:11434
# NOMINATIM_BASE_URL=http://10.0.0.128:8089 # NOMINATIM_BASE_URL=http://10.0.0.128:8089
# NOMINATIM_COUNTRY_CODES=us # NOMINATIM_COUNTRY_CODES=us
# SHORTENER_BASE_URL=https://shortener-beta.aimloperations.com # SHORTENER_BASE_URL=https://beta.piha.li
# SHORTENER_API_TOKEN=monica:replace-with-a-different-token # SHORTENER_API_TOKEN=monica:replace-with-a-different-token
+4 -4
View File
@@ -78,12 +78,12 @@ Campaign UTM short links (piha.li) need **both** sides:
| File | Vars | | File | Vars |
|------|------| |------|------|
| `monica_site_prod.env` | `SHORTENER_BASE_URL=https://shortener.aimloperations.com` · `SHORTENER_API_TOKEN=monica:<secret>` | | `monica_site_prod.env` | `SHORTENER_BASE_URL=https://piha.lc` · `SHORTENER_API_TOKEN=monica:<secret>` |
| `monica_site_beta.env` | `SHORTENER_BASE_URL=https://shortener-beta.aimloperations.com` · distinct `SHORTENER_API_TOKEN` | | `monica_site_beta.env` | `SHORTENER_BASE_URL=https://beta.piha.li` · distinct `SHORTENER_API_TOKEN` |
| `url_shortening_service_prod.env` | `SHORTENER_API_TOKENS=monica:<same-secret>` · `SHORT_ALLOWED_HOSTS` includes `mkdrealtor.com` · `PUBLIC_SHORT_URL=https://piha.li` | | `url_shortening_service_prod.env` | `SHORTENER_API_TOKENS=monica:<same-secret>` · `SHORT_ALLOWED_HOSTS` includes `mkdrealtor.com` · `PUBLIC_SHORT_URL=https://piha.lc` |
| `url_shortening_service_beta.env` | matching beta token · `PUBLIC_SHORT_URL=https://beta.piha.li` | | `url_shortening_service_beta.env` | matching beta token · `PUBLIC_SHORT_URL=https://beta.piha.li` |
Generate the secret with `python -c "import secrets; print(secrets.token_urlsafe(32))"`. Do not put it in git. Call the API host, never `piha.li`, to mint links. Generate the secret with `python -c "import secrets; print(secrets.token_urlsafe(32))"`. Do not put it in git. Mint and redirects share the short host; Bearer is required on `/api/`.
## Deploy ## Deploy
+1 -1
View File
@@ -50,7 +50,7 @@ long HTTPS URL to `url_shortening_service` (`POST /api/links/`, Bearer
`monica:<secret>`) and puts `short_url` (`https://piha.li/<code>`) in SMS, `monica:<secret>`) and puts `short_url` (`https://piha.li/<code>`) in SMS,
email hrefs, and postcard QR codes. Empty env → long UTM URL (local default). email hrefs, and postcard QR codes. Empty env → long UTM URL (local default).
Mint against the **API host**, not `piha.li`. See `.env.example` / `.env.prod.example`. Mint against the short host (`https://piha.lc` / `https://beta.piha.li`). See `.env.example` / `.env.prod.example`.
SMS correlation uses `message_id` (SMS id), then `destination_number` phone SMS correlation uses `message_id` (SMS id), then `destination_number` phone
fallback. Do **not** treat webhook `id` as the SMS id. fallback. Do **not** treat webhook `id` as the SMS id.
+2 -2
View File
@@ -1,6 +1,6 @@
"""Server-to-server client for url_shortening_service (piha.li). """Server-to-server client for url_shortening_service (piha.lc).
Call the API host (`SHORTENER_BASE_URL`), never the public short domain. Call SHORTENER_BASE_URL (https://piha.lc / https://beta.piha.li).
Auth: Authorization: Bearer <SHORTENER_API_TOKEN> (name:secret). Auth: Authorization: Bearer <SHORTENER_API_TOKEN> (name:secret).
""" """
+3 -3
View File
@@ -1598,7 +1598,7 @@ class CampaignUtmLinkTests(TestCase):
} }
with self.settings( with self.settings(
PUBLIC_SITE_URL="https://mkdrealtor.com", PUBLIC_SITE_URL="https://mkdrealtor.com",
SHORTENER_BASE_URL="https://shortener.aimloperations.com", SHORTENER_BASE_URL="https://piha.lc",
SHORTENER_API_TOKEN="monica:test-token", SHORTENER_API_TOKEN="monica:test-token",
): ):
with patch( with patch(
@@ -1630,7 +1630,7 @@ class CampaignUtmLinkTests(TestCase):
mock.text = '{"detail":"Unauthorized"}' mock.text = '{"detail":"Unauthorized"}'
with self.settings( with self.settings(
PUBLIC_SITE_URL="https://mkdrealtor.com", PUBLIC_SITE_URL="https://mkdrealtor.com",
SHORTENER_BASE_URL="https://shortener.aimloperations.com", SHORTENER_BASE_URL="https://piha.lc",
SHORTENER_API_TOKEN="monica:bad", SHORTENER_API_TOKEN="monica:bad",
): ):
with patch("messaging.shortener.requests.post", return_value=mock): with patch("messaging.shortener.requests.post", return_value=mock):
@@ -1687,7 +1687,7 @@ class CampaignUtmLinkTests(TestCase):
url = reverse("messaging:campaign_short_link") url = reverse("messaging:campaign_short_link")
with self.settings( with self.settings(
PUBLIC_SITE_URL="https://mkdrealtor.com", PUBLIC_SITE_URL="https://mkdrealtor.com",
SHORTENER_BASE_URL="https://shortener.aimloperations.com", SHORTENER_BASE_URL="https://piha.lc",
SHORTENER_API_TOKEN="monica:test-token", SHORTENER_API_TOKEN="monica:test-token",
): ):
with patch("messaging.shortener.requests.post", return_value=mock): with patch("messaging.shortener.requests.post", return_value=mock):
+3 -3
View File
@@ -332,9 +332,9 @@ NOMINATIM_USER_AGENT = env(
) )
NOMINATIM_API_KEY = env("NOMINATIM_API_KEY", "") NOMINATIM_API_KEY = env("NOMINATIM_API_KEY", "")
# --- URL shortener (piha.li) --- # --- URL shortener (piha.lc) ---
# Call the API host, never the public short domain. Empty = skip minting # Same host as SMS links. Empty = skip minting (composer falls back to the
# (composer falls back to the long UTM URL). Token format: name:secret. # long UTM URL). Token format: name:secret.
SHORTENER_BASE_URL = env("SHORTENER_BASE_URL", "") SHORTENER_BASE_URL = env("SHORTENER_BASE_URL", "")
SHORTENER_API_TOKEN = env("SHORTENER_API_TOKEN", "") SHORTENER_API_TOKEN = env("SHORTENER_API_TOKEN", "")
SHORTENER_TIMEOUT_SECONDS = int(env("SHORTENER_TIMEOUT_SECONDS", "10") or "10") SHORTENER_TIMEOUT_SECONDS = int(env("SHORTENER_TIMEOUT_SECONDS", "10") or "10")