在 #14375(PR #14430)做真实启动取证时撞到,先在 PR 分支上出现,再在 origin/main6aea1f5(dist 里 withWritableVerdict 计数为 0,即不含 #14430 的任何改动)上逐字复现。既有缺陷,与 #14430 无关;单独立卡。
复现(实测,os dev)
cd examples/app-showcase && ./node_modules/.bin/objectstack dev --seed-admin -p 4377 -d file:/tmp/x/data.db
# 登录 POST /api/v1/auth/sign-in/email → set-auth-token
GET /api/v1/packages → HTTP 500
GET /api/v1/packages/com.example.showcase → HTTP 500
GET /api/v1/meta/package → HTTP 500 {"error":"Internal server error","code":"INTERNAL_ERROR"}
GET /api/v1/packages?type=plugin → HTTP 200(把 showcase 这条应用记录过滤掉就正常)
信封原文:
Converting circular structure to JSON
--> starting at object with constructor '_ObjectQL'
| property 'actionActivation' -> object with constructor 'ActionActivationProjection'
| property 'store' -> object with constructor 'ObjectStoreActionActivationStore'
--- property 'engine' closes the circle
同一进程里 POST /api/v1/packages/com.example.showcase/duplicate 也在 service-package 的 publish(JSON.stringify(manifest) 持久化到 sys_packages)处以同一错误失败:"sys_packages persist FAILED for 'com.acme.dupbase'"。
对照:examples/app-todo(栈定义里没有任何插件 / 数据源实例)同一流程 GET /api/v1/packages 200、23 行,复制 base 也正常。
根因(源码锚点)
examples/app-showcase/objectstack.config.ts:134-162:plugins: [new ConnectorOpenApiPlugin(), new ConnectorMcpPlugin(...), …],datasources: [ShowcaseExternalDatasource] —— 栈定义里带运行时实例。packages/runtime/src/app-plugin.ts:263-266:servicePayload = { ...this.bundle.manifest, ...this.bundle } 后直接 manifest.register(servicePayload) —— 实例原样进了注册载荷。SchemaRegistry.installPackage 把 manifest原样存进包记录(registry.ts,D7 位一致性也依赖"原样")。启动后这些插件实例持有 engine,于是任何对包记录做 JSON.stringify 的门(两条 GET /packages 门、getMetaItems({type:'package'})、sys_packages 持久化)都被循环引用炸掉。
影响
Studio 包选择器读的就是 GET /api/v1/packages:凡栈定义里带插件实例的应用(showcase 这一类),Studio 的包列表整体不可用;纯元数据应用(hotcrm、app-todo)不受影响。?type= 过滤掉应用记录时能过,说明只有那一条记录不可序列化。
待决定的修法方向(不在本卡拍板,给 dev / 维护者)
- A. 注册时把不可序列化的运行时键(
plugins / datasources 实例)从进包记录的 manifest 上剥掉,只留可声明部分;D7 单包 bit-identity pin 要一起看(它比的是什么就得说清)。 - B. 包记录照存,但所有服务包行的门统一经一个"可序列化视图"出去(去掉实例键)。
- 两者都要有一条 pin:带插件实例的栈启动后
GET /api/v1/packages 200 且行数正确。
关联
在 #14375(PR #14430)做真实启动取证时撞到,先在 PR 分支上出现,再在
origin/main6aea1f5(dist 里withWritableVerdict计数为 0,即不含 #14430 的任何改动)上逐字复现。既有缺陷,与 #14430 无关;单独立卡。复现(实测,
os dev)信封原文:
同一进程里
POST /api/v1/packages/com.example.showcase/duplicate也在service-package的publish(JSON.stringify(manifest)持久化到sys_packages)处以同一错误失败:"sys_packages persist FAILED for 'com.acme.dupbase'"。对照:
examples/app-todo(栈定义里没有任何插件 / 数据源实例)同一流程GET /api/v1/packages200、23 行,复制 base 也正常。根因(源码锚点)
examples/app-showcase/objectstack.config.ts:134-162:plugins: [new ConnectorOpenApiPlugin(), new ConnectorMcpPlugin(...), …],datasources: [ShowcaseExternalDatasource]—— 栈定义里带运行时实例。packages/runtime/src/app-plugin.ts:263-266:servicePayload = { ...this.bundle.manifest, ...this.bundle }后直接manifest.register(servicePayload)—— 实例原样进了注册载荷。SchemaRegistry.installPackage把manifest原样存进包记录(registry.ts,D7 位一致性也依赖"原样")。启动后这些插件实例持有engine,于是任何对包记录做JSON.stringify的门(两条GET /packages门、getMetaItems({type:'package'})、sys_packages持久化)都被循环引用炸掉。影响
Studio 包选择器读的就是
GET /api/v1/packages:凡栈定义里带插件实例的应用(showcase 这一类),Studio 的包列表整体不可用;纯元数据应用(hotcrm、app-todo)不受影响。?type=过滤掉应用记录时能过,说明只有那一条记录不可序列化。待决定的修法方向(不在本卡拍板,给 dev / 维护者)
plugins/datasources实例)从进包记录的manifest上剥掉,只留可声明部分;D7 单包 bit-identity pin 要一起看(它比的是什么就得说清)。GET /api/v1/packages200 且行数正确。关联
GET /packages与GET /packages/:id每行携带服务端自己的可写判定writable(isWritablePackage),Studio 不再用scope启发式反推 #14375 / PR feat(packages): GET /packages and GET /packages/:id rows carry the server's own writable verdict (isWritablePackage) #14430 的真实启动取证;该 PR 的证据改用app-todo,并把本卡记为既有缺陷。