Repository navigation
ADR-0076: remaining objectql/protocol layering work (cross-repo window) #2462
Copy link
Copy link
Closed
Description
Tracking issue for the remaining work from ADR-0076 (objectql layering / protocol segmentation / honest capabilities).
Done (for context)
- ✅ protocol relocated out of the engine →
@objectstack/metadata-protocol; lean@objectstack/objectql/coreentry + boundary ratchet (refactor(objectql): extract metadata-protocol + add lean ./core entry (ADR-0076 Step 1) #2415). - ✅ D9 step-1:
ObjectStackProtocolsegmented into per-domain interfaces (DataProtocol/MetadataProtocol/…), composed alias for back-compat — non-breaking (feat(spec): segment ObjectStackProtocol into per-domain interfaces (ADR-0076 D9, step 1) #2429). - ✅ ADR D1–D12 recorded (rev.9).
Remaining — all gated to a coordinated cross-repo window (framework + cloud + ../objectui), unless noted
- D10 — distribute protocol implementations to domain packages. Data facade → transport; analytics/feed/realtime impls owned by their existing services (
service-analytics/service-messaging/service-realtime); the metadata-management impl stays in@objectstack/metadata-protocol(name retained — OQ#7). Dissolve the central facade. Risk: med; cross-repo. - D11 — decompose the transport god-implementation.
runtime/http-dispatcher.ts(~3.8k) +rest/rest-server.ts(~5.1k) → thin framework-agnostic port + per-domain normalized handlers (NOT framework-specific routes — keep multi-adapter). Confirm dispatcher↔rest-server overlap; validate multi-adapter by writing a 2ndIHttpServeradapter (thin Workers/Express) to prove the port is free of Hono-isms. Risk: high; cross-repo. - D12 — honest capabilities (fixes agents being misled by fake services). Standardize a stub/dev/fallback marker; make
http-dispatchersvcAvailablerespect it (reportstatus:'stub'/handlerReady:false, neveravailable); add thestubstatus to the discovery schema; update consumers (agents, console) to trust only real services. Mark the analytics fallback + plugin-dev stubs honestly — do not delete (no/analytics404). Risk: med; cross-repo (console readsdiscovery.services). See OQ#11 (marker convention). - Step 2 — make the
@objectstack/objectqlpackage itself protocol-free. Turn the protocol wiring into aMetadataProtocolPlugin(capability plugin, like plugin-security); update framework boot sites + cloud's ~8new ObjectQLPlugin()sites to also register it. Risk: high; breaking boot contract; cross-repo (cloud). - D7 — engine repo-split (trigger-gated). Only when the cross-package commit ratio of
engine.ts/registry.ts(currently 88%) falls to a low, stable level. Track the metric in CI. Then extract on the objectui sibling-link model. Risk: high; deferred. - (optional, low-risk, any time) A1.5 — narrow consumers to the new sub-interfaces (e.g. data-only callers →
DataProtocol), per the D9 incremental guidance.
Notes
- Resolved, no action: A2 (delete the "duplicated" analytics) — it's a deliberate fallback+
replaceService, not a collision; handled by D12 (mark honestly). - Sequencing: D9 contract segmentation is spec/type-level and already started (feat(spec): segment ObjectStackProtocol into per-domain interfaces (ADR-0076 D9, step 1) #2429). The implementation-level items above touch cloud boot and/or the console discovery contract, so they batch into one coordinated window.
Generated from the ADR-0076 kernel review.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
os-zhuang commentedon Jul 16, 2026
Concrete D12 instance: discovery advertises a
/realtimeroute that 404sSurfaced while auditing HTTP surfaces for #2567 (anonymous-deny). Not a security hole (there is no inbound realtime request path —
service-realtimeis an in-process pub/sub bus that registers zero HTTP routes, and no dispatcher/plugin mounts/realtime), but it is exactly the D12 "honest capabilities / agents misled by fake services" problem — an advertised capability with no real handler behind it.Three reference points:
packages/runtime/src/http-dispatcher.tsgetDiscoveryInfo()— setsrealtime: hasWebSockets ? \${prefix}/realtime` : undefined, wherehasWebSockets = !!realtimeSvc`. Merely registering the in-process service makes discovery advertise an HTTP route that was never mounted.packages/plugins/plugin-hono-server/src/hono-plugin.ts— the static discovery blob also listsrealtime: \${prefix}/realtime``.packages/metadata-protocol/src/protocol.ts(~L460) —SERVICE_CONFIG.realtimenames providerplugin-realtime, a package that does not exist (the real one ispackages/services/service-realtime, which registers no routes). The service-realtime README also documents endpoints (POST /realtime/broadcast,ws://…/ws, …) that are unimplemented.Fix options (for the D12 window): either implement the realtime HTTP/WS surface (and then it must go through the
shouldDenyAnonymousgate + a #2567 conformance ratchet probe), or mark it honestly — gate the discovery advertisement on real handler-readiness (not just!!realtimeSvc) so agents/console don't see a/realtimeroute that 404s. The client SDK (packages/client/src/realtime-api.ts) may read this field, so a bare removal needs a compat check.Filed here rather than as a fresh issue since it's a specific case of D12, not a new workstream.
Generated by Claude Code
Merge pull request #3028 from objectstack-ai/claude/objectql-protocol…
os-zhuang commentedon Jul 16, 2026
进度更新:D12 framework 侧已合并;D11 两个前置项已完成(PR #3037)
已合并(#3028,merge commit
9ea3c93) — D12 framework 侧切片:标准化__serviceInfo自描述标记(OQ#11 已决)、两个 discovery 构建器尊重标记、analytics fallback 如实报degraded、/realtime假路由不再广告(本 issue 评论里的具体实例)、A1.5 REST 层收窄到DataProtocol & MetadataProtocol、D7 触发指标进 CI(当前读数:近 30 天引擎核心提交 100% 跨包 → D7 继续搁置)。console 侧"只信handlerReady:true"仍留跨仓库窗口。新 PR #3037 — D11 的两个前置项,结论已记入 ADR-0076 OQ#9/OQ#10:
OQ#10 多适配器验证:端口无硬性 Hono 依赖(已证明)。 新增零依赖的裸
node:http适配器@objectstack/plugin-node-server+ 跨适配器一致性套件:dispatcher 桥 + REST 生成器在两个适配器上真实 socket 行为完全一致(/dataCRUD 全流程、:param路由、404/405、discovery、SSE,40 条断言)。Hono 适配器的 Host 头回填是 Fetch API 产物、非端口泄漏;剩余 Hono 耦合全部在特性探测的getRawApp()逃生舱内。窗口期跟进:把res.write/end(SSE)、getPort()和 404/405 语义正式写进IHttpServer契约。OQ#9 重叠审计:划清边界,不要合并。 dispatcher 与 rest-server 按域瓜分 API 面,真正双挂载的只有 discovery 和 packages(注册序先到先得);dispatcher 的
/data//meta//ui//notifications//share-links//security分支在标准启动中未挂载(仅作为 callable 被树外适配器直调时才活)。D11 工作清单:①删除或委托死的 callable 分支(近零爆炸半径,可先行);②packages + discovery 各归一主,消除注册序竞态;③按域抽取 normalized handler 到所属服务包;④环境解析统一到注入的KernelResolver缝(退役 rest-server 内建的 hostname→env 平行实现)。剩余跨仓库窗口项:D10、D11 拆解本体、Step 2(cloud ~8 处 boot 站点)、console 消费方更新。前置证据已齐,窗口可以排期。
Generated by Claude Code
ADR-0076 D11 前置验证:HTTP 端口一致性门(packages/qa/http-conformance)+ OQ#9/10 …
#3071 诊断与修复:plugin-audit#test 在托管 runner 上静默失败 (#3073)
refactor(rest): narrow the REST protocol dependency to DataProtocol &…
feat(discovery): honest capabilities — stub/fallback marker + realtim…
ci: track the ADR-0076 D7 engine repo-split trigger metric (objectsta…
feat(runtime): single owner for /discovery + one pipeline for /packag…
os-zhuang commentedon Jul 17, 2026
Progress update — cross-repo window (2026-07-17)
✅ Completed since this issue was filed
__serviceInfomarker (ServiceSelfInfoSchema+readServiceSelfInfo()inspec/api/discovery.zod.ts);svcAvailableno longer hardcodesavailable;plugin-dev's legacy_dev:truenormalized to{status:'stub', handlerReady:false}; analytics fallback self-identifies asdegraded;/realtimeno longer advertised. (ADR-0076 剩余工作的 framework 侧切片:D12 诚实能力 + A1.5 消费方收窄 + D7 指标追踪 (#2462) #3028)isServiceUsable()predicate —enabled && (handlerReady ?? status==='available')— so dev stubs / unusable services stop lighting up UI; degraded-with-live-handler stays usable. (feat(console): API 浏览器按诚实能力标记过滤服务分组(ADR-0076 D12) objectui#2637, converged with feat(spec,security): nav landing exclusivity + field-permission predicate guard (anti filter-oracle) #2630)DataProtocol & MetadataProtocol. (ADR-0076 剩余工作的 framework 侧切片:D12 诚实能力 + A1.5 消费方收窄 + D7 指标追踪 (#2462) #3028)engine.ts/registry.tscross-package commit-ratio metric now tracked in CI; the repo-split itself stays gated on the ratio falling to a low, stable level (currently ~100%, threshold OQ#5 open). (ADR-0076 剩余工作的 framework 侧切片:D12 诚实能力 + A1.5 消费方收窄 + D7 指标追踪 (#2462) #3028 +engine-split-metric.yml)node:httpreference adapter + 41-assertion cross-adapter conformance suite (private@objectstack/http-conformanceunderpackages/qa/) prove theIHttpServerport is free of hard Hono-isms; remaining coupling confined to the feature-detectedgetRawApp()escape hatch. (ADR-0076 D11 前置验证:HTTP 端口一致性门(packages/qa/http-conformance)+ OQ#9/10 结论 (#2462) #3037)kernel.hasPlugin(); the dispatcher bridge cedes${prefix}/discoverytocom.objectstack.rest.apiwhen present (/.well-known/objectstackstays dispatcher-owned); the/packagesfamily now flows throughdispatch()(one pipeline; also fixes droppedreq.query→ the documented?overwrite=trueinstall flag). (feat(runtime): /discovery 单一归属 + /packages 统一管线(ADR-0076 D11 步骤②) #3142)🔻 Remaining
createHonoAppcatch-all. Unblocks step ① below./data·/meta·/ui·/notifications·/share-links·/securitydispatch()branches are not dead — cloud's two hosts delegate every unmatched${prefix}/*todispatch()via thecreateHonoAppcatch-all. There,/share-linksis the designed primary surface for per-env kernels (registerShareLinkRoutes:false; host dispatcher serves after kernel swap — documented in cloudartifact-kernel-factory+default-environment-plugins) and/notificationshas no other HTTP owner anywhere. Killing therefore waits until the catch-all is retired by step ③. (corrects the original OQ#9 "callable-only" note — see ADR-0076 §OQ#9)KernelResolverseam (framework; more bounded, relatively independent — a good pre-step ③ cleanup).@objectstack/objectqlprotocol-free and distribute impls (framework + cloud ~8new ObjectQLPlugin()boot sites). objectql →MetadataProtocolimpl;DataProtocolimpl → engine-adjacent; dissolve the central facade, transport routes each contract-slice to the owning service. Analytics fallback preserved consciously (no/analytics404), not deleted. Highest risk; deserves its own coordinated window.Dependency shape
step ③unblocksstep ①;step ④is independent and can go first;Step 2/D10(the cloud-touching core goal) is best sequenced afterstep ③gives a clean per-domain seam.Two PRs merged this session: #3142 (framework D11 step②), objectstack-ai/objectui#2637 (D12 console).
Generated by Claude Code
docs(spec): annotate schema-only event/subscription/connector enums a…
docs(spec): annotate schema-only event/subscription/connector enums a…
feat(rest): unify request→environment resolution on the kernel-resolv…
feat(runtime): thin domain-handler registry seam in the HTTP dispatch…
22 remaining items
fix(metadata-protocol,objectql)!: retire the degraded analytics shim …
fix(spec,runtime,metadata-protocol): discovery's "install this to ena…
refactor(spec,client,metadata-protocol,runtime)!: 退役 workflow 服务槽位与 g…
fix(runtime): dispatcher `capabilities.search` answers a stated `fals…
fix(mcp): register the object tools on the stdio transport (objectsta…
docs(api): stop documenting a `/graphql` route the dispatcher removed
fix(core,hono): retire /graphql residue — stale surface list and iner…
docs(skills): drop the five GraphQL residue sites and the stale /stor…
docs(api): stop documenting a `/graphql` route the dispatcher removed (…
fix(core,hono): retire /graphql residue — stale surface list and iner…
docs(skills): clear the GraphQL residue from the published catalog an…
docs: correct two stale GraphQL residue sites in package source comments
fix(runtime): ActionEngineFacade.delete refuses a nullish id instead …
test(spec): the first api/ file group's test titles state each cited …