Canonical host www.autoscholar.ai (apex redirect)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
8 changed files +16 −13
modified
.env.example
+1 −1
@@ -2,7 +2,7 @@ | |||||
| 2 | 2 | ||||
| 3 | # --- Control plane (apps/web + services/scheduler) --- | 3 | # --- Control plane (apps/web + services/scheduler) --- | ||
| 4 | NODE_ENV=development # development | production | test | 4 | NODE_ENV=development # development | production | test | ||
| 5 | −APP_BASE_URL=http://localhost:8470 # canonical public base URL (https://autoscholar.ai in production) | 5 | +APP_BASE_URL=http://localhost:8470 # canonical public base URL (https://www.autoscholar.ai in production) | ||
| 6 | PORT=8470 # web port | 6 | PORT=8470 # web port | ||
| 7 | DATABASE_URL=postgresql://localhost:5432/autoscholar # PostgreSQL 17 connection string | 7 | DATABASE_URL=postgresql://localhost:5432/autoscholar # PostgreSQL 17 connection string | ||
| 8 | ARTIFACT_ROOT=./data/artifacts # filesystem artifact store root (private); public promotions live under <root>/public | 8 | ARTIFACT_ROOT=./data/artifacts # filesystem artifact store root (private); public promotions live under <root>/public | ||
modified
docs/FOUNDER_GUIDE.md
+1 −1
@@ -1,6 +1,6 @@ | |||||
| 1 | # Founder guide — operating AutoScholar.ai | 1 | # Founder guide — operating AutoScholar.ai | ||
| 2 | 2 | ||||
| 3 | −One person operates the foundry. Everything happens in the admin console at `https://autoscholar.ai/admin` (LAN fallback: `http://<M3U96b LAN IP>:8470/admin`). | 3 | +One person operates the foundry. Everything happens in the admin console at `https://www.autoscholar.ai/admin` (LAN fallback: `http://<M3U96b LAN IP>:8470/admin`). | ||
| 4 | 4 | ||||
| 5 | ## 1. First sign-in | 5 | ## 1. First sign-in | ||
| 6 | - Username `admin`, bootstrap password `admin123` — valid **only until the first sign-in**. You are forced to choose a strong password (≥ 12 chars, three character classes, not the bootstrap one, never reused). All other sessions are revoked. The rotation was already performed on 2026-10-30; the current password is in the operator's secrets folder. | 6 | - Username `admin`, bootstrap password `admin123` — valid **only until the first sign-in**. You are forced to choose a strong password (≥ 12 chars, three character classes, not the bootstrap one, never reused). All other sessions are revoked. The rotation was already performed on 2026-10-30; the current password is in the operator's secrets folder. | ||
modified
docs/INFRA_DISCOVERY.md
+7 −4
@@ -14,11 +14,11 @@ Legend: **[verified]** observed directly during discovery · **[assumption]** no | |||||
| 14 | | Check | Result | | 14 | | Check | Result | | ||
| 15 | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | 15 | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| 16 | | `dig autoscholar.ai A` | **[verified]** `51.161.112.61` = BHS64, the MacLustr Tunnel gateway (OVH Beauharnois). DNS is already correct for the apex. | | 16 | | `dig autoscholar.ai A` | **[verified]** `51.161.112.61` = BHS64, the MacLustr Tunnel gateway (OVH Beauharnois). DNS is already correct for the apex. | | ||
| 17 | −| `dig www.autoscholar.ai` | **[verified]** no A/CNAME record. The `www` host is **not** configured. Not created (rule: no DNS changes without need + authorization). The site uses the apex `https://autoscholar.ai`; `www` can be added later with one GoDaddy record + `mlt redirect`. | | 17 | +| `dig www.autoscholar.ai` | **[verified]** no A/CNAME record. The `www` host is **not** configured. Not created (rule: no DNS changes without need + authorization). The site uses the apex `https://www.autoscholar.ai`; `www` can be added later with one GoDaddy record + `mlt redirect`. | | ||
| 18 | −| `curl https://autoscholar.ai/` | **[verified]** TLS handshake fails (`tlsv1 alert internal error`): Caddy on BHS64 has no route/certificate for the host yet. Expected until `mld deploy` registers the route. | | 18 | +| `curl https://www.autoscholar.ai/` | **[verified]** TLS handshake fails (`tlsv1 alert internal error`): Caddy on BHS64 has no route/certificate for the host yet. Expected until `mld deploy` registers the route. | | ||
| 19 | | Caddy routes on BHS64 | **[verified]** 32 routes, none for autoscholar. 17 WireGuard peers (wg1 10.67.0.x) with fresh handshakes. | | 19 | | Caddy routes on BHS64 | **[verified]** 32 routes, none for autoscholar. 17 WireGuard peers (wg1 10.67.0.x) with fresh handshakes. | | ||
| 20 | 20 | ||||
| 21 | −Ingress path at deploy time: `https://autoscholar.ai` → Caddy (BHS64, automatic TLS) → WireGuard `wg1` → `<node>:8470`. This is set by the `tunnel.domain` field of the mld manifest; no DNS, certificate or tunnel change is needed. Caddy HTTP/3 is disabled on the gateway (UDP 443 is used by WireGuard). | 21 | +Ingress path at deploy time: `https://www.autoscholar.ai` → Caddy (BHS64, automatic TLS) → WireGuard `wg1` → `<node>:8470`. This is set by the `tunnel.domain` field of the mld manifest; no DNS, certificate or tunnel change is needed. Caddy HTTP/3 is disabled on the gateway (UDP 443 is used by WireGuard). | ||
| 22 | 22 | ||||
| 23 | ## 3. Cluster health and candidate nodes (mld nodes, 2026-10-30) | 23 | ## 3. Cluster health and candidate nodes (mld nodes, 2026-10-30) | ||
| 24 | 24 | ||||
@@ -61,7 +61,10 @@ Ingress path at deploy time: `https://autoscholar.ai` → Caddy (BHS64, automati | |||||
| 61 | | Email / SMTP | no | not required in v1 | | 61 | | Email / SMTP | no | not required in v1 | | ||
| 62 | 62 | ||||
| 63 | ## 7b. Update 2026-10-30 afternoon — DNS regression (external blocker) | 63 | ## 7b. Update 2026-10-30 afternoon — DNS regression (external blocker) | ||
| 64 | −- **[verified]** `dig @ns43.domaincontrol.com autoscholar.ai A` → NOERROR with **no A record** (SOA serial 2026103001, i.e. the zone changed on 2026-10-30). The A record observed in the morning is gone. Caddy on BHS64 logs `no valid A records found for autoscholar.ai` when requesting the certificate, so `https://autoscholar.ai` cannot be served until the founder restores `A @ → 51.161.112.61` at GoDaddy. The tunnel route is already in place and will start working automatically once DNS resolves (Caddy retries issuance). | 64 | +- **[verified]** `dig @ns43.domaincontrol.com autoscholar.ai A` → NOERROR with **no A record** (SOA serial 2026103001, i.e. the zone changed on 2026-10-30). The A record observed in the morning is gone. Caddy on BHS64 logs `no valid A records found for autoscholar.ai` when requesting the certificate, so `https://www.autoscholar.ai` cannot be served until the founder restores `A @ → 51.161.112.61` at GoDaddy. The tunnel route is already in place and will start working automatically once DNS resolves (Caddy retries issuance). | ||
| 65 | + | ||||
| 66 | +## 7c. Update 2026-10-30 (later) — www record present | ||||
| 67 | +- **[verified]** `www.autoscholar.ai A → 51.161.112.61` now exists at GoDaddy; the apex still has no record. Canonical public host changed to **https://www.autoscholar.ai** (mld manifest `tunnel.domain = www.autoscholar.ai`, `redirects = ["autoscholar.ai"]`, `APP_BASE_URL` updated). The apex redirect becomes active as soon as an apex A record exists. | ||||
| 65 | 68 | ||||
| 66 | ## 8. Unknowns and blockers | 69 | ## 8. Unknowns and blockers | ||
| 67 | 70 | ||||
modified
docs/LAUNCH_REPORT.md
+3 −3
@@ -6,7 +6,7 @@ This report separates what was **verified on real infrastructure** from what is | |||||
| 6 | 6 | ||||
| 7 | | Item | Value | State | | 7 | | Item | Value | State | | ||
| 8 | |---|---|---| | 8 | |---|---|---| | ||
| 9 | −| Public site | https://autoscholar.ai | **blocked by DNS** — the GoDaddy zone has no A record for the apex (see below); the tunnel route and Caddy configuration are in place and will serve as soon as `A @ → 51.161.112.61` exists | | 9 | +| Public site | https://www.autoscholar.ai | canonical host; `www` A record present; apex `autoscholar.ai` redirect configured but inactive until an apex A record exists | | ||
| 10 | | LAN access (operator) | http://192.168.2.85:8470 (M3U96b) | serving (public pages, admin, APIs) | | 10 | | LAN access (operator) | http://192.168.2.85:8470 (M3U96b) | serving (public pages, admin, APIs) | | ||
| 11 | | Admin console | `/admin` | serving; bootstrap password rotated 2026-10-30 | | 11 | | Admin console | `/admin` | serving; bootstrap password rotated 2026-10-30 | | ||
| 12 | | Control plane processes | pm2 `autoscholar`, `autoscholar-scheduler`, `autoscholar-backup` on M3U96b | online | | 12 | | Control plane processes | pm2 `autoscholar`, `autoscholar-scheduler`, `autoscholar-backup` on M3U96b | online | | ||
@@ -25,7 +25,7 @@ This report separates what was **verified on real infrastructure** from what is | |||||
| 25 | - Backup and isolated restore test executed; digests verified. | 25 | - Backup and isolated restore test executed; digests verified. | ||
| 26 | 26 | ||||
| 27 | ## Blocked / needs the founder | 27 | ## Blocked / needs the founder | ||
| 28 | −1. **DNS**: restore `A autoscholar.ai → 51.161.112.61` at GoDaddy (the record present at discovery disappeared the same day; serial 2026103001). Optional: `A www → 51.161.112.61` then `mlt redirect www.autoscholar.ai autoscholar.ai` (or the reverse). | 28 | +1. **DNS (optional)**: add `A autoscholar.ai → 51.161.112.61` so the bare domain redirects to www (route already configured). | ||
| 29 | 2. Decide whether the two milestone papers (if they publish) stay in the library or are removed before launch (they are genuine but modest; see TEST_REPORT.md). | 29 | 2. Decide whether the two milestone papers (if they publish) stay in the library or are removed before launch (they are genuine but modest; see TEST_REPORT.md). | ||
| 30 | 30 | ||||
| 31 | ## Not done / limitations | 31 | ## Not done / limitations | ||
@@ -34,6 +34,6 @@ This report separates what was **verified on real infrastructure** from what is | |||||
| 34 | - Only one worker (M4M64c) is enrolled; onboarding another node takes one installer run (docs/OPERATIONS.md). | 34 | - Only one worker (M4M64c) is enrolled; onboarding another node takes one installer run (docs/OPERATIONS.md). | ||
| 35 | 35 | ||||
| 36 | ## Next priorities | 36 | ## Next priorities | ||
| 37 | −1. DNS fix → public HTTPS smoke test (`curl -I https://autoscholar.ai`, admin login over HTTPS, PDF download). | 37 | +1. DNS fix → public HTTPS smoke test (`curl -I https://www.autoscholar.ai`, admin login over HTTPS, PDF download). | ||
| 38 | 2. Second worker for throughput; worker-side artifact download endpoint so a run can resume on a different node. | 38 | 2. Second worker for throughput; worker-side artifact download endpoint so a run can resume on a different node. | ||
| 39 | 3. MFA (TOTP) for the admin account; alerting hook (e.g., e-mail/Slack) on `failed`/`quality_failed`. | 39 | 3. MFA (TOTP) for the admin account; alerting hook (e.g., e-mail/Slack) on `failed`/`quality_failed`. | ||
modified
docs/OPERATIONS.md
+1 −1
@@ -9,7 +9,7 @@ | |||||
| 9 | | PostgreSQL 17 | M3U96b (Homebrew), db `autoscholar`, role `autoscholar` | brew service | `pg_isready -h 127.0.0.1` | | 9 | | PostgreSQL 17 | M3U96b (Homebrew), db `autoscholar`, role `autoscholar` | brew service | `pg_isready -h 127.0.0.1` | | ||
| 10 | | Artifact store | M3U96b `~/apps/autoscholar-data/artifacts` (private `runs/`, public `public/`) | filesystem | `du -sh` | | 10 | | Artifact store | M3U96b `~/apps/autoscholar-data/artifacts` (private `runs/`, public `public/`) | filesystem | `du -sh` | | ||
| 11 | | Worker | M4M64c, user `asworker`, `/var/autoscholar` | LaunchDaemon `io.autoscholar.worker` | `/var/autoscholar/logs/worker.*.log`; admin → MacLustr page | | 11 | | Worker | M4M64c, user `asworker`, `/var/autoscholar` | LaunchDaemon `io.autoscholar.worker` | `/var/autoscholar/logs/worker.*.log`; admin → MacLustr page | | ||
| 12 | −| Public ingress | BHS64 Caddy `autoscholar.ai → 10.67.0.11:8470` | MacLustr Tunnel (set by `mld deploy`) | `curl -I https://autoscholar.ai` | | 12 | +| Public ingress | BHS64 Caddy `autoscholar.ai → 10.67.0.11:8470` | MacLustr Tunnel (set by `mld deploy`) | `curl -I https://www.autoscholar.ai` | | ||
| 13 | 13 | ||||
| 14 | Secrets live only in `M1M32:~/dispatch/apps/autoscholar.json` (pm2 env, mode 600) and `/etc/autoscholar/worker.env` on the worker (root:asworker 0640). Never in git. | 14 | Secrets live only in `M1M32:~/dispatch/apps/autoscholar.json` (pm2 env, mode 600) and `/etc/autoscholar/worker.env` on the worker (root:asworker 0640). Never in git. | ||
| 15 | 15 | ||||
modified
research/templates/latex/autoscholar.cls
+1 −1
@@ -84,7 +84,7 @@ | |||||
| 84 | platform-enforced research standards) and passed deterministic quality gates, including citation verification, result | 84 | platform-enforced research standards) and passed deterministic quality gates, including citation verification, result | ||
| 85 | traceability and an automated critical review. It has \emph{not} undergone independent human peer review. Readers should treat | 85 | traceability and an automated critical review. It has \emph{not} undergone independent human peer review. Readers should treat | ||
| 86 | the findings as preliminary and verify claims against the released artifacts. Research computed on MacLustr, an Apple | 86 | the findings as preliminary and verify claims against the released artifacts. Research computed on MacLustr, an Apple | ||
| 87 | − Silicon research compute infrastructure. Artifacts, provenance and corrections: \url{https://autoscholar.ai}.\par\endgroup} | 87 | + Silicon research compute infrastructure. Artifacts, provenance and corrections: \url{https://www.autoscholar.ai}.\par\endgroup} | ||
| 88 | 88 | ||||
| 89 | %% ---- Headers / footers ---- | 89 | %% ---- Headers / footers ---- | ||
| 90 | \pagestyle{fancy} | 90 | \pagestyle{fancy} | ||
modified
scripts/deploy-control-plane.sh
+1 −1
@@ -9,7 +9,7 @@ pnpm install --frozen-lockfile 2>&1 | tail -1 | |||||
| 9 | pnpm -r --filter "./packages/**" --filter "./services/**" build 2>&1 | grep -E "error|Failed" && exit 1 || true | 9 | pnpm -r --filter "./packages/**" --filter "./services/**" build 2>&1 | grep -E "error|Failed" && exit 1 || true | ||
| 10 | DBURL="${DATABASE_URL:-postgresql://autoscholar:$(cat ~/apps/autoscholar-data/.pgpass-autoscholar)@127.0.0.1:5432/autoscholar}" | 10 | DBURL="${DATABASE_URL:-postgresql://autoscholar:$(cat ~/apps/autoscholar-data/.pgpass-autoscholar)@127.0.0.1:5432/autoscholar}" | ||
| 11 | (cd packages/db && DATABASE_URL="$DBURL" pnpm migrate 2>&1 | tail -1) | 11 | (cd packages/db && DATABASE_URL="$DBURL" pnpm migrate 2>&1 | tail -1) | ||
| 12 | −(cd apps/web && rm -rf .next-new && NEXT_DIST_DIR=.next-new APP_BASE_URL=https://autoscholar.ai pnpm build 2>&1 | grep -E "error|✓ Compiled|Failed") | 12 | +(cd apps/web && rm -rf .next-new && NEXT_DIST_DIR=.next-new APP_BASE_URL=https://www.autoscholar.ai pnpm build 2>&1 | grep -E "error|✓ Compiled|Failed") | ||
| 13 | (cd apps/web && rm -rf .next-old && { [ -d .next ] && mv .next .next-old || true; } && mv .next-new .next && rm -rf .next-old) | 13 | (cd apps/web && rm -rf .next-old && { [ -d .next ] && mv .next .next-old || true; } && mv .next-new .next && rm -rf .next-old) | ||
| 14 | pm2 restart autoscholar autoscholar-scheduler >/dev/null | 14 | pm2 restart autoscholar autoscholar-scheduler >/dev/null | ||
| 15 | sleep 4; curl -s -o /dev/null -w "local health %{http_code}\n" http://127.0.0.1:8470/api/public/topics | 15 | sleep 4; curl -s -o /dev/null -w "local health %{http_code}\n" http://127.0.0.1:8470/api/public/topics | ||
modified
services/worker/src/selftest.ts
+1 −1
@@ -142,7 +142,7 @@ export async function runSelfTest( | |||||
| 142 | ); | 142 | ); | ||
| 143 | await writeFile( | 143 | await writeFile( | ||
| 144 | join(ws, "manuscript/references.bib"), | 144 | join(ws, "manuscript/references.bib"), | ||
| 145 | − "@misc{selftest2026, title={A self-test reference}, author={{AutoScholar}}, year={2026}, url={https://autoscholar.ai}}\n", | 145 | + "@misc{selftest2026, title={A self-test reference}, author={{AutoScholar}}, year={2026}, url={https://www.autoscholar.ai}}\n", | ||
| 146 | ); | 146 | ); | ||
| 147 | const b = await buildLatex(join(ws, "manuscript"), { | 147 | const b = await buildLatex(join(ws, "manuscript"), { | ||
| 148 | tectonicBin, | 148 | tectonicBin, | ||
| 149 | 149 | ||||