// Karaoke Pipeline — MPS → Unsandbox → Container → S3
// Render: dot -Tsvg docs/karaoke-pipeline.dot -o docs/karaoke-pipeline.dot.svg
digraph karaoke_pipeline {
    rankdir=LR;
    node [shape=box, style="rounded,filled", fontname="monospace", fontsize=10];
    edge [fontname="monospace", fontsize=9];

    subgraph cluster_mps {
        label="MPS (uWSGI)";
        style=dashed;
        color="#5871ad";

        trigger [label="Trigger\n(upload / on-demand / backfill)", fillcolor="#e8eaf6"];
        s3_down [label="S3 Download\n→ /tmp/karaoke_*/media.bin\n64KB chunks", fillcolor="#e8eaf6"];
        upload_media [label="POST /upload\n(streaming file body)\n→ upload_id", fillcolor="#e8eaf6"];
        upload_vox [label="POST /upload\nvoxsplit.c\n→ upload_id", fillcolor="#e8eaf6"];
        execute [label="POST /execute\n{upload_ids, script}\ntiny JSON, no file bytes", fillcolor="#e8eaf6"];
        stream_resp [label="Stream response\n→ /tmp/karaoke_*/response.json\n64KB chunks", fillcolor="#e8eaf6"];
        decode [label="Decode artifacts\n(base64 → tmpfile)\nupload to S3", fillcolor="#e8eaf6"];
        db_update [label="Update product\nextensions + file_bytes\nset S3 ACLs", fillcolor="#e8eaf6"];
    }

    subgraph cluster_api {
        label="api.unsandbox.com";
        style=dashed;
        color="#ad5871";

        recv_upload [label="Receive upload\nAES-256-CTR encrypt\n→ /tmp/uploads/{id}.enc\nkey in ETS only", fillcolor="#fce4ec"];
        dispatch [label="Dispatch execute\nErlang RPC\n~200B metadata only", fillcolor="#fce4ec"];
    }

    subgraph cluster_pool {
        label="Pool Node";
        style=dashed;
        color="#58ad71";

        pull [label="GET /internal/upload/{id}\nX-Upload-Key auth\nstreaming decrypt", fillcolor="#e8f5e9"];
        inject [label="lxc exec ... cat >\n/root/input/{filename}\n64KB streaming pipe", fillcolor="#e8f5e9"];
    }

    subgraph cluster_container {
        label="Zerotrust Container";
        style=dashed;
        color="#ad8f58";

        compile [label="gcc -O2 voxsplit.c -lm", fillcolor="#fff8e1"];
        extract [label="ffmpeg -i media\n-vn -acodec pcm_s16le\n-ar 44100 -ac 2\naudio.wav", fillcolor="#fff8e1"];
        split [label="voxsplit audio.wav\n→ split-instrumental.wav\n→ split-vocal.wav", fillcolor="#fff8e1"];
        remux [label="ffmpeg remux\n(video: copy video +\nisolated audio)\n(audio: copy wav)", fillcolor="#fff8e1"];
        artifacts [label="/tmp/artifacts/\ninstrumentals.{ext}\nvocals.{ext}", fillcolor="#fff8e1"];
    }

    s3 [label="S3 / CDN\n(DO Spaces or BYOB)", shape=cylinder, fillcolor="#f3e5f5"];
    browser [label="Browser\n(watch.js)", shape=ellipse, fillcolor="#e0f2f1"];

    trigger -> s3_down;
    s3_down -> upload_media [label="file on disk"];
    s3_down -> upload_vox;
    upload_media -> recv_upload [label="streaming\noctet-stream"];
    upload_vox -> recv_upload;
    recv_upload -> execute [label="upload_id", style=dashed, dir=back];
    execute -> dispatch [label="JSON\n{upload_ids}"];
    dispatch -> pull [label="RPC\nmetadata only"];
    pull -> recv_upload [label="HTTPS GET\nstreaming decrypt", style=dotted];
    pull -> inject;
    inject -> compile;
    compile -> extract;
    extract -> split;
    split -> remux;
    remux -> artifacts;
    artifacts -> stream_resp [label="response JSON\nbase64 artifacts", style=dotted];
    stream_resp -> decode;
    decode -> s3 [label="PUT instrumentals\nPUT vocals"];
    db_update -> s3 [label="ACL update", style=dashed];
    decode -> db_update;
    s3 -> browser [label="presigned URL\n15 min TTL"];
}
