Skip to main content

AI Integration

:::info Source Sourced from services/tenant-service/AI_INTEGRATION.md in the documentation repo. :::

Blueprint doc 8 of 17. Companion: 03 ai-gateway-service | 13 §8 AI Safety


1. Scope of AI Use

The tenant-service is a light consumer of AI. It does not generate learning content or perform AI grading. Its AI surfaces are focused on operational hygiene:

CapabilityPurposeClassification (EU AI Act)
Invite abuse detectionClassify invite email domains for spam/abuseLimited risk
Role suggestionSuggest roles based on org-unit compositionLimited risk (suggestion-only, HITL required)
Dynamic group query assistanceNatural-language → ABAC query translationLimited risk (suggestion-only, HITL required)
Settings anomaly detectionAlert on unusual tenant configuration changesLimited risk (internal alerting)
Org-unit hierarchy suggestionGiven a spreadsheet of users, suggest hierarchyLimited risk (suggestion-only, HITL required)

No AI call in the tenant-service ever auto-applies a change. All AI output is advisory; a human must accept.


2. AIClient Port Contract

Per frozen F09 contract, all AI calls route through the AIClient port:

interface AIClient {
classify(req: ClassifyRequest): Promise<ClassifyResult>;
complete(req: CompleteRequest): Promise<CompleteResult>;
completeStream(req: CompleteRequest): AsyncIterable<CompleteChunk>;
embed(req: EmbedRequest): Promise<EmbedResult>;
}

interface ClassifyRequest {
promptId: string;
promptVersion: SemVer;
input: JSONValue;
tenantId: TenantId;
correlationId: ULID;
budgetId: string;
residency: Region;
}

interface ClassifyResult {
label: string;
confidence: number;
provenance: AIProvenance;
}

The tenant-service imports only this port. An infrastructure adapter AiGatewayHttpClient wires to the ai-gateway-service. No vendor SDKs imported directly.


3. Registered Prompts

All prompts live in the prompt registry (frozen F10 + F22) under namespace tenant/:

3.1 tenant/invite.abuse_classifier v1

Purpose: Classify email invitation payloads for spam/abuse.

Input schema:

{
email: string; // redacted username → 'user@domain.com' passed as 'x@domain.com'
tenantAge: ISODuration;
invitesLast24h: number;
domainReputation: 'known_good' | 'known_bad' | 'unknown';
}

Output schema:

{
label: 'legitimate' | 'suspicious' | 'abusive';
confidence: number;
reasons: string[];
}

Policy: Runs pre-call PII redaction; email username hashed. Budget quota: 10k calls/day per tenant. Route: local model first (tiny classifier), escalate to small cloud only on uncertainty.

3.2 tenant/role.suggester v1

Purpose: Given a user's profile snippet and org-unit context, suggest 1-3 role templates.

Input schema:

{
userSnippet: { displayName: string; titleHint?: string }; // no email, no PII
orgUnitPath: string;
existingRoles: string[];
tenantIndustry?: string;
}

Output schema:

{
suggestions: Array<{
roleName: string;
confidence: number;
rationale: string;
}>;
}

HITL: UI shows suggestions; admin must click "Apply". Audit records decisionId linking suggestion to acceptance/rejection.

3.3 tenant/dg_query.nl_to_dsl v1

Purpose: Convert natural language ("engineering learners who joined in the last 90 days") to ABAC ABACQuery DSL.

Input schema:

{
nlQuery: string; // max 500 chars
schemaDescription: string; // canned context
availableFields: string[];
}

Output schema: Structured generation (JSON Schema = ABACQuery).

Policy: Structured output validation required — invalid output returned as unresolved and a fallback UI builder is shown. Prompt injection shield pre-call (mandatory since input is user-controlled).

3.4 tenant/settings.anomaly_detector v1

Purpose: Detect anomalous settings changes (e.g., bulk role deletion, MFA disabled off-hours).

Input schema: Recent audit event sequence (redacted).

Output schema: { anomalyScore: number; explanation: string }.

Policy: Runs on sampled audit events; alerts routed to #sec-tenant-anomalies. Not user-facing.

3.5 tenant/org.hierarchy_suggester v1

Purpose: Given an uploaded CSV of users (name, title, department), suggest an org-unit hierarchy.

Input schema: CSV rows with PII-minimized fields.

Output schema: Suggested OrgUnitTree.

HITL: Admin reviews and edits tree before applying. Acceptance creates actual OrgUnit rows.


4. AIProvenance Invariant

Per frozen F04, every AI-produced artifact carries:

interface AIProvenance {
model: string;
version?: string;
promptId: string;
promptVersion: SemVer;
traceId: string;
decisionId?: string; // present when HITL acceptance occurred
local: boolean;
generatedAt: ISODate;
reviewedBy?: UserId;
reviewedAt?: ISODate;
cost?: { microUSD: number; tokens: { in: number; out: number } };
}

Storage: AIProvenance attached to any persisted AI suggestion (e.g., in authz_decisions_audit.request_context.ai_provenance when AI was consulted).


5. Budget & Quota

Per platform AI governance:

CapabilityDefault tenant budgetHard stop behavior
Invite abuse classifier$5/dayFall back to heuristic rules only
Role suggester$2/dayHide suggestion UI
NL→DSL translator$3/dayShow empty-state; fall back to manual builder
Anomaly detector$1/day (platform-scoped)Disable; alert SRE
Hierarchy suggester$10/importReject suggestion; manual CSV mapping required

Budgets enforced by ai-gateway-service; tenant-service receives BUDGET_EXCEEDED error and handles gracefully.


6. Safety & Moderation

Every call routed via ai-gateway-service, which applies:

  1. Pre-call PII redaction (configurable; enabled by default for tenant data).
  2. Prompt-injection shield (mandatory for nl_to_dsl since input is user-controlled text).
  3. Post-call moderation (mandatory for any output surfaced to admins).
  4. Structured-output schema validation (Ajv against declared output schema).

Violations: event ai.safety_violation.v1 emitted; request fails; fallback UI shown.


7. No-Training Guarantee

All prompts in tenant namespace are tagged no_training: true. The ai-gateway-service enforces this against provider configs (OpenAI org_training_disabled, Anthropic no-train flag, vendor-specific assertions verified at integration test layer).


8. Tenant-Scoped AI Governance

Per-tenant controls (stored in TenantSettings.ai):

interface TenantAISettings {
aiEnabled: boolean; // master gate
aiTutorEnabled: boolean; // downstream feature
allowedCapabilities: string[]; // e.g., ['invite_classifier', 'role_suggester']
forbiddenCapabilities: string[];
localOnly: boolean; // disallow cloud models
residencyStrictMode: boolean; // enforce AI calls stay in homeRegion
opt_out_reason?: string;
}

9. Bias Monitoring

role.suggester is sampled quarterly for demographic parity on consenting tenants. Metrics:

  • Do org_owner suggestions correlate with proxy gender signals (from first names)?
  • Do author suggestions correlate with department language (English vs Arabic)?

Output: quarterly bias report; material drift triggers prompt version bump with mitigations.


10. Human Override Paths

  • Role suggester: Dismiss/reject button always visible. Reason field optional.
  • NL→DSL: Always allow switching to manual query builder.
  • Hierarchy suggester: Diff UI lets admin edit any suggested node before accepting.
  • Anomaly detector: Ack/dismiss in SRE dashboard.

All overrides logged with decisionId for the quarterly AI safety review.


11. Testing

  • Prompt regression suite: fixed inputs → asserted outputs within tolerance (evaluated by ai-gateway-service eval harness on every prompt version bump).
  • Safety eval: adversarial inputs (prompt injection, PII exfiltration attempts) must be refused or safe.
  • Contract test: tenant-service consumes AIClient — Pact contract with ai-gateway-service.
  • Fallback test: AI disabled → all tenant flows still work (feature-flag override to disable AI globally).

12. AI Readiness Gate (G5)

MilestoneRequirement
M0No AI features required at tenant-service L2
M3Invite classifier + role suggester live; prompt regression green
M4NL→DSL + hierarchy suggester live; bias eval baseline
M5All five capabilities in production; quarterly external bias audit