Change is complete (17/17 tasks). Deltas synced: MODIFIED the cloud-planner-proxy "Endpoint resolves exactly one tool-call decision" requirement to resolve provider config from the active database profile, and created a new main spec openspec/specs/llm-provider-management/spec.md. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,7 +25,7 @@ The Cloud Control Plane SHALL expose an internal endpoint that accepts an AI Pla
|
|||||||
LLM provider
|
LLM provider
|
||||||
|
|
||||||
### Requirement: Endpoint resolves exactly one tool-call decision using cloud-held provider configuration
|
### Requirement: Endpoint resolves exactly one tool-call decision using cloud-held provider configuration
|
||||||
The Cloud Control Plane SHALL use its own configured LLM provider, model, and credentials -- not any value supplied by the requesting Host Agent -- to resolve a planner-decision request to exactly one tool name and one arguments object, within the request's timeout.
|
The Cloud Control Plane SHALL use its own configured LLM provider, model, and credentials -- not any value supplied by the requesting Host Agent -- to resolve a planner-decision request to exactly one tool name and one arguments object, within the request's timeout. The endpoint SHALL resolve the active database-managed Provider profile for every request and use its provider, model, timeout, configured base URL, and encrypted cloud-held credential. It SHALL NOT read Cloud API planner Provider/model/timeout/API-key environment variables.
|
||||||
|
|
||||||
#### Scenario: Provider returns a usable decision
|
#### Scenario: Provider returns a usable decision
|
||||||
- **WHEN** the configured provider responds to a planner-decision request
|
- **WHEN** the configured provider responds to a planner-decision request
|
||||||
@@ -39,6 +39,11 @@ The Cloud Control Plane SHALL use its own configured LLM provider, model, and cr
|
|||||||
- **THEN** the endpoint returns a structured failure response rather than a
|
- **THEN** the endpoint returns a structured failure response rather than a
|
||||||
fabricated decision, and does not crash the Cloud Control Plane process
|
fabricated decision, and does not crash the Cloud Control Plane process
|
||||||
|
|
||||||
|
#### Scenario: Database profile is the only planner configuration source
|
||||||
|
- **WHEN** the Cloud API process has legacy planner environment variables
|
||||||
|
- **THEN** subsequent planner-decision requests use only the active database
|
||||||
|
profile and do not read a legacy Provider credential for that decision
|
||||||
|
|
||||||
### Requirement: Cloud-proxy transport removes the need for Host Agent-held provider credentials
|
### Requirement: Cloud-proxy transport removes the need for Host Agent-held provider credentials
|
||||||
A Host Agent using the cloud-proxy transport for its AI Planner SHALL be able to execute AI-planned tasks without any locally configured LLM provider API key.
|
A Host Agent using the cloud-proxy transport for its AI Planner SHALL be able to execute AI-planned tasks without any locally configured LLM provider API key.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
# llm-provider-management Specification
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
Define how the Cloud Control Plane stores, protects, and activates
|
||||||
|
administrator-managed LLM Provider profiles in a durable database, so that
|
||||||
|
cloud-transport planner decisions resolve provider, model, timeout, base URL,
|
||||||
|
and API key from a single active database profile instead of from environment
|
||||||
|
variables.
|
||||||
|
|
||||||
|
## 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`; either profile MAY specify an absolute
|
||||||
|
HTTP(S) base URL and SHALL use its official provider 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: Administrator creates an Anthropic profile with a custom base URL
|
||||||
|
- **WHEN** an authorized administrator submits a unique profile name,
|
||||||
|
`anthropic` provider type, model, valid timeout, API key, and a valid
|
||||||
|
Anthropic-compatible base URL
|
||||||
|
- **THEN** the Cloud Control Plane persists the normalized URL with the profile
|
||||||
|
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
|
||||||
|
|
||||||
|
#### Scenario: Active Anthropic profile is used with a custom base URL
|
||||||
|
- **WHEN** the active profile is Anthropic and includes a base URL
|
||||||
|
- **THEN** the Cloud Control Plane makes the existing Anthropic native
|
||||||
|
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
|
||||||
Reference in New Issue
Block a user