Repository Public
1// Auteur : Simon-Pierre Boucher — contact@spboucher.ai2// KA ID v2 — ingestion du journal d'interactions (serveur-à-serveur).3// Les plateformes poussent les événements comportementaux de leurs membres4// (recherche, consultation, favori, masquage…), signés du secret SSO partagé.5// POST { client_id, ka_id, ts, sig, events: [{ type, entity_type?,6// entity_id?, session_id?, query?, filters?, position?, features?,7// dwell_ms?, ts? }] } (max 50 événements par lot)8// Respecte le réglage « Historique » du membre (rien n'est stocké si OFF).9import { NextRequest, NextResponse } from "next/server";10import { findUserByKaId } from "@/lib/db";11import { verifyClientSig } from "@/lib/sso";12import { ingestEvents, privacyOf } from "@/lib/kaid-data";1314export async function POST(req: NextRequest) {15 const body = (await req.json().catch(() => ({}))) as Record<string, unknown>;16 const clientId = String(body.client_id ?? "").slice(0, 30);17 const kaId = String(body.ka_id ?? "").slice(0, 20);18 if (!verifyClientSig(clientId, kaId, String(body.ts ?? ""), String(body.sig ?? "")))19 return NextResponse.json({ error: "signature invalide" }, { status: 401 });20 const user = findUserByKaId(kaId);21 if (!user)22 return NextResponse.json({ error: "membre introuvable" }, { status: 404 });2324 if (!privacyOf(user.id).history)25 return NextResponse.json({ ok: true, stored: 0, history: false });2627 const events = Array.isArray(body.events) ? (body.events as Record<string, unknown>[]) : [];28 const stored = ingestEvents(user.id, clientId, events);29 return NextResponse.json({ ok: true, stored });30}31