Air-Gap Hardcoded-Value Audit (core-service · assistant-service · KMS)¶
Source-code audit (2026-06-17) for values hardcoded in src/ that bypass TOML/env/models.yaml
config and therefore break silently in the air-gapped environment — cloud model ids, external
endpoints, and baked defaults. These can't be fixed by Helm values; they need a source patch or a
LiteLLM/DNS alias. Severity is about whether the broken path fails loudly (crash) or silently
(caught exception → degraded feature).
Scope
Tests/notebooks excluded. "Silent" = the feature returns empty/unchanged/fallback on error instead of crashing, so "all pods Running" hides it.
Severity 1 — silent functional breaks (fix before relying on the feature)¶
| # | Service | Location | Hardcoded value | Effect air-gap |
|---|---|---|---|---|
| 1 | assistant-service | tooling/.../knowledge_base/core_tools/retrieval/retrieval_tool.py:81; retrieve_schemas.py:83; mufti_agent/.../knowledge_search_tool.py:43 |
embeddings allow-list = {BAAI/bge-m3, BAAI/bge-large-en-v1.5}, default BAAI/bge-m3; rejects anything else |
VERIFIED LIKELY INERT (downgraded). KMS embeds the query with the organization's stored model (retriever_service.py:134 → organization_config.embedding_model_id = our qwen/qwen3-embedding-0-6b), not the caller's value — so the tool's BAAI id is ignored at retrieval. ⚠️ Residual risk only if the tool embeds the query locally with BAAI and sends a vector (it sends text + an id, so KMS does the embedding). Confirm with a real KB search. |
| 2 | assistant-service | intelligence/.../citations/post_answer_citations.py:37 |
model_name="azure/gpt-5-chat" |
citation LLM 404s → node catches it, returns chunks unchanged → citations silently skipped |
| 3 | assistant-service | tooling/config/settings.py:168,172,176,462 |
defaults azure/gpt-5-chat ×3, anthropic/claude-3-7-sonnet |
ToolsSettings reads ENV; if a field isn't env-overridden the cloud default 404s when that tool runs |
| 4 | assistant-service | assistants/services/meta_agent_service.py:79 |
_DEFAULT_LLM_MODEL_ID = "gpt-5" |
meta-agent default → 404 if meta-agent runs without an explicit served model |
Severity 2 — baked model catalogs (layer-2; air-gap override needed)¶
| # | Service | Location | Issue |
|---|---|---|---|
| 5 | core-service | model_provider/models/models.yml |
full cloud catalog (anthropic/claude-*, gpt-5*, grok, BAAI/*) — core-service's equivalent of assistant's models.yaml; user/org model choices resolve to unserved ids |
| 6 | assistant-service | assistants/services/llm_model_service.py _TEXT/_VOICE_MODEL_PRIORITY |
cloud-ordered picker priority; filtered by get_enabled_models_for_org (cloud entries are noise if org enables only served models) |
| 7 | assistant-service | src/shared/llm/llm_models/models.yaml |
the baked catalog with cloud api_model_names — see model-references Layer 2 |
Severity 3 — dormant with current config (don't enable)¶
| # | Service | Location | Note |
|---|---|---|---|
| 8 | KMS | knowledge_management/config/document_understanding.py:50 |
https://{di_resource_name}.cognitiveservices.azure.com/ — Azure Document Intelligence. Only built when parsing_strategy = AZURE_DOCUMENT_INTELLIGENCE. Our config uses generic/quick (Foundry VLM), so it's dormant. Do not switch parsing strategy to azure. |
Severity 4 — external optional integrations (feature-level, fail only when invoked)¶
| # | Service | Location | Note |
|---|---|---|---|
| 9 | assistant-service | tooling/tools/google_maps/*, tooling/tools/email/* (Gmail), tooling/core/auth/providers/google.py |
maps.googleapis.com, gmail.googleapis.com, oauth2.googleapis.com — external SaaS tools; unreachable air-gap, fail only if a user invokes that tool |
| 10 | core-service | core_service/configs/connector_catalog.yaml, utils/connection_utils.py |
Google Drive/Gmail/Calendar connector scopes (googleapis.com) + cdn.ask.dev.ai71services.ai icon URLs (external CDN — icons won't load, cosmetic) |
KMS source is clean
KMS src/ has no hardcoded model ids — embedding/VLM models come from config
(embedding_model_id, vlm_model_name), which we set to served qwen models. Its only external
hardcode is the gated Azure DI endpoint (#8).
Recommended remediation¶
- #1 (KB embeddings) — highest priority for the assistant↔KMS story. Either patch the tool's
allow-list/default to the served
qwen/qwen3-embedding-0-6b, or confirm KMS ignores the caller-suppliedembedding_model_idand uses the collection's stored model (then the BAAI value is inert). Verify with a real KB search before trusting it. - #2/#3/#4 (
azure/gpt-5-chatetc. in source) — the pragmatic fix is a LiteLLM alias on the Foundry gateway: registerazure/gpt-5-chat→qwen/qwen3-5-122b-a10b(andanthropic/claude-3-7-sonnet→ a served model). One alias fixes every hardcoded reference at once, no source edits. See model-references Layer 3. - #5/#6/#7 (catalogs) — air-gap catalog override (ConfigMap for
models.yaml; equivalent for core-servicemodels.yml) + org-enabled-models limited to served ids. - #8 — leave
parsing_strategyongeneric/quick; neverazure. - #9/#10 — disable the external connector/tool features in the catalog, or accept they're inactive air-gap.
LiteLLM alias request (for the Foundry/platform team)¶
The Severity-1/2 hardcoded cloud model ids in source (azure/gpt-5-chat, anthropic/claude-3-7-sonnet,
gpt-5) can't be fixed by our Helm values. Rather than patch every call site in the sanitized repo,
the cleanest fix is to alias them on the LiteLLM gateway so each resolves to a served OSS model.
One alias neutralizes every hardcoded reference at once.
Request to the team that owns foundry-litellm (the foundry-litellm-config ConfigMap):
add alias entries to the LiteLLM model_list so these resolve to served models:
| Hardcoded id (from assistant-service source) | Alias to (served) | Used by |
|---|---|---|
azure/gpt-5-chat |
qwen/qwen3-5-122b-a10b |
citations (post_answer_citations), tooling defaults, token counting |
anthropic/claude-3-7-sonnet |
qwen/qwen3-5-122b-a10b |
tooling settings.py:462 default |
gpt-5 |
qwen/qwen3-5-122b-a10b |
meta-agent default (meta_agent_service.py:79) |
LiteLLM config shape (illustrative — the team applies it in their ConfigMap):
model_list:
- model_name: azure/gpt-5-chat # the alias clients call
litellm_params:
model: hosted_vllm/qwen-3-5-122b-a10b # the real served backend
api_base: http://<vllm-backend>/v1
- model_name: anthropic/claude-3-7-sonnet
litellm_params: { model: hosted_vllm/qwen-3-5-122b-a10b, api_base: ... }
- model_name: gpt-5
litellm_params: { model: hosted_vllm/qwen-3-5-122b-a10b, api_base: ... }
Why aliases, not source edits: the ids are hardcoded across multiple files in a vendored/sanitized
repo; aliasing keeps the fix in one place (the gateway), survives chart bumps, and matches how the
deviation is otherwise handled. Trade-off: a chat that says it used "claude-3-7-sonnet" is really
served by qwen — acceptable for air-gap, and documented here. Verify after: re-run a flow that hits
citations and confirm no 404 model not found in the intelligence logs.
How to re-run this audit¶
cd <repo>/src
# hardcoded cloud model ids
grep -rnE "\"(azure|anthropic|openai|x-ai|cohere|google|BAAI)/[A-Za-z0-9._-]+\"|\"gpt-5[A-Za-z0-9.-]*\"|\"claude-[A-Za-z0-9.-]+\"|\"grok-[0-9]" . | grep -viE "test|\.ipynb"
# hardcoded external hosts
grep -rnE "azurecr\.io|\.azure\.com|\.openai\.com|blob\.core\.windows\.net|cognitiveservices|amazonaws\.com|\.googleapis\.com|\.gov\.ae|ai71services\.ai|cohere\.(ai|com)|cr\.weaviate\.io|sentry\.io" . | grep -viE "test|\.ipynb"