Something went wrong. Try again.
A local-first event pipeline for independent agents, built on Jazz.
Something went wrong. Try again.
3.3 kB · 76 lines
Shell
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677#!/usr/bin/env bash# Provision a project root for the dedicated Jazz storage-server topology.## Generates 256-bit backend/admin secrets, writes a 0600 env file for the# storage server and a separate 0600 env file for client services, and prints# credential-dark next steps. Secrets are never echoed, logged, or written to# world-readable files. Idempotent: an existing env file is left untouched# unless FORCE=1.## Usage:# scripts/provision-jazz-storage.sh /path/to/project [--force]## Outputs (under <root>/.thoughtstream/):# state/jazz.sqlite.server.env — for scripts/serve-jazz-storage.ts (owner)# jazz-clients.env — for client services (JAZZ_SERVER_URL,# JAZZ_BACKEND_SECRET, storage mode=client)## The client env file deliberately does NOT contain the admin secret.# Deployment notes:# - The storage server and the trusted runtime may share an isolated# host/container boundary; the discovery file and env files are 0600 and# must never be mounted into the model sandbox. Model consumers stay# disabled until proven against the sandbox constraints (see# spec/jazz-alpha55-port.md, open items).
set -euo pipefail
root="${1:?usage: provision-jazz-storage.sh <project-root> [--force]}"force=0[[ "${2:-}" == "--force" || "${FORCE:-}" == "1" ]] && force=1
state_dir="$root/.thoughtstream/state"owner_env="$state_dir/jazz.sqlite.server.env"client_env="$root/.thoughtstream/jazz-clients.env"
if [[ -f "$owner_env" && $force -ne 1 ]]; then echo "provision: $owner_env already exists; leaving untouched (use --force to regenerate)" >&2 exit 0fi
mkdir -p "$state_dir"port="${JAZZ_SERVER_PORT:-4316}"[[ "$port" =~ ^[0-9]+$ ]] && (( port >= 1 && port <= 65535 )) || { echo "Invalid storage port" >&2; exit 1; }app_id="${JAZZ_APP_ID:-thoughtstream-local}"[[ "$app_id" =~ ^[a-zA-Z0-9_-]+$ ]] || { echo "Invalid app id" >&2; exit 1; }# 256-bit secrets (32 bytes hex). Never use the upstream dev-helper defaults.backend_secret="thoughtstream-backend-$(od -An -N32 -tx1 /dev/urandom | tr -d ' \n')"admin_secret="thoughtstream-admin-$(od -An -N32 -tx1 /dev/urandom | tr -d ' \n')"
umask 077cat > "$owner_env" <<EOF# Jazz storage-server credentials (0600, provisioned $(date -Is))# Source this ONLY into scripts/serve-jazz-storage.ts.JAZZ_APP_ID=$app_idJAZZ_SERVER_PORT=$portJAZZ_BACKEND_SECRET=$backend_secretJAZZ_ADMIN_SECRET=$admin_secretEOFchmod 600 "$owner_env"
cat > "$client_env" <<EOF# Jazz client credentials (0600, provisioned $(date -Is))# Source this into every service that opens the store. Storage mode is# pinned to client: services must never silently become storage owners.THOUGHTSTREAM_JAZZ_STORAGE_MODE=clientJAZZ_SERVER_URL=http://127.0.0.1:$portJAZZ_BACKEND_SECRET=$backend_secretEOFchmod 600 "$client_env"
# Owner and client share exactly the same backend credential. Only the owner# receives the admin credential. Both stay stable across owner restarts.echo "provision: wrote $owner_env and $client_env (mode 0600)"echo "provision: start the owner with: THOUGHTSTREAM_ROOT=$root tsx scripts/serve-jazz-storage.ts"echo "provision: owner must load $owner_env; clients must load $client_env"echo "provision: no secrets were logged; verify with: ls -l $owner_env $client_env"