feat(cloud): manage LLM providers in database
Tests / Test passed: 664

This commit is contained in:
2026-07-14 00:31:47 +08:00
parent b613a315ff
commit a166ffd8a4
35 changed files with 2432 additions and 204 deletions
@@ -0,0 +1,100 @@
## ADDED Requirements
### Requirement: Cloud-wide LLM Provider profiles are durable and validated
The Cloud Control Plane SHALL persist administrator-managed LLM Provider
profiles with a unique name, provider type, model, timeout, enabled state,
revision, and timestamps. A profile's provider type SHALL be either
`anthropic` or `openai-compatible`; an OpenAI-compatible profile MAY specify
an absolute HTTP(S) base URL and SHALL use the official OpenAI endpoint when
it does not.
#### Scenario: Administrator creates an OpenAI-compatible profile
- **WHEN** an authorized administrator submits a unique profile name,
`openai-compatible` provider type, model, valid timeout, API key, and an
optional valid base URL
- **THEN** the Cloud Control Plane persists an enabled profile with a new
revision and returns its non-secret metadata
#### Scenario: Invalid profile configuration is rejected
- **WHEN** an administrator submits an unsupported provider type, blank model,
non-positive timeout, duplicate name, or invalid base URL
- **THEN** the Cloud Control Plane rejects the write without creating or
changing a profile
### Requirement: Provider API keys are encrypted and never disclosed
The Cloud Control Plane SHALL encrypt Provider API keys before persistence
using a deployment-held encryption key, and SHALL not expose plaintext keys in
read responses, validation errors, audit records, or application logs.
#### Scenario: Provider profile is listed after creation
- **WHEN** an authorized administrator lists Provider profiles after creating
one with an API key
- **THEN** every response reports only key-presence and rotation metadata and
does not contain the submitted API key or its ciphertext
#### Scenario: Encryption configuration is unavailable
- **WHEN** a database-managed profile is created, rotated, activated, or
resolved without a valid deployment encryption key
- **THEN** the operation fails with a controlled configuration error that does
not reveal an API key
### Requirement: Administrators can manage and activate Provider profiles
The Cloud Control Plane SHALL expose session-CSRF-protected and scope-guarded
operations to list, create, update, rotate a key, enable, disable, activate,
and delete inactive LLM Provider profiles. Mutating operations SHALL require
the `llm-providers:admin` scope and record a non-secret audit event.
#### Scenario: Non-administrator attempts to modify a profile
- **WHEN** a principal without `llm-providers:admin` invokes a Provider
mutation endpoint
- **THEN** the Cloud Control Plane rejects the request before decrypting or
modifying a Provider credential
#### Scenario: Administrator switches the active profile
- **WHEN** an authorized administrator activates an enabled profile
- **THEN** the Cloud Control Plane atomically selects that profile as the one
Cloud-wide active profile and records the activation without retaining an
API key in the audit event
#### Scenario: Administrator attempts to retire the active profile
- **WHEN** an administrator attempts to disable or delete the active profile
before activating a replacement
- **THEN** the Cloud Control Plane rejects the operation and preserves the
active profile selection
### Requirement: Activation dynamically selects one Provider for cloud transport
The Cloud Control Plane SHALL resolve the active database-managed profile for
each Cloud planner decision and SHALL apply an activation to subsequent
requests without requiring a Cloud API restart or any Host Agent
reconfiguration.
#### Scenario: A Host requests a decision after a model switch
- **WHEN** an administrator activates a different enabled profile and a
cloud-transport Host Agent submits its next planner-decision request
- **THEN** the Cloud Control Plane calls that profile's provider, model,
timeout, base URL, and API key while the Host Agent continues using the same
Cloud Control Plane endpoint
#### Scenario: Active OpenAI-compatible profile is used
- **WHEN** the active profile is OpenAI-compatible and includes a base URL
- **THEN** the Cloud Control Plane makes the existing OpenAI Chat Completions
tool-calling request to that base URL using the profile's decrypted API key
and returns the resulting single tool-call decision
### Requirement: Cloud planner Provider configuration is database-only
The Cloud Control Plane SHALL resolve Cloud planner Provider, model, timeout,
base URL, and API key from the active database profile and SHALL NOT read
planner Provider/model/timeout or Provider API-key environment variables.
When no usable active profile exists, it SHALL fail a planner request with a
structured unavailable response.
#### Scenario: Active profile is unavailable
- **WHEN** the active database Provider profile is missing, disabled, or
cannot be decrypted
- **THEN** the planner decision fails without invoking a legacy
environment-configured Provider
#### Scenario: Legacy environment variables are present
- **WHEN** the Cloud API process has legacy planner Provider or API-key
environment variables but an active database profile exists
- **THEN** the planner decision uses only the active database profile