Kliento Pusės DI Valdymas: Architektūriniai Modeliai Politikos Taikymui, C2PA Kilmei ir DLP Next.js
Išsami apžvalga apie dirbtinio intelekto valdymo integravimą Next.js sąsajose, apimanti kliento pusės DLP, OWASP LLM išvesties valymą, ES DI akto C2PA kilmės pasirašymą ir audito telemetriją.

Generatyvinio dirbtinio intelekto funkcijoms ir naršyklėje veikiantiems inferencijos modeliams (tokiems kaip WebLLM, Vercel AI SDK bei vietiniams darbuotojų įskiepiams) kylant į šiuolaikinių žiniatinklio programų standartą, DI valdymas persikėlė tiesiai į sąsajos technologijų stack'ą. Saugumas nebėra vien tik galinės dalies vartų atsakomybė; kliento pusės programos privalo taikyti griežtą duomenų nutekėjimo prevenciją (DLP), tikrinti nedeterministines modelio išvestis nuo įterpimo pažeidžiamumų, užtikrinti atitiktį reglamentams, tokiems kaip ES DI akto 50 straipsnis, ir teikti struktūrizuotą audito telemetriją.
Nuo 2026 m. rugpjūčio mėn. ES DI aktas aiškiai reikalauja mašininiu būdu nuskaitomo, sąveikaus atskleidimo ir kilmės žymėjimo DI sugeneruotam turiniui. Žiniatinklio inžinerijos komandoms, norinčioms atitikti šiuos teisinius ir saugumo reikalavimus, reikalinga struktūrizuota visapusiškos gynybos architektūra, įdiegta tiesiai mūsų React ir Next.js programose.
Šiame vadove nagrinėjame 4 lygmenų kliento pusės DI valdymo sluoksnį, sukurtą Next.js App Router programoms, kartu su TypeScript realizacijomis užklausų DLP, Zod grindžiamoms srauto apsaugoms, C2PA metaduomenų pasirašymui ir privatumą saugantiems OpenTelemetry audito žurnalams.
4 Lygmenų Sąsajos DI Valdymo Sluoksnis
Norint apsaugoti vartotojo sesijos būseną, išvengti OWASP Top 10 LLM pažeidžiamumų (ypač LLM01: Užklausų Įterpimo ir LLM05: Netinkamo Išvesties Tvarkymo) bei įvykdyti skaidrumo reikalavimus, mūsų sąsajos architektūra padalija valdymą į keturis skirtingus lygmenis:
┌───────────────────────────────────────────────────────────────────────┐
│ Next.js App Router Application │
│ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Tier 1: Client DLP & Input Sanitization │ │
│ │ ├─ Regex entropy scanning & PII redaction │ │
│ │ └─ Prompt injection detection heuristics │ │
│ └────────────────────────────────┬────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Tier 2: Edge Guardrail & Output Sanitizer │ │
│ │ ├─ Zod schema stream validation │ │
│ │ └─ DOMPurify AST filter & XSS containment │ │
│ └────────────────────────────────┬────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Tier 3: C2PA Provenance & Watermark Injector │ │
│ │ ├─ Article 50 manifest digital signing │ │
│ │ └─ Machine-readable visual provenance badge │ │
│ └────────────────────────────────┬────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────────────────┐ │
│ │ Tier 4: Privacy-Preserving Audit Telemetry │ │
│ │ ├─ SHA-256 context hashing & model latency metrics │ │
│ │ └─ Structured OpenTelemetry audit logger │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────────┘1 Lygmuo: Kliento Pusės Duomenų Nutekėjimo Prevencija (DLP)
Prieš išsiunčiant vartotojo užklausą LLM teikėjui arba vietiniam WebGPU varikliui, ji turi būti įvertinta kliento pusėje, kad jautrūs duomenys (API raktai, kreditinės kortelės, JWT žetonai, PII) neišeitų iš vartotojo naršyklės smėlio dėžės.
Kuriame lengvą React kabliuką (useSanitizedPrompt), kuris atlieka entropija grindžiamą slapukų skenavimą ir reguliariųjų reškinių kaukes prieš tinklo išsiuntimą:
import { useMemo, useState } from "react";
interface PIIPattern {
name: string;
regex: RegExp;
replacement: string;
}
const DEFAULT_PATTERNS: PIIPattern[] = [
{
name: "API_KEY",
regex: /(?:sk|pk)_(?:live|test)_[0-9a-zA-Z]{24,32}/g,
replacement: "[REDACTED_API_KEY]"
},
{
name: "BEARER_TOKEN",
regex: /Bearer\s+[A-Za-z0-9\-\._~\+\/]+=*/g,
replacement: "Bearer [REDACTED_TOKEN]"
},
{
name: "EMAIL",
regex: /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,
replacement: "[REDACTED_EMAIL]"
},
{
name: "CREDIT_CARD",
regex: /\b(?:\d[ -]*?){13,16}\b/g,
replacement: "[REDACTED_CARD]"
}
];
// Shannon Entropy check to catch high-randomness string tokens
function calculateShannonEntropy(str: string): number {
const map: Record<string, number> = {};
for (let i = 0; i < str.length; i++) {
const char = str[i];
map[char] = (map[char] || 0) + 1;
}
let entropy = 0;
for (const char in map) {
const p = map[char] / str.length;
entropy -= p * Math.log2(p);
}
return entropy;
}
export function useSanitizedPrompt() {
const [violations, setViolations] = useState<string[]>([]);
const sanitize = (rawInput: string): { cleanPrompt: string; isSafe: boolean } => {
let cleanPrompt = rawInput;
const detectedViolations: string[] = [];
// 1. Apply RegEx Redaction
for (const pattern of DEFAULT_PATTERNS) {
if (pattern.regex.test(cleanPrompt)) {
detectedViolations.push(pattern.name);
cleanPrompt = cleanPrompt.replace(pattern.regex, pattern.replacement);
}
}
// 2. High Entropy Word Detection (Catch secrets not matching fixed regex)
const words = cleanPrompt.split(/\s+/);
const sanitizedWords = words.map((word) => {
if (word.length > 20 && calculateShannonEntropy(word) > 4.5) {
detectedViolations.push("HIGH_ENTROPY_TOKEN");
return "[REDACTED_HIGH_ENTROPY_TOKEN]";
}
return word;
});
cleanPrompt = sanitizedWords.join(" ");
setViolations(detectedViolations);
return {
cleanPrompt,
isSafe: detectedViolations.length === 0
};
};
return { sanitize, violations };
}2 Lygmuo: Srauto Išvesties Apsaugos ir XSS Suvaldymas
OWASP LLM05 (Netinkamas Išvesties Tvarkymas) įvyksta, kai DI modelio atsakymai atvaizduojami tiesiai sąsajoje neatlikus DOM valymo, kas sukelia išsaugotas arba atspindėtas Cross-Site Scripting (XSS) atakas.
Next.js App Router programose transliuojami LLM atsakymai turi būti patikrinti pagal griežtą Zod schemą serverio arba krašto maršrute, o atvaizduojami HTML komponentai apdoroja AST fragmentus per sukonfigūruotą DOMPurify grandinę:
import { z } from "zod";
import DOMPurify from "isomorphic-dompurify";
// Define strict output expectations for structured AI component responses
export const AIComponentResponseSchema = z.object({
componentName: z.string().max(64),
summary: z.string().max(500),
actionPayload: z.record(z.unknown()).optional(),
renderedHtml: z.string().transform((val) =>
DOMPurify.sanitize(val, {
ALLOWED_TAGS: ["b", "i", "em", "strong", "a", "code", "pre", "p", "ul", "li"],
ALLOWED_ATTR: ["href", "target", "rel", "class"],
ALLOW_DATA_ATTR: false
})
)
});
export type AIComponentResponse = z.infer<typeof AIComponentResponseSchema>;
export async function validateAndSanitizeStream(rawChunk: unknown): Promise<AIComponentResponse> {
const parseResult = AIComponentResponseSchema.safeParse(rawChunk);
if (!parseResult.success) {
throw new Error(`AI Governance Guardrail Violation: ${parseResult.error.message}`);
}
return parseResult.data;
}3 Lygmuo: ES DI Akto 50 Straipsnis ir C2PA Kilmės Pasirašymas
ES DI akto 50 straipsnis reikalauja, kad sintetinį turinį (tekstą, garso įrašus, kodą ar vaizdus) kuriančios žiniatinklio programos įterptų mašininiu būdu nuskaitomus metaduomenis ir pateiktų aiškius vizualius atskleidimus.
1. Serverio Pusės C2PA Manifesto Pasirašymas (Server Action)
Sugeneruotus išteklius pasirašome jų sukūrimo metu, kurdami C2PA manifestą, kuriame yra pretenzijos informacija, generatoriaus metaduomenys ir skaitmeniniai parašai:
"use server";
import { createC2PAManifest } from "@contentauth/c2pa-node";
export interface AIContentProvenanceOptions {
modelName: string;
promptHash: string;
authorOrg: string;
}
export async function signGeneratedAssetProvenance(
assetBuffer: Buffer,
options: AIContentProvenanceOptions
): Promise<Buffer> {
const manifest = createC2PAManifest({
claim_generator: `${options.authorOrg}/NextJS-AIGovernanceEngine/1.0`,
title: "Generative AI Output Asset",
assertions: [
{
label: "c2pa.actions",
data: {
actions: [
{
action: "c2pa.created",
digitalSourceType: "https://cv.iptc.org/newscodes/digitalsourcetype/trainedAlgorithmicMedia"
}
]
}
},
{
label: "org.eu.aiact.compliance",
data: {
article: "Article 50",
model_name: options.modelName,
prompt_sha256: options.promptHash,
timestamp: new Date().toISOString()
}
}
]
});
// Embed signed manifest into binary buffer
const signedBuffer = await manifest.embedIntoBuffer(assetBuffer);
return signedBuffer;
}2. Prieinamas Vartotojo Sąsajos Kilmės Ženkliuko Komponentas
Kiekvienas DI sugeneruotas sąsajos blokas turi rodyti nuolatinį, netrukdantį ženkliuką, leidžiantį vartotojams patikrinti kilmės duomenis:
"use client";
import React, { useState } from "react";
interface ProvenanceBadgeProps {
modelName: string;
timestamp: string;
isCompliant: boolean;
}
export const ContentProvenanceBadge: React.FC<ProvenanceBadgeProps> = ({
modelName,
timestamp,
isCompliant
}) => {
const [showModal, setShowModal] = useState(false);
return (
<div className="inline-flex items-center gap-2 text-xs font-mono text-neutral-600 bg-neutral-100 dark:bg-neutral-800 px-2.5 py-1 rounded-md border border-neutral-200 dark:border-neutral-700">
<span className="inline-block w-2 h-2 rounded-full bg-emerald-500" aria-hidden="true" />
<span>AI Generated ({modelName})</span>
<button
onClick={() => setShowModal(!showModal)}
className="underline hover:text-neutral-900 dark:hover:text-neutral-100 transition-colors ml-1"
aria-label="View C2PA Provenance Metadata"
>
Verify C2PA
</button>
{showModal && (
<div
role="dialog"
aria-modal="true"
aria-label="Provenance Metadata Details"
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm p-4"
>
<div className="bg-white dark:bg-neutral-900 border border-neutral-200 dark:border-neutral-800 rounded-lg max-w-md w-full p-6 shadow-xl text-left">
<h3 className="text-sm font-semibold text-neutral-900 dark:text-neutral-100 mb-2">
EU AI Act Article 50 Provenance Card
</h3>
<div className="space-y-2 text-xs text-neutral-600 dark:text-neutral-300 font-mono">
<p><strong>Generator Model:</strong> {modelName}</p>
<p><strong>Generation Timestamp:</strong> {timestamp}</p>
<p><strong>C2PA Standard:</strong> Manifest V1.3 Signed</p>
<p><strong>Compliance Status:</strong> {isCompliant ? "VERIFIED_COMPLIANT" : "UNVERIFIED"}</p>
</div>
<div className="mt-4 flex justify-end">
<button
onClick={() => setShowModal(false)}
className="px-3 py-1.5 bg-neutral-900 text-white dark:bg-neutral-100 dark:text-neutral-900 rounded text-xs font-medium"
>
Close
</button>
</div>
</div>
</div>
)}
</div>
);
};4 Lygmuo: Nekintamas Auditas ir Telemetrijos Redagavimas
Įmonės atitikčiai ir tyrimams po incidentų kiekviena DI sąveika privalo generuoti struktūrizuotus žurnalus. Svarbiausia, kad telemetrija fiksuotų valdymo vykdymą neišsaugodama atvirojo teksto vartotojo įvesčių ar asmeninių identifikatorių.
Kuriame kriptografinį audito registratorių, naudojantį Web Crypto API užklausoms maišyti ir telemetrijos įvykiams įrašyti:
export interface GovernanceAuditEvent {
sessionId: string;
modelIdentifier: string;
promptHash: string;
dlpViolations: string[];
outputSanitized: boolean;
latencyMs: number;
timestamp: string;
}
export async function createGovernanceAuditEvent(
sessionId: string,
modelIdentifier: string,
rawPrompt: string,
dlpViolations: string[],
outputSanitized: boolean,
latencyMs: number
): Promise<GovernanceAuditEvent> {
// Compute SHA-256 hash of raw prompt to prevent PII log persistence
const encoder = new TextEncoder();
const data = encoder.encode(rawPrompt);
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const promptHash = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
const auditEvent: GovernanceAuditEvent = {
sessionId,
modelIdentifier,
promptHash,
dlpViolations,
outputSanitized,
latencyMs,
timestamp: new Date().toISOString()
};
// Dispatch to OpenTelemetry endpoint or internal log aggregator
if (process.env.NODE_ENV === "production") {
fetch("/api/telemetry/governance", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(auditEvent)
}).catch((err) => console.error("Failed to ship governance audit log:", err));
}
return auditEvent;
}Našumo ir Atvaizdavimo Biudžetai
Kliento pusės DLP skenavimo, Zod srauto tikrinimo ir C2PA metaduomenų analizės įtraukimas sukelia papildomą vykdimo apkrovą. Sklandžiai 60fps vartotojo sąsajos patirčiai palaikyti reikalingi griežti našumo biudžetai:
1. DLP Papildomos Apkrovos Švelninimas
Reguliariųjų reškinių skenavimas ir Šanono entropijos skaičiavimas 2000 žodžių užklausai šiuolaikiniuose V8 varikliuose užtrunka ~1,8 ms. Kad įvesties laukai išliktų reaktyvūs, vykdykite useSanitizedPrompt atidėtame (debounced) iškvietime arba perkelkite sunkius skaičiavimus į Web Worker.
2. Rinkinio Dydžio Biudžetai
DOMPurify(izomorfinė versija): ~9.2kB gzippedZod: ~12.4kB gzipped@contentauth/c2paNode SDK: Laikomas griežtai serveryje (Server Actions / API maršrutuose), kad į kliento rinkinius nebūtų siunčiamos sunkios WASM kriptografinės bibliotekos. Kliento komponentas (ContentProvenanceBadge) sveria < 2kB.
3. Vėlavimo Metrikų Suvestinė
| Governance Tier | Runtime Location | Average Latency Impact | Bundle Impact (Gzipped) |
|---|---|---|---|
| Tier 1: Client DLP | React Hook / Client | 1.2ms - 2.5ms | ~1.5kB |
| Tier 2: Output Sanitizer | Edge Middleware / Server | 3.0ms - 8.0ms | ~21.6kB (Server/Shared) |
| Tier 3: C2PA Signing | Server Action | 15.0ms - 45.0ms | 0kB (Server Only) |
| Tier 4: Audit Telemetry | Async Fetch / Background | 0ms (Non-blocking) | ~0.8kB |
Santrauka
Sąsajos DI valdymas yra būtina inžinerinė disciplina šiuolaikinėms žiniatinklio programoms. Įdiegiant kliento pusės DLP skenavimą, taikant transliuojamus Zod schemos apsaugos rėmus, pasirašant išvestis C2PA metaduomenimis ES DI akto atitikčiai ir generuojant anonimizuotus audito žurnalus, sąsajos komandos gali kurti saugias, atsparias ir visiškai reikalavimus atitinkančias DI valdomas vartotojo sąsajas.