Skip to content

Commit ea0a7f4

Browse files
SiarheiFedziukovichclaude
andcommitted
docs(dial-unified-config): pin names-only wire shape for file-config listing
The list response shape of GET /v1/admin/config/file/{type} existed only in FileConfigController and its tests — 03-api-reference.md defined the endpoints and authz but never the wire contract. Pin it: names-only stub items, full bodies only on the single-entry GET, bodies-in-bulk deferred to /v1/admin/export (Defer.1). Extra per-item fields (type, description) are YAGNI but the shape is forward-compatible with adding them. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 69c8656 commit ea0a7f4

2 files changed

Lines changed: 2 additions & 2 deletions

File tree

docs/sandbox/dial-unified-config-lite/03-api.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ GET /v1/admin/audit # Phase 7 — deferred
6565
# GET /v1/admin/export?type=models # deferred — Defer.1
6666
```
6767

68-
`/v1/admin/config/file/*` is the operator-facing read-only surface for file-sourced entries. File entries are no longer addressable on the per-entity Configuration API (`/v1/{type}/{bucket}/{name}`) — that surface is blob-only, symmetric with the metadata listings. The list form returns a names-only stub listing (`{"items": [{"name": "…"}]}`) — no entity bodies and no `ResourceItemMetadata` fields (file entries carry no blob, so there is no `etag` / timestamps / `author`); the full entity body is returned only by the single-entry GET. Admin gates every type **except** `keys`, which is **denied for every caller including admin** — slice U.4 retired the security-admin tier along with the `?reveal_secrets=true` flow (see [`04-security.md`](04-security.md)). The carve-out exists because file-sourced `Config.keys` keeps the legacy map-key-as-secret format per OQ-12, so leaking even the *names* of file keys via URL or listing would expose secrets; operators with strict need read `aidial.config.json` directly off the deployment. No `PUT` / `DELETE` — file remains operator-managed via `aidial.config.json`.
68+
`/v1/admin/config/file/*` is the operator-facing read-only surface for file-sourced entries. File entries are no longer addressable on the per-entity Configuration API (`/v1/{type}/{bucket}/{name}`) — that surface is blob-only, symmetric with the metadata listings. The list form returns a names-only stub listing (`{"items": [{"name": "…"}]}`) — no entity bodies and no `ResourceItemMetadata` fields (file entries carry no blob, so there is no `etag` / timestamps / `author`); the full entity body is returned only by the single-entry GET. Extra per-item fields (e.g. `type`, `description`) are YAGNI for now — the stub shape is forward-compatible with adding them later if an operator workflow shows the need. Admin gates every type **except** `keys`, which is **denied for every caller including admin** — slice U.4 retired the security-admin tier along with the `?reveal_secrets=true` flow (see [`04-security.md`](04-security.md)). The carve-out exists because file-sourced `Config.keys` keeps the legacy map-key-as-secret format per OQ-12, so leaking even the *names* of file keys via URL or listing would expose secrets; operators with strict need read `aidial.config.json` directly off the deployment. No `PUT` / `DELETE` — file remains operator-managed via `aidial.config.json`.
6969

7070
`export` was originally the single source of truth for runtime state — it returns the effective merged config DIAL Core is actually serving (file + API entries). **Deferred from MVP at core-team request 2026-05-20** — see `../dial-unified-config/IMPLEMENTATION.md` §5.5 Defer.1; design preserved. Until it ships, operators consult `aidial.config.json` directly for file-sourced entries. `health/config` exposes invalid-entity skip state separately from the unauthenticated Kubernetes `/health` liveness probe, which is unchanged.
7171

docs/sandbox/dial-unified-config/03-api-reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ Validation is performed by `ResourceDescriptorFactory`, which enforces type, buc
114114

115115
**No `source` field on per-entity GET (slice U.1).** The previously-projected `source: "api" | "file" | "default"` field on the singleton GET — and the analogous `source: "api" | "file"` on every other per-entity GET / invalid-entity GET response — is **retired entirely**. The URL itself discloses the source: per-entity URLs (`/v1/{type}/{bucket}/{name}`) reflect the blob; file-config URLs (`/v1/admin/config/file/{type}[/{name}]`) reflect the file. Runtime resolution (`findDeployment`, chat-completion routing, `RateLimiter`, etc.) continues to consume the union via the merged `Config` map — only the operator-facing API surface is single-source. The `ETag` returned via the HTTP header is computed over the response body.
116116

117-
**File-config inspection surface.** Operators inspect file-sourced entries via a dedicated read-only surface — `GET /v1/admin/config/file/{type}` (list) and `GET /v1/admin/config/file/{type}/{name}` (single). Authorization (post-U.4): admin role for every supported type EXCEPT `keys`, which is denied for every caller including admin. File-sourced `Config.keys` keeps the legacy map-key-as-secret format per [OQ-12](08-open-questions-and-references.md), so the names themselves are secret-equivalent. Slice U.4 retired the `security-admin` tier that previously distinguished "may read secret-equivalent names" from plain admin; the surface now denies `keys` unconditionally — operators with strict need read `aidial.config.json` directly off the deployment. For the singleton, `GET /v1/admin/config/file/settings/global` returns the file-defined and schema-default values regardless of whether an API blob exists on the per-entity endpoint — this surface is the file-side window, independent of the blob's presence. No `PUT` / `DELETE` on file entries — `aidial.config.json` remains operator-managed; file write workflows continue through the existing config-file mechanism.
117+
**File-config inspection surface.** Operators inspect file-sourced entries via a dedicated read-only surface — `GET /v1/admin/config/file/{type}` (list) and `GET /v1/admin/config/file/{type}/{name}` (single). The list form returns a **names-only stub listing** — `{"items": [{"name": "gpt-4"}, …]}` — with no entity bodies and no `ResourceItemMetadata` fields (file entries have no blob, hence no `etag`, no timestamps, no `author`; `name` is the only metadata a file entry has). The full entity body is returned only by the single-entry GET: entity fields + `name` + `status`, with `@EncryptedField` fields dropped (`WRITE_ONLY` — no reveal path post-U.4). Bodies-in-bulk is deliberately not this surface's job — that is the deferred `GET /v1/admin/export` (see [IMPLEMENTATION.md §5.5 Defer.1](IMPLEMENTATION.md)), keeping the API-wide "no entity bodies in listings" contract (§4) uniform. Additional per-item fields on the listing (e.g. `type`, `description`, or observability fields) are YAGNI for now — they can be added later if an operator workflow shows the need, since the stub shape is forward-compatible with extra keys per item. Authorization (post-U.4): admin role for every supported type EXCEPT `keys`, which is denied for every caller including admin. File-sourced `Config.keys` keeps the legacy map-key-as-secret format per [OQ-12](08-open-questions-and-references.md), so the names themselves are secret-equivalent. Slice U.4 retired the `security-admin` tier that previously distinguished "may read secret-equivalent names" from plain admin; the surface now denies `keys` unconditionally — operators with strict need read `aidial.config.json` directly off the deployment. For the singleton, `GET /v1/admin/config/file/settings/global` returns the file-defined and schema-default values regardless of whether an API blob exists on the per-entity endpoint — this surface is the file-side window, independent of the blob's presence. No `PUT` / `DELETE` on file entries — `aidial.config.json` remains operator-managed; file write workflows continue through the existing config-file mechanism.
118118

119119
**Listing on the singleton — `GET /v1/metadata/settings/platform/` returns `405 Method Not Allowed`.** The listing path for the singleton type is not meaningful (there is exactly one entity at the fixed name `global`). The controller returns `405 Method Not Allowed` with `Allow: GET` — the metadata surface is read-only; the singleton's write verbs (`PUT`, `DELETE`) live on the entity URL `/v1/settings/platform/global`, not on the metadata URL. Per RFC 9110 §15.5.6 the `Allow` header lists verbs valid on the **requested** resource, so emitting `PUT`/`DELETE` here would mislead a caller. Admin MCP and CLI clients should use the per-entity GET rather than listing — see [`09-admin-mcp-spec.md`](09-admin-mcp-spec.md) §6.1.
120120

0 commit comments

Comments
 (0)