diff --git a/index.html b/index.html index 4672da1..2f03f33 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ - + diff --git a/package.json b/package.json index 4735835..b26a9ac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "amerc-site", - "version": "0.35.0-account", + "version": "0.36.0-https", "private": true, "type": "module", "scripts": { diff --git a/server/amerc-api.mjs b/server/amerc-api.mjs index ba41969..2276925 100644 --- a/server/amerc-api.mjs +++ b/server/amerc-api.mjs @@ -6,6 +6,7 @@ import http from 'node:http'; import { DatabaseSync } from 'node:sqlite'; import crypto from 'node:crypto'; import fs from 'node:fs'; +import { spawn } from 'node:child_process'; import { existsSync, mkdirSync, createReadStream } from 'node:fs'; import { dirname, join, basename } from 'node:path'; @@ -496,8 +497,10 @@ const server = http.createServer(async (req, res) => { const host = `${name}.${handle}.amerc.ai`; if (db.prepare('SELECT id FROM showcases WHERE host=?').get(host)) return send(res, 409, { ok: false, error: 'showcase already registered' }); const dns = await godaddyEnsureWildcard(handle); + // provision per-user wildcard TLS cert + nginx vhost (idempotent, async) + try { if (existsSync('/home/amerc/showcase-cert.sh')) spawn('/home/amerc/showcase-cert.sh', [handle], { detached: true, stdio: 'ignore' }).unref(); } catch { /* best effort */ } db.prepare('INSERT INTO showcases(owner,name,host,created_at) VALUES(?,?,?,?)').run(id.user.handle, name, host, Date.now()); - return send(res, 200, { ok: true, host, url: `http://${host}/`, edgeToken: showcaseToken(host), edgeWs: 'wss://amerc.ai/showcase/ws', dns: dns.ok ? 'configured' : (dns.error || 'pending') }); + return send(res, 200, { ok: true, host, url: `https://${host}/`, edgeToken: showcaseToken(host), edgeWs: 'wss://amerc.ai/showcase/ws', dns: dns.ok ? 'configured' : (dns.error || 'pending'), tls: 'HTTPS provisions automatically (~1-2 min on your first showcase)' }); } if ((m = path.match(/^\/showcase\/(\d+)$/)) && method === 'DELETE') { if (id?.kind !== 'user') return send(res, 401, { ok: false, error: 'login required' }); diff --git a/src/Mansion.jsx b/src/Mansion.jsx index 9107917..9fa067c 100644 --- a/src/Mansion.jsx +++ b/src/Mansion.jsx @@ -50,6 +50,7 @@ function Showcase({ handle }) { {created && (
✅ {created.host} reserved · DNS {created.dns}
+ {created.tls &&🔒 {created.tls}
} diff --git a/src/Scene2D.jsx b/src/Scene2D.jsx index 29c5db8..3653984 100644 --- a/src/Scene2D.jsx +++ b/src/Scene2D.jsx @@ -7,7 +7,7 @@ import Account from './Account.jsx'; import TavernGame from './TavernGame.jsx'; import { api } from './api.js'; -const RELEASE = '0.35.0-account'; +const RELEASE = '0.36.0-https'; const NAV = [ { id: 'home', label: 'Tavern' },