SPB Git

spb/autoscholar

Public
11.8 KB

# Infrastructure discovery — AutoScholar.ai on MacLustr

Date: 2026-10-30. Read-only discovery performed from the operator laptop (SSH, mld, mlt, dig, curl). Legend: [verified] observed directly during discovery · [assumption] not yet verified · [blocker] needs founder action.

# 1. Repository and legacy assets

  • [verified] No AutoScholar repository exists on spbgit (M1M32:~/srv/git/ has no *scholar* repo), none in the mld registry, and none under ~/Desktop on the laptop (the 2026-06 local copy was removed during the 2026-10-02 desktop reorganisation).
  • [verified] The legacy copy lived on M1M32:/Volumes/ssd-2to-vv2/v2/autoscholar; that volume is no longer mounted (only /Volumes/ssd, empty). Backup copies were reported on M2M32c and M4BP48 in June 2026; they are not used, inspected, deleted or migrated by this build. The legacy product (6 named agents, Vite/Express/SQLite) is not reused in any way.
  • [verified] This repository (~/Desktop/Cluster/autoscholar) is greenfield. First deployment goes through mld stage → mld deploy → mld adopt; afterwards the deployed directory on the node is the git source of truth (origin = spbgit autoscholar.git), per the MacLustr remote-first rule.

# 2. Public DNS, TLS and ingress

Check Result
dig autoscholar.ai A [verified] 51.161.112.61 = BHS64, the MacLustr Tunnel gateway (OVH Beauharnois). DNS is already correct for the apex.
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.
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.
Caddy routes on BHS64 [verified] 32 routes, none for autoscholar. 17 WireGuard peers (wg1 10.67.0.x) with fresh handshakes.

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).

# 3. Cluster health and candidate nodes (mld nodes, 2026-10-30)

  • [verified] 29 LAN Macs answered mld nodes except M2M32b (SSH timeout from the laptop at discovery time — hosts the UQO course sites; not needed by AutoScholar, flagged for the operator).
  • [verified] Control-plane candidate M3U96b (Mac Studio M3 Ultra, 28 cores, 96 GB, 79.7 GB free, 454 GB free disk, load 1.8): PostgreSQL 17 listening (scram on TCP; socket access used for provisioning), Redis answering, Node v25.9.0, pm2 (toveli + logrotate only), wg1 peer 10.67.0.11, claude CLI 2.1.314, ports 8470–8472 free. Docker CLI present but daemon not running.
  • [verified] Worker candidate M4M64c (Mac Studio M4 Max, 16 cores, 64 GB, 372 GB free, macOS 26.4): empty node (no pm2 apps), Node v26.10.0, Python 3.14.7, uv 0.12, Homebrew 7.0.6, /usr/bin/sandbox-exec present, sysadminctl/dscl present, pf available but disabled, only user simon-pierreboucher (home drwxr-x---), no Docker, no LaTeX, no claude CLI (the Agent SDK bundles its own binary). Tailscale/wg1 peer present.
  • [verified] LaTeX is installed on no cluster node (no tectonic/pdflatex/latexmk anywhere probed). The laptop has tectonic + MacTeX. → the worker install step installs tectonic via Homebrew on the worker node (self-contained, downloads packages on demand).
  • [verified] Docker Desktop/colima is not running on any node (M3U96a/b, M2U64, M4M64a/b probed). Linux-container isolation is therefore not available today; macOS-native isolation is used (see §6 and docs/SECURITY.md).

# 4. Private control channel (control plane ↔ workers)

  • [verified] All nodes share the LAN 192.168.2.0/24 (M3U96b 192.168.2.85, M4M64c 192.168.2.103). The *.maclustr.io names resolve to Tailscale 100.x addresses whose ACL blocks inter-node SSH; LAN IPs are the reliable inter-node path (mld discovers them live).
  • Chosen transport: worker-initiated outbound HTTPS/HTTP from the worker node to the control plane's private LAN endpoint (http://192.168.2.85:8470/api/internal/workers/*), authenticated with a scoped bearer token issued at enrollment, over the LAN only. Nothing new is exposed on the public gateway except the normal public site; /api/internal/* is blocked for requests that arrive through the tunnel (checked on the X-Forwarded-For/host layer and by token). No inbound port is opened on the worker.
  • [verified] Safe health probe of the chosen worker performed: ssh M4M64c returned sw_vers, memory (68 719 476 736 B), 16 CPUs, disk 372 GB free. SSH is used only for installation and operations by the operator, never by the platform at runtime.

# 5. Model provider, SDK and authentication

  • [verified] @anthropic-ai/claude-agent-sdk latest on npm: 0.3.314 (bundles native Claude Code binary @anthropic-ai/claude-agent-sdk-darwin-arm64); Claude Code CLI on laptop 2.1.314. Node ≥ 18.14 required.
  • [verified from official docs] query() options used: cwd, settingSources: ['project'] (loads CLAUDE.md from the working directory; must be explicit), systemPrompt preset claude_code + append, permissionMode: 'dontAsk' (denies anything that would prompt; canUseTool never reached), allowedTools, disallowedTools (scoped rules like Bash(sudo *) apply in every mode), hooks.PreToolUse (deny beats everything, incl. bypass), sandbox (SandboxSettings: Seatbelt on macOS, writes limited to cwd, hostname-allowlisted network proxy, failIfUnavailable, allowUnsandboxedCommands: false), maxBudgetUsd, maxTurns, abortController, env (replaces the subprocess environment), persistSession: false, agents (subagent definitions), mcpServers (in-process createSdkMcpServer). Result message carries total_cost_usd, modelUsage, num_turns, duration_ms, subtype ∈ {success, error_max_turns, error_max_budget_usd, error_during_execution, …}.
  • [verified from official docs] Third-party products must use API-key authentication (ANTHROPIC_API_KEY in the subprocess env); claude.ai subscription login is not permitted for products. The platform uses the API key only.
  • [verified, presence only] An Anthropic API key is already provisioned in the cluster (present in the pm2 environment of apps on M3U96a, M3U96b, M4M64a, M4M64b via mld manifests). Its value was not displayed. It will be copied by the operator path (M1M32 manifest → root-owned env file on the worker node) and never committed.
  • [verified] Laptop shell has no ANTHROPIC_API_KEY; local development runs with the key absent (research execution disabled locally, simulated worker for tests only).
  • MCP servers anthropic and openalex configured in Claude Code failed to connect this session; irrelevant to the platform (it uses its own HTTP connectors to Crossref/OpenAlex/arXiv/Semantic Scholar).

# 6. Isolation primitives available on macOS workers

  • [verified] sysadminctl + dscl (create a dedicated non-admin user), sandbox-exec/Seatbelt (used by the Agent SDK sandbox), pfctl (per-uid egress rules), launchd LaunchDaemon with UserName (run the worker as the dedicated user), per-user TCC/POSIX separation (operator home is drwxr-x---, Desktop/Documents drwx------).
  • [verified] Sudo on nodes is non-interactive with the documented operator password; used only by the operator install scripts, never by the platform.

# 7. Credentials inventory (presence only)

Credential Present? Where
Anthropic API key yes mld manifests on M1M32 / pm2 envs of 4 nodes (values not read)
PostgreSQL superuser (M3U96b) yes local socket on the node (Homebrew install); app role created at provisioning
Object storage (S3) no none in the cluster → filesystem artifact store with checksums (docs/DECISIONS.md D-07)
Worker enrollment token n/a generated by the platform at install
GoDaddy API not needed DNS already correct
DOI agency (Crossref/DataCite) no DOIs are not issued; UI shows none
Email / SMTP no not required in v1

# 7b. Update 2026-10-30 afternoon — DNS regression (external blocker)

  • [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).

# 8. Unknowns and blockers

  • [assumption] The Agent SDK sandbox (sandbox.enabled) works under a LaunchDaemon-run non-GUI user on macOS 26.4. Verified in Phase 5 with a real run; failIfUnavailable: true makes the worker refuse to run unsandboxed.
  • [assumption] tectonic can fetch its package bundle from the worker node (outbound HTTPS from the node is open; the sandbox allowlist must include the tectonic bundle hosts). Verified in Phase 5.
  • No external blocker identified for Phases 0–5. www.autoscholar.ai remains unconfigured (needs one GoDaddy A record; founder decision).

# 9. Chosen architecture (summary; details in docs/DECISIONS.md)

  • Control plane = one mld app autoscholar on M3U96b:8470 (Next.js web + API, plus a autoscholar-scheduler pm2 process for leases, retries, QA gates and publication), PostgreSQL 17 database autoscholar on the same node, artifact store ~/apps/autoscholar-data (private) + public promoted artifacts served by the web app.
  • Worker = autoscholar-worker installed on M4M64c under the dedicated user asworker (LaunchDaemon), workspaces under /var/autoscholar/runs/<run-id>, Claude Agent SDK with sandbox + hooks + budgets, tectonic for LaTeX, uv-managed Python per run.
  • Public exposure = existing MacLustr Tunnel route autoscholar.ai → M3U96b:8470 created by mld deploy (no DNS change).
Files · 0d8280a29f83e41fbeda1fded3fa94709eba2e7d
Menu

Theme