AI_INTEGRATION — analytics-service
Sibling: APPLICATION_LOGIC · DOMAIN_MODEL · DATA_MODEL §5.6 · platform anchors: docs/08 AI Architecture, docs/07 §11
analytics-service is the read-side data plane for the platform's AI stack. It does not run inference itself. Two relationships matter:
- Outbound: we publish aggregated, AI-ready signals (
metric.computed.v1) and expose curated tables thatai-orchestrator-servicequeries through its own service account. - Inbound: we consume
melmastoon.ai.forecast.produced.v1and writeback model outputs intofact_demand_forecast_v1so dashboards andreporting-servicecan show forecasts side-by-side with actuals.
We also use the platform AIClient for two narrowly scoped capabilities used inside analytics-service itself.
1. Capabilities exposed to the platform
| Capability | Producer | Consumer | Purpose |
|---|---|---|---|
metric.computed.v1 events for a forecast feature set | this service | ai-orchestrator-service | Inputs to demand-forecast model |
Curated read access to fact_reservation_v1, fact_payment_v1, dim_* | this service (BigQuery view binding) | ai-orchestrator-service (own GSA) | Training and feature extraction |
dim_calendar_v1 shared dimension | this service | all model consumers | Stable date attributes, holidays |
Write-target fact_demand_forecast_v1 | this service | ai-orchestrator-service (event-driven writeback) | Forecast outputs |
The orchestrator's GSA is granted roles/bigquery.dataViewer on the curated dataset and on per-tenant authorized views; it does not have access to events_raw.* to limit raw PII exposure.
2. Capabilities used by analytics-service
| Capability key | Goal | Pattern | Surface |
|---|---|---|---|
analytics.metric_explainer.v1 | Plain-language explanation of a metric value & trend ("Occupancy fell 18 % vs 4-week median; explained by a 30 % drop in OTA bookings on Sun") | LLM with grounded numeric facts | API: GET /api/v1/analytics/metrics/{key}/explain?from=…&to=… |
analytics.dashboard_assistant.v1 | Convert a natural-language ask ("show me last month's RevPAR vs forecast for Property A") into a widget spec | LLM tool-use over metric registry | API: POST /api/v1/analytics/ai/widget-draft |
Both flow through ai-orchestrator-service over the AIClient port. They are off by default and enabled per tenant in tenant settings.
3. Capability invariants
- Tenant-scoped. Every call carries
tenantId, optionaluserId,correlationId. Orchestrator enforces tenant model allow-list and data residency. - No raw PII as prompt context. Prompts include only aggregated values, dimensions, and metric metadata. We never send guest names, document numbers, or raw event payloads.
- Citations required. Outputs are stored with
AIProvenance(DOMAIN_MODEL §2) and rendered with an "AI-generated · review before sharing" badge. Explanations include numeric citations referenced back to the underlying fact rows by(metric_key, window, dimension_value). - HITL for write actions. "Apply this draft widget" creates a draft
Widgetwith a flag and never mutates the live dashboard until a human confirms (POST /api/v1/analytics/widgets/{id}:confirm). - Budget guardrails. Per-tenant monthly cap configured via
tenant-service. Orchestrator returns429 MELMASTOON.AI.BUDGET_EXHAUSTEDand we degrade gracefully (skip explanation; surface raw values). - Off-switch. Tenant admin can disable any capability under Settings → AI; the off-switch is enforced server-side.
4. Outbound feature signal pipeline
[ETL completes]
▼
[ComputeMetricUseCase] computes the forecast feature set per (tenant, property, room_type, business_date) at 06:00 local
▼
publish: melmastoon.analytics.metric.computed.v1 (one envelope per feature batch)
▼
[ai-orchestrator-service] subscribes selectively to feature metric keys
▼
[forecast-model] produces predictions + confidence intervals
▼
publish: melmastoon.ai.forecast.produced.v1
▼
[analytics-service.IngestForecastWritebackUseCase]
▼
MERGE INTO fact_demand_forecast_v1 …
▼
publish: melmastoon.analytics.projection.refreshed.v1 (target: fact_demand_forecast_v1)
Feature set keys (default): reservation.occupancy_pct, reservation.adr, reservation.alos_nights, reservation.cancellation_rate, funnel.meta_to_book_pct, channel.revenue_mix_pct, housekeeping.task_throughput. Lead times, day-of-week, and holiday flags come from dim_calendar_v1.
5. Forecast writeback contract
Inbound payload melmastoon.ai.forecast.produced.v1:
interface AIForecastProducedV1 {
tenantId: string;
forecastId: string; // fcs_<ulid>
modelId: string; // 'demand_forecast'
modelVersion: string; // '2026.04.01-v3'
producedAt: string;
predictions: Array<{
propertyId: string;
roomTypeId: string;
businessDate: string;
horizonDays: number;
predictedOccupancyPct: number;
predictedAdr: number;
ci80LowOccupancy: number;
ci80HighOccupancy: number;
}>;
provenance: AIProvenance;
}
Writeback logic:
- Validate tenant and property scope (every prediction must belong to the envelope's tenant).
- Idempotency:
MERGEon(tenant_id, property_id, room_type_id, business_date, horizon_days, model_version). - Bound batch sizes (≤ 5,000 rows per envelope). Larger payloads are split by the publisher.
- Reject (
MELMASTOON.ANALYTICS.FORECAST_INVALID_TENANT) if the envelope'stenantIdmismatches a row.
6. Provenance & audit
Every AI-affected analytics output stores a non-null aiProvenance on the relevant entity (widget snapshot, metric explanation, widget draft). The completed event payloads include metadata.ai. Acceptance is measured by the platform-shared metric ai_orchestrator.acceptance_rate:
- For
analytics.dashboard_assistant.v1: drafted widgets that are subsequently confirmed. - For
analytics.metric_explainer.v1: explanations that the user kept (vs dismissed).
7. Privacy & residency
- AI calls inherit
tenant.dataResidency. If a tenant's residency isKSAand the only model satisfying the capability isEU-hosted, the orchestrator returnsMELMASTOON.AI.RESIDENCY_VIOLATIONand we degrade. - Explanations cite numeric facts present in the rendered widget; the renderer rejects any citation whose
factRefdoes not resolve. - Tenant admin can require that prompts never be retained by the orchestrator (
tenant.aiSettings.retainPrompts === false).
8. Failure & degradation matrix
| Failure | Effect | UX |
|---|---|---|
Orchestrator timeout (> maxLatencyMs) | Skip explanation; emit warning | Widget renders without AI block |
| Orchestrator 5xx | Skip + structured warn log; circuit-breaker opens for 60 s | |
| Budget exhausted | Skip + once-per-day notify tenant.owner | |
| Residency violation | Skip; structured warn log | |
| Forecast writeback validation fail | Drop the offending row; log; emit data_quality.alert.v1 { severity: 'critical' } | Operator alerted |
| Forecast writeback partial fail | MERGE within tx; partial commit not allowed; entire envelope rejected for retry | n/a |
9. Cross-references
- AIProvenance shape: DOMAIN_MODEL §2
- Capability registry: docs/08 §3
- Forecast table DDL: DATA_MODEL §5.6
- Tenant AI settings:
services/tenant-service/DOMAIN_MODEL.md - Acceptance metric definition: DOMAIN_MODEL §3 (
ai_orchestrator.acceptance_rate)