From 6f17c36947e19b7e2e0118487b64b094f35ec413 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 21 Aug 2026 12:45:17 +0000 Subject: [PATCH] docs(api): stop documenting a `/graphql` route the dispatcher removed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `content/docs/api/index.mdx` carried GraphQL as a behaviour contract, and both halves of it were false. Re-derived at this base: 1. `IGraphQLService` exists nowhere in `packages/**/src` — the only survivors repo-wide are three CHANGELOGs, `packages/spec/llms.txt:171`, and the doc page itself. 2. The route is not mounted, so it cannot answer 501. `packages/runtime/src/http-dispatcher.ts:2026` is the whole of it: `// /graphql removed — GraphQL is not in the product plan (#2462 follow-on).` There is no `createGraphQLDomain` beside the fifteen domains registered at `http-dispatcher.ts:556-574`, and no `handleGraphQL` in the runtime at all. Remove, do not rewrite. `packages/runtime/src/domains/unavailable.ts` is the canonical statement of what the "absent capability" table's two rows are: 501 is "the route is there; the implementation is not — every domain mounted unconditionally", 404 is "the route is not there". Every other entry in the 501 row (`/automation`, `/notifications`, `/ui/*`, `/ai/*`, `/auth/*`, `/i18n/*`) has a domain module registered unconditionally; `/graphql` has none, so it belongs in neither list. `content/docs/permissions/authorization.mdx:53` already says so in prose — "`/graphql` now 404s". A row reading "not available" would still tell a reader GraphQL was once a surface worth listing on the API landing page, which is the false implication itself. So the row goes. Sites corrected: - `api/index.mdx:19` — GraphQL row deleted from "Surfaces at a glance". - `api/index.mdx:172` — `/graphql` dropped from the 501 example list. - `api/index.mdx:28` — "REST and GraphQL are how code consumes your app" → "REST is how code consumes your app". Same page, same false claim; leaving it would have left the page contradicting its own surfaces table. - `getting-started/quick-reference.mdx:135`, `data-modeling/fields.mdx:320` — the two lower-severity residues the card names, same family. Docs-only: `content/` sits outside every workspace package and `apps/docs` is `private: true`, so this publishes nothing — skip-changeset. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01DdCnBGcHeufjrq7drTD3wt --- content/docs/api/index.mdx | 5 ++--- content/docs/data-modeling/fields.mdx | 2 +- content/docs/getting-started/quick-reference.mdx | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/content/docs/api/index.mdx b/content/docs/api/index.mdx index cd70fc3d0c..1de637be5c 100644 --- a/content/docs/api/index.mdx +++ b/content/docs/api/index.mdx @@ -16,7 +16,6 @@ ObjectStack exposes a fully typed REST API. All endpoints use JSON request/respo | **REST** | ✅ Auto-generated from the protocol (`@objectstack/rest`) — CRUD, query, batch, metadata, packages | | **Realtime** | ⚠️ In-process pub/sub service (`@objectstack/service-realtime`, single-instance); the `/realtime/*` REST routes and WebSocket/SSE transport are plugin-provided — none ships in the open framework | | **MCP** | ✅ Non-system objects exposed automatically as Model Context Protocol tools; actions additionally require the author's `ai.exposed` opt-in — every call is gated by the caller's permissions/RLS ([AI module](/docs/ai)) | -| **GraphQL** | ⚠️ Route is wired but **bring-your-own service**: `/graphql` returns 501 unless an implementation of the `IGraphQLService` contract is registered — none ships in the open framework | | **OData** | ⚠️ Vocabulary only: REST list endpoints accept OData-style operators (e.g. `$top`), but there is no standalone OData endpoint | @@ -25,7 +24,7 @@ ObjectStack exposes a fully typed REST API. All endpoints use JSON request/respo ## Your app as an MCP server -REST and GraphQL are how *code* consumes your app. **MCP is how *AI* consumes it.** +REST is how *code* consumes your app. **MCP is how *AI* consumes it.** Because every object and action is typed metadata, ObjectStack can expose the whole app as a [Model Context Protocol](https://modelcontextprotocol.io) server — so an AI client (Claude Code, Claude Desktop, Cursor, a local model) can inspect and *operate* the app @@ -169,7 +168,7 @@ Discovery never advertises a route for a service it reports `unavailable`. If yo | You get | Meaning | Example | | :--- | :--- | :--- | | **404** | The route is not mounted. The server does not expose this path at all. | `/analytics/*` without an analytics service — the mount itself is gated; `/mcp` when the MCP server is disabled for the environment | -| **501** | The route is mounted; nothing implements it. The request reached a handler that had nothing to delegate to. | `/automation`, `/notifications`, `/ui/*`, `/ai/*`, `/auth/*`, `/i18n/*`, `/graphql` without their backing service | +| **501** | The route is mounted; nothing implements it. The request reached a handler that had nothing to delegate to. | `/automation`, `/notifications`, `/ui/*`, `/ai/*`, `/auth/*`, `/i18n/*` without their backing service | A 501 body names the package that would provide the capability — the same sentence `services..message` carries in discovery, so the wall and the discovery entry always agree. A 404 here means what 404 always means: check the path. diff --git a/content/docs/data-modeling/fields.mdx b/content/docs/data-modeling/fields.mdx index 6fa5b294d2..3fcc2c68ac 100644 --- a/content/docs/data-modeling/fields.mdx +++ b/content/docs/data-modeling/fields.mdx @@ -317,7 +317,7 @@ These properties are available on all field types: | `description` | `string` | — | Developer documentation | | `inlineHelpText` | `string` | — | Help text shown in UI | | `hidden` | `boolean` | `false` | Hide from default views | -| `readonly` | `boolean` | `false` | Prevent editing — hidden from create/edit forms AND server-enforced on both write paths: a non-system write to the field is silently dropped on `UPDATE` (in the engine) and on `INSERT` through the data API (REST/GraphQL/MCP/import, at the DataProtocol ingress). A stripped field still falls back to its `defaultValue`; **seeding a `readonly` column at create requires a system context** (import/migration/programmatic seed). Platform (`sys_`/`managedBy`) objects are governed by their own write policy instead — the resolved-affordance write guard keyed off the object's [lifecycle bucket](/docs/data-modeling/objects#lifecycle-bucket-managedby) (ADR-0103), not this field-level flag. | +| `readonly` | `boolean` | `false` | Prevent editing — hidden from create/edit forms AND server-enforced on both write paths: a non-system write to the field is silently dropped on `UPDATE` (in the engine) and on `INSERT` through the data API (REST/MCP/import, at the DataProtocol ingress). A stripped field still falls back to its `defaultValue`; **seeding a `readonly` column at create requires a system context** (import/migration/programmatic seed). Platform (`sys_`/`managedBy`) objects are governed by their own write policy instead — the resolved-affordance write guard keyed off the object's [lifecycle bucket](/docs/data-modeling/objects#lifecycle-bucket-managedby) (ADR-0103), not this field-level flag. | | `sortable` | `boolean` | `true` | Allow sorting by this field | | `group` | `string` | — | Group name for organizing in forms (e.g. `'billing'`) | diff --git a/content/docs/getting-started/quick-reference.mdx b/content/docs/getting-started/quick-reference.mdx index d52e165136..5c02811906 100644 --- a/content/docs/getting-started/quick-reference.mdx +++ b/content/docs/getting-started/quick-reference.mdx @@ -132,7 +132,7 @@ AI/ML capabilities - agents, skills, tools, MCP exposure, RAG, and cost tracking ## API Protocol (17 of 28 schemas) -REST/GraphQL endpoints, real-time subscriptions, and discovery. +REST endpoints, real-time subscriptions, and discovery. | Protocol | Source File | Key Schemas | Purpose | |:---------|:-----------|:------------|:--------|