- .env.example lists the keys the scripts actually read (NAS_HOST/NAS_USER/
NAS_SSH_PORT/NAS_DEPLOY_PATH, web build args, Supabase access token and
project ref, CRON_SECRET, Cloudflare token/account/zone/tunnel) and drops
unused ones (DSM_HOST, NAS_DEPLOY_ROOT, NAS_ADMIN_PORT, NAS_LANDING_PORT,
APP_DOMAIN, ADMIN_DOMAIN).
- docs/map/02-infrastructure.md gains a credentials map (names only) with the
matching Forgejo/Supabase/NAS copies, plus the public routing summary.
- Deploy scripts no longer point to the removed /admin static page or portal.
apps/web was never deployed, so /billing on the public domain returned the
landing page and d3ro.dev (desktop "upgrade") did not resolve.
- apps/web runs with basePath /app and output standalone; /download and
/releases redirect to the site's #download. A Dockerfile and a d3ro-web
compose service (port 3002) deploy it to the NAS with the other images.
- The site bridge worker forwards /app/* to WEB_APP_ORIGIN (the tunnel host)
and rewrites upstream redirects; everything else still goes to Pages.
With no origin configured /app answers 503 instead of the landing page.
- Desktop upgrade, desktop Stripe return, mobile subscription management,
the web checkout/portal returns and the site all use billingUrl(); the
return query is success=1 / canceled=1, which the billing page reads.
The billing page highlights ?tier=pro|pro_plus, and signing in from a
billing link returns to the same plan.
- auth/callback pins the redirect origin in production and rejects
protocol-relative next= values (open redirect).
- Mobile legal links use SITE_URLS (fixes the missing slash on /terms).
- Compose drops the unused NEXT_PUBLIC_API_URL and the dead wwwroot legal
mounts; deploy scripts add the web image and the SUPABASE_* values the NAS
compose already required; .dockerignore keeps app .env files out of images.
- Supabase auth redirects allow /app/** (remote dashboard must match).
Policy: docs/REFACTOR_POLICY.md Wave 3, W3-3 and W3-4.