Skip to content

docs(data-modeling): an OData datasources guide, and the three-way choice between declarative OData, a plugin driver and a synced real object - #27871

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/project-thread-uz3qfd
Oct 30, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/project-thread-uz3qfd

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by 田騏 · project thread

Fixes #27747

Clause-②: no
Metadata-protocol: none

维护者速读

What changes

  • New page content/docs/data-modeling/odata-datasources.mdx (nav: after External datasources). Sections: check the service (v4 only, a key per entity set, the auth it takes); mount createODataDriverPlugin in the stack's plugins with its option table; declare the datasource and bind objects (an os:check example: schemaMode: 'external', driver equal to the plugin name, remoteName as the entity set, columnMap, id as the entity key, lazy $metadata, checkOnBoot: false); credentials through external.credentialsRef only (bearer, basic, none; resolved at the first request and again after a 401; fail-closed; what secrets must be on a composed kernel and on os serve); what the service is asked behind the engine floor ($filter operators, what is left to the engine, the never-narrower rule, $orderby with the key, @odata.nextLink paging, the 1000-row cap); writes (double opt-in, POST / PATCH / DELETE by key, If-Match, refusal mapping, what is refused by name) and the sharing-model choice; the failure table; what the driver does not do.
  • virtual-objects.mdx: "Virtual, or a real object?" becomes "Which way in: OData, a plugin driver, or a real object", opening with the card's three rules in order (slow-changing reference data, then OData v4, then a plugin driver) above the existing copy-or-not table. A paragraph says Salesforce publishes no OData service for its own records, so it takes a plugin driver over its REST API. The SAP sales-orders example points to the OData page when the ERP publishes OData v4, and See also links it.
  • external-datasources.mdx: the opening callout and See also route OData v4 services to the new page.
  • meta.json, index.mdx and scripts/docs-audit/handwritten-docs.json: list the new page (the nav, the module index block, and the hand-written docs audit scope, regenerated with check-audit-scope.mjs --write).
  • packages/drivers/driver-odata/README.md: one cross-link to the guide, with a patch changeset (.changeset/27747-odata-guide-readme-link.md), since the README ships in the package.

Why

Epic #27261 P2 (ruling 6486145005, Tier B = declarative OData; 田騏 2026-10-29T21:58Z 「现在启动全部 P2」). #27741 shipped the driver (PR #27796, 0a4b0fb2); no guide page showed an OData datasource or said when to choose declarative OData, a plugin driver, or a synced real object.

Verification

  • The examples parse against main's schema. The os:check block run through defineStack from packages/spec/src with tsx: it parses (one datasource, one object, external kept as written). The plugin options in the mount example run through parseODataDriverConfig: accepted. The four refusals the page names (credentials in serviceRoot, a query string, version: '2.0', an unknown key) are each refused with the message the page describes.
  • Every claim was read off the driver's source and tests at 0a4b0fb2: config.ts, plugin.ts, transport.ts (401 re-resolve, same-origin links, Prefer: odata.maxpagesize), filter.ts (the pushdown list and the never-narrower rules), odata-driver.ts (key as id, columnMap both ways, lazy $metadata, writes and refusals), and the floor and conformance tests. The os serve statement was read off packages/cli/src/commands/serve.ts (the binder is built inline and passed only to DatasourceAdminServicePlugin) and service-datasource (no service exposes it).
  • Local gates: node scripts/pm/dispatch-gates.mjs --commands derived 88 families from the changed files (71 before the changeset, index row and audit-scope row were added); every one was run, exit codes recorded before any pipe. First pass: check-section-landing-index and check:docs-audit-scope red on the new page (the module index row and scripts/docs-audit/handwritten-docs.json), both fixed; check:skill-examples (which type-checks the page's os:check block), check:dual-build-cjs-loads and check:lean-entry-closure exited 3 until the packages were built. Final pass, after building ./packages/**: dispatch-gates --ran: "88 derived famil(ies) accounted for — 88 run, 0 NOT-MEASURED (a DERIVED zero)". origin/main merged at c62ec8e2 (none of the 12 incoming commits touched these files); check:doc-anchors, check-section-landing-index and check:docs-audit-scope re-run green on the merged head. The full battery is CI's.

Acceptance notes

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (Not touched.)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; no source file changed (pnpm lint is CI's).
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset.
  • 6. packages/spec touched: not touched.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English (the 维护者速读 block is the repo's own Chinese reader section).
  • The Before Submitting list in CONTRIBUTING.md is done.

🤖 Generated with Claude Code

https://claude.ai/code/session_017ihL2fzEsUhDQ2VCWQJ5eu

…ice between OData, a plugin driver and a synced real object

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2fzEsUhDQ2VCWQJ5eu
…dex and the hand-written docs audit scope

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2fzEsUhDQ2VCWQJ5eu
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling labels Oct 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 1 changed file(s) yielded no anchor (packages/drivers/driver-odata/README.md), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/drivers/driver-odata/README.md) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 1 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json c4cb5ec0c3936dd2c24ae2aa9a349449d8e33bef → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV
ACCEPT · PR #27871 @ c62ec8e278e5fe97316450d0d34577c43ea48a58 · 2026-10-30T02:42Z

维护者速读

席位意见:ACCEPT。无契约面(Clause-②: no,无 packages/spec/src/**、skills/**),席位审读即审核记录。

席位核对

  1. Shape: +331/−7, 8 files. One new page, a three-way-rule rewrite at the top of virtual-objects.mdx plus two cross-links, the OData route on external-datasources.mdx, nav and index cards, a README link, and a patch changeset.
  2. Premise measured / seat review: the page's claims were read against the driver the seat reviewed on feat(driver-odata): a declarative OData v4 datasource driver, published as a plugin driver id behind the engine floor #27796 (7f91132b), and each matches the code. The pushed-down operator list and what is left to the engine match filter.ts. Paging to 1001 under the floor's cap, and the same-origin nextLink refusal, match transport.ts. So do 401 re-resolution and fail-closed credentials. The write refusal mapping (400/409/412/422 → 422 EXTERNAL_WRITE_REFUSED) and the read mapping (400 INVALID_QUERY, else 503) match the floor. The os:check example parses on main.
  3. Gate check-runs on c62ec8e2: 47 runs: 35 success, 12 skipped, 0 failed or pending. mergeable_state: clean.
  4. Accepted deviations: content/docs/data-modeling/index.mdx and scripts/docs-audit/handwritten-docs.json, both required by docs gates for a new page. The changeset is there for the README link.
  5. Out of scope, routed: the os serve caveat (a stack plugin cannot reach the host's secret binder) is filed as os serve: a stack's plugin driver resolves its datasource's external.credentialsRef through the host's datasource secret binder (driver-odata on os serve) — epic #27261 P2 #27875, which drops the caveat when it lands. "Nothing generates fields from $metadata today" is rewritten by datasource import: generate object drafts from an OData $metadata document, and the Studio datasource page lists and imports its entity sets — epic #27261 P2 #27745 when import lands. The external.connector mention and the conformance-kit pointer go to skills + docs: teach external.connector (D7) beside credentialsRef in the datasources skill rule and the two data-modeling guides — epic #27261 P2 #27786. Skills-docs: skills + docs: teach external.connector (D7) beside credentialsRef in the datasources skill rule and the two data-modeling guides — epic #27261 P2 #27786.
  6. Landing: not governed (check-governed-merges --pr 27871: 338 lines ≤ 3000). No contract face, so the seat's read is the review of record. Landed by the seat through the relay.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 30, 2026 02:43
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 30, 2026 02:43
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit 6e53003 Oct 30, 2026
48 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-uz3qfd branch October 30, 2026 03:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

2 participants