[{"data":1,"prerenderedAt":680},["ShallowReactive",2],{"navigation_docs":3,"-docs-architecture-llm-settings-and-secret-storage":174,"-docs-architecture-llm-settings-and-secret-storage-surround":675},[4,25,54,88,112,127],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":6},"Getting Started",false,"\u002Fdocs\u002Fgetting-started","docs\u002F1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Why Zeeq?","\u002Fdocs\u002Fgetting-started\u002Fintroduction","docs\u002F1.getting-started\u002F1.introduction","i-lucide-house",{"title":16,"path":17,"stem":18,"icon":19},"Key Features","\u002Fdocs\u002Fgetting-started\u002Fkey-features","docs\u002F1.getting-started\u002F2.key-features","i-lucide-blocks",{"title":21,"path":22,"stem":23,"icon":24},"Connecting Agents","\u002Fdocs\u002Fgetting-started\u002Fconnecting-agents","docs\u002F1.getting-started\u002F3.connecting-agents","i-lucide-plug",{"title":26,"icon":6,"path":27,"stem":28,"children":29,"page":6},"Feature Overview","\u002Fdocs\u002Fkey-features","docs\u002F2.key-features",[30,34,38,42,46,50],{"title":31,"path":32,"stem":33,"icon":19},"Knowledge Libraries","\u002Fdocs\u002Fkey-features\u002Fknowledge-libraries","docs\u002F2.key-features\u002F1.knowledge-libraries",{"title":35,"path":36,"stem":37,"icon":19},"Code Reviews","\u002Fdocs\u002Fkey-features\u002Fcode-reviews","docs\u002F2.key-features\u002F2.code-reviews",{"title":39,"path":40,"stem":41,"icon":19},"Code Review as Agent Tool","\u002Fdocs\u002Fkey-features\u002Fcode-review-tool","docs\u002F2.key-features\u002F3.code-review-tool",{"title":43,"path":44,"stem":45,"icon":19},"Telemetry","\u002Fdocs\u002Fkey-features\u002Ftelemetry","docs\u002F2.key-features\u002F4.telemetry",{"title":47,"path":48,"stem":49,"icon":19},"Dynamic Skills (2026 Q3)","\u002Fdocs\u002Fkey-features\u002Fdynamic-skills","docs\u002F2.key-features\u002F5.dynamic-skills",{"title":51,"path":52,"stem":53,"icon":19},"World Model (2026 Q3)","\u002Fdocs\u002Fkey-features\u002Fworld-model","docs\u002F2.key-features\u002F6.world-model",{"title":55,"path":56,"stem":57,"children":58,"page":6},"Managing Zeeq","\u002Fdocs\u002Fmanaging-zeeq","docs\u002F3.managing-zeeq",[59,64,69,73,78,83],{"title":60,"path":61,"stem":62,"icon":63},"GitHub Configuration","\u002Fdocs\u002Fmanaging-zeeq\u002Fgithub-configuration","docs\u002F3.managing-zeeq\u002F1.github-configuration","i-lucide-github",{"title":65,"path":66,"stem":67,"icon":68},"Organizations and Membership","\u002Fdocs\u002Fmanaging-zeeq\u002Forgs-membership-invitations","docs\u002F3.managing-zeeq\u002F2.orgs-membership-invitations","i-hugeicons-cube",{"title":31,"path":70,"stem":71,"icon":72},"\u002Fdocs\u002Fmanaging-zeeq\u002Fdocument-libraries","docs\u002F3.managing-zeeq\u002F3.document-libraries","i-lucide-library-big",{"title":74,"path":75,"stem":76,"icon":77},"LLM Settings Configuration","\u002Fdocs\u002Fmanaging-zeeq\u002Fllm-settings-configuration","docs\u002F3.managing-zeeq\u002F4.llm-settings-configuration","i-hugeicons-ai-magic",{"title":79,"path":80,"stem":81,"icon":82},"Agent Code Review","\u002Fdocs\u002Fmanaging-zeeq\u002Fagent-code-reviews","docs\u002F3.managing-zeeq\u002F5.agent-code-reviews","i-hugeicons-chat-spark-01",{"title":84,"path":85,"stem":86,"icon":87},"Credentials & API Tokens","\u002Fdocs\u002Fmanaging-zeeq\u002Fcredentials","docs\u002F3.managing-zeeq\u002F6.credentials","i-hugeicons-key-01",{"title":89,"path":90,"stem":91,"children":92,"page":6},"Runtime Configuration","\u002Fdocs\u002Fconfiguration","docs\u002F5.configuration",[93,98,102,107],{"title":94,"path":95,"stem":96,"icon":97},"Google Cloud Configuration","\u002Fdocs\u002Fconfiguration\u002Fgcp-runtime","docs\u002F5.configuration\u002F1.gcp-runtime","i-hugeicons-google",{"title":60,"path":99,"stem":100,"icon":101},"\u002Fdocs\u002Fconfiguration\u002Fgithub-configuration","docs\u002F5.configuration\u002F2.github-configuration","i-hugeicons-github",{"title":103,"path":104,"stem":105,"icon":106},"Local OpenIddict Certificates","\u002Fdocs\u002Fconfiguration\u002Flocal-openiddict-certificates","docs\u002F5.configuration\u002F3.local-openiddict-certificates","i-lucide-file-lock",{"title":108,"path":109,"stem":110,"icon":111},"System Admin Access","\u002Fdocs\u002Fconfiguration\u002Fsystem-admin-access","docs\u002F5.configuration\u002F4.system-admin-access","i-hugeicons-shield-01",{"title":113,"path":114,"stem":115,"children":116,"page":6},"Metrics","\u002Fdocs\u002Fmetrics","docs\u002F6.metrics",[117,122],{"title":118,"path":119,"stem":120,"icon":121},"Metrics Dashboard","\u002Fdocs\u002Fmetrics\u002Fmetrics-dashboard","docs\u002F6.metrics\u002F1.metrics-dashboard","i-hugeicons-analytics-01",{"title":123,"path":124,"stem":125,"icon":126},"Metrics Pipeline","\u002Fdocs\u002Fmetrics\u002Fmetrics-pipeline","docs\u002F6.metrics\u002F2.metrics-pipeline","i-hugeicons-database-02",{"title":128,"path":129,"stem":130,"children":131,"page":6},"Design and Architecture","\u002Fdocs\u002Farchitecture","docs\u002F9.architecture",[132,137,142,146,150,155,160,165,170],{"title":133,"path":134,"stem":135,"icon":136},"Caching","\u002Fdocs\u002Farchitecture\u002Fcaching","docs\u002F9.architecture\u002F1.caching","i-lucide-database",{"title":138,"path":139,"stem":140,"icon":141},"Messaging and Queueing","\u002Fdocs\u002Farchitecture\u002Fmessaging-and-queueing","docs\u002F9.architecture\u002F2.messaging-and-queueing","i-lucide-message-square",{"title":143,"path":144,"stem":145,"icon":63},"GitHub Comment Rendering","\u002Fdocs\u002Farchitecture\u002Fgithub-comment-rendering","docs\u002F9.architecture\u002F3.github-comment-rendering",{"title":147,"path":148,"stem":149,"icon":63},"GitHub Integration","\u002Fdocs\u002Farchitecture\u002Fgithub-integration","docs\u002F9.architecture\u002F4.github-integration",{"title":151,"path":152,"stem":153,"icon":154},"LLM Settings and Secret Storage","\u002Fdocs\u002Farchitecture\u002Fllm-settings-and-secret-storage","docs\u002F9.architecture\u002F5.llm-settings-and-secret-storage","i-lucide-key",{"title":156,"path":157,"stem":158,"icon":159},"Organization Activation and Routes","\u002Fdocs\u002Farchitecture\u002Forganization-activation-and-routes","docs\u002F9.architecture\u002F6.organization-activation-and-routes","i-lucide-door-open",{"title":161,"path":162,"stem":163,"icon":164},"MCP Uploaded-Diff Code Reviews","\u002Fdocs\u002Farchitecture\u002Fmcp-uploaded-diff-code-reviews","docs\u002F9.architecture\u002F7.mcp-uploaded-diff-code-reviews","i-lucide-file-search",{"title":166,"path":167,"stem":168,"icon":169},"Repository Content Ingest","\u002Fdocs\u002Farchitecture\u002Frepository-content-ingest","docs\u002F9.architecture\u002F8.repository-content-ingest","i-lucide-file-stack",{"title":171,"path":172,"stem":173},"Telemetry Ingest (2026 Q3)","\u002Fdocs\u002Farchitecture\u002Ftelemetry-ingest","docs\u002F9.architecture\u002F9.telemetry-ingest",{"id":175,"title":151,"body":176,"description":668,"extension":669,"links":670,"meta":671,"navigation":672,"path":152,"seo":673,"stem":153,"__hash__":674},"docs\u002Fdocs\u002F9.architecture\u002F5.llm-settings-and-secret-storage.md",{"type":177,"value":178,"toc":656},"minimark",[179,184,188,192,211,214,279,290,293,297,300,334,356,360,370,377,380,422,425,429,436,439,443,446,449,452,490,493,497,507,510,513,550,560,563,567,570,653],[180,181,183],"h2",{"id":182},"summary","Summary",[185,186,187],"p",{},"Zeeq stores organization LLM settings separately from API key material. The organization configuration records provider, model, and an optional encrypted key reference for each workload tier; key plaintext is never persisted.",[180,189,191],{"id":190},"data-model","Data model",[185,193,194,198,199,202,203,206,207,210],{},[195,196,197],"code",{},"Organization.LlmConfiguration"," is a typed JSON document stored on the organization row. It contains the ",[195,200,201],{},"Fast",", ",[195,204,205],{},"High",", and ",[195,208,209],{},"Max"," tier selections.",[185,212,213],{},"Each tier stores:",[215,216,217,230],"table",{},[218,219,220],"thead",{},[221,222,223,227],"tr",{},[224,225,226],"th",{},"Field",[224,228,229],{},"Meaning",[231,232,233,255,265],"tbody",{},[221,234,235,241],{},[236,237,238],"td",{},[195,239,240],{},"Provider",[236,242,243,244,202,247,250,251,254],{},"Provider name such as ",[195,245,246],{},"Fireworks",[195,248,249],{},"OpenAI",", or ",[195,252,253],{},"Anthropic",".",[221,256,257,262],{},[236,258,259],{},[195,260,261],{},"Model",[236,263,264],{},"Provider model identifier.",[221,266,267,272],{},[236,268,269],{},[195,270,271],{},"KeyId",[236,273,274,275,278],{},"Optional encrypted-value ID. ",[195,276,277],{},"null"," is valid only for Fireworks default-key tiers.",[185,280,281,282,285,286,289],{},"Tenant-owned API keys are stored in ",[195,283,284],{},"core_encrypted_values"," as ",[195,287,288],{},"EncryptedValueKind.LlmApiKey"," rows. Each row includes organization scope, display name, ciphertext, timestamps, disabled state, and the encryption provider that produced the ciphertext.",[185,291,292],{},"The encrypted row does not store the LLM provider. Provider selection belongs to tier configuration, not secret metadata.",[180,294,296],{"id":295},"credential-paths","Credential paths",[185,298,299],{},"Zeeq uses two credential paths:",[215,301,302,312],{},[218,303,304],{},[221,305,306,309],{},[224,307,308],{},"Path",[224,310,311],{},"Use",[231,313,314,326],{},[221,315,316,319],{},[236,317,318],{},"Default credentials",[236,320,321,322,325],{},"App-level Fireworks defaults loaded from runtime configuration. These are Zeeq-owned credentials and are not tenant data. The default model is Fireworks GLM 5.2 (",[195,323,324],{},"accounts\u002Ffireworks\u002Fmodels\u002Fglm-5p2",").",[221,327,328,331],{},[236,329,330],{},"Tenant credentials",[236,332,333],{},"Organization-owned managed keys encrypted before persistence. These are required for OpenAI and Anthropic selections.",[185,335,336,337,340,341,202,343,206,345,347,348,351,352,355],{},"The default-key path registers scoped keyed ",[195,338,339],{},"IChatClient"," services for ",[195,342,201],{},[195,344,205],{},[195,346,209],{}," and wraps them in ",[195,349,350],{},"DefaultLlmChatClients",". Tenant credentials are resolved at runtime and passed to ",[195,353,354],{},"ILlmClientFactory","; they are not registered as singleton or scoped DI services.",[180,357,359],{"id":358},"encryption-providers","Encryption providers",[185,361,362,365,366,369],{},[195,363,364],{},"KeyEncryptionService"," orchestrates encryption and decryption. The active ",[195,367,368],{},"AppSettings:Llm:EncryptionProvider"," controls new and rotated rows only.",[185,371,372,373,376],{},"On decrypt, the service uses the row's stored ",[195,374,375],{},"EncryptionProvider",", not the current app setting. This allows an environment to move from local Data Protection to Cloud KMS without breaking older rows.",[185,378,379],{},"Supported provider names:",[215,381,382,394],{},[218,383,384],{},[221,385,386,388,391],{},[224,387,240],{},[224,389,390],{},"Environment",[224,392,393],{},"Purpose",[231,395,396,409],{},[221,397,398,403,406],{},[236,399,400],{},[195,401,402],{},"data-protection",[236,404,405],{},"Development only",[236,407,408],{},"Local persisted key ring for developer machines.",[221,410,411,416,419],{},[236,412,413],{},[195,414,415],{},"cloud-kms",[236,417,418],{},"Production",[236,420,421],{},"Google Cloud KMS-backed encryption for tenant secrets.",[185,423,424],{},"Plaintext decrypt results are cached in memory for 30 minutes by organization, encrypted row ID, and row update timestamp. Disabled rows are checked before cache lookup, so disabled keys cannot be served from cache.",[180,426,428],{"id":427},"local-data-protection","Local data protection",[185,430,431,432,435],{},"Local development uses ASP.NET Core Data Protection with a persisted file-system key ring at ",[195,433,434],{},".secrets\u002Fdata-protection-keys"," by default. The directory is created automatically and is ignored by the repository.",[185,437,438],{},"This lets encrypted keys survive app restarts without introducing a hand-managed symmetric key. The provider is rejected outside Development.",[180,440,442],{"id":441},"cloud-run-and-kms","Cloud Run and KMS",[185,444,445],{},"Production uses Cloud KMS because Cloud Run file systems are ephemeral and not shared across instances. The key-encryption key remains in Google Cloud, access is governed by IAM, and key versions can be rotated or disabled centrally.",[185,447,448],{},"Zeeq uses direct symmetric Cloud KMS encrypt\u002Fdecrypt operations for small API key strings. It does not currently use envelope encryption because the plaintext payload is a small secret, not a large document or blob.",[185,450,451],{},"KMS cost is bounded by the call pattern:",[215,453,454,464],{},[218,455,456],{},[221,457,458,461],{},[224,459,460],{},"Event",[224,462,463],{},"KMS use",[231,465,466,474,482],{},[221,467,468,471],{},[236,469,470],{},"Create managed key",[236,472,473],{},"Encrypt once.",[221,475,476,479],{},[236,477,478],{},"Rotate managed key",[236,480,481],{},"Encrypt once with the currently active provider.",[221,483,484,487],{},[236,485,486],{},"First decrypt after cache miss",[236,488,489],{},"Decrypt once, then cache briefly server-side.",[185,491,492],{},"Plaintext is never logged, traced, returned to clients, stored in Postgres, or used as a cache key.",[180,494,496],{"id":495},"provider-clients-and-agents","Provider clients and agents",[185,498,499,502,503,506],{},[195,500,501],{},"LlmClientFactory"," builds ",[195,504,505],{},"Microsoft.Extensions.AI"," chat clients and Microsoft Agent Framework agents from resolved configuration.",[185,508,509],{},"The factory stores only non-secret dependencies. Provider SDK clients receive API keys only when a caller creates a client or agent for a specific resolved credential.",[185,511,512],{},"The current implementation supports OpenAI-compatible providers through the OpenAI SDK path:",[215,514,515,524],{},[218,516,517],{},[221,518,519,521],{},[224,520,240],{},[224,522,523],{},"Client path",[231,525,526,536,543],{},[221,527,528,530],{},[236,529,246],{},[236,531,532,533,254],{},"OpenAI-compatible endpoint ",[195,534,535],{},"https:\u002F\u002Fapi.fireworks.ai\u002Finference\u002Fv1",[221,537,538,540],{},[236,539,249],{},[236,541,542],{},"OpenAI SDK default endpoint.",[221,544,545,547],{},[236,546,253],{},[236,548,549],{},"UI cataloged, but not wired to a chat-client adapter yet.",[185,551,552,553,556,557,254],{},"DeepSeek models are reachable only through Fireworks (e.g. ",[195,554,555],{},"accounts\u002Ffireworks\u002Fmodels\u002Fdeepseek-v4-pro","). DeepSeek-direct is no longer a selectable provider and is rejected by the factory as ",[195,558,559],{},"unsupported_provider",[185,561,562],{},"Provider access tests and future runtime consumers must resolve organization, tier, provider, model, key source, and endpoint before calling the factory.",[180,564,566],{"id":565},"api-surface","API surface",[185,568,569],{},"LLM settings endpoints are organization-scoped and owner\u002Fadmin restricted:",[215,571,572,581],{},[218,573,574],{},[221,575,576,579],{},[224,577,578],{},"Endpoint",[224,580,393],{},[231,582,583,593,603,613,623,633,643],{},[221,584,585,590],{},[236,586,587],{},[195,588,589],{},"GET \u002Fapi\u002Fv1\u002Forgs\u002F{orgId}\u002Fllm-settings",[236,591,592],{},"Reads tier settings and key metadata for managers; non-admin members receive a notice-only response.",[221,594,595,600],{},[236,596,597],{},[195,598,599],{},"PUT \u002Fapi\u002Fv1\u002Forgs\u002F{orgId}\u002Fllm-settings",[236,601,602],{},"Saves all three tier selections after validating managed-key references.",[221,604,605,610],{},[236,606,607],{},[195,608,609],{},"POST \u002Fapi\u002Fv1\u002Forgs\u002F{orgId}\u002Fllm-settings\u002Ftest",[236,611,612],{},"Runs a bounded provider\u002Fmodel\u002Fkey access test with sanitized output.",[221,614,615,620],{},[236,616,617],{},[195,618,619],{},"POST \u002Fapi\u002Fv1\u002Forgs\u002F{orgId}\u002Fllm-settings\u002Fkeys",[236,621,622],{},"Creates a tenant-managed encrypted key.",[221,624,625,630],{},[236,626,627],{},[195,628,629],{},"PATCH \u002Fapi\u002Fv1\u002Forgs\u002F{orgId}\u002Fllm-settings\u002Fkeys\u002F{keyId}\u002Fname",[236,631,632],{},"Renames key metadata.",[221,634,635,640],{},[236,636,637],{},[195,638,639],{},"PUT \u002Fapi\u002Fv1\u002Forgs\u002F{orgId}\u002Fllm-settings\u002Fkeys\u002F{keyId}\u002Frotate",[236,641,642],{},"Replaces the encrypted value for an existing key ID.",[221,644,645,650],{},[236,646,647],{},[195,648,649],{},"DELETE \u002Fapi\u002Fv1\u002Forgs\u002F{orgId}\u002Fllm-settings\u002Fkeys\u002F{keyId}",[236,651,652],{},"Soft-disables an unreferenced key.",[185,654,655],{},"The API never returns plaintext, masked key text derived from plaintext, API key prefixes or suffixes, raw provider bodies, or generated model text.",{"title":657,"searchDepth":658,"depth":658,"links":659},"",2,[660,661,662,663,664,665,666,667],{"id":182,"depth":658,"text":183},{"id":190,"depth":658,"text":191},{"id":295,"depth":658,"text":296},{"id":358,"depth":658,"text":359},{"id":427,"depth":658,"text":428},{"id":441,"depth":658,"text":442},{"id":495,"depth":658,"text":496},{"id":565,"depth":658,"text":566},"Architecture for organization LLM configuration, encrypted tenant keys, and default LLM clients.","md",null,{"icon":87},{"icon":154},{"title":151,"description":668},"Bac4e_JLHK4UXnTEQWcxw9ykKWmHLYmXgLRBvqvSlzo",[676,678],{"title":147,"path":148,"stem":149,"description":677,"icon":63,"children":-1},"How Zeeq links a GitHub App installation and registers repositories for webhook work.",{"title":156,"path":157,"stem":158,"description":679,"icon":159,"children":-1},"How organization activation gates mutation APIs and why org-scoped APIs use route org IDs.",1784410275537]