Repository navigation
test: spike a virtual object on a plugin driver through steps a to g - #27330
Merged
Merged
Conversation
…d to end (WIP) Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2fiCyHoxhseMhHUuhN
… receives (WIP) Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2fiCyHoxhseMhHUuhN
…ders, locks and writes on drag Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2fiCyHoxhseMhHUuhN
…her liftable The slot-lookup ratchet refuses an any-typed lookup; the where-matcher lift pulled in the module-level driver because the matcher's messages named it. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2fiCyHoxhseMhHUuhN
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2fiCyHoxhseMhHUuhN
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017ihL2fiCyHoxhseMhHUuhN
This was referenced Oct 28, 2026
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
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 #27276
Clause-②: no
Metadata-protocol: none
维护者速读
public_read_write;留在平台默认共享模型时,持有编辑权的成员也改不了任何外部行,现状钉在 (e3)。packages/runtime/src/plugin-driver-external-object.spike.test.ts的 (e3) 段(默认共享下的缺口)和 (c) 段(驱动收到的 DriverQuery 原样);再看ui/packages/plugin-gantt/src/ObjectGantt.pluginDriverTree.test.tsx。pnpm --filter @objectstack/runtime exec vitest run src/plugin-driver-external-object.spike.test.ts,预期Tests 12 passed (12)。What changes
Two test files, no product code.
packages/runtime/src/plugin-driver-external-object.spike.test.ts(12 tests). A plugin publishesdriver.spike_tree, an in-memory stand-in for a remote system that records every call it receives and refuses every method or operator outside the spike by name.defineStackdeclares a datasource on it (schemaMode: 'external',validation: { onMismatch: 'fail', checkOnBoot: false },allowWrites: true, nointrospectSchemaon the driver) and two external objects:spike_node(a tree withparent,depends_on, acurrent_userformulalocked, abeforeUpdatehook with aPLAN_LOCKEDrefusal, a gantt list view) andspike_owned(left on the platform's default sharing model). The kernel boots the real REST, auth, security and sharing plugins over it, and each step is asserted on what reached the driver, not on what the engine says it sent.ui/packages/plugin-gantt/src/ObjectGantt.pluginDriverTree.test.tsx(4 tests). The realGanttViewover the records that read serves: the tree, the formula lock on the rendered bars, and the write a pointer drag produces.Why
#27276 asks, before any platform change in #27261, which of the seven steps a virtual object on a plugin driver passes today. Each step is now a test; the one that does not pass is pinned as it behaves, so the change that lifts it turns that test red on purpose.
Tests
driver: 'spike_tree'withconfig: {}resolves to the plugin'sdriver.spike_treeservice; the engine routesspike_nodeto that instance; the connection service reportsalready-registeredand leaves it alone; the boot callsconnectonce.onMismatch: 'fail'andcheckOnBoot: falseon a driver with nointrospectSchema, and nosyncSchemais sent. A latervalidateAll()reportsspike_nodeok: false, so the opt-out is what lets it boot.driver.findas{ where: { archived: false }, orderBy: [{ field: 'start_date', order: 'asc' }], limit: 50, object: 'spike_node' }. Nofields, nooffset. A separatecountwith the samewherefollows.current_user.idis computed engine-side per caller: the same row readslocked: falsefor the planner andlocked: truefor the administrator.sharingModel: 'public_read_write'RESOURCE_CONFLICT,declaredCode: 'PLAN_LOCKED', with the catalogue message, andupdateis never sent. An allowed write reachesdriver.updatelast with the patch, the hook's stamp, and the engine'sid,updated_at,updated_by; the returned row is served with the formula recomputed.allowEditgets 403PERMISSION_DENIEDon every row ofspike_owned: the sharing check readsowner_idand the ownership floor readscreated_by, and no remote row carries either.dataSource.update('spike_node', 'n_cut', { start_date, end_date }). The adapter'sPATCH /data/:object/:idis pinned inpackages/client/src/client.test.ts:2177.spike_nodegets 403 on the list read with zero driver calls, and 403 on a PATCH after one by-idfindOneand no write.Acceptance notes
os validatewarning (a warning, since adefineStackrefusal would narrow it) for an external object left on an owner-keyed sharing model with no owner column mapped, naming both ways out (public_read_writeplus a hook, or acolumnMapto an owner column). Left for the seat to file as a sub-card of [Decision] Ontology over external systems: virtual objects on ADR-0015 federation — two driver tiers (plugin code · declarative OpenAPI), pushdown/identity/catalog/cache rules, Studio and AI drafts (2026 ontology research + deep design) #27261.applyDriverQueryInMemoryhelper, per-datasource row cap with a loud refusal,supportshonoured for plugin drivers, refusal-envelope mapping for driver failures (epic #27261 P1) #27277: every PATCH reads the pre-image from the remote three times by id, and every list read is afindplus a separatecount.objectrides inside the DriverQuery although the type omits it, anddriver.updatereceives the audit stampsupdated_atandupdated_byplusid, so a driver's writable column set has to accept them or drop them.Verification
Head
680ce37b, branched fromb4458075;mainhas since moved 11 commits, none in the paths this diff reaches, and the gate derivation on currentmainwith this diff applied is the same 53 commands. Local runs on a shared box, so seconds are shared-box seconds.Spike tests: 12/12 and 4/4
Package suites and type-checks
680ce37bchanged only the gantt test's schema annotation (typed asObjectGanttHandoff, sotype: 'object-gantt'); its file and the test-program type-check were rerun there.Derived gates: 53 of 53, all exit 0
Second pass at
680ce37b.node scripts/pm/dispatch-gates.mjs --ranon the recorded exit codes: 53 derived, 53 run, 0 NOT-MEASURED, 0 UNRUN (a derived zero).The first pass at
fbd9e598had five non-zero exits. Two were this diff and are now green:check:slot-lookup(two lookups typedany; now typed with their contracts) andcheck:where-matcher(the lift pulled in a module-level declaration named in the matcher's message text; the text no longer names it). Two were exit 3, prerequisite not met (check-plugin-teardown-shape --self-testneeded its pinned fixture fetched;check:dual-build-cjs-loadsneeded builtdist/), and both pass on rerun.pnpm --dir ui exec vitest run scripts/failed on 31 unresolved@objectstack/*imports beforedist/was built plus one 15s timeout under load; rerun after the build: 174 passed, 2 skipped (176 files, 4990 tests).Human Minimum
packages/specholds no runtime logic. (Not touched.)pnpm lintpasses. (Root eslint run on both files, exit 0.)main, one pull request. (Branched atb4458075;mainhas moved 11 commits since, none in these paths.)skip-changeset.)packages/spectouched: its generated artifacts are regenerated and committed. (Not touched.)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code