Skip to content

ADR-0076 D11 前置验证:HTTP 端口一致性门(packages/qa/http-conformance)+ OQ#9/10 结论 (#2462) - #3037

Merged
os-zhuang merged 13 commits into
mainfrom
claude/objectql-protocol-layering-s2sn67
Jul 16, 2026
Merged

ADR-0076 D11 前置验证:HTTP 端口一致性门(packages/qa/http-conformance)+ OQ#9/10 结论 (#2462)#3037
os-zhuang merged 13 commits into
mainfrom
claude/objectql-protocol-layering-s2sn67

Conversation

@os-zhuang

@os-zhuangos-zhuang commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

继续 #2462:落地 D11 的两个前置项(均为 framework 单仓库、不动现有行为),为跨仓库窗口的 transport 拆解扫清前提。

OQ#10 — 多适配器验证(本 PR 的代码部分)

ADR-0076 D11 的警告是"multi-adapter 未经验证,normalized context 有 Hono 痕迹"。本 PR 给出验证:

  • 新私有 QA 门 @objectstack/http-conformance(packages/qa/http-conformance,private: true 不发布):在裸 node:http 上实现 IHttpServer 端口的参照实现,除 @objectstack/core 外零依赖——没有框架替端口补路由/补解析,消费方一旦依赖任何 Hono 特有能力,套件立即失败。定位是验证仪器,不是产品服务器(生产继续用 plugin-hono-server;面向用户的 Express/Workers 适配器留到窗口期作为产品决策单独做,届时插进本套件的 ADAPTERS 数组即可免费获得同套验证)。
  • 跨适配器一致性测试套件:在参照实现与 plugin-hono-server 上分别拉起真实栈(dispatcher 桥 + REST 生成器 + ObjectQL + 内存驱动,真实 socket),断言行为一致——/data CRUD 全流程、/meta 读取、/ready/health、discovery、:param 路由、404/405+Allow、SSE,外加逐探针的响应形状对比矩阵。41 条断言全绿。

结论:端口没有硬性 Hono 依赖。 Hono 适配器里的 Host 头回填是 Fetch API 的产物、属适配器本地行为而非端口泄漏;剩余 Hono 耦合全部锁定在 getRawApp() 逃生舱(metadata HMR、cloud-connection 路由、static/SPA + CORS + Server-Timing),消费方均做了特性探测、可优雅降级。窗口期跟进项:把消费方已依赖的两个软扩展(res.write/endgetPort())和 404/405 语义正式写进 IHttpServer 契约。

目录组织:packages/qa/ 作为不发布验证门的统一位置(新 workspace glob);现有同类包 packages/dogfoodpackages/downstream-contract 建议后续迁入对齐(单独 PR,涉及 spec-liveness-check.yml 的路径触发更新)。

OQ#9 — dispatcher vs rest-server 重叠审计(结论已记入 ADR)

判定:划清边界,不要合并。 二者在实际运行中按域瓜分 API 面而非互为冗余:标准启动下 REST 独占 data/meta/batch/导入导出/search/email/forms/sharing/reports/approvals/security,dispatcher 桥独占 mcp/ai/graphql/keys/automation/actions/storage/i18n/analytics/health/ready。真正双挂载的只有 discoverypackages 两处(注册序先到先得——正是 D11 要消除的味道);dispatcher 的 /data//meta//uidispatch() 分支在标准启动中并未挂载(仅当 HttpDispatcher 被树外适配器当 callable 直调时才活)。据此得出 D11 工作清单:①处理死的 callable 分支;②packages + discovery 各归一主;③按域抽取 handler;④环境解析统一到注入的 KernelResolver 缝。

变更内容

  • packages/qa/http-conformance/(新私有 QA 门:参照适配器 + 41 条一致性测试;不发布、无 changeset)
  • pnpm-workspace.yaml:新增 packages/qa/* glob
  • docs/adr/0076-objectql-core-tiering.md:OQ#9/OQ#10/OQ#11 标注 Resolved 并记录证据

验证

  • 一致性套件 41/41(含 CodeQL 修复后的原型污染回归测试);全 monorepo pnpm test 130/130 任务通过
  • changeset 守卫(no-major / fixed-group,69 个公开包)通过

🤖 Generated with Claude Code

https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu

…pter on raw node:http (ADR-0076 D11/OQ#10, #2462)
Multi-adapter was designed but unproven: only the Hono adapter existed, and
ADR-0076 D11 flagged 'the normalized context shows Hono-isms' as a caveat
blocking the transport decomposition. This adds the validation:
- New @objectstack/plugin-node-server: a thin IHttpServer implementation on
raw node:http with ZERO dependencies beyond @objectstack/core — :param +
trailing-* routing (registration-order first-match, same as the primary
adapter), eager JSON/urlencoded body parse with lazy rawBody() for binary,
SSE via native res.write/end, 404/405-with-Allow semantics, EADDRINUSE
retry, graceful drain on close. Deliberately no getRawApp()/mount().
- Cross-adapter conformance suite: boots the dispatcher bridge AND the REST
route generator (with ObjectQL + memory driver) on BOTH adapters over real
sockets — /data CRUD roundtrip, /meta reads, /ready, /health, discovery,
:param routing, 404/405 parity, plus a probe-for-probe response-shape
parity matrix between the two adapters. 40 assertions, all green.
Findings recorded in ADR-0076 (OQ#9/OQ#10/OQ#11 resolution notes):
- The port has NO hard Hono-isms. The Host-header backfill in the Hono
adapter is a Fetch-API artifact local to that adapter, not a port leak.
- All remaining Hono coupling is confined to the feature-detected
getRawApp() escape hatch (metadata HMR, cloud-connection routes,
static/SPA + CORS + Server-Timing) which degrades gracefully.
- Follow-up for the D11 window: codify res.write/res.end (SSE) and
getPort() — extensions consumers already rely on — plus 404/405
semantics into the IHttpServer contract.
- OQ#9 audit verdict (delineate, don't merge; only discovery + packages
are genuinely double-mounted) recorded in the ADR open-questions list.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
@vercel

vercelBot commented Jul 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJul 16, 2026 2:40pm

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling size/xl labels Jul 16, 2026
@github-actions

github-actionsBot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 4 package(s): @objectstack/plugin-security, packages/qa, packages/services, @objectstack/spec.

104 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/spec)
  • content/docs/api/environment-routing.mdx(via @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via packages/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via packages/services, @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via packages/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/cli.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via packages/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/audit-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/services, packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/settings-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via packages/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/spec)
  • content/docs/permissions/access-recipes.mdx(via packages/plugins/plugin-security)
  • content/docs/permissions/authorization.mdx(via @objectstack/plugin-security, packages/qa, @objectstack/spec)
  • content/docs/permissions/delegated-administration.mdx(via packages/qa)
  • content/docs/permissions/explain.mdx(via @objectstack/plugin-security)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via packages/plugins/plugin-security, @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/plugins/packages.mdx(via @objectstack/plugin-security, packages/services, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via packages/services, @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/spec)
  • content/docs/ui/audience-based-interfaces.mdx(via packages/plugins/plugin-security)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/plugin-security, @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

Comment threadpackages/plugins/plugin-node-server/src/adapter.ts Fixed
claude added 2 commits July 16, 2026 08:32
…ion (CodeQL)
CodeQL flagged remote property injection: query-param keys come straight
from the request URL, so building the map on a plain object literal let
'?__proto__=…' write through the prototype chain. Use null-prototype
objects for query and params and drop the dangerous keys
(__proto__/constructor/prototype) outright; regression test pins that
'?__proto__=polluted' is dropped and Object.prototype stays clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
…deQL flags
The blacklist guard added in the previous commit was not recognized as a
sanitizer by CodeQL's js/remote-property-injection rule — the sink is the
computed write itself (obj[userKey] = …). Build query and params via
Object.fromEntries (own data properties only, no prototype-chain walk) so
the sink no longer exists; the __proto__/constructor/prototype drop stays
as defense in depth. Regression test unchanged and green (41/41).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
… gate — packages/qa/http-conformance
Maintainer review: the node:http adapter is a validation instrument, not a
product server, so it must not ship as a publishable plugin- package.
Reposition it accordingly:
- Move packages/plugins/plugin-node-server → packages/qa/http-conformance;
rename @objectstack/plugin-node-server → @objectstack/http-conformance,
private: true, test-only (no build/publish), matching the existing
verification-gate packages (dogfood, downstream-contract).
- packages/qa/ becomes the unified home for non-published verification
gates (new pnpm-workspace glob); migrating dogfood/downstream-contract
there is proposed as a follow-up.
- Drop the changeset + fixed-group entry (private packages are not
versioned); update the ADR-0076 OQ#10 note to the new name.
Behavior unchanged: same adapter, same 41-assertion cross-adapter
conformance suite, all green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
@os-zhuangos-zhuang changed the title ADR-0076 D11 前置验证:第二个 IHttpServer 适配器(裸 node:http)+ OQ#9/10 结论 (#2462)ADR-0076 D11 前置验证:HTTP 端口一致性门(packages/qa/http-conformance)+ OQ#9/10 结论 (#2462)Jul 16, 2026
… (unified verification-gate home)
Completes the packages/qa/ consolidation started with http-conformance:
all three non-published verification gates (dogfood regression gate,
downstream-contract compatibility gate, http-conformance port gate) now
live under one directory.
Mechanical path migration — no behavior change:
- git mv packages/{dogfood,downstream-contract} → packages/qa/
- rewrite every 'packages/dogfood' / 'packages/downstream-contract'
breadcrumb: spec liveness proof registry + JSON ledgers,
spec-liveness-check.yml path trigger, eslint ignore, docs/ADRs,
source comments
- bump the repo-root traversal one level in the four dogfood conformance
tests that resolve REPO_ROOT from __dirname
Verified from the new locations: dogfood 273 passed / 3 skipped,
downstream-contract typecheck + 14 tests, spec check:liveness resolves
all bound proofs, http-conformance 41/41.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
claude added 3 commits July 16, 2026 13:14
…col-layering-s2sn67
# Conflicts:
#	packages/qa/dogfood/test/owner-anchor-and-bulk-writes.dogfood.test.ts
claude added 2 commits July 16, 2026 13:50
…echeck job + correct stale ADR-0076 D12 status
Two follow-ups after merging latest main:
- lint.yml: the example-app typecheck step built only ./packages/* (direct
children). The connector packages the showcase imports were built purely
by accident — through dogfood's dependency chain — which broke when
dogfood moved to packages/qa/. Request the examples' dependency closure
explicitly (--filter='./examples/*^...') so the step no longer depends
on which package happens to live at the top level.
- ADR-0076: the round-2 status verification merged from main (#3061) was
read against a pre-#3028 snapshot — svcAvailable no longer hardcodes
'available'; the D12 framework side shipped in #3028. Correct the status
line and note OQ#9/OQ#10 resolution (#3037).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
claude added 3 commits July 16, 2026 14:10
…itigation)
Test Core started failing deterministically on the hosted runner —
plugin-audit#test dies with ZERO vitest output (kernel OOM-kill
signature) while passing locally on Node 20 and 22 — first on main
@4f8c2d1, then twice on this PR (initial run + job re-run). Onset
correlates with the task graph growing past ~100 tasks (connector
packages + qa gates): turbo's default concurrency (10) schedules that
many vitest workers + tsup DTS builds onto a 4-vCPU runner and peak
memory tips over.
Cap test-step concurrency at 4 (PR affected-tests + push full-run).
CPU-bound workload, so wall-clock cost is minimal; peak memory becomes
bounded.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
…col-layering-s2sn67
# Conflicts:
#	packages/qa/dogfood/test/showcase-declarative-mcp.dogfood.test.ts
#	pnpm-lock.yaml
…dogfood test + regen lockfile after merge
showcase-declarative-mcp.dogfood.test.ts landed on main (#3062) against
the old packages/dogfood location; after the packages/qa migration its
'../../../examples/app-showcase' URL resolved inside packages/. One more
level, same as the other conformance tests. Lockfile regenerated after
taking main's side in the merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
@os-zhuang
os-zhuang marked this pull request as ready for review July 16, 2026 14:57
@os-zhuang
os-zhuang merged commit 1ab8752 into mainJul 16, 2026
17 of 18 checks passed
@os-zhuang
os-zhuang deleted the claude/objectql-protocol-layering-s2sn67 branch July 16, 2026 14:58
@os-zhuang
os-zhuang restored the claude/objectql-protocol-layering-s2sn67 branch July 16, 2026 15:06
os-zhuang pushed a commit that referenced this pull request Jul 16, 2026
os-zhuang pushed a commit that referenced this pull request Jul 16, 2026
…aned search-conformance files
- build-probes.test.ts publish suite: spy promoteDraftForPublish +
runPublishSideEffects (the batch no longer calls publishMetaItem per
item, ADR-0067 D2). objectql suite back to 904/904.
- The #3037 packages/dogfood -> packages/qa/dogfood restructure merged
concurrently with #3065 and did not carry its three just-added files;
they were orphaned at the old path outside every workspace (silently
not running in CI). git mv them to packages/qa/dogfood/test — all 5
dogfood suites green at the new home (21 tests).
os-zhuang added a commit that referenced this pull request Jul 16, 2026
* feat(transport): prove the IHttpServer port is Hono-free — second adapter on raw node:http (ADR-0076 D11/OQ#10, #2462)
Multi-adapter was designed but unproven: only the Hono adapter existed, and
ADR-0076 D11 flagged 'the normalized context shows Hono-isms' as a caveat
blocking the transport decomposition. This adds the validation:
- New @objectstack/plugin-node-server: a thin IHttpServer implementation on
raw node:http with ZERO dependencies beyond @objectstack/core — :param +
trailing-* routing (registration-order first-match, same as the primary
adapter), eager JSON/urlencoded body parse with lazy rawBody() for binary,
SSE via native res.write/end, 404/405-with-Allow semantics, EADDRINUSE
retry, graceful drain on close. Deliberately no getRawApp()/mount().
- Cross-adapter conformance suite: boots the dispatcher bridge AND the REST
route generator (with ObjectQL + memory driver) on BOTH adapters over real
sockets — /data CRUD roundtrip, /meta reads, /ready, /health, discovery,
:param routing, 404/405 parity, plus a probe-for-probe response-shape
parity matrix between the two adapters. 40 assertions, all green.
Findings recorded in ADR-0076 (OQ#9/OQ#10/OQ#11 resolution notes):
- The port has NO hard Hono-isms. The Host-header backfill in the Hono
adapter is a Fetch-API artifact local to that adapter, not a port leak.
- All remaining Hono coupling is confined to the feature-detected
getRawApp() escape hatch (metadata HMR, cloud-connection routes,
static/SPA + CORS + Server-Timing) which degrades gracefully.
- Follow-up for the D11 window: codify res.write/res.end (SSE) and
getPort() — extensions consumers already rely on — plus 404/405
semantics into the IHttpServer contract.
- OQ#9 audit verdict (delineate, don't merge; only discovery + packages
are genuinely double-mounted) recorded in the ADR open-questions list.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(plugin-node-server): harden query/params against prototype pollution (CodeQL)
CodeQL flagged remote property injection: query-param keys come straight
from the request URL, so building the map on a plain object literal let
'?__proto__=…' write through the prototype chain. Use null-prototype
objects for query and params and drop the dangerous keys
(__proto__/constructor/prototype) outright; regression test pins that
'?__proto__=polluted' is dropped and Object.prototype stays clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(plugin-node-server): eliminate the dynamic property-write sink CodeQL flags
The blacklist guard added in the previous commit was not recognized as a
sanitizer by CodeQL's js/remote-property-injection rule — the sink is the
computed write itself (obj[userKey] = …). Build query and params via
Object.fromEntries (own data properties only, no prototype-chain walk) so
the sink no longer exists; the __proto__/constructor/prototype drop stays
as defense in depth. Regression test unchanged and green (41/41).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* refactor(qa): reposition the port-conformance adapter as a private QA gate — packages/qa/http-conformance
Maintainer review: the node:http adapter is a validation instrument, not a
product server, so it must not ship as a publishable plugin- package.
Reposition it accordingly:
- Move packages/plugins/plugin-node-server → packages/qa/http-conformance;
rename @objectstack/plugin-node-server → @objectstack/http-conformance,
private: true, test-only (no build/publish), matching the existing
verification-gate packages (dogfood, downstream-contract).
- packages/qa/ becomes the unified home for non-published verification
gates (new pnpm-workspace glob); migrating dogfood/downstream-contract
there is proposed as a follow-up.
- Drop the changeset + fixed-group entry (private packages are not
versioned); update the ADR-0076 OQ#10 note to the new name.
Behavior unchanged: same adapter, same 41-assertion cross-adapter
conformance suite, all green.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* refactor(qa): migrate dogfood + downstream-contract into packages/qa/ (unified verification-gate home)
Completes the packages/qa/ consolidation started with http-conformance:
all three non-published verification gates (dogfood regression gate,
downstream-contract compatibility gate, http-conformance port gate) now
live under one directory.
Mechanical path migration — no behavior change:
- git mv packages/{dogfood,downstream-contract} → packages/qa/
- rewrite every 'packages/dogfood' / 'packages/downstream-contract'
breadcrumb: spec liveness proof registry + JSON ledgers,
spec-liveness-check.yml path trigger, eslint ignore, docs/ADRs,
source comments
- bump the repo-root traversal one level in the four dogfood conformance
tests that resolve REPO_ROOT from __dirname
Verified from the new locations: dogfood 273 passed / 3 skipped,
downstream-contract typecheck + 14 tests, spec check:liveness resolves
all bound proofs, http-conformance 41/41.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* chore: retrigger CI — Actions did not fire on dc6507c
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* docs(changeset): fix dogfood path breadcrumb after packages/qa migration
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(ci): build the examples' dependency closure explicitly in the typecheck job + correct stale ADR-0076 D12 status
Two follow-ups after merging latest main:
- lint.yml: the example-app typecheck step built only ./packages/* (direct
children). The connector packages the showcase imports were built purely
by accident — through dogfood's dependency chain — which broke when
dogfood moved to packages/qa/. Request the examples' dependency closure
explicitly (--filter='./examples/*^...') so the step no longer depends
on which package happens to live at the top level.
- ADR-0076: the round-2 status verification merged from main (#3061) was
read against a pre-#3028 snapshot — svcAvailable no longer hardcodes
'available'; the D12 framework side shipped in #3028. Correct the status
line and note OQ#9/OQ#10 resolution (#3037).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(ci): cap turbo test concurrency at the runner's core count (OOM mitigation)
Test Core started failing deterministically on the hosted runner —
plugin-audit#test dies with ZERO vitest output (kernel OOM-kill
signature) while passing locally on Node 20 and 22 — first on main
@4f8c2d1, then twice on this PR (initial run + job re-run). Onset
correlates with the task graph growing past ~100 tasks (connector
packages + qa gates): turbo's default concurrency (10) schedules that
many vitest workers + tsup DTS builds onto a 4-vCPU runner and peak
memory tips over.
Cap test-step concurrency at 4 (PR affected-tests + push full-run).
CPU-bound workload, so wall-clock cost is minimal; peak memory becomes
bounded.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* fix(qa): bump repo-relative path in the newly-merged declarative-mcp dogfood test + regen lockfile after merge
showcase-declarative-mcp.dogfood.test.ts landed on main (#3062) against
the old packages/dogfood location; after the packages/qa migration its
'../../../examples/app-showcase' URL resolved inside packages/. One more
level, same as the other conformance tests. Lockfile regenerated after
taking main's side in the merge.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
* ci: TEMPORARY #3071 diagnostics — isolated verbose plugin-audit runs + dmesg OOM probe
plugin-audit#test dies on the hosted runner with zero captured output
(3x deterministic since main@4f8c2d1) while passing locally under Node
20/22 with the exact CI command. Bracket the turbo test step with an
isolated, verbose, ungrouped vitest run (before: fresh machine; after:
post-graph machine + kernel OOM traces) so the real failure output cannot
be lost to the GH log pipeline. SIGQUIT-on-timeout dumps Node thread
stacks if it hangs. To be REMOVED once #3071's root cause is fixed.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A1BtxNeUaGmvUYr8FwtUNu
---------
Co-authored-by: Claude <noreply@anthropic.com>
os-zhuang added a commit that referenced this pull request Jul 16, 2026
…mit cannot half-land (ADR-0067 D2, #3066) (#3074)
* feat(metadata-protocol/objectql): turn-atomic package publish (ADR-0067 D2, #3066)
Phase 1: every draft promotion + the sys_metadata_commit record run inside
ONE engine.transaction() — a mid-batch failure rolls back everything
(publishedCount 0; causal item carries its real error, the rest report
batch_aborted). publishMetaItem is split into promoteDraftForPublish
(guards + promote, metadata-only) and runPublishSideEffects so the batch
can transact promotions while deferring side effects.
Phase 2 (post-commit): registry refresh, DDL, seed batch apply,
materializers, ADR-0094 projections, events — best-effort, surfaced via
materializeApplied.failures instead of faking an unpublish (metadata is
live; boot reconciliation heals side-effect drift).
objectql: engine.transaction() now JOINS an already-open ambient
transaction instead of opening a nested driver transaction — a nested
begin deadlocks single-connection pools (SQLite knex) and escapes the
outer rollback. Locked by two new engine-ambient-transaction tests.
BREAKING (behavioral): consumers relying on partial batch publishes now
get all-or-nothing. Engines without transaction() keep the previous
sequential behavior (same fallback stance as the repo's withTxn).
Tests: publish contract suite rewritten to the two-phase seams (+4 new
cases incl. rollback/commit tracking and side-effect-failure surfacing);
commit-history suite updated; 29 green across the three suites.
* fix(tests): migrate build-probes spy to the phase-1 seam; rescue orphaned search-conformance files
- build-probes.test.ts publish suite: spy promoteDraftForPublish +
runPublishSideEffects (the batch no longer calls publishMetaItem per
item, ADR-0067 D2). objectql suite back to 904/904.
- The #3037 packages/dogfood -> packages/qa/dogfood restructure merged
concurrently with #3065 and did not carry its three just-added files;
they were orphaned at the old path outside every workspace (silently
not running in CI). git mv them to packages/qa/dogfood/test — all 5
dogfood suites green at the new home (21 tests).
* docs(adr-0067): flip to Accepted — Decision-2 turn-atomicity lands with this PR (#3066)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@os-zhuang@github-advanced-security@claude