diff --git a/.env.example b/.env.example index 01a39f5..c81f4ab 100644 --- a/.env.example +++ b/.env.example @@ -1,9 +1,10 @@ # ClassBuild — API Keys -# Keys are entered through the app's Setup page (not read from environment variables). +# In the app, keys are entered on the Setup page. The CLI scripts read them from environment variables. # This file documents what you'll need. # Required — Anthropic Claude API key ANTHROPIC_API_KEY=sk-ant-... -# Optional — Google Gemini API key for infographics and voice narration (TTS) +# Optional — Google Gemini API key, used as a course-content provider (alternative to Claude) +# and by `npm run smoke:gemini` and `scripts/canvas-course.ts --provider gemini`. GEMINI_API_KEY= diff --git a/.gitignore b/.gitignore index 8278b95..90c6ab1 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,10 @@ public/voices/ # Pitch scratch — not part of the app pitch/ + +# Secrets — keys are entered in the app / passed via env vars, never committed +.env +.env.* +!.env.example +*.pem +*.key diff --git a/tools/canvas-test/README.md b/tools/canvas-test/README.md index b7642bf..019319d 100644 --- a/tools/canvas-test/README.md +++ b/tools/canvas-test/README.md @@ -25,7 +25,7 @@ anything under `src/services/export/` or `src/services/template/`. tools/canvas-test/build-demo-cartridge.sh # 2. import into Canvas and inspect what it built (Canvas on another box → set CCT_SSH) -export CCT_SSH=canvas@192.168.1.139 CCT_SSH_KEY=~/.ssh/canvas_vm_ed25519 +export CCT_SSH=canvas@ CCT_SSH_KEY=~/.ssh/ tools/canvas-test/cct.sh import output/demo-course-native.imscc "native demo" tools/canvas-test/cct.sh import output/demo-template-export.imscc "template demo" @@ -51,7 +51,7 @@ instance details** (LAN address, account UUID/ids in `course_settings/context.xm ## Building the Canvas instance ```bash -CCT_LAN_HOST=192.168.1.139 tools/canvas-test/setup-canvas.sh # 30–90 min the first time +CCT_LAN_HOST= tools/canvas-test/setup-canvas.sh # 30–90 min the first time ``` Run on Ubuntu 22.04/24.04 with Docker + compose plugin, git, python3, openssl, curl; ~8 GB RAM (add diff --git a/tools/canvas-test/setup-canvas.sh b/tools/canvas-test/setup-canvas.sh index e3fecf0..d605125 100755 --- a/tools/canvas-test/setup-canvas.sh +++ b/tools/canvas-test/setup-canvas.sh @@ -4,9 +4,9 @@ # Reproducible and resumable. Run it on an Ubuntu 22.04/24.04 box (a VM is ideal) that has # Docker + the compose plugin, git, python3, openssl and curl, and ~8 GB RAM (+ swap), ~60 GB disk. # -# CCT_LAN_HOST=192.168.1.139 ./setup-canvas.sh # full build (30–90 min the first time) -# CCT_LAN_HOST=192.168.1.139 ./setup-canvas.sh fixes # only (re)apply the config/dependency fixes -# CCT_LAN_HOST=192.168.1.139 ./setup-canvas.sh smoke # only check that it is up and QTI is enabled +# CCT_LAN_HOST= ./setup-canvas.sh # full build (30–90 min the first time) +# CCT_LAN_HOST= ./setup-canvas.sh fixes # only (re)apply the config/dependency fixes +# CCT_LAN_HOST= ./setup-canvas.sh smoke # only check that it is up and QTI is enabled # # Phases that finished are recorded in $CANVAS_DIR/.cct/state/; a re-run skips them # (SETUP_FORCE=1 redoes everything). Progress lines start with "PHASE". @@ -35,7 +35,7 @@ QTI_REF="aab28af7a05142140c6fd2f45ed67a4c925a7d1b" # 2026-03-23 PLATFORM_ALERTS_VERSION="1.0.1" CANVAS_DIR="${CANVAS_DIR:-$HOME/canvas-lms}" -LAN_HOST="${CCT_LAN_HOST:?set CCT_LAN_HOST to the address you will browse to, e.g. 192.168.1.139}" +LAN_HOST="${CCT_LAN_HOST:?set CCT_LAN_HOST to the address you will browse to, e.g. 192.168.1.50}" PORT="${CCT_PORT:-3000}" ADMIN_EMAIL="${ADMIN_EMAIL:-admin@canvas-test.local}" ADMIN_FILE="$HOME/canvas-admin.txt" diff --git a/tools/smoke-gemini.ts b/tools/smoke-gemini.ts index 8cd0d12..f2693d6 100644 --- a/tools/smoke-gemini.ts +++ b/tools/smoke-gemini.ts @@ -112,7 +112,7 @@ await check('unknown model id → a clear "model not found" message', true, asyn // Needs no real key: Google must reject it, and we must explain that well. await check('bad key → "API key rejected" (against Google\'s real error text)', false, async () => { try { - await streamMessageGemini({ apiKey: 'AIzaThisIsNotARealKey000000000000000000', model: MODEL, messages: [{ role: 'user', content: 'hi' }] }, {}); + await streamMessageGemini({ apiKey: 'not-a-real-key', model: MODEL, messages: [{ role: 'user', content: 'hi' }] }, {}); } catch (e) { const raw = (e as Error).message; const friendly = friendlyError(e);