AdvisoryAI Deployment Guide (AIAI-31-008)
This guide covers packaging AdvisoryAI for on-prem / offline environments, toggling remote inference, and recommended scaling settings.
Artifacts
- Dockerfile:
ops/advisory-ai/Dockerfile(multi-role build for WebService / Worker). - Local compose:
ops/advisory-ai/docker-compose.advisoryai.yaml(web + worker, shared data volume). - Kubernetes and Helm are not a supported Stella Ops release target. Any legacy chart material is historical only and must not be used as deployment or release guidance.
Build and run locally
# Build images
make advisoryai-web: docker build -f ops/advisory-ai/Dockerfile -t stellaops-advisoryai-web:dev \
--build-arg PROJECT=src/AdvisoryAI/StellaOps.AdvisoryAI.WebService/StellaOps.AdvisoryAI.WebService.csproj \
--build-arg APP_DLL=StellaOps.AdvisoryAI.WebService.dll .
make advisoryai-worker: docker build -f ops/advisory-ai/Dockerfile -t stellaops-advisoryai-worker:dev \
--build-arg PROJECT=src/AdvisoryAI/StellaOps.AdvisoryAI.Worker/StellaOps.AdvisoryAI.Worker.csproj \
--build-arg APP_DLL=StellaOps.AdvisoryAI.Worker.dll .
# Compose (offline friendly)
docker compose -f ops/advisory-ai/docker-compose.advisoryai.yaml up -d --build
Remote inference toggle
- Default:
ADVISORYAI__AdvisoryAI__Inference__Mode=Local(fully offline). - Remote: set
ADVISORYAI__AdvisoryAI__Inference__Mode=RemoteADVISORYAI__AdvisoryAI__Inference__Remote__BaseAddress=https://inference.example.comADVISORYAI__AdvisoryAI__Inference__Remote__Endpoint=/v1/inferenceADVISORYAI__AdvisoryAI__Inference__Remote__ApiKey=<token>- Optional:
ADVISORYAI__AdvisoryAI__Inference__Remote__Timeout=00:00:30
- Guardrails still enforced locally (see
ADVISORYAI__AdvisoryAI__Guardrails__*options); keep secrets in mounted env/secret rather than images.
Evidence retrieval binding
advisory-ai-webrequiresAdvisoryAI:EvidenceRetrieval:BaseAddressin production-like hosts so explanation requests can anchor claims to live Scanner evidence.- The supported compose setup sets
ADVISORYAI__AdvisoryAI__EvidenceRetrieval__BaseAddress=${ADVISORY_AI_EVIDENCE_RETRIEVAL_BASEADDRESS:-http://scanner.stella-ops.local}. - The binding calls Scanner’s unified triage evidence endpoint (
/api/v1/triage/findings/{findingId}/evidence) through thescanner-internalHTTP client, so Authority client-credentials auth and tenant claims follow the same path as the AdvisoryAI live search adapters. - If this setting is missing outside an explicit Development/Testing local harness,
IEvidenceRetrievalServiceremains fail-closed. Do not useAdvisoryAI:RuntimeBindings:AllowLocalHarnessFakes=trueto make a supported compose stack pass.
Frontdoor routing
- The supported compose gateway proxies AdvisoryAI HTTP surfaces directly to
http://advisoryai.stella-ops.local:/api/v1/advisory-ai/*,/v1/advisory-ai/*,/api/v1/search/*, and/v1/evidence-packs/*. - These gateway entries use
ReverseProxywithPreserveAuthHeaders=truebecauseadvisory-ai-webtrusts the gateway-signed identity envelope. Do not configure these paths as gatewayMicroserviceroutes in compose; that path depends on router service-discovery metadata and can return gateway-level 404s even when the AdvisoryAI container is healthy.
Volume ownership
- The supported compose setup runs
advisory-ai-data-initbeforeadvisory-ai-webandadvisory-ai-worker. It creates/var/lib/advisory-ai/{queue,plans,outputs}on the named volumes, owns them as UID/GID10001:10001, and restricts permissions to the service user. - Both hosts mount the same named volumes at
/var/lib/advisory-ai/queue,/var/lib/advisory-ai/plans, and/var/lib/advisory-ai/outputs; do not point either host at/tmpin supported setup. - Without this init step, Docker-created named volumes are root-owned. The web service can still answer read-only explanation requests, but plan creation fails when
FileSystemAdvisoryTaskQueuetries to create its.quarantinedirectory and the worker will not reliably drain shared plans.
Storage & persistence
- File-system queue/cache/output paths default to
/app/data/{queue,plans,outputs}and are pre-created at startup. - Compose mounts separate
advisory-ai-queue,advisory-ai-plans, andadvisory-ai-outputsvolumes. Kubernetes PVC and Helm persistence settings are outside the supported release model. - In sealed/air-gapped mode, mount guardrail lists/policy knobs under
/app/etcand point env vars accordingly. - Runtime PostgreSQL is required for live consent, attestation, explanation replay, policy-intent, run, conversation, chat-settings, and chat-audit state. Connection resolution is
AdvisoryAI:Storage:ConnectionString->ConnectionStrings:Default->Database:ConnectionString; the host auto-migrates theadvisoryaischema when configured. - Production-like hosts fail closed when durable/runtime bindings are missing.
Null*,NoOp*, andInMemory*runtime bindings may only bind inDevelopmentorTestingwithAdvisoryAI:RuntimeBindings:AllowLocalHarnessFakes=true; do not set that flag in supported release manifests. - The
dummyLLM provider is also gated by the same explicit local harness switch. Production-like hosts do not register it, so a straydummy.yamlunderetc/llm-providerscannot become an available LLM backend.
In-house model gateway readiness
- Production-like
advisory-ai-webchat binds the in-house OpenAI-compatible gateway withADVISORYAI__AdvisoryAI__Chat__Inference__Provider=inhouse-ternaryand an operator-suppliedADVISORYAI__AdvisoryAI__Chat__Inference__BaseUrl. - The default setup example uses
microsoft/bitnet-b1.58-2B-4T, an MIT-licensed native 1.58-bit/ternary roughly 2B-parameter model. Stella Ops does not bundle model weights; operators must install/serve the model through an approved local gateway, for example a bitnet.cpp CPU gateway using a locally approved GGUF variant. - Production validation remains fail-closed. Set
ADVISORYAI__AdvisoryAI__Chat__Inference__ModelDigest=sha256:<digest>andADVISORYAI__AdvisoryAI__Chat__Inference__CapabilityValidation__RequireModelDigestMatch=trueonce the gateway registry exposes the operator-approved digest or signed model manifest. No release note, benchmark, or support claim should be made until the configured endpoint, digest/manifest, capabilities, JSON mode, and citation behavior pass validation. - The gateway registry (
GET /v1/models) must list the configured model withchat.completions,response_format.json_object,citations.required,seed, andtop_kcapabilities. - Supported release probes should use
/health/readyfor readiness and/health/livefor process liveness./health/modelreturns the gateway status object for operators. - Readiness fails closed with a structured diagnostic when the gateway is unreachable, the model is absent, required capabilities are missing, or the digest rule fails. There is no cloud fallback, dummy fallback, sanitized prompt echo, or production prompt-preview behavior.
- Compose and appsettings examples wire these settings explicitly. For a full appsettings sample, see
docs/modules/advisory-ai/samples/inhouse-model-gateway.appsettings.json. - Release guide note: model-selection guidance must be updated before adopting a future custom or larger Stella Ops model, including the new model id, license, local runtime, hardware envelope, digest/manifest requirement, and validation evidence.
PostgreSQL attribution and pooling
- AdvisoryAI knowledge-search and unified-search PostgreSQL traffic now uses a shared pooled
NpgsqlDataSourceinstead of per-operation transient data sources or raw connections. - Default
application_nameisstellaops-advisory-ai-web/knowledge-search, which makespg_stat_activityattribution stable for the web service. - Default idle-pool retention is
900seconds so the shared pool stays warm across the 5-minute unified-search refresh cycle instead of re-opening physical sessions each run. - Override these with:
ADVISORYAI__KnowledgeSearch__DatabaseApplicationNameADVISORYAI__KnowledgeSearch__DatabasePoolingEnabledADVISORYAI__KnowledgeSearch__DatabaseMinPoolSizeADVISORYAI__KnowledgeSearch__DatabaseMaxPoolSizeADVISORYAI__KnowledgeSearch__DatabaseConnectionIdleLifetimeSeconds
- Existing
ADVISORYAI__KnowledgeSearch__ConnectionStringremains authoritative for host/database/credentials; the new options only stamp attribution and pool behavior.
Scaling guidance
- WebService: start with 1 process, scale horizontally by CPU (tokenization) or queue depth; set
ADVISORYAI__AdvisoryAI__Queue__DirectoryPathto shared durable storage only when running multiple web/worker processes on supported hosts. - Worker: scale independently with compose or service-manager replicas. Workers are CPU-bound; pin CPU/memory in the host supervisor.
- Set rate limiter headers: add
X-StellaOps-Clientper caller to avoid shared buckets.
Offline posture
- Images build from source without external runtime downloads; keep
ADVISORYAI__AdvisoryAI__Inference__Mode=Localto stay offline. - For registry-mirrored environments, push
stellaops-advisoryai-webandstellaops-advisoryai-workerto the allowed registry and reference them from the supported compose/service-manager release path. - Disable OTEL exporters unless explicitly permitted; logs remain structured JSON to stdout.
Air-gap checklist
- Remote inference disabled (or routed through approved enclave).
- Guardrail phrase list mounted read-only.
- Data volume scoped per tenant/project if multi-tenant; enforce scope via
X-StellaOps-Scopes. - Validate that
/app/datavolume has backup/retention policy; cache pruning handled by storage options.
Deliverables mapping
- Compose + Dockerfile satisfy on-prem packaging.
- Kubernetes/Helm packaging is out of scope for current Stella Ops releases.
- This guide documents scaling/offline posture required by Sprint 0110 AIAI-31-008.
