Skip to content

feat: serving classes v1 - #1774

Open
hachall wants to merge 18 commits into
mainfrom
preview/serving-classes
Open

hachall wants to merge 18 commits into
mainfrom
preview/serving-classes

Conversation

@hachall

@hachall hachall commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Preview build for serving classes v1 (dispatch-mode resolution in onwards, pool tag + priority envelope to the self-hosted serving stack, account-level customisation, catalog-declared active classes and overlays).

Everything is dormant by default: no model activates a class and no account is granted one, so every request resolves to standard and upstream bytes are unchanged until a model and an organisation are opted in. This branch exists to exercise default and customised behaviour in a preview environment against a database fork.

Design notes and rollout plan are tracked internally; the commit message carries the component-level summary.

🤖 Generated with Claude Code

…the pool envelope

Adds serving classes v1: a per-request dispatch mode (`interactive`,
`throughput`, or the default `standard`) resolved in onwards and carried to
the self-hosted serving stack as a pool tag plus priority band. Everything
ships dormant: no model activates a class and no account is granted one, so
every request resolves to `standard` and the bytes reaching upstreams are
unchanged until an operator opts a model and an organisation in.

Onwards
- `serving` module: class type, suffix parsing (`alias:class`, unknown class
  is a 400), key policy (`KeyServing`: key class, account default, no
  external failover, per-model overlays), and the pure resolver
  (suffix > key > overlay default > account default; gated by the alias's
  active classes and the org's grant; batch and continuation purposes always
  resolve to standard).
- Handler: resolves after auth and routing rules, records requested and
  resolved class on the span, a counter and a `ServingClassOutcome` response
  extension; stamps `x-dynamo-interactivity-pool` and
  `x-dynamo-request-priority` only on members that accept scheduling fields
  and only for elevated classes; skips untrusted (external) members for
  self-hosted-only accounts, consuming the attempt budget so the request
  never falls over externally.
- Config: `PoolSpec.serving_classes` on the default pool,
  `KeyDefinition.serving`, `Targets.key_serving` kept in sync on reload.

dwctl
- Migration 141: `deployed_models.serving_classes`, `api_keys.serving_class`
  (in the NOTIFY column set), `users.default_serving_class` and
  `users.self_hosted_only` (account settings next to ZDR, with a NOTIFY
  trigger), `model_overlays` (org × model: tariff name, granted classes,
  default class, routing override, provisioning source), and the two
  analytics columns.
- Inference middleware strips the class suffix at the outermost layer so
  analytics, the prompt cache and billing key on the bare alias, passes the
  class to onwards as a request extension, and scrubs the client-side
  envelope (headers and `nvext.interactivity_pool`) alongside the existing
  priority strip.
- Onwards sync emits the per-key serving policy (omitted when empty) and the
  per-alias active classes.
- Analytics rows record requested and resolved class.
- API: `serving_class` on API keys; `default_serving_class` and
  `self_hosted_only` on users and organisations (UpdateAll or org owner);
  `serving_classes` on model responses.
- Model catalog: `clay.serving_classes` and `clay.overlays` (org by account
  username, tariff, classes, default class, routing override), validated
  and materialised into `model_overlays`; JSON schema regenerated.

Not yet: pricing by overlay tariff, legacy alias rewrite, console views,
fusillade `retry_after_ms`, dashboards.
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 14, 2026

Copy link
Copy Markdown

Deploying control-layer with  Cloudflare Pages  Cloudflare Pages

Latest commit: c96393f
Status: ✅  Deploy successful!
Preview URL: https://5b326000.control-layer.pages.dev
Branch Preview URL: https://preview-serving-classes.control-layer.pages.dev

View logs

@hachall hachall changed the title preview: serving classes v1 feat: serving classes v1 Sep 15, 2026
# Conflicts:
#	dwctl/src/request_logging/batcher.rs
…verlay files and endpoint kind

Reshapes v1 after review:

- Per-key serving class removed. Precedence is request suffix, then the
  organisation's per-model overlay default, then its account default.
- An elevated class applies when the organisation holds it (account setting
  `granted_serving_classes`) and the model offers it (`serving_classes` in
  the model catalog). Strict mode: a class named on the request that is not
  held or not offered is refused with 403 `serving_class_unavailable`; only
  the silent defaults degrade to `standard`.
- Account settings (granted classes, default class, self-hosted-only) live
  on users and organisations and are set through the API, gated to UpdateAll
  or the organisation owner.
- Per-organisation overlay catalog (`org_overlays`): one YAML per
  organisation carrying per-model overrides only (default class, routing),
  applied after the model catalog; organisations only; rows are owned by the
  file and pruned when no longer declared.
- Explicit endpoint kind (`dynamo`, `hosted`, `external`) on inference
  endpoints, backfilled from the scheduling capability, exposed on the
  endpoint API. The envelope is stamped only on dynamo members and the
  self-hosted-only restriction skips only external members; neither reads
  another flag any more.
- Onwards config carries accounts once per organisation and overlays on the
  alias's pool spec; every key gains an `account` label. Unaffected keys'
  definitions are unchanged.
- Migration renumbered to 143 after main's 142.
# Conflicts:
#	dwctl/src/db/handlers/deployments.rs
#	dwctl/src/db/handlers/model_provisioning.rs
#	dwctl/src/sync/onwards_config/tests.rs
#	onwards/src/handlers.rs
Inference lab is moving from forked interactivity pools to dynamo's
GlobalRouter and GlobalPlanner, which place a request by objective targets
rather than a pool name. Serving classes follow:

- A model's `serving_classes` is now a map of class -> preset
  `{ttft_ms, itl_ms, priority}` (JSONB; catalog `clay.serving_classes:`).
  Offering a class = declaring its preset; an optional `standard` preset pins
  what unclassed traffic asks for, otherwise standard sends nothing.
- Onwards writes the resolved preset into the body of `dynamo`-kind members
  as `nvext.router.{ttft_target, itl_target}`, and the priority as
  `nvext.agent_hints.priority` only when non-zero. The two envelope headers
  and the fixed priority bands are gone. A resolution without targets leaves
  the body untouched.
- An org overlay names either `default_class` or explicit `targets` (CHECK
  and validator refuse both). Explicit targets apply as-is when the request
  names no class, imply authority (no grant check) and resolve as `custom`.
- dwctl's ingress scrubs client-sent `nvext.router` targets, alongside the
  body priority, and no longer strips the removed headers.
- Migration renumbered to 147 (main took 146).
@hachall
hachall requested a balanced review from Copilot September 17, 2026 22:51
@hachall
hachall marked this pull request as ready for review September 17, 2026 22:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Request scrubbing can be bypassed, organization owners can self-grant elevated classes, and generated contracts and SQLx metadata are inconsistent.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Introduces serving-class routing, account/model overlays, endpoint classification, and analytics persistence across onwards and dwctl.

Changes:

  • Adds serving-class resolution and provider routing metadata.
  • Adds database/API support for account grants, overlays, presets, and endpoint kinds.
  • Persists serving-class analytics and refreshes SQLx metadata.
File summaries
File Description
onwards/src/strict/mod.rs Updates test target state.
onwards/src/load_balancer.rs Stores serving presets and overlays.
model-provisioning.schema.json Defines serving-preset schema.
dwctl/src/test/utils.rs Updates user fixtures.
dwctl/src/sync/endpoint_sync.rs Updates sync fixtures.
dwctl/src/sample_files/mod.rs Updates deployment fixture.
dwctl/src/request_logging/serializers.rs Extracts serving outcomes.
dwctl/src/request_logging/batcher.rs Persists serving analytics.
dwctl/src/request_logging/analytics_handler.rs Propagates serving metrics.
dwctl/src/metrics/cache_info.rs Updates endpoint fixtures.
dwctl/src/lib.rs Applies organization overlays.
dwctl/src/db/models/users.rs Adds account serving fields.
dwctl/src/db/models/organizations.rs Adds organization serving updates.
dwctl/src/db/models/inference_endpoints.rs Adds endpoint kinds.
dwctl/src/db/models/deployments.rs Adds serving presets.
dwctl/src/db/handlers/organizations.rs Persists organization settings.
dwctl/src/db/handlers/model_provisioning.rs Provisions model presets.
dwctl/src/db/handlers/deployments.rs Projects serving presets.
dwctl/src/config.rs Configures overlay directory.
dwctl/src/auth/middleware.rs Updates endpoint fixtures.
dwctl/src/auth/current_user.rs Updates user-update fixture.
dwctl/src/api/models/users.rs Exposes user serving settings.
dwctl/src/api/models/organizations.rs Exposes organization settings.
dwctl/src/api/models/inference_endpoints.rs Exposes endpoint kinds.
dwctl/src/api/models/deployments/mod.rs Exposes model presets.
dwctl/src/api/models/deployments/enrichment.rs Updates enrichment fixtures.
dwctl/src/api/handlers/users.rs Validates serving updates.
dwctl/src/api/handlers/payments.rs Updates account mutations.
dwctl/src/api/handlers/organizations.rs Authorizes organization settings.
dwctl/src/api/handlers/mod.rs Adds class validation.
dwctl/src/api/handlers/inference_endpoints.rs Persists endpoint kinds.
dwctl/src/api/handlers/auth.rs Updates user mutations.
dwctl/migrations/147_serving_classes.sql Creates serving-class schema.
.sqlx/query-f6313c….json API-key insert metadata.
.sqlx/query-e21376….json API-key update metadata.
.sqlx/query-d9bbd3….json Stale analytics metadata.
.sqlx/query-d57c49….json Endpoint bulk-query metadata.
.sqlx/query-cc71ec….json Overlay-query metadata.
.sqlx/query-c28831….json Organization-query metadata.
.sqlx/query-c1deed….json User-query metadata.
.sqlx/query-c1dbc0….json Organization-insert metadata.
.sqlx/query-b26923….json Organization-insert metadata.
.sqlx/query-a8267e….json Account-policy metadata.
.sqlx/query-a3d4a7….json Endpoint-list metadata.
.sqlx/query-a341d2….json User-query metadata.
.sqlx/query-a289a4….json User-update metadata.
.sqlx/query-9fbf45….json Organization-update metadata.
.sqlx/query-8ad0f8….json Removes superseded metadata.
.sqlx/query-880598….json API-key bulk metadata.
.sqlx/query-847c27….json Organization-update metadata.
.sqlx/query-7e5b73….json Composite-key metadata.
.sqlx/query-718d03….json Endpoint-insert metadata.
.sqlx/query-71802b….json Endpoint-get metadata.
.sqlx/query-6cedb5….json User-query metadata.
.sqlx/query-6c53c3….json Composite-key metadata.
.sqlx/query-5e2e7b….json Overlay-query metadata.
.sqlx/query-58ce43….json Composite-model metadata.
.sqlx/query-5849bc….json Organization-query metadata.
.sqlx/query-42d523….json Overlay-query metadata.
.sqlx/query-3eeeff….json User-query metadata.
.sqlx/query-39b331….json Analytics-insert metadata.
.sqlx/query-3899b1….json API-key get metadata.
.sqlx/query-2f988a….json API-key update metadata.
.sqlx/query-2dac89….json API-key insert metadata.
.sqlx/query-185aa2….json Composite-model metadata.
.sqlx/query-17af29….json API-key list metadata.
.sqlx/query-0eac1f….json User-insert metadata.
.sqlx/query-0e8ba1….json Endpoint-update metadata.
Review details

Files not reviewed (43)

  • .sqlx/query-005684c6b3cb520548bd107621b475cff7981f3929f0d9e73252f339765cd2dc.json: Generated file
  • .sqlx/query-0d04b215ce9a85392b8805e2fd8ab7a6cde6b040bbe36461d9404a937b9f2593.json: Generated file
  • .sqlx/query-0e8ba17bbd07d3aba6fa3c89a357bdc0b1544bbaa853d0ddcaff60792fec0b65.json: Generated file
  • .sqlx/query-17af2947bdf088fa1d831c7408139f43bed741349b93a5d6757e88ac1945efc2.json: Generated file
  • .sqlx/query-185aa2bcf4edcfcdd404d62b4052d1c76dc72c04f15cd97b1be6eb5e47fa9baa.json: Generated file
  • .sqlx/query-1e58059d2038426045c82e58c7eb452fae8f00be38bd884b57ceeef70dbcc8cf.json: Generated file
  • .sqlx/query-2c443be50801c391b4323ed83847fdc4e4fb747cb5465a74bdfd451b1549aa14.json: Generated file
  • .sqlx/query-2dac896d9529ee0ee4bdf09851a565307a6a3354da26e7f493447072da8cdffc.json: Generated file
  • .sqlx/query-2f988ac0d6052a573b0277fdc137f3a16f73e5292adf7b913272c0e3a1774dca.json: Generated file
  • .sqlx/query-3760af261851960f785fa7318d9567dfe90150961bad41ce15f9e0c9423eefdc.json: Generated file
  • .sqlx/query-3899b1a854d897ffb6ab1a7f44e351278f9623c4f46247a034e0a592faafafa8.json: Generated file
  • .sqlx/query-39b331b3b9ec624cf01444e3c065bc5dd2fdf6d9f998dbe709c6ae0f49f80b3f.json: Generated file
  • .sqlx/query-3eeeff204fd4edb60c30709611619a9005bdb5fd4f1fdd8e87faa4322f295677.json: Generated file
  • .sqlx/query-42d523ce78860a8358b81d5f8d43fcacce9f59c7c4259f60331b31f86069e473.json: Generated file
  • .sqlx/query-5849bc1e94bb696c829b8b37f792a908da49c92f3e2b8e3dbaa3a601473d13b2.json: Generated file
  • .sqlx/query-5bee3bad4a63e4b46a016115a1776622affe52125e2c1364284f1d56a27c6b4d.json: Generated file
  • .sqlx/query-5e2e7b9e79dbaa73ed44d626b8128ba65082fbae6fcc141f641c74e585f0d5dd.json: Generated file
  • .sqlx/query-66494123fee88db52c985676a783eeac92cc99165ed65804b45802a6b697ce1a.json: Generated file
  • .sqlx/query-66d87d1c182fc66f447a8da5b796ba82f106d53df4da8b936f05f90e70d4ab9b.json: Generated file
  • .sqlx/query-6c53c32ae51e6c9f8fe76429af124f964e24cb6896aafa928065ae77e5f6eaf9.json: Generated file
  • .sqlx/query-6dc1f2e8e5ee7eb2cd49a3890a46537bf6e0be92906fabe93efa6e59efda8266.json: Generated file
  • .sqlx/query-71802b819175b2e644063162a4bcba1c5f49c61148211716725bbcb3175d46a9.json: Generated file
  • .sqlx/query-718d03f3e12dafc9d9bd34f144bfb5279bf64ea292875d33012e85af1c8e848c.json: Generated file
  • .sqlx/query-75b7faa96dc55e600008464fa10d84280884266cc88e4a2b6a7f9df4595e03b3.json: Generated file
  • .sqlx/query-7e5b73f7064b6ddf18c203e68623be7543d7376b69f0922f2390da7aa4cb6a2b.json: Generated file
  • .sqlx/query-847c277e34b28ff500376f7140e61c88ee23e596824a257a91565b3da079cae3.json: Generated file
  • .sqlx/query-880598e51f20cae01484f689084dff474ff1bc5a65233fd21050da8fe4b279b6.json: Generated file
  • .sqlx/query-8ad0f85894651acb48f8c2c48eaf9277afd20b5ea8a8aff5b616e33bbeb21e1c.json: Generated file
  • .sqlx/query-9fbf45082890e8ce04783e093ed014d5e4df6a2b52278a807fd90419e941fb64.json: Generated file
  • .sqlx/query-a341d2e54b667a7020e013cb6fdbb6bf6ec887e855399f6175330776cfe01a40.json: Generated file
  • .sqlx/query-a3d4a784ffa4285fe7b54aa8d6f19e1a3b6865f9f2721684ffc53b6142164d4e.json: Generated file
  • .sqlx/query-a8267e1c6bf5ae1e38c2ddb155ba103831eb7aaa02edbdbe1bdd805600ee31c3.json: Generated file
  • .sqlx/query-b26923e64d58f98e50cac53a7ab94d0b6fc105e312b9ead96336a0f20b098c8a.json: Generated file
  • .sqlx/query-c1dbc09d5eeb32a77dada7b99b570ff30fcda3e277a785f2e14c8b4ca963bd8c.json: Generated file
  • .sqlx/query-c288315499617e5e980f2607631512f72e5ffe9c7096aa8ea92f43d20bf1f850.json: Generated file
  • .sqlx/query-cc71ec28d68425eca8840fe6f500f5dfe48d391711ad7095ae2344eee84d7253.json: Generated file
  • .sqlx/query-cde54777d647f1bda5e589d6dd6f94d074142297b4c7421765801f868b47fdb2.json: Generated file
  • .sqlx/query-d57c4928455820ad54035cadd826191eb71ac3985e7cae9ff67f616e6d6f135b.json: Generated file
  • .sqlx/query-d9bbd3aa686c2021e550f852a9850f19d3154475192d177c8de61bc8d6d615f6.json: Generated file
  • .sqlx/query-e08ffcd23ac10fd1d7d195a30da54a584b1954c88b5a64dcd93613b882e4e5eb.json: Generated file
  • .sqlx/query-e21376d172135d01534230b034c94a6ff3bd860cce49536343b5622505b82930.json: Generated file
  • .sqlx/query-e734f12eb9058c6c11a6ece8a525b47114701ffcdc87afc39f99c2c140ae71c6.json: Generated file
  • .sqlx/query-f6313c114e1306c743699ff40320de7e61fcecdb66e8f0efd5b85c22df799468.json: Generated file
  • Files reviewed: 50/93 changed files
  • Comments generated: 5
  • Review effort level: Balanced

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread dwctl/src/inference/middleware.rs Outdated
Comment thread dwctl/src/api/handlers/organizations.rs Outdated
Comment thread model-provisioning.schema.json Outdated
Comment thread .sqlx/query-d9bbd3aa686c2021e550f852a9850f19d3154475192d177c8de61bc8d6d615f6.json Outdated
Comment thread dwctl/src/request_logging/serializers.rs Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed against the latest diff

Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread dwctl/src/api/handlers/users.rs
Comment thread dwctl/src/inference/middleware.rs Outdated
Comment thread onwards/src/handlers.rs Outdated
Comment thread onwards/src/handlers.rs Outdated
Comment thread model-provisioning.schema.json Outdated
Comment thread dwctl/src/config.rs
Comment thread dwctl/migrations/147_serving_classes.sql Outdated
Comment thread dwctl/src/request_logging/serializers.rs Outdated
Comment thread dwctl/src/request_logging/serializers.rs Outdated
Comment thread dwctl/src/db/handlers/inference_endpoints.rs
… catalog schema

- Inference middleware: every scrubber now reports whether it removed
  something, and the realtime body is rebuilt whenever any of them did.
  Onwards forwards the bytes it receives, so a top-level or nvext scheduling
  priority (and a client-supplied response id) removed only from the parsed
  value would otherwise have reached the upstream unchanged.
- Organisations: granted serving classes require UpdateAll (platform
  operator), matching the users endpoint; the default class and routing
  preference stay owner-settable like ZDR. Test added.
- Catalog schema: ttft_ms and itl_ms carry minimum 1, matching the runtime
  validator.
- Analytics doc comment: precedence no longer mentions a per-key class.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 68 files

Requires human review: Auto-approval blocked because this review re-detected 9 unresolved issues already reported by Cubic.
Tip: instead of fixing issues one by one fix them all with cubic

Re-trigger cubic

Comment thread dwctl/src/request_logging/batcher.rs
Comment thread dwctl/migrations/147_serving_classes.sql
Comment thread dwctl/src/org_overlays.rs
Comment thread dwctl/src/lib.rs
Comment thread dwctl/src/sync/onwards_config/mod.rs
Comment thread dwctl/src/api/handlers/mod.rs Outdated
Comment thread dwctl/src/api/models/inference_endpoints.rs Outdated
onwards:
- Resolve presets and overlays from the alias's default pool whichever
  named pool serves the request; a completions-pool request no longer sees
  an empty policy.
- A self-hosted-only account's external members are excluded before the
  attempt budget is spent, under every strategy; an alias with no eligible
  member is refused as 503 `no_eligible_provider` rather than 429.
- The serving outcome extension also rides on upstream-error responses so
  analytics records the resolved class for failed requests.
- A class suffix on the selected model string (Model-Override header)
  outranks the body-derived extension.
- `custom` is an outcome only: not deserialisable from configuration.
- Alias serving policy is shared (Arc) so per-request pool clones do not
  scale with the number of organisations configured.

dwctl:
- Overlays of soft-deleted accounts are not synced.
- Org-overlay apply takes a transaction advisory lock; both catalogs are
  parsed and validated before either is applied.
- An overlay path that exists but is not a directory fails startup.
- Outbox rows written before the serving-class fields existed still
  deserialise.
- Endpoint create derives `kind` from `accepts_scheduling_priority` when
  omitted; endpoint kind round-trip test added.
- Migration: local lock_timeout; column comment lists `custom`.
- Config reference documents `org_overlays_directory`.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 21 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread docs/src/reference/configuration.md

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Model-override precedence, incomplete analytics outcomes, and non-atomic catalog application can produce incorrect or transient routing behavior.

Get a fresh assessment by requesting another Copilot review.

Review details

Files not reviewed (18)

  • .sqlx/query-0d04b215ce9a85392b8805e2fd8ab7a6cde6b040bbe36461d9404a937b9f2593.json: Generated file
  • .sqlx/query-0e8ba17bbd07d3aba6fa3c89a357bdc0b1544bbaa853d0ddcaff60792fec0b65.json: Generated file
  • .sqlx/query-2812e4f2b125ba6710354865fa125d23761fc8f43b2a37f3e111369eae847349.json: Generated file
  • .sqlx/query-3760af261851960f785fa7318d9567dfe90150961bad41ce15f9e0c9423eefdc.json: Generated file
  • .sqlx/query-39b331b3b9ec624cf01444e3c065bc5dd2fdf6d9f998dbe709c6ae0f49f80b3f.json: Generated file
  • .sqlx/query-5849bc1e94bb696c829b8b37f792a908da49c92f3e2b8e3dbaa3a601473d13b2.json: Generated file
  • .sqlx/query-5bee3bad4a63e4b46a016115a1776622affe52125e2c1364284f1d56a27c6b4d.json: Generated file
  • .sqlx/query-66d87d1c182fc66f447a8da5b796ba82f106d53df4da8b936f05f90e70d4ab9b.json: Generated file
  • .sqlx/query-6c53c32ae51e6c9f8fe76429af124f964e24cb6896aafa928065ae77e5f6eaf9.json: Generated file
  • .sqlx/query-71802b819175b2e644063162a4bcba1c5f49c61148211716725bbcb3175d46a9.json: Generated file
  • .sqlx/query-718d03f3e12dafc9d9bd34f144bfb5279bf64ea292875d33012e85af1c8e848c.json: Generated file
  • .sqlx/query-75b7faa96dc55e600008464fa10d84280884266cc88e4a2b6a7f9df4595e03b3.json: Generated file
  • .sqlx/query-8ad0f85894651acb48f8c2c48eaf9277afd20b5ea8a8aff5b616e33bbeb21e1c.json: Generated file
  • .sqlx/query-9fbf45082890e8ce04783e093ed014d5e4df6a2b52278a807fd90419e941fb64.json: Generated file
  • .sqlx/query-a3d4a784ffa4285fe7b54aa8d6f19e1a3b6865f9f2721684ffc53b6142164d4e.json: Generated file
  • .sqlx/query-a8267e1c6bf5ae1e38c2ddb155ba103831eb7aaa02edbdbe1bdd805600ee31c3.json: Generated file
  • .sqlx/query-b26923e64d58f98e50cac53a7ab94d0b6fc105e312b9ead96336a0f20b098c8a.json: Generated file
  • .sqlx/query-d57c4928455820ad54035cadd826191eb71ac3985e7cae9ff67f616e6d6f135b.json: Generated file
  • Files reviewed: 51/69 changed files
  • Comments generated: 4
  • Review effort level: Balanced

Comment thread dwctl/src/inference/middleware.rs
Comment thread dwctl/src/lib.rs
Comment thread dwctl/src/request_logging/serializers.rs
Comment thread dwctl/src/api/models/organizations.rs Outdated
…rror type, clippy

- Model responses include `serving_classes` only for callers with
  Models::ReadAll: the presets are an operator detail, never shown to
  customers.
- The serving outcome travels on OnwardsErrorResponse and is attached as a
  response extension on conversion, so error handling (including strict
  mode's) is unchanged and analytics still sees the class on failures.
- clippy (newer toolchain in CI): redundant closure in the overlay upsert.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Model-override precedence and post-resolution error paths can still produce incorrect serving-class attribution, and overlay ownership documentation is inconsistent.

Get a fresh assessment by requesting another Copilot review.

Review details

Files not reviewed (18)

  • .sqlx/query-0d04b215ce9a85392b8805e2fd8ab7a6cde6b040bbe36461d9404a937b9f2593.json: Generated file
  • .sqlx/query-0e8ba17bbd07d3aba6fa3c89a357bdc0b1544bbaa853d0ddcaff60792fec0b65.json: Generated file
  • .sqlx/query-2812e4f2b125ba6710354865fa125d23761fc8f43b2a37f3e111369eae847349.json: Generated file
  • .sqlx/query-3760af261851960f785fa7318d9567dfe90150961bad41ce15f9e0c9423eefdc.json: Generated file
  • .sqlx/query-39b331b3b9ec624cf01444e3c065bc5dd2fdf6d9f998dbe709c6ae0f49f80b3f.json: Generated file
  • .sqlx/query-5849bc1e94bb696c829b8b37f792a908da49c92f3e2b8e3dbaa3a601473d13b2.json: Generated file
  • .sqlx/query-5bee3bad4a63e4b46a016115a1776622affe52125e2c1364284f1d56a27c6b4d.json: Generated file
  • .sqlx/query-66d87d1c182fc66f447a8da5b796ba82f106d53df4da8b936f05f90e70d4ab9b.json: Generated file
  • .sqlx/query-6c53c32ae51e6c9f8fe76429af124f964e24cb6896aafa928065ae77e5f6eaf9.json: Generated file
  • .sqlx/query-71802b819175b2e644063162a4bcba1c5f49c61148211716725bbcb3175d46a9.json: Generated file
  • .sqlx/query-718d03f3e12dafc9d9bd34f144bfb5279bf64ea292875d33012e85af1c8e848c.json: Generated file
  • .sqlx/query-75b7faa96dc55e600008464fa10d84280884266cc88e4a2b6a7f9df4595e03b3.json: Generated file
  • .sqlx/query-8ad0f85894651acb48f8c2c48eaf9277afd20b5ea8a8aff5b616e33bbeb21e1c.json: Generated file
  • .sqlx/query-9fbf45082890e8ce04783e093ed014d5e4df6a2b52278a807fd90419e941fb64.json: Generated file
  • .sqlx/query-a3d4a784ffa4285fe7b54aa8d6f19e1a3b6865f9f2721684ffc53b6142164d4e.json: Generated file
  • .sqlx/query-a8267e1c6bf5ae1e38c2ddb155ba103831eb7aaa02edbdbe1bdd805600ee31c3.json: Generated file
  • .sqlx/query-b26923e64d58f98e50cac53a7ab94d0b6fc105e312b9ead96336a0f20b098c8a.json: Generated file
  • .sqlx/query-d57c4928455820ad54035cadd826191eb71ac3985e7cae9ff67f616e6d6f135b.json: Generated file
  • Files reviewed: 53/71 changed files
  • Comments generated: 1
  • Review effort level: Balanced

Comment thread dwctl/src/org_overlays.rs
Comment on lines +12 to +14
//! Rows written here are owned by the file (`provisioning_source`) and are
//! rewritten on every start, exactly like the model catalog; a row the
//! catalog does not mention is left alone.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 7 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="dwctl/src/api/models/deployments/mod.rs">

<violation number="1" location="dwctl/src/api/models/deployments/mod.rs:701">
P2: Platform-manager create and update responses now drop `serving_classes` because they use this converter without the privileged enrichment applied by list/get. Attach the presets in those responses too, so all `Models::ReadAll` model endpoints expose the same catalog metadata.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Fix all with cubic | Re-trigger cubic

.filter(|m| *m != ModelCatalogMetadata::default()),
provisioning_source: db.provisioning_source,
// Attached by the handler for platform managers only.
serving_classes: None,

@cubic-dev-ai cubic-dev-ai Bot Sep 18, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Platform-manager create and update responses now drop serving_classes because they use this converter without the privileged enrichment applied by list/get. Attach the presets in those responses too, so all Models::ReadAll model endpoints expose the same catalog metadata.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At dwctl/src/api/models/deployments/mod.rs, line 701:

<comment>Platform-manager create and update responses now drop `serving_classes` because they use this converter without the privileged enrichment applied by list/get. Attach the presets in those responses too, so all `Models::ReadAll` model endpoints expose the same catalog metadata.</comment>

<file context>
@@ -700,7 +697,8 @@ impl From<DeploymentDBResponse> for DeployedModelResponse {
             provisioning_source: db.provisioning_source,
-            serving_classes: db.serving_classes,
+            // Attached by the handler for platform managers only.
+            serving_classes: None,
         }
     }
</file context>
Fix with cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants