You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
test(client,runtime): the last wildcard was wrong evidence, not weak — AI ratchet 3 → 0 (#3718) (#3727)
* test(client,runtime): the last wildcard was wrong evidence, not weak — AI ratchet 3 → 0 (#3718)
The capstone (#3642) ratcheted "matched only by a `**` family" as WEAKER
evidence, to be driven down by enumerating each dynamic family. 60 → 3 after
#3656. The last 3 were `ai.nlq` / `ai.suggest` / `ai.insights` on `* /ai/**`.
Enumerating that family — in `cloud`, where service-ai lives — answered the
question the ratchet was really asking. `buildAIRoutes()` mounts 12 routes
(chat, chat/stream, complete, models, status, effective-model, six
conversations) and NONE is `/nlq`, `/suggest` or `/insights`.
client.ai methods: 3 answered by any repo: 0
real AI routes: 12 expressed by the SDK: 0
The two sets are disjoint. So the wildcard was not weak evidence, it was WRONG
evidence: it certified three URLs nothing anywhere serves. Its note even
asserted the client "expresses nlq/suggest/insights against the REST AI
routes" — never verified, and false. `DEFAULT_AI_ROUTES` declares all three but
has no runtime consumer (only the spec's own test reads it), and
`aiNlq?`/`aiSuggest?`/`aiInsights?` are optional protocol methods nothing
implements. Declared, never built (#3718) — instances 7-9 of the
`the method exists != the method can be called` class.
`/api/v1/ai/` becomes a bounded prefix exemption alongside the control plane:
two cross-repo surfaces, both ledgered in `cloud`. Only `ai.*` may use it, and
the namespace must still be reaching it, so the hole cannot widen.
The wildcard assertion becomes `toBe(0)`, not a ratchet. Zero is the point:
every matched call now rests on an exact enumerated route, and reintroducing a
`**` match reintroduces the one kind of evidence this audit family has caught
being wrong.
Mutation-checked both ways: removing the exemption re-exposes exactly the three
methods, and running the PRE-change capstone with the bound at 0 confirms the
old wildcard set was exactly `ai.insights`, `ai.nlq`, `ai.suggest` and nothing
else.
Adds audit §14 with the lesson worth carrying out of §1-§14: a claim about a
family is not a claim about a member. Wildcards, prefixes and "the service
handles that" all read as coverage in a green suite, and every one this audit
opened was hiding something.
Test-and-comment changes only; no runtime behaviour is affected.
Co-Authored-By: Claude <noreply@anthropic.com>
* docs(api): the published AI surface was inverted — correct it (#3718)
The docs-drift advisory on this PR prompted a check of whether any published
doc advertises the three dead `ai.*` methods. It does, and the AI docs turn out
to be backwards in both directions at once:
- `plugin-endpoints.mdx` tabled `/ai/nlq`, `/ai/suggest`, `/ai/insights` as
the AI plugin's endpoints. None of the three is mounted by anything.
- The same section's callout stated "There is no `/ai/chat` route".
`/api/v1/ai/chat` IS mounted, along with `/chat/stream`, `/complete`,
`/models` and six `/conversations` routes.
So the documentation named the three routes that do not exist and explicitly
denied the one that does — while `client-sdk.mdx` carried three
copy-pasteable examples that 404 on every call. That is Prime Directive #10 in
the literal sense: advertising a capability the runtime does not deliver.
Corrected:
- `client-sdk.mdx` — the three examples are marked declared-but-unimplemented
with the reason, and the chat note now says the chat endpoint exists and it
is the SDK that lacks a method for it.
- `plugin-endpoints.mdx` — status column on the three, plus the real 12-route
table and a pointer to cloud's ai-route-ledger.ts. The callout's surviving
point (use `useChat()` directly) is kept; only its false premise is fixed.
- `services-checklist.mdx` — notes that all three are optional protocol
methods nothing implements.
Deliberately does NOT decide #3718 (implement vs remove vs express the real
surface). Every edit here states what is true today and stays true whichever
way that lands.
Co-Authored-By: Claude <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: content/docs/api/plugin-endpoints.mdx
+30-7Lines changed: 30 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -95,14 +95,37 @@ The core dispatcher implements only the list / read / read-all routes above. Dev
95
95
96
96
### AI (`/ai`) — Plugin Required
97
97
98
-
| Method | Endpoint | Description |
99
-
|:-------|:---------|:------------|
100
-
| POST |`/ai/nlq`| Natural language → query |
101
-
| POST |`/ai/suggest`| Get value suggestions |
102
-
| POST |`/ai/insights`| Get data insights |
98
+
| Method | Endpoint | Description | Status |
99
+
|:-------|:---------|:------------|:-------|
100
+
| POST |`/ai/nlq`| Natural language → query |**Not implemented**|
101
+
| POST |`/ai/suggest`| Get value suggestions |**Not implemented**|
102
+
| POST |`/ai/insights`| Get data insights |**Not implemented**|
103
103
104
-
<Callouttype="info">
105
-
There is no `/ai/chat` route — the AI chat route was removed so the wire protocol aligns with the Vercel AI SDK. Use `useChat()` (`@ai-sdk/react`) directly against the streaming chat endpoint rather than the client SDK's `ai` namespace, which intentionally does not expose a `chat` method.
104
+
<Callouttype="warn">
105
+
**This table was inverted, and is corrected here (#3718).** The three routes
106
+
above are declared in `DEFAULT_AI_ROUTES` and called by
107
+
`client.ai.nlq/suggest/insights`, but **no plugin in any repo mounts them** —
108
+
every call 404s. Conversely, this callout used to state "there is no
109
+
`/ai/chat` route", which was wrong: `/ai/chat` is mounted.
110
+
111
+
What the AI plugin (`service-ai`) actually serves is a different set of
112
+
**12** routes:
113
+
114
+
| Method | Endpoint |
115
+
|:-------|:---------|
116
+
| POST |`/ai/chat`, `/ai/chat/stream`, `/ai/complete`|
117
+
| GET |`/ai/models`, `/ai/status`, `/ai/effective-model`|
118
+
| POST / GET |`/ai/conversations`|
119
+
| GET / PATCH / DELETE |`/ai/conversations/:id`|
120
+
| POST |`/ai/conversations/:id/messages`|
121
+
122
+
None of those has a client-SDK method — the SDK's `ai` namespace and the real
123
+
AI surface do not overlap at all. Reviewed dispositions for all 12 live in the
note: 'wholesale delegate to the auth service. Not enumerable route-by-route HERE, but no longer unenumerated: since #3656 plugin-auth/src/auth-route-ledger.ts carries the 55 SDK-reached routes plus the full mounted inventory, read off better-auth\'s live auth.api table'},
182
192
183
-
// ── ai (dynamic route table) ──────────────────────────────────────────────
193
+
// ── ai (dynamic route table, owned by another repo) ───────────────────────
note: 'routes come from service-ai buildAIRoutes() at plugin start; client expresses nlq/suggest/insights against the REST AI routes'},
195
+
note: 'routes come from service-ai buildAIRoutes() at plugin start — service-ai is a Cloud/EE package in the `cloud` repo, so this repo cannot enumerate them and the dispatcher only proxies (or 404s "AI service is not configured"). Enumerated on the other side of that boundary since #3718: cloud packages/service-ai/src/ai-route-ledger.ts. The previous note here claimed the client "expresses nlq/suggest/insights against the REST AI routes"; that was never verified and is FALSE — nothing mounts those three paths (#3718)'},
186
196
187
197
// ── meta (legacy chain) ───────────────────────────────────────────────────
0 commit comments