Seam card filed by the repo:cloud PM seat (objectstack#6026, session session_01EK4Q5Nrx779cxjdeTxsK7P) — 2026-09-04T04:4xZ. Named reader: whichever domain:services seat owns packages/services/service-storage, at first-touch grading. ⛔ Not the cloud seat's lane to implement (cloud card req 6: no framework changes).
Measured (cloud PR #1965, cloud#1963)
cloud#1963 (owner ruling 2026-09-04: 「每一套租户的系统都应该是完整的 ObjectOS」) force-mounts settings / storage / cache / email on every hosted tenant kernel. Hosted per-environment kernels have no http-server service (artifact-kernel-factory.ts ~:896), so any framework service plugin that self-registers its routes on http-server at kernel:ready has no HTTP door on cloud.
For settings cloud bridged it: a host plugin mounts the framework's own registerSettingsRoutes on the raw Hono app and dispatches into the env kernel's route table — verified 200 / 403 / 405 end-to-end on a booted host. That works because registerSettingsRoutes and everything it needs are on @objectstack/service-settings's public surface.
For storage the same bridge is not possible:
packages/services/service-storage/src/index.ts:30 — declares (deliberately) as package-internal:
buildAuthSessionResolver · buildFileReadAuthorizer · findFileHolder
registerStorageRoutes needs all three. buildFileReadAuthorizer is the ADR-0104 D3 download-authorization gate. So bridging storage from cloud means either (a) exporting them from the framework, or (b) re-implementing a file-access authorizer in the consumer — and (b) is how a security decision acquires a second, divergent definition, so cloud refused it and stopped.
Consequence today: storage is mounted on tenant kernels (service, sys_file / sys_upload_session / sys_attachment, lifecycle hooks, reap guards all present) but /api/v1/storage/* returns 404 — an AI-built app with an attachment field cannot upload. That is inside ADR-0112's v1 scope.
Options (input, not a ruling)
A — export the three helpers (or a single registerStorageRoutes-shaped entry that takes the raw app and a kernel accessor, the way settings already works). Smallest change; keeps one owner for the file-access authorization decision, which is the property that makes the settings bridge safe.
B — give per-environment kernels a real route-collecting http-server service, so every self-registering framework service plugin lights up at once. The general answer to this whole class — but its blast radius is every plugin's kernel:ready branch simultaneously (plugin-auth reaches for getRawApp()), and a throw there rolls back plugins and takes a tenant environment offline, which cloud has already paid for once.
C — cloud re-implements the storage route wiring from the public surface. ⛔ Refused on the cloud side: a second authorizer.
Cloud seat's recommendation: A now; B as a deliberate later card if a third surface needs it. A and B are not exclusive.
四维(本席建议 A)
项目长远合理性(权重最高):文件访问授权只能有一个定义,住在框架里。A 让 cloud 逐字复用框架的决定——settings 桥之所以安全,正是因为路由与它需要的一切都在公开面上;storage 缺的只是把同一形状补齐。B 是这一类问题的通解,但通解的爆炸半径是所有插件的 kernel:ready 分支同时点亮,需要单独的可靠性论证,不该搭在这张卡上。
实际业务需求:ADR-0112 第一版明确含附件/图片字段;今天托管租户上传是 404。拉动是实测的。
防 AI 写代码犯错:C 是 AI 最容易「顺手做掉」的那条——在消费端重写一个授权器,测试全绿,而平台从此有两份下载门。拒绝 C 的理由就是要把这个错误在结构上堵死。
创业阶段不扩散需求:A 是把三个已有函数(或一个已有形状)放到公开面,不新增能力;B 是新基础设施。先 A。
Re-check
packages/services/service-storage/src/index.ts:30 (the internal declaration) · registerStorageRoutes's parameter list · cloud packages/objectos-runtime/src/env-settings-routes-plugin.ts (PR #1965) as the working template for the bridge.
Related: cloud#1963 · cloud PR #1965 · ADR-0104 D3.
Seam card filed by the
repo:cloudPM seat (objectstack#6026, sessionsession_01EK4Q5Nrx779cxjdeTxsK7P) — 2026-09-04T04:4xZ. Named reader: whicheverdomain:servicesseat ownspackages/services/service-storage, at first-touch grading. ⛔ Not the cloud seat's lane to implement (cloud card req 6: no framework changes).Measured (cloud PR #1965, cloud#1963)
cloud#1963 (owner ruling 2026-09-04: 「每一套租户的系统都应该是完整的 ObjectOS」) force-mounts
settings / storage / cache / emailon every hosted tenant kernel. Hosted per-environment kernels have nohttp-serverservice (artifact-kernel-factory.ts~:896), so any framework service plugin that self-registers its routes onhttp-serveratkernel:readyhas no HTTP door on cloud.For settings cloud bridged it: a host plugin mounts the framework's own
registerSettingsRouteson the raw Hono app and dispatches into the env kernel's route table — verified 200 / 403 / 405 end-to-end on a booted host. That works becauseregisterSettingsRoutesand everything it needs are on@objectstack/service-settings's public surface.For storage the same bridge is not possible:
registerStorageRoutesneeds all three.buildFileReadAuthorizeris the ADR-0104 D3 download-authorization gate. So bridging storage from cloud means either (a) exporting them from the framework, or (b) re-implementing a file-access authorizer in the consumer — and (b) is how a security decision acquires a second, divergent definition, so cloud refused it and stopped.Consequence today:
storageis mounted on tenant kernels (service,sys_file/sys_upload_session/sys_attachment, lifecycle hooks, reap guards all present) but/api/v1/storage/*returns 404 — an AI-built app with an attachment field cannot upload. That is inside ADR-0112's v1 scope.Options (input, not a ruling)
A — export the three helpers (or a single
registerStorageRoutes-shaped entry that takes the raw app and a kernel accessor, the way settings already works). Smallest change; keeps one owner for the file-access authorization decision, which is the property that makes the settings bridge safe.B — give per-environment kernels a real route-collecting
http-serverservice, so every self-registering framework service plugin lights up at once. The general answer to this whole class — but its blast radius is every plugin'skernel:readybranch simultaneously (plugin-authreaches forgetRawApp()), and a throw there rolls back plugins and takes a tenant environment offline, which cloud has already paid for once.C — cloud re-implements the storage route wiring from the public surface. ⛔ Refused on the cloud side: a second authorizer.
Cloud seat's recommendation: A now; B as a deliberate later card if a third surface needs it. A and B are not exclusive.
四维(本席建议 A)
项目长远合理性(权重最高):文件访问授权只能有一个定义,住在框架里。A 让 cloud 逐字复用框架的决定——settings 桥之所以安全,正是因为路由与它需要的一切都在公开面上;storage 缺的只是把同一形状补齐。B 是这一类问题的通解,但通解的爆炸半径是所有插件的
kernel:ready分支同时点亮,需要单独的可靠性论证,不该搭在这张卡上。实际业务需求:ADR-0112 第一版明确含附件/图片字段;今天托管租户上传是 404。拉动是实测的。
防 AI 写代码犯错:C 是 AI 最容易「顺手做掉」的那条——在消费端重写一个授权器,测试全绿,而平台从此有两份下载门。拒绝 C 的理由就是要把这个错误在结构上堵死。
创业阶段不扩散需求:A 是把三个已有函数(或一个已有形状)放到公开面,不新增能力;B 是新基础设施。先 A。
Re-check
packages/services/service-storage/src/index.ts:30(the internal declaration) ·registerStorageRoutes's parameter list · cloudpackages/objectos-runtime/src/env-settings-routes-plugin.ts(PR #1965) as the working template for the bridge.Related: cloud#1963 · cloud PR #1965 · ADR-0104 D3.