veylant/web/src/pages/docs/getting-started/KeyConceptsPage.tsx
2026-02-27 23:33:07 +01:00

128 lines
6.1 KiB
TypeScript

import { Callout } from "../components/Callout";
const concepts = [
{
term: "Tenant",
definition:
"A logical unit of isolation — typically a company or business unit. All data in PostgreSQL is isolated by tenant_id via Row-Level Security. A tenant can have multiple users, multiple routing rules, and separate cost quotas.",
},
{
term: "Routing Rule",
definition:
"A policy that matches incoming AI requests based on conditions (user role, department, model, token estimate, sensitivity) and routes them to a specific provider with optional fallback. Rules are sorted by priority (lower = evaluated first). First match wins.",
},
{
term: "PII (Personally Identifiable Information)",
definition:
"Data that can identify a person: names, email addresses, phone numbers, IBANs, SSNs, credit card numbers, etc. Veylant IA detects and anonymizes PII in prompts before they leave your network.",
},
{
term: "Pseudonymization",
definition:
"A reversible PII replacement technique. Detected PII tokens are replaced with synthetic identifiers (e.g., PERSON_001) and the original→synthetic mapping is stored in Redis (AES-256-GCM encrypted, TTL-based). The LLM works with the synthetic data; the response can optionally be de-pseudonymized.",
},
{
term: "Audit Log",
definition:
"An immutable record of every AI request: tenant, user, model, provider, token counts, cost, PII entities detected, policy matched, latency, and response status. Stored in ClickHouse (append-only). Retention via TTL policies — no DELETE operations.",
},
{
term: "Provider Adapter",
definition:
"A Go interface (Send, Stream, Validate, HealthCheck) implemented for each LLM provider. The routing engine selects the adapter; all adapters return OpenAI-format responses regardless of the upstream API.",
},
{
term: "Circuit Breaker",
definition:
"A per-provider failure counter. When failures exceed a threshold (default: 5), the breaker opens and the provider is bypassed for a TTL period (default: 60s). The fallback chain in the routing rule is used instead.",
},
{
term: "RBAC",
definition:
"Role-Based Access Control. Four roles: admin (full access), manager (read-write policies and users), user (inference only, restricted models), auditor (read-only logs and compliance, no inference). Roles are embedded in the Keycloak JWT.",
},
{
term: "Feature Flag",
definition:
"A boolean or string flag stored in PostgreSQL with an in-memory cache. Used to gate features without redeployment. Falls back to in-memory defaults if the database is unavailable.",
},
{
term: "GDPR Article 30",
definition:
"The GDPR requirement to maintain a Record of Processing Activities (ROPA). Veylant IA provides a built-in registry with fields for use case, legal basis, data categories, retention period, recipients, and processors.",
},
{
term: "EU AI Act",
definition:
"EU regulation classifying AI systems by risk level: forbidden, high, limited, or minimal. Veylant IA's compliance module helps you classify each use case through a structured questionnaire and generates PDF reports.",
},
{
term: "SLO (Service Level Objective)",
definition:
"Veylant IA targets 99.5% availability and p95 latency < 500ms. These are tracked in the production Grafana dashboard with an error budget that updates in real time.",
},
];
export function KeyConceptsPage() {
return (
<div>
<h1 id="key-concepts">Key Concepts</h1>
<p>
This glossary explains the core abstractions you'll encounter when working with Veylant IA.
</p>
<Callout type="tip" title="Reading order">
If you're new to Veylant IA, read{" "}
<a href="/docs">What is Veylant IA?</a> first, then come back here before
diving into the API reference or guides.
</Callout>
<h2 id="glossary">Glossary</h2>
<div className="space-y-4 my-4">
{concepts.map((c) => (
<div key={c.term} className="rounded-lg border bg-card p-4">
<dt className="font-semibold text-foreground mb-1.5">{c.term}</dt>
<dd className="text-sm text-muted-foreground leading-relaxed">{c.definition}</dd>
</div>
))}
</div>
<h2 id="request-lifecycle">Request Lifecycle</h2>
<p>What happens when a client sends a request to <code>POST /v1/chat/completions</code>:</p>
<div className="my-4 rounded-lg border bg-zinc-950 text-zinc-100 p-4 font-mono text-xs leading-loose overflow-x-auto">
<pre>{`1. Request arrives at Go proxy (:8090)
2. RequestID middleware → generate X-Request-ID
3. SecurityHeaders middleware → set CSP, HSTS, COOP headers
4. CORS middleware → validate Origin header
5. Auth middleware → validate Bearer JWT (Keycloak or mock)
→ extract tenant_id, user_id, role, department from claims
6. RateLimit middleware → check per-tenant token bucket (Redis)
→ if exceeded: 429 with Retry-After header
7. RBAC check → validate role has access to requested model
8. Routing engine → evaluate rules (priority ASC, first match)
→ select provider + fallback chain
9. PII detection → gRPC call to PII service (<50ms budget)
→ anonymize/pseudonymize prompt
10. Circuit breaker check → skip if provider is open
11. Provider adapter → forward to LLM (stream or batch)
12. Audit logger → async ClickHouse write (non-blocking)
13. Response returned to client`}</pre>
</div>
<h2 id="multi-tenancy">Multi-tenancy Model</h2>
<p>
Veylant IA uses <strong>logical isolation</strong> via PostgreSQL Row-Level Security (RLS).
The application connects as role <code>veylant_app</code> and sets{" "}
<code>app.tenant_id</code> per session using a middleware. All queries automatically filter
by tenant without requiring explicit <code>WHERE</code> clauses in application code.
</p>
<p>
Physical isolation (separate database instances per tenant) is a V2 feature. See the
feedback backlog.
</p>
</div>
);
}