S4 (a1): the media engine — VOICE templates, /desk, Ghost drafts

4a VOICE v1.1 committed (board start); lint is EXECUTABLE — banned list +
   no-exclamation law enforced in the engine (throws in test, drops in
   prod) and locked by tests. Curly-apostrophe variants covered.
4b mediaEngine: deterministic templates (MORNING WIRE, SIGNAL, STREAK
   WATCH, THE SETTLE, RECEIPTS, ARCHETYPE WATCH, LINE DISPATCH) filled
   ONLY from snapshot/ledger/streaks JSON. Record percentages never render
   under n>=20 (counts + 'Record building' below). Stark layer = curated
   committed library (content/stark-lines.json), day-rotated selection —
   selected, never generated.
4c /desk (founder-only: requireAuth + DESK_OWNERS email allowlist,
   deny-by-default): all formats as text + <=280-char pre-segmented tweets
   with per-tweet copy buttons + char counts, wire/numbers-only variants,
   DATA BRIEF block (structured day numbers) with copy-for-claude.ai.
   ntfy ping after the day's first snapshot: 'Desk pack ready'.
4d ghostPublisher: DRAFTS ONLY (status:'draft' test-locked), env-gated
   no-op, HS256 JWT via node crypto (zero new deps). POST
   /api/internal/ghost/drafts saves slate preview + settle drafts.
   Nothing anywhere auto-posts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kev
2026-07-11 14:31:35 -04:00
parent d242b11b4b
commit 0e7871ac0e
12 changed files with 912 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
import { NextRequest, NextResponse } from 'next/server';
export const dynamic = 'force-dynamic';
const BACKEND_URL = process.env.BACKEND_URL || 'http://localhost:3000';
/** Desk pack proxy (Session 63 / A1-S4) — forwards the founder's auth. */
export async function GET(req: NextRequest) {
const auth = req.headers.get('authorization');
if (!auth) return NextResponse.json({ error: 'auth required' }, { status: 401 });
try {
const upstream = await fetch(`${BACKEND_URL}/api/desk/pack`, {
headers: { Accept: 'application/json', Authorization: auth },
cache: 'no-store',
});
const data = await upstream.json().catch(() => ({}));
return NextResponse.json(data, { status: upstream.status });
} catch {
return NextResponse.json({ error: 'desk unavailable' }, { status: 200 });
}
}