feat(ai): the provider status says whether the shared provider fits

GET /api/user/ai-provider gains three additive fields: the instance-wide
health tri-state, whether this caller already holds a receipt, and the one
boolean that answers 'may the shared provider be offered in one tap'.

The offer is the conjunction of five preconditions and every one of them
can only take it away: the operator's provider is the one that would serve
the caller, the health is demonstrably healthy, the assistant master and
coach flags are on, the acting record holds its own credentials, and no
receipt is on file yet. A managed profile is excluded by the positive form
of the policy test - 'not deny' would have let a child's record through.

Nothing here probes a provider; a probe would bill the operator for every
registration on the instance. docs/api/openapi.yaml is regenerated from the
schema source.
This commit is contained in:
Marc-André Bombeck committed 2026-09-11 09:07:45 +02:00
1 parent 82b7c11b05
commit 0d2bad69e3
4 files changed
+261

No files matched your search

+27
View File
@@ -44485,6 +44485,30 @@ components:
- type: "null"
description: v1.22 (#89) — per-user response timeout for AI generation, in seconds (10–600). Null = the built-in
comprehensive-briefing default (~120 s). Mainly for slow local/self-hosted backends.
serverProviderHealth:
type: string
enum:
- healthy
- unhealthy
- unknown
description: "Instance-wide health of the operator's shared providers (`admin-openai` / `admin-codex`), folded across
all accounts and reduced to a tri-state: `healthy` when one of them demonstrably served somebody within the
last 24 h and no credential sits in its auth-failure cooldown, `unhealthy` when they have been tried and are
not working, `unknown` when nothing has been tried yet on this instance or the read failed. Deliberately
carries no count, no timestamp and no account identity — 'the provider of this instance last worked' is a
statement about the instance, not about other people. Fails closed: treat `unknown` exactly like
`unhealthy`. Reading this never probes a provider."
serverProviderOffer:
type: boolean
description: "Whether the shared provider may honestly be offered to this caller in one tap. True only when all of: the
operator's provider is the one that would serve them (`managedBy: \"server\"`), `serverProviderHealth` is
`healthy`, the operator's assistant master + coach flags are on, the acting record holds its own credentials
(a managed profile never does), and the caller holds no receipt yet. Anything unknown makes it false."
serverProviderConsent:
type: boolean
description: Whether this caller already holds an active `ai_full` / `ai_coach` receipt — the grant `POST
/api/consent/ai/web` mints. When true there is nothing left to offer, and `serverProviderOffer` is false for
that reason rather than for a bad one.
required:
- provider
- model
@@ -44500,6 +44524,9 @@ components:
- compatModel
- hasCompatKey
- responseTimeoutSeconds
- serverProviderHealth
- serverProviderOffer
- serverProviderConsent
additionalProperties: false
description: The calling user's AI-provider configuration plus the effective availability (`aiAvailable` + `managedBy`).
Reports key presence + a masked preview only — never a plaintext key.