feat: AI dev stream over HTTPS (SSE read + draft writeback)

Replaces the Redis-over-Tailscale handoff with a far simpler HTTP surface
on the existing public API — no Redis client, Tailscale, or firewall changes
needed on the dev side.

- GET /ai/stream — SSE feed of every ingested message, reads the internal
  Redis stream; resumes from Last-Event-ID on reconnect (no missed messages);
  heartbeats keep the connection warm through proxies
- POST /ai/drafts — writeback: creates a ContentDraft (PENDING_REVIEW) that
  shows up in the admin /admin/drafts review UI
- AiStreamGuard — static bearer token auth (AI_STREAM_TOKEN), accepts header
  or ?token= query for browser EventSource
- Remove Tailscale sidecar + public Redis port; Redis stays internal-only

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-20 13:06:17 +05:30
parent 7cafbc8ba6
commit 530f81416a
8 changed files with 270 additions and 23 deletions
+24
View File
@@ -0,0 +1,24 @@
import { IsString, IsIn, IsOptional, IsNumber, IsObject, Min, Max } from 'class-validator';
import { DraftType } from '@prisma/client';
const DRAFT_TYPES: DraftType[] = ['EVENT', 'SEVA_TASK', 'FAQ_ITEM'];
export class CreateDraftDto {
@IsString()
tenantId!: string;
@IsString()
sourceMessageId!: string;
@IsIn(DRAFT_TYPES)
type!: DraftType;
@IsObject()
proposedJson!: Record<string, unknown>;
@IsOptional()
@IsNumber()
@Min(0)
@Max(1)
confidence?: number;
}