import { useEffect, useState, type ReactNode } from 'react'; import type { PublicBuildDTO } from '../types'; import { AETHERFORGE_CLIENT_HEADER, AETHERFORGE_CLIENT_VALUE, authHeaders, clearStoredAuth, consumeAuthExpiredFlag, encodeBasicToken, getStoredAuth, setStoredAuth, } from '../api/auth'; import { useSound } from '../context/SoundContext'; import { FlowerOfLifeWatermark, KnowledgeKey } from './Visual/sacredGeometry/motifs'; export default function SessionGate({ children }: { children: ReactNode }) { const { play } = useSound(); const [ready, setReady] = useState(false); const [authed, setAuthed] = useState(!!getStoredAuth()); const [degraded, setDegraded] = useState(false); const [user, setUser] = useState(''); const [pass, setPass] = useState(''); const [err, setErr] = useState(''); const [sessionExpired, setSessionExpired] = useState(false); const [publicOpen, setPublicOpen] = useState(false); const [publicBuilds, setPublicBuilds] = useState([]); const [publicLoading, setPublicLoading] = useState(false); const [publicErr, setPublicErr] = useState(''); useEffect(() => { const sync = () => { const hasAuth = !!getStoredAuth(); setAuthed(hasAuth); if (!hasAuth) { setSessionExpired(consumeAuthExpiredFlag()); } }; window.addEventListener('aetherforge-auth', sync); return () => window.removeEventListener('aetherforge-auth', sync); }, []); useEffect(() => { const token = getStoredAuth(); if (!token) { setAuthed(false); setSessionExpired(consumeAuthExpiredFlag()); setReady(true); return; } fetch('/api/v1/config', { headers: authHeaders() }) .then((r) => { if (r.status === 401) { clearStoredAuth({ silent: true, expired: true }); setAuthed(false); setSessionExpired(true); } else if (!r.ok) { // Server reachable but unhappy — keep saved credentials (degraded mode). setAuthed(true); setDegraded(true); } else { setAuthed(true); setDegraded(false); } setReady(true); }) .catch(() => { // Network blip — trust stored credentials until the server responds. setAuthed(true); setDegraded(true); setReady(true); }); }, []); const handleLogin = async (e: React.FormEvent) => { e.preventDefault(); setErr(''); setSessionExpired(false); const headers: Record = { [AETHERFORGE_CLIENT_HEADER]: AETHERFORGE_CLIENT_VALUE, Authorization: `Basic ${encodeBasicToken(user, pass)}`, }; try { const res = await fetch('/api/v1/config', { headers }); if (!res.ok) { setErr('Login failed — check username and password.'); play('error'); return; } setStoredAuth(user, pass); setAuthed(true); setDegraded(false); play('success'); } catch { setErr('Cannot reach server — check that miner-server is running.'); } }; if (!ready) { return (

Starting AetherForge…

); } const loadPublicBuilds = async () => { setPublicLoading(true); setPublicErr(''); try { const res = await fetch('/api/v1/public/builds'); if (!res.ok) throw new Error('unavailable'); const data = (await res.json()) as { builds: PublicBuildDTO[] }; setPublicBuilds(data.builds ?? []); setPublicOpen(true); } catch { setPublicErr('Public builds are not available yet — forge an installer first.'); setPublicOpen(true); } finally { setPublicLoading(false); } }; if (!authed) { return (

AetherForge

Sign in to open the command deck.

{sessionExpired && (

Your session expired — please sign in again.

)} setUser(e.target.value)} autoComplete="username" /> setPass(e.target.value)} autoComplete="current-password" /> {err &&

{err}

}

ψ · the deck remembers every key

{publicOpen && (

Pinned + latest forged installers — no credentials required.

{publicErr &&

{publicErr}

} {publicBuilds.length === 0 && !publicErr && (

No public builds yet.

)}
    {publicBuilds.map((b) => (
  • {b.worker_name} · {b.platform} {b.pinned && 📌}
    Download
  • ))}
)}
); } return ( <> {degraded && (
Cannot reach server — using saved credentials. Some data may be stale until connectivity returns.
)} {children} ); }