Repository navigation
Conversation
sci#287 (source-code-intelligence) routes the runner pool's model
delivery through a provider's connection block: the wire it speaks, its
endpoint, its harness and where its credential lives. The Go executor
parses the block leniently, but the engine's config-completeness audit
validates the registry against config/v1/model-registry.schema.json,
whose providers carried additionalProperties: false — so a registry
declaring a connection failed startup (live on the dev cluster,
2026-11-06: "providers/enmaas: Additional properties are not allowed
('connection' was unexpected)"; a dev-only Containerfile patch worked
around it).
The block is optional and mirrors the executor's validate() exactly:
- type (required): anthropic, anthropic-compatible, gemini, openai,
openai-compatible — the wire and credential format, not the model
family. Registered as provider_connection_type.
- base_url: required on the compatible types (they exist for endpoint
overrides), empty on the proprietary types (an empty string reads as
absent, as the executor does).
- harness: the harness a gateway connection fronts its wire with
(omp, claude); empty keeps the default.
- credential (required): {source: env|secret, name?, key?} — a
reference, never the credential itself; source secret requires the
Secret's name and key. Registered as credential_source.
The block is routing data only, never credentials: any other key on it
is refused. Providers without one load unchanged (backward compat);
traust-core/engine pin bumps pick this up.
Tests: tests/test_model_registry_connections.py — valid blocks
(including the dev cluster's enmaas shape), unknown type, secret
credential without name/key, base_url on a proprietary type, and the
no-connection backward-compat case.
💘 Generated with Crush
Assisted-by: Crush:rits/zai-org/glm-5-3
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: gurnben The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
Code Review by Qodo
1.
|
Qodo's review of the connection block caught a divergence from the executor's validate(): the schema required the secret credential's name and key to be present but not non-empty, so name: "" or key: "" passed the engine's audit while the executor refuses them at dispatch (sci#287's internal/traustcore/model.go: "a %q credential needs the Secret's name and key" — Name == "" || Key == ""). Mirror the Go check exactly: minLength 1 on both, inside the source: secret then-branch — the executor ignores name/key entirely on source: env, so the schema must not grow stricter there (the same conditional idiom the base_url rules use). Two new negative tests cover the empty name and the empty key; 0.63.0 is unreleased, so its CHANGELOG bullet now says non-empty. 💘 Generated with Crush Assisted-by: Crush:rits/zai-org/glm-5-3
|
Addressed in 85257ba (fix(config): refuse empty secret references in provider connections). Real finding — the executor's validate() refuses empty strings, not just absent fields (sci#287, Fixed by mirroring the Go check exactly: |
|
Code review by qodo was updated up to the latest commit 85257ba |
|
Closing in favor of #121 — the stack-consistent connection schema this duplicated. Context: this PR and #121 were opened in parallel (a dispatch-timing miss on my side; #121 is the sci#287 stack's own contracts piece, already consumed by core#386 and referenced by the foundry plan). The design resolution favors #121's open vocabulary — Worth cherry-picking from this PR into #121 if the lane wants it (does not conflict with the open-vocabulary choice):
The qodo finding on this PR (empty secret references pass validation) is already covered by #121's |
What
The model-registry schema (
config/v1/model-registry.schema.json) now declares the providerconnectionblock, so provider routing declarations validate. The block is optional — registries without one load unchanged (backward compat is tested).Why
sci#287 (source-code-intelligence) delivers provider routing from the model-registry's provider
connectionblocks. Its Go executor parses the block leniently (yaml.Unmarshalinto its own structs), but traust-core's config-completeness audit — run by the engine at startup — validates the registry against this repo'sconfig/v1/model-registry.schema.json, whose providers carriedadditionalProperties: falsewith onlydata_handlingandmodels. A registry carrying a connection block therefore failed startup (live on the dev cluster, 2026-11-06; a dev-only Containerfile patch currently works around it — this PR makes it permanent):The shape
The authoritative semantics are sci#287's Go structs (
internal/traustcore/model.go); the schema mirrors the executor'svalidate()exactly:typeanthropic|anthropic-compatible|gemini|openai|openai-compatibleprovider_connection_type.gemini/openaiare known vocabulary — the executor refuses them at delivery until the worker grows their lanes, which is worker state, not registry shape.base_urlanthropic-compatible/openai-compatible(they exist for endpoint overrides); empty on the proprietary types, whose default endpoint serves (an empty string reads as absent, as the executor'svalidate()does).harnessomp,claude); empty keeps the default. The executor passes it through unvalidated, so the schema documents the values rather than pinning them.credential{source: env | secret, name?, key?}— a reference, never the credential itself.source: secretrequires the Secret'snameandkey(if/then). Registered ascredential_source.The block is routing data only — never the credentials themselves (the registry is policy, the deployment is delivery, as the component README puts it).
additionalProperties: falseon both the block and the credential refuses anything else, including inline credentials.Tests
New
tests/test_model_registry_connections.py:enmaasshape (an openai-compatible gateway, omp harness, secret credential) and an emptybase_urlon a proprietary type reading as absent;type, a secret credential withoutname+key, abase_urlon each proprietary type, the compatible types' missing endpoint, an unknown credential source, and inline credentials / stray keys;No existing tests were changed. The typed sections stay permissive by design (the schema is the authority), so
ProviderSpeckeeps the block as an extra field — no Python model change.Downstream
traust-core/engine pin bumps pick this up; a parallel engine PR notes the dependency. Version 0.63.0 (minor: an optional property added to a closed object — the compat gate's allowed class).
💘 Generated with Crush