forked from boos/BoosAPI
feat: merge opus comfyui and login updates
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
# route-candidate-api Specification
|
||||
|
||||
## Purpose
|
||||
TBD - created by archiving change add-route-rebuild-pipeline. Update Purpose after archive.
|
||||
## Requirements
|
||||
### Requirement: `GET /api/models/token-candidates` is registered
|
||||
|
||||
The admin router SHALL register `GET /api/models/token-candidates`
|
||||
behind the standard admin auth layer. The handler SHALL return a JSON
|
||||
object with exactly four top-level keys: `models`,
|
||||
`modelsWithoutToken`, `modelsMissingTokenGroups`, `endpointTypesByModel`.
|
||||
|
||||
#### Scenario: Endpoint returns 200 with the four-key shape
|
||||
- **WHEN** an authenticated admin sends `GET /api/models/token-candidates`
|
||||
- **THEN** the response is HTTP 200 with a JSON body containing keys
|
||||
`models`, `modelsWithoutToken`, `modelsMissingTokenGroups`, and
|
||||
`endpointTypesByModel` — no extra top-level keys, no missing keys
|
||||
|
||||
#### Scenario: Unauthenticated request is rejected
|
||||
- **WHEN** a request without a valid admin token reaches the endpoint
|
||||
- **THEN** the admin auth layer returns 401 before the handler runs
|
||||
|
||||
### Requirement: `models` lists every (model, token) candidate
|
||||
|
||||
The `models` field SHALL be an object whose keys are model names and
|
||||
whose values are arrays of candidate descriptors. A `(model, token)`
|
||||
combination SHALL appear in the `models` array for that model exactly
|
||||
when ALL of the following hold:
|
||||
- a row in `model_availability` reports `available = 1` for the model
|
||||
on the token's account
|
||||
- the token's `enabled` is truthy (NULL treated as enabled)
|
||||
- the token's `value_status` is `'ready'` (NULL treated as ready)
|
||||
- the account's `status = 'active'`
|
||||
- the site's `status` is `'active'` (NULL treated as active)
|
||||
|
||||
Each candidate descriptor SHALL contain: `accountId`, `tokenId`,
|
||||
`tokenName`, `isDefault` (boolean), `username`, `siteId`, `siteName`.
|
||||
Within a single model's array, descriptors SHALL be deduplicated by
|
||||
`tokenId`.
|
||||
|
||||
#### Scenario: Active token with available model appears
|
||||
- **WHEN** account 5 (active, site active) has token 11 (enabled,
|
||||
ready) and `model_availability(account=5, model='gpt-4')` is
|
||||
available
|
||||
- **THEN** `models['gpt-4']` includes a descriptor with
|
||||
`accountId = 5, tokenId = 11`
|
||||
|
||||
#### Scenario: Disabled token is excluded
|
||||
- **WHEN** account 5 has token 11 with `enabled = 0`
|
||||
- **THEN** no descriptor with `tokenId = 11` appears in `models` for
|
||||
any model
|
||||
|
||||
#### Scenario: Duplicate tokens in source data deduped
|
||||
- **WHEN** the underlying join produces two rows for the same
|
||||
`(model, tokenId)` pair (e.g., joins fan out)
|
||||
- **THEN** the descriptor appears exactly once in
|
||||
`models[model_name]`
|
||||
|
||||
### Requirement: `modelsWithoutToken` surfaces accounts missing tokens
|
||||
|
||||
The `modelsWithoutToken` field SHALL be an object keyed by model name.
|
||||
For each `(account, model)` combination where the model is available
|
||||
on the active account but no qualifying token (per the `models`
|
||||
requirement) exists for that account, the handler SHALL include a
|
||||
descriptor `{ accountId, username, siteId, siteName }` under that
|
||||
model name. Descriptors SHALL be deduplicated by `accountId` within
|
||||
each model's array.
|
||||
|
||||
#### Scenario: Account with available model but no enabled tokens
|
||||
- **WHEN** account 8 reports `gpt-4` available but has zero rows in
|
||||
`account_tokens` (or all rows are disabled)
|
||||
- **THEN** `modelsWithoutToken['gpt-4']` includes a descriptor with
|
||||
`accountId = 8`, and that account does NOT appear in `models['gpt-4']`
|
||||
|
||||
#### Scenario: Account with token does not appear here
|
||||
- **WHEN** account 5 reports `gpt-4` available and has a usable token
|
||||
- **THEN** account 5 does NOT appear in `modelsWithoutToken['gpt-4']`
|
||||
|
||||
### Requirement: `modelsMissingTokenGroups` and `endpointTypesByModel` are empty
|
||||
|
||||
The handler SHALL return `modelsMissingTokenGroups` and
|
||||
`endpointTypesByModel` as empty JSON objects (`{}`). The frontend
|
||||
contract permits empty objects and these fields SHALL NOT be
|
||||
populated until a marketplace-cache or pricing-catalog source is
|
||||
added to the backend.
|
||||
|
||||
#### Scenario: Both fields are empty objects
|
||||
- **WHEN** the handler returns successfully under any state of the
|
||||
database
|
||||
- **THEN** `response.modelsMissingTokenGroups === {}` and
|
||||
`response.endpointTypesByModel === {}`
|
||||
|
||||
Reference in New Issue
Block a user