Repository navigation
docs(data-modeling): virtual objects — rows from your server, shown in any view (plugin-driver recipe) - #27349
Merged
Merged
Conversation
…a plugin driver A new guide page: the three-way rule (computed / must-not-land / real-time => virtual; slow reference data => a real object fed by a scheduled pull), the plugin-driver recipe as the reference test boots it (driver skeleton, plugin, datasource, external object, current_user lock formula, beforeUpdate guard, gantt view, permission set), what a driver receives, the sharing-model rule, the credentialsRef reading for plugin drivers, a driver shape-pin test template and five business examples. Linked from the external-datasources and drivers pages; nav and the docs-audit scope artifact updated. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2c5z3q4h8inrn5kwqV
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2c5z3q4h8inrn5kwqV
Contributor
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
Contributor
Author
|
epic:#27261#1 · marchtian · session_017ihL2c5z3q4h8inrn5kwqV 维护者速读
席位意见:ACCEPT。页面只陈述 main 上实测的行为:引擎兜底(#27277)写作「计划中」,凭据一节如实写明插件 driver 不解析 席位核对
|
This was referenced Oct 29, 2026
3 tasks
This was referenced Oct 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by 田騏 · project thread
Fixes #27278
Clause-②: no
Metadata-protocol: none
维护者速读
current_user锁公式、beforeUpdate守卫、甘特视图、权限集)、driver 实际收到的调用、共享模型规则、driver 形状 pin 测试模板、五个业务例;从 external-datasources、drivers 与模块首页链入。apisource (read + write) #27130 这类客户要「行来自自家服务器、任何视图可看可改」,平台零协议改动已能做到,但没有一页可照抄的配方;AI 作者也照这页写。content/docs/data-modeling/virtual-objects.mdx的「Credentials」段(实测:插件 driver 的数据源上credentialsRef不被解析)与「Choose the sharing model on purpose」提示框;其次第一个 driver 骨架代码块。pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec check:skill-examples,预期✅ 272 prose examples type-check,页内两个os:check代码块在其中(变异后报virtual-objects.mdx:140与:288)。What changes
content/docs/data-modeling/virtual-objects.mdx("Virtual objects — rows from your server, shown in any view"):whereor refuse by name, forward only remote-owned columns onupdate,supports.transactionsUnsupported), the plugin that publishesdriver.NAMEininit, and onedefineStackblock with the datasource (driver= the service suffix,config: {},checkOnBoot: false), the external object (sharingModel: 'public_read_write', the per-callerlockedformula overcurrent_user), thebeforeUpdateguard with declared refusals, the gantt list view and a permission set;applyDriverQueryInMemoryhelper, per-datasource row cap with a loud refusal,supportshonoured for plugin drivers, refusal-envelope mapping for driver failures (epic #27261 P1) #27277's engine floor named as planned, not existing;owner_id/created_by, which no remote row carries —os validatesays nothing (epic #27261, found by the P0 spike) #27332, no fix promised);remoteName,objectinside the query, the extraid/updated_at/updated_bykeys, by-id reads before a write);mapping+jobpull).external-datasources.mdx, a paragraph after "Writing a driver" ondrivers.mdx, a card ondata-modeling/index.mdx, the nav entry indata-modeling/meta.json.scripts/docs-audit/handwritten-docs.json: the one-line regenerationcheck-audit-scope.mjs --writeproduces for a new page.Tests
Docs only; nothing published changes. Every code block on the page was run before it was written down:
packages/runtime, same plugin set asplugin-driver-external-object.spike.test.ts) with the page's driver skeleton, plugin anddefineStackblock (identical but for comments) behind an in-memory transport: 6/6 passed under the verify lock (VERDICT command-exit 0). Measured: list read with the view's filter, sort andtop=50reaches the remote asfilter [archived eq false],sort start_date asc,limit 50, then acountwith the same filter; the formula readslocked: falsefor the planner andtruefor the administrator; a PATCH on a locked slot answers409 RESOURCE_CONFLICT/declaredCode: PLAN_LOCKED; the administrator's PATCH answers403 PERMISSION_DENIED/declaredCode: NOT_PLANNERwith no remote write; the planner's PATCH makes three by-id reads and onepatchcarrying exactlystart_date,end_date,plan_note; an outsider's list read is403; a filter the driver refuses (>=) answers500 INTERNAL_ERROR. The probe files were deleted; the tree carries no new test.vitest run, identical text to the page's block except the import path).plugin-driver-external-object.spike.test.ts12/12 (VERDICT command-exit 0).os:checkblocks are really compiled: withtransactionsUnsupported: 'yes'andsharingModel: 'public_rw'injected,check:skill-examplesexits 1 namingvirtual-objects.mdx:140:17and:288:7; restored bygit checkout HEAD, blob hash equal to HEAD.Acceptance notes
credentialsRefis not resolved for a plugin driver (measured, seam level).DatasourceConnectionService.attemptConnectreturnsalready-registeredfor a driver a plugin registered before it reaches credential resolution. Probe on6d7634a9: pre-registered driver +credentialsRef⇒already-registeredwith no secret store and with a resolver (resolver calls 0); not pre-registered ⇒failed-credentials/connected(resolver calls 1). So the fail-closed sentence in external-datasources §4 does not hold for a plugin driver, and the epic's standing rule "credentials only throughcredentialsRef" has no channel on Tier A today. The page states the fact and points to the plugin convention (the host passes options to the plugin it composes); it does not claim a platform channel. Not filed: the reach is a seam probe, not a public door.DataSyncConfigis retired (never executed); a sync is defined on its target as amappingwithconnectorSourcedriven by ajobpull. The counter-example links/docs/automation/jobs#pulling-a-mappingand says there is no separate data-sync type.defineStack({ plugins })is not measured underobjectstack serve. The boot probe composes withkernel.use, as the reference test does; thepluginssentence follows the documented plugin convention (plugins/developmentstep 6), and the "register ininit" rule rests on readingObjectQLPlugin.start(adoptsdriver.*services) andAppPlugin.start(connects declared datasources).apisource (read + write) #27130 is not answered here; per the card the triage seat replies after this lands.applyDriverQueryInMemoryhelper, per-datasource row cap with a loud refusal,supportshonoured for plugin drivers, refusal-envelope mapping for driver failures (epic #27261 P1) #27277 item "Driver shape pin test template in the guide (P1-2)" is carried by the template section; objectql: virtual-object correctness floor —applyDriverQueryInMemoryhelper, per-datasource row cap with a loud refusal,supportshonoured for plugin drivers, refusal-envelope mapping for driver failures (epic #27261 P1) #27277's helper, row cap and refusal envelopes are described only as planned.Verification
Final head
beadd67a.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderives 53 families for this diff; all 53 run, all exit 0;--ranreconciles53 derived, 53 run, 0 NOT-MEASURED, 0 UNRUN.Docs gates (selected verdict lines)
check:doc-anchors: 803 internal fragment links across 476 source files all resolve.check:docs-audit-scope: green after the regeneration.node scripts/docs-audit/check-affected-docs.mjs: exit 0;affected-docs.mjs origin/main: 0 docs (nopackages/**change).check-section-landing-index: 9 section index blocks enumerate theirmeta.jsonpages (red before the index card was added, green after).check:skill-examples: 272 prose examples type-check (needs@objectstack/client-reactbuilt with declarations first, otherwise it refuses with exit 3).check:doc-formula-expressions,check:doc-security-posture,check:doc-authoring,check:doc-frontmatter,check:docs-single-h1,check:nul-bytes: exit 0.🤖 Generated with Claude Code
https://claude.ai/code/session_017ihL2c5z3q4h8inrn5kwqV