@hanamesh/dsh-app-host 0.2.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/LICENSE +31 -0
  2. package/README.md +104 -0
  3. package/consistency.json +101 -0
  4. package/dist/client-ui.d.ts +19 -0
  5. package/dist/client-ui.js +271 -0
  6. package/dist/client.d.ts +16 -0
  7. package/dist/client.js +42 -0
  8. package/dist/consistency.js +12 -0
  9. package/dist/descriptor.js +141 -0
  10. package/dist/dsh.d.ts +25 -0
  11. package/dist/dsh.js +194 -0
  12. package/dist/errors.js +25 -0
  13. package/dist/gateway.js +224 -0
  14. package/dist/guardian.js +113 -0
  15. package/dist/index.d.ts +130 -0
  16. package/dist/index.js +15 -0
  17. package/dist/launcher.js +17 -0
  18. package/dist/library/catalog.js +108 -0
  19. package/dist/library/domain.js +8 -0
  20. package/dist/library/install.js +87 -0
  21. package/dist/library/installed.js +67 -0
  22. package/dist/library/locate.js +79 -0
  23. package/dist/library/routes.js +17 -0
  24. package/dist/library/service.js +76 -0
  25. package/dist/manager.js +605 -0
  26. package/dist/provision/LICENSE +6 -0
  27. package/dist/provision/THIRD_PARTY_NOTICES.md +13 -0
  28. package/dist/provision/archive.d.ts +28 -0
  29. package/dist/provision/archive.js +66 -0
  30. package/dist/provision/check.d.ts +10 -0
  31. package/dist/provision/check.js +51 -0
  32. package/dist/provision/checkpoints.d.ts +12 -0
  33. package/dist/provision/checkpoints.js +23 -0
  34. package/dist/provision/cli.d.ts +1 -0
  35. package/dist/provision/cli.js +169 -0
  36. package/dist/provision/download.d.ts +21 -0
  37. package/dist/provision/download.js +242 -0
  38. package/dist/provision/errors.d.ts +11 -0
  39. package/dist/provision/errors.js +13 -0
  40. package/dist/provision/extract.d.ts +17 -0
  41. package/dist/provision/extract.js +124 -0
  42. package/dist/provision/fsutil.d.ts +8 -0
  43. package/dist/provision/fsutil.js +71 -0
  44. package/dist/provision/index.d.ts +7 -0
  45. package/dist/provision/index.js +6 -0
  46. package/dist/provision/ledger.d.ts +14 -0
  47. package/dist/provision/ledger.js +50 -0
  48. package/dist/provision/manifest.d.ts +11 -0
  49. package/dist/provision/manifest.js +171 -0
  50. package/dist/provision/paths.d.ts +27 -0
  51. package/dist/provision/paths.js +95 -0
  52. package/dist/provision/platform.d.ts +6 -0
  53. package/dist/provision/platform.js +7 -0
  54. package/dist/provision/provision.d.ts +17 -0
  55. package/dist/provision/provision.js +454 -0
  56. package/dist/provision/tar.d.ts +7 -0
  57. package/dist/provision/tar.js +169 -0
  58. package/dist/provision/types.d.ts +174 -0
  59. package/dist/provision/types.js +7 -0
  60. package/dist/provision/zip.d.ts +4 -0
  61. package/dist/provision/zip.js +194 -0
  62. package/dist/router/broker.js +161 -0
  63. package/dist/router/domain.js +18 -0
  64. package/dist/router/receipts-domain.js +8 -0
  65. package/dist/router/receipts.js +156 -0
  66. package/dist/router/routes.js +48 -0
  67. package/dist/router/sources.js +87 -0
  68. package/dist/routes.js +74 -0
  69. package/dist/runtime.js +222 -0
  70. package/dist/store.js +250 -0
  71. package/dist/usage-evidence.js +117 -0
  72. package/docs/APP_PACKAGE.md +38 -0
  73. package/docs/CONTRACT.md +190 -0
  74. package/docs/DSH_INTEGRATION.md +43 -0
  75. package/docs/LIBRARY.md +45 -0
  76. package/docs/LICENSES.json +185 -0
  77. package/docs/PROVENANCE.json +63 -0
  78. package/docs/SECURITY.md +52 -0
  79. package/package.json +112 -0
  80. package/profile/cordis.patch.yml +4 -0
  81. package/schemas/catalog-provider-page.schema.json +376 -0
  82. package/schemas/catalog-source.schema.json +151 -0
@@ -0,0 +1,43 @@
1
+ # DSH 集成
2
+
3
+ > **NPM-APPHOST-01(2026-10-05,当前候选):** 目标为官方 `@deepseek-ai/dsh@0.2.0-rc.2`;本地 tarball 在隔离官方 profile 的 `dsh.profile.bundles` 中落座,`--dump-config` 可见 `hanamesh-app-host`。以下 rc.11 及更早说明保留为历史,不作为本候选的公开 npm 门。owner D-2026-10-05-02 已确认内联 `lib-provision` 为自有且可分发;独立许可分区见根 `LICENSE`,PUBLIC_NPM 由 PM 执行。浏览器可见性证据以 BlueMap 当前卡 REPORT 为准。
4
+
5
+ > **2026-09-19(rc.11):** 本包现在声明 DSH bundle。对独立 profile 执行 `dsh plugin --profile <name> add <本包.tgz>` 即会通过 `profile/cordis.patch.yml` 激活包根 `@hanamesh/dsh-app-host`,不要再手写 insert。包根保留核心 API,并以懒加载方式落座 Host;固定版本 `dsh-client-modules` 只有在 loader entry 是包根时才会发现 `./client`。HanaMesh 套件已内含本包;套件用户不要单独安装。若此前装过单包,先 `plugin remove @hanamesh/dsh-app-host` 再安装套件,避免重复 `hanamesh-app-host` loader id。桌面 Electron 壳必须在 config 提供独立可执行 `nodeBinary`。
6
+ >
7
+ > 应用库浏览可只配置 `library.fixture` 或 `library.sources`;`sources` 未配置时默认 HanaMesh 目录源(rc.26)。安装/卸载需要绝对 `library.profileDir`、`library.profileName`、`library.dshBin` 与 `nodeBinary`——桌面壳 overlay 显式给出;纯 DSH CLI profile 下 rc.26 从本包自身真实安装位置、启动本进程的 `@deepseek-ai/dsh/lib/bin.js` 和(非 Electron 的)`process.execPath` 推断,显式配置优先。钉版本宿主没有公开 profile-directory 服务,因此仍不从 cwd、PATH 或个人 `~/.dsh` 猜。目录源与安装契约见 `LIBRARY.md`,推断规则见 `CONTRACT.md`「应用库配置」。
8
+
9
+ > **2026-09-12(rc.3):** 干净安装锁文件和占用 Stop 的 HTTP 409 已修复;五个动作的重新验收证据见 `acceptance/wave01-resolution-report.md`。rc.2 的回收证据保留在下方,不能作为 rc.3 的包摘要。
10
+
11
+ > **2026-09-12(rc.2):DSH 侧已实现并在真实 profile 加载。** 入口 `@hanamesh/dsh-app-host/dsh`(`src/dsh.js`)绑定固定版本 DSH 0.1.5-alpha.1 **声明过的**公开 API:`ctx.storageDomain.open()`(single 布局,整个快照是一个 global,`global.set` 即一次整体发布)、`ctx.webServer.register()`(八条 exact 路由)、`ctx.connection.requestRejection()`(与 `/api` 通道相同的 Host/Origin 栅栏 + 浏览器 cookie;主体为本 profile 唯一的本地浏览器会话 `dsh-browser`)、`ctx.provide/ctx.effect`。`inject` 声明三项服务,缺 `connection` 时插件不激活、不会有公开路由。profile 接法:
12
+ >
13
+ > ```yaml
14
+ > - insert:
15
+ > - id: hanamesh-app-host
16
+ > name: '@hanamesh/dsh-app-host/dsh'
17
+ > config: { dataRoot: /abs/path, applications: [ …AppDefinition… ] }
18
+ > ```
19
+ >
20
+ > 证据:`docs/acceptance/recovery-20260912/h01-real-profile.log`、`dsh-real-cordis.tap`。下文是 rc.1 交付方写下的当时缺口,作为历史保留。
21
+
22
+ ## rc.1 时的缺口(历史)
23
+
24
+ **当时不支持直接把本候选当成已加载的 DSH 插件。** `apply()` 有意抛出 DSH_BINDING_REQUIRED。`createDshPlugin()` 接受的 bridge 是本仓定义的集成端口,不是已验证的官方 API 名称;不能填几个假函数就把 H01/H11 标 PASS。
25
+
26
+ ## 已知目标与实际证据
27
+
28
+ 输入文档锁定 DSH `0.1.5-alpha.1`、Node `24.13.1`、pnpm `10.33.0`、desktop `v0.1.0`、Tauri `2.11.5`、macOS arm64 / web profile。当前只有 Linux Node22.16.0,未安装真实 DSH。npm registry 网络解析失败;所需私有原型仓通过连接器读取返回404。
29
+
30
+ 因此以下结论没有成立:原型代码提取完成、原许可证继承、Cordis 服务加载成功、DSH domain 持久化成功、DSH session 写后自读成功、Tauri iframe兼容、macOS进程组/端口检查通过、workspace依赖已满足。
31
+
32
+ ## 接续开发只做这几步
33
+
34
+ 1. **取得指定原型。** `yzsnstotz/hanamesh` 的 `research/dsh-greenfield-2026-09-09/workspace/packages/hanamesh-app-host/`。记录实际 commit、许可证、package exports、描述符与路由契约;与本候选比对,尽量把已验证核心回归合入原型提取版,而不是机械替换未核对的接口。
35
+ 2. **读取固定版本公开扩展点。** 在独立 profile 查清 `ctx.provide`、`ctx.webServer.register`、卸载 hook、认证/授权上下文,以及官方 storage-domain 的 single 布局完整镜像发布 API。不要修改 DSH 内核,不调用猜测名称的接口,不写未知 Session.append 事件。
36
+ 3. **实现一个小的真实 bridge。** `storage(ctx)` 返回 `{layout:'single',domain:'hanamesh-app-host',readSnapshot,publishSnapshot,acquireExclusive,releaseExclusive}`;publishSnapshot 必须一次提交整个镜像。`mountAuthenticatedRoutes`、`provide` 返回真实注销函数;`onDispose` await 本模块 dispose;authenticate/authorize 连接宿主既有身份系统。bridge版本判断必须来自实际运行宿主,不是配置字符串自证。
37
+ 4. **最小 profile 真实加载验证。** 安装固定 tarball、实际读取 `ctx.hanameshApps`、注册受控应用并调用 Open/Close;移除研究目录仍能启动。随后通过 DSH 自己的 session API 建立/读取合法 session,执行租约写入,再通过 DSH 自己读取原 session;保存实际输入输出,完成 H01/H11。
38
+ 5. **复跑强杀和浏览器验收。** 在真实 single domain 发布边界运行 X02/X03;Mac上验证应用监听端口确属已启动进程组。允许正常回环访问的合法测试环境复跑浏览器H10/H13/H14,不绕过任何管理员控制。MOD-05 上游应用行为由对应适配包验收,不挤进 app-host 伪造通过。
39
+ 6. **核对版本与依赖门。** 修改与原型的差异按版本说明,发布新锁定产物和摘要。只有完整门通过才可标 DELIVERED;ACCEPTED 仍由用户操作。不要直接把本 rc 改成正式0.1.0并解锁 workspace。
40
+
41
+ peer 范围保留输入要求:`@deepseek-ai/cordis ^4.0.2` 与 `@deepseek-ai/schemastery ^3.18.2`。目前标 optional 仅为了核心独立安装不从网络拉未验证组件;不表示 DSH 集成可以不用它们。
42
+
43
+ 运行 `npm run preflight:dsh` 会输出当前缺失项并以代码2退出,这个预检是阻塞说明,不是安装器,也不是自动联网修复。
@@ -0,0 +1,45 @@
1
+ # HanaMesh 市场(原应用库)
2
+
3
+ > rc.28:入口改名「市场」,插件与应用同一入口、同一 `dsh plugin add/remove` 路径;已装列表含插件;可升级 / 需重启;新路由与响应形状见 `CONTRACT.md`「市场」。下文旧称「应用库」的段落仍然成立。
4
+
5
+ ## 范围
6
+
7
+ 应用库是 app-host 自带的 DSH 页面,不依赖第三方市场。它读取一个启用的目录源,同时独立扫描当前 profile 已安装的应用包;由 Community Market 安装的同一包会被接管,不做宿主市场探测。
8
+
9
+ ## 目录源
10
+
11
+ - `library.fixture` 只用于受控验收;内容必须符合 `schemas/catalog-provider-page.schema.json`。
12
+ - `library.sources` **未配置**时默认为 HanaMesh 目录源 `https://market.hanamesh.com/catalog-source.json`(rc.26;显式 `[]` = 不要来源);可有多项,但浏览时必须恰好启用一项。远端 manifest 只接受标准端口 HTTPS、无凭据/query/fragment;endpoint 必须同源。
13
+ - 请求固定 `Accept: application/json` 与 `Accept-Encoding: identity`;最多三次同源跳转,拒绝压缩响应与超过 2 MiB 的响应。
14
+ - `categories` 含 `hanamesh-app` 且 `package.registry` 为 `npm` 的条目是应用(安装后读 `app.json`、供给 runtime);其它 `package.registry` 为 `npm` 的条目是插件(rc.28 起同样可装卸,只跑 `dsh plugin add/remove`);无 npm 包的条目(repository-only)只展示。
15
+
16
+ ## Profile 与安装
17
+
18
+ 钉版本 DSH 没有向插件公开 profile 目录或 profile 名。桌面壳通过 overlay 显式给出 `library.profileDir`(绝对路径)、`library.profileName`、`library.dshBin` 与 `nodeBinary`,显式值永远优先。**纯 DSH CLI profile(rc.26)** 下缺省值按 `CONTRACT.md`「应用库配置」推断:`profileDir` 来自本包自身真实安装位置所属的 profile、`profileName` 为其目录名、`dshBin` 只取启动本进程的 `@deepseek-ai/dsh/lib/bin.js`、`nodeBinary` 只在非 Electron 进程取 `process.execPath`。Electron 下仍必须由 dsh-runtime/core 提供绝对 `nodeBinary`;应用库不会在 Electron 里回退到 `process.execPath`。
19
+
20
+ 安装先向 registry 的 `latest` 端点复核精确稳定版本,再用显式 Node 执行 DSH 自己的 `bin.js plugin --profile <name> add --save-exact <package>@<version>`。成功后读取包内 `app.json`;如果描述符声明 runtime,则调用随包内联的锁定 `@hanamesh/lib-provision@0.1.0-rc.1`。生产默认拒绝 prerelease;隔离 Verdaccio 验收可显式设 `allowPrerelease: true`。
21
+
22
+ 安装/卸载完成只返回 `restart-required`,绝不静默重启 DSH。卸载只删除包与 lib-provision 账本认领的 runtime 文件,保留 `<dataRoot>` 下应用数据;彻底删除需用户手动处理对应数据目录。
23
+
24
+ ## 状态与路由
25
+
26
+ 已安装应用扫描给出 `registered`、`installed-not-loaded`、`runtime-missing` 或 `invalid`;已安装插件扫描(rc.28)给出 `installed`、`installed-not-loaded`、`uninstalled-not-unloaded` 或 `invalid`。浏览器路由为 `/hanamesh/library`、`/hanamesh/library/sources`、`/hanamesh/library/install`、`/hanamesh/library/provision`、`/hanamesh/library/uninstall`、`/hanamesh/library/events`、`/hanamesh/library/installedPlugins`、`/hanamesh/library/plugins/install` 和 `/hanamesh/library/plugins/uninstall`,全部复用 app-host 的 Host/Origin/iframe/auth/CSRF 防护链。
27
+
28
+ 应用打开仍只走 app-host 的视图租约 API;页面只保存临时 receipt,不拥有第二份实例状态。
29
+
30
+ ## 锁定产物
31
+
32
+ 私有 `@hanamesh/lib-provision` 不作为 package dependency 或 peer。build 校验 vendor tgz 的 SHA-256 后提取 `lib/**` 到 `dist/provision/`,并带入 notices 与独立 `LICENSE` 声明;来源、SHA-256 与许可分区记录在 `docs/PROVENANCE.json`、`docs/LICENSES.json` 和根 `LICENSE`。
33
+
34
+
35
+ ## rc.16 · 浏览语义(2026-09-20 线上目录门后定)
36
+
37
+ - `GET /hanamesh/library?q=&category=&cursor=`:`category` 缺省为 `hanamesh-app`(本页是**应用库**,只列应用条目);显式 `category=`(空)列出来源的全部条目;`q` 与 `cursor` 原样透传给目录源的 `/v1/plugins`(`limit=50`)。未知参数 → `UNKNOWN_FIELDS`。
38
+ - 客户端:搜索框(回车/「搜索」)、「只看应用」开关(默认开)、「更多」按 `page.nextCursor` 追加。
39
+ - 背景:真实来源 `market.hanamesh.com` 有 12,121 条,rc.15 之前只显示按更新时间排序的前 50 条且无搜索,应用条目实际不可达。
40
+
41
+ ## rc.28 · 市场浏览语义
42
+
43
+ - 市场页默认 `category=`(全部);筛选:全部 / 应用(`hanamesh-app`)/ 插件(客户端视图:本页非应用的 npm 条目)/ 目录页里出现过的类别(累积自 `categories`)。路由 `/hanamesh/library` 的缺省 `category=hanamesh-app` 不变(向后兼容)。
44
+ - 卡片:`kind · 发布者 · latestVersion · 类别`;已装行显示状态与版本;「升级到 x.y.z」出现在 `upgradeAvailable` 时;插件「卸载」走 `plugins/uninstall`。页面底部「已安装」列出应用与插件(含 bundle 未启用为 profile 层的提示)。
45
+ - 「需重启 DSH」横幅:任一装卸操作完成后,或列表 `restartRequired` 为真时显示;壳内为 `hanamesh://restart` 链接,官方 DSH 直开为文字提示。
@@ -0,0 +1,185 @@
1
+ {
2
+ "package": {
3
+ "name": "@hanamesh/dsh-app-host",
4
+ "version": "0.2.0-rc.2",
5
+ "license": "SEE LICENSE IN LICENSE",
6
+ "source": "git+https://github.com/yzsnstotz/hanamesh-plugin-app-host.git",
7
+ "purpose": "Application ownership, view leases, Router forwarding, and application library for official DSH"
8
+ },
9
+ "scope": "Direct dependencies and build-time inlined module. External packages retain their own licenses; the root MIT terms do not cover dist/provision/**.",
10
+ "components": {
11
+ "@hanamesh/lib-provision": {
12
+ "version": "0.1.0-rc.1",
13
+ "license": "UNLICENSED",
14
+ "source": "vendor/hanamesh-lib-provision-0.1.0-rc.1.tgz",
15
+ "purpose": "Inlined runtime download, extraction, atomic promotion, and ledger logic in dist/provision/**",
16
+ "sha256": "386d57361ccc3c8578f54cad8137acc291dd72e01b3ff987e65dfaa716f2e0b0"
17
+ },
18
+ "zod": {
19
+ "version": "4.5.4",
20
+ "license": "MIT",
21
+ "source": "https://registry.npmjs.org/zod/-/zod-4.5.4.tgz",
22
+ "purpose": "Runtime snapshot validation",
23
+ "usedAs": [
24
+ "dependencies"
25
+ ]
26
+ },
27
+ "@deepseek-ai/cordis": {
28
+ "version": "4.0.4",
29
+ "license": "MIT",
30
+ "source": "https://registry.npmjs.org/@deepseek-ai/cordis/-/cordis-4.0.4.tgz",
31
+ "purpose": "Official DSH plugin lifecycle and service container",
32
+ "usedAs": [
33
+ "peerDependencies",
34
+ "devDependencies"
35
+ ]
36
+ },
37
+ "@deepseek-ai/dsh-storage-domain": {
38
+ "version": "0.2.0-rc.2",
39
+ "license": "MIT",
40
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-storage-domain/-/dsh-storage-domain-0.2.0-rc.2.tgz",
41
+ "purpose": "Official DSH persistent storage service",
42
+ "usedAs": [
43
+ "peerDependencies",
44
+ "devDependencies"
45
+ ]
46
+ },
47
+ "@deepseek-ai/schemastery": {
48
+ "version": "3.18.4",
49
+ "license": "MIT",
50
+ "source": "https://registry.npmjs.org/@deepseek-ai/schemastery/-/schemastery-3.18.4.tgz",
51
+ "purpose": "Official DSH configuration schema service",
52
+ "usedAs": [
53
+ "peerDependencies",
54
+ "devDependencies"
55
+ ]
56
+ },
57
+ "@deepseek-ai/dsh-host-webserver": {
58
+ "version": "0.2.0-rc.2",
59
+ "license": "MIT",
60
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-host-webserver/-/dsh-host-webserver-0.2.0-rc.2.tgz",
61
+ "purpose": "Official DSH authenticated HTTP route host",
62
+ "usedAs": [
63
+ "peerDependencies",
64
+ "devDependencies"
65
+ ]
66
+ },
67
+ "@deepseek-ai/dsh-client-connection": {
68
+ "version": "0.2.0-rc.2",
69
+ "license": "MIT",
70
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-client-connection/-/dsh-client-connection-0.2.0-rc.2.tgz",
71
+ "purpose": "Official DSH client connection service",
72
+ "usedAs": [
73
+ "peerDependencies"
74
+ ]
75
+ },
76
+ "@deepseek-ai/dsh-client-ui-slots": {
77
+ "version": "0.2.0-rc.2",
78
+ "license": "MIT",
79
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-slots/-/dsh-client-ui-slots-0.2.0-rc.2.tgz",
80
+ "purpose": "Official DSH client UI placement",
81
+ "usedAs": [
82
+ "peerDependencies"
83
+ ]
84
+ },
85
+ "@deepseek-ai/dsh-client-ui-settings": {
86
+ "version": "0.2.0-rc.2",
87
+ "license": "MIT",
88
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-client-ui-settings/-/dsh-client-ui-settings-0.2.0-rc.2.tgz",
89
+ "purpose": "Official DSH client settings surface",
90
+ "usedAs": [
91
+ "peerDependencies"
92
+ ]
93
+ },
94
+ "@deepseek-ai/dsh-client-locale": {
95
+ "version": "0.2.0-rc.2",
96
+ "license": "MIT",
97
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-client-locale/-/dsh-client-locale-0.2.0-rc.2.tgz",
98
+ "purpose": "Official DSH client localization",
99
+ "usedAs": [
100
+ "peerDependencies"
101
+ ]
102
+ },
103
+ "react": {
104
+ "version": "18.3.1",
105
+ "license": "MIT",
106
+ "source": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
107
+ "purpose": "Official DSH client UI peer",
108
+ "usedAs": [
109
+ "peerDependencies"
110
+ ]
111
+ },
112
+ "@deepseek-ai/dsh-scope": {
113
+ "version": "0.2.0-rc.2",
114
+ "license": "MIT",
115
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-scope/-/dsh-scope-0.2.0-rc.2.tgz",
116
+ "purpose": "Build and test fixture for official DSH scopes",
117
+ "usedAs": [
118
+ "devDependencies"
119
+ ]
120
+ },
121
+ "@deepseek-ai/dsh-session": {
122
+ "version": "0.2.0-rc.2",
123
+ "license": "MIT",
124
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-session/-/dsh-session-0.2.0-rc.2.tgz",
125
+ "purpose": "Build and test fixture for official DSH sessions",
126
+ "usedAs": [
127
+ "devDependencies"
128
+ ]
129
+ },
130
+ "@deepseek-ai/dsh-session-persistence": {
131
+ "version": "0.2.0-rc.2",
132
+ "license": "MIT",
133
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-session-persistence/-/dsh-session-persistence-0.2.0-rc.2.tgz",
134
+ "purpose": "Build and test fixture for official DSH session persistence",
135
+ "usedAs": [
136
+ "devDependencies"
137
+ ]
138
+ },
139
+ "@deepseek-ai/dsh-session-persistence-jsonl": {
140
+ "version": "0.2.0-rc.2",
141
+ "license": "MIT",
142
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-session-persistence-jsonl/-/dsh-session-persistence-jsonl-0.2.0-rc.2.tgz",
143
+ "purpose": "Build and test fixture for official DSH JSONL session persistence",
144
+ "usedAs": [
145
+ "devDependencies"
146
+ ]
147
+ },
148
+ "@deepseek-ai/dsh-session-projection": {
149
+ "version": "0.2.0-rc.2",
150
+ "license": "MIT",
151
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-session-projection/-/dsh-session-projection-0.2.0-rc.2.tgz",
152
+ "purpose": "Build and test fixture for official DSH session projections",
153
+ "usedAs": [
154
+ "devDependencies"
155
+ ]
156
+ },
157
+ "@deepseek-ai/dsh-storage": {
158
+ "version": "0.2.0-rc.2",
159
+ "license": "MIT",
160
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-storage/-/dsh-storage-0.2.0-rc.2.tgz",
161
+ "purpose": "Build and test fixture for official DSH storage",
162
+ "usedAs": [
163
+ "devDependencies"
164
+ ]
165
+ },
166
+ "@deepseek-ai/dsh-storage-json": {
167
+ "version": "0.2.0-rc.2",
168
+ "license": "MIT",
169
+ "source": "https://registry.npmjs.org/@deepseek-ai/dsh-storage-json/-/dsh-storage-json-0.2.0-rc.2.tgz",
170
+ "purpose": "Build and test fixture for official DSH JSON storage",
171
+ "usedAs": [
172
+ "devDependencies"
173
+ ]
174
+ },
175
+ "typescript": {
176
+ "version": "5.8.3",
177
+ "license": "Apache-2.0",
178
+ "source": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
179
+ "purpose": "Build-time type checking and declarations",
180
+ "usedAs": [
181
+ "devDependencies"
182
+ ]
183
+ }
184
+ }
185
+ }
@@ -0,0 +1,63 @@
1
+ {
2
+ "currentCandidate": {
3
+ "version": "0.2.0-rc.2",
4
+ "dshTarget": "0.2.0-rc.2",
5
+ "vendorSha256VerifiedAtBuild": true,
6
+ "libProvisionDistribution": "Owner confirmed self-owned and distributable; source license remains UNLICENSED; see LICENSE and docs/LICENSES.json",
7
+ "publicNpmGate": "NOT_RUN"
8
+ },
9
+ "module": "app-host",
10
+ "version": "0.1.0-rc.12",
11
+ "status": "PARTIAL",
12
+ "implementationOrigin": "New implementation candidate based on supplied specifications; not an extraction of the inaccessible prototype",
13
+ "inputArchive": {
14
+ "file": "90fe3c76-3f06-4abd-b83c-52c17429cba9.zip",
15
+ "sha256": "cd79ef78b311537f0a9425e0b7b8c9f0c44f2581d8c9156f23f1fe431832c1c7",
16
+ "bytes": 2121179
17
+ },
18
+ "inputDocsHead": "195ee9f2e71a41caede474e29d58237fab7e4b89",
19
+ "inputDocsWorkingTree": "Contains pre-existing modifications in supplied archive; original files left unchanged",
20
+ "requiredPrototype": {
21
+ "repository": "yzsnstotz/hanamesh",
22
+ "path": "research/dsh-greenfield-2026-09-09/workspace/packages/hanamesh-app-host/",
23
+ "commit": null,
24
+ "license": null,
25
+ "retrieval": "GitHub.get_repo returned HTTP 404"
26
+ },
27
+ "remoteDelivery": {
28
+ "created": false,
29
+ "pushed": false,
30
+ "pullRequest": null,
31
+ "reason": "No create_repository action exposed; requested prototype repository is not readable; unrelated repository not modified"
32
+ },
33
+ "runtime": {
34
+ "node": "v22.16.0",
35
+ "npm": "10.9.2",
36
+ "platform": "Linux",
37
+ "arch": "x86_64",
38
+ "typescript": "Version 5.8.3"
39
+ },
40
+ "target": {
41
+ "dsh": "0.1.5-alpha.1",
42
+ "node": "24.13.1",
43
+ "pnpm": "10.33.0",
44
+ "platform": "darwin-arm64",
45
+ "tested": false
46
+ },
47
+ "actualModel": "GPT-6 Astra Pro",
48
+ "effortSetting": "not exposed; not claimed",
49
+ "defaultModelInInput": "Opus 5 High (not executed here)",
50
+ "auxiliaryAgents": 0,
51
+ "tokenUsage": "not independently metered",
52
+ "upstreamFilesModified": 0,
53
+ "bundledArtifacts": {
54
+ "@hanamesh/lib-provision": {
55
+ "version": "0.1.0-rc.1",
56
+ "source": "vendor/hanamesh-lib-provision-0.1.0-rc.1.tgz",
57
+ "sha256": "386d57361ccc3c8578f54cad8137acc291dd72e01b3ff987e65dfaa716f2e0b0",
58
+ "mode": "build-time inline into dist/provision; no package dependency or peer declaration"
59
+ }
60
+ },
61
+ "sessionLogWrites": 0,
62
+ "historicalCandidateLicense": "UNLICENSED; no upstream-license inheritance or open-source grant asserted"
63
+ }
@@ -0,0 +1,52 @@
1
+ # 安全与运行边界
2
+
3
+ ## 可信边界
4
+
5
+ 注册描述符、DSH bridge 与宿主代码可信;浏览器请求、应用 HTTP 内容、旧租约和磁盘错误不可信。浏览器不能传命令、argv、env、cwd、dataDir 或任意上游 URL。实际 HTTP 拒绝和负向测试见 acceptance。
6
+
7
+ 本实现**不是 OS 沙箱**。独立数据路径证明正常应用按配置写入隔离目录,不保证恶意的同 UID 本地程序不能访问其他文件、网络或自行调用 setsid。需要强隔离时应另行使用经过验收的 OS sandbox/container,本模块没有实现也没有宣称实现该能力。禁止 daemonizing 启动器;上游适配包必须验证应用使用所分配的 data/HOME/XDG 路径。
8
+
9
+ ## owned 与 attach
10
+
11
+ 每个 owned runtime 使用独立 guardian 及锚定进程组的 launcher。宿主 IPC 断开会触发 guardian 清理;清理仅对该精确子进程创建的进程组,绝不按名称匹配或复用磁盘 PID 发 kill。收到清理确认才发布 stopped。attach 无 guardian、无 kill 路径。
12
+
13
+ 主机断电、内核崩溃、存储损坏、恶意 daemon 脱离进程组不在此次证明范围。
14
+
15
+ ### runtime lock 的死主接管(rc.25)
16
+
17
+ 每个 owned 数据根下的 `.runtime.lock` 由 guardian 持有,记录 `{pid, start, id, children:[{pid,start,command,role,group}], port}`:`start` 是进程启动时间令牌(macOS/Linux 由 `ps -o lstart=` 或 `/proc/<pid>/stat` + boot_id 得到),`children` 是 guardian 自己创建的 launcher(进程组组长)与应用进程。launcher 在收到 launch 指令之前就已被记录,所以它还没机会派生任何东西时锁里已经有它。
18
+
19
+ guardian 被强杀(桌面壳整棵树被 kill、`kill -9`)后,下一次 acquire 的判定顺序固定为:
20
+
21
+ 1. **owner 活着**(pid 存在且启动令牌一致,或旧格式无令牌但 pid 存在)→ `DATA_ROOT_BUSY`,`details = {pid, start, reason:'owner-alive', port}`,不发任何信号。
22
+ 2. **owner 死了**(pid 不存在,或同 pid 启动令牌不同 = pid 被复用)→ 逐个核对 `children`:
23
+ - pid 不存在、或启动令牌与记录不同(pid 被无关进程复用)→ 视为已消失,**不发信号**;
24
+ - pid + 启动令牌 + 可执行文件(realpath 比较)三者一致 → **可证明是我们的孤儿**,先 SIGTERM(进程组组长连同 `-pid` 组一起),等 `stopGraceMs`,再 SIGKILL,确认退出后接管;
25
+ - 活着但证明不了(记录或平台缺启动令牌、可执行文件不同)→ `DATA_ROOT_BUSY`,`details = {pid, pids, ownerPid, reason:'orphan-unproven', children}`,不发信号,锁原样保留。
26
+ 3. 接管仍走原有的 `.recovery` 独占标记序列化;损坏的锁文件依旧 `LOCK_RECOVERY_REQUIRED`,不自动删。
27
+
28
+ Windows 与无 `ps` 的环境退化为只判 pid 存活:活着的进程永远无法被证明是我们的,只会 `DATA_ROOT_BUSY`,不会接管。绝不按进程名匹配,不 `pkill node`;人工维修时先看 `details.pid`。
29
+
30
+ Linux 的 socket 所有权检查已实际运行;macOS lsof 路径未实测;Windows owned 在 spawn 前拒绝。平台声明不是跨平台验收。
31
+
32
+ ## 网关
33
+
34
+ 仅 `http://127.0.0.1:<显式端口>`,固定一个上游,不解析用户传入 target,不跟随 redirect,不接受 CONNECT 或绝对请求目标。只有携带当前租约 generation 能力 cookie 的请求可访问;bootstrap 限时单次票据要求指定父页面的 iframe 导航。直接顶层导航、未列名 Origin、过期/旧代能力拒绝。应用响应正文不改写,不注入 HTML、SDK 或 postMessage bridge。
35
+
36
+ 只删除 X-Frame-Options、将 CSP 的 frame-ancestors 设为一个 parent origin,保留其他 CSP 指令和应用头。HTTP hop-by-hop framing/连接由 Node 传输管理;不是网络原始报文字节镜像。bootstrap 是本模块自己的303响应,不冒称上游应用响应。真实浏览器 cookie/iframe 行为本环境被管理员策略拦截,所以不保证 H13 已全通过。
37
+
38
+ DSH/宿主 cookie、控制头与 Authorization 默认不传上游;应用 cookie 必须逐名白名单,应用 Authorization 需要受信显式开启。父页和应用均在127.0.0.1时,浏览器 cookie 不是按端口隔离的,因此不把“不同端口”当作 cookie 安全边界。本网关的转发过滤只守住到上游这一跳,不能代替原应用正确设计自己的 cookie/auth。
39
+
40
+ 不更改原应用 Origin/CSRF/CORS;带严格自身 origin 校验或绝对 URL 的应用可能拒绝网关请求,必须如实报告并由适配器走受支持的配置,不得通过关掉应用安全策略解决。direct embedding 返回原上游 URL,沿用原应用自己的认证/框架限制,不具有 gateway 能力保护。
41
+
42
+ ## 日志与凭据
43
+
44
+ 日志有界、按完整行处理、Bearer/常见 token 字段及显式 secret env 值脱敏;超大行丢弃。此规则不可能识别任意业务敏感信息,默认不记录请求体/配置环境。leaseToken 原文只在回执中返回,磁盘保存哈希;工作台不得把 token 放进公开 URL、分析日志或应用 iframe。
45
+
46
+ 恢复凭据属于同一已认证 owner 的显式操作,要求 confirm:true,旋转 generation;真实 DSH bridge 的 authorize 必须对该路径落实授权。示例/测试的固定认证值绝不能作为真实 DSH 身份实现。
47
+
48
+ ## 浏览器测试限制
49
+
50
+ 实际 Chromium 启动于独立临时 profile,但回环导航返回 `net::ERR_BLOCKED_BY_ADMINISTRATOR`。未改管理员 policy、未关 CSP、未使用绕过标志。两个 REAL_BROWSER 测试显式 skip 并在产品矩阵标 PARTIAL,不算 PASS。
51
+
52
+ 测试 Chromium 的 `--no-sandbox` 仅为隔离容器内以 root 运行测试驱动所需,绝非生产应用/DSH 的启动配置;不应该移植到生产 profile。
package/package.json ADDED
@@ -0,0 +1,112 @@
1
+ {
2
+ "name": "@hanamesh/dsh-app-host",
3
+ "version": "0.2.0-rc.2",
4
+ "description": "HanaMesh application ownership, durable view leases, and application library for official DSH 0.2.0-rc.2",
5
+ "type": "module",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/yzsnstotz/hanamesh-plugin-app-host.git"
10
+ },
11
+ "engines": {
12
+ "node": ">=24.13.1 <25"
13
+ },
14
+ "main": "./dist/index.js",
15
+ "types": "./dist/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.js"
20
+ },
21
+ "./dsh": {
22
+ "types": "./dist/dsh.d.ts",
23
+ "default": "./dist/dsh.js"
24
+ },
25
+ "./package.json": "./package.json",
26
+ "./client": {
27
+ "types": "./dist/client.d.ts",
28
+ "node": "./dist/client.js",
29
+ "default": "./dist/client-ui.js"
30
+ },
31
+ "./client-ui": {
32
+ "types": "./dist/client-ui.d.ts",
33
+ "default": "./dist/client-ui.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "dist",
38
+ "consistency.json",
39
+ "README.md",
40
+ "LICENSE",
41
+ "docs/CONTRACT.md",
42
+ "docs/DSH_INTEGRATION.md",
43
+ "docs/APP_PACKAGE.md",
44
+ "docs/LIBRARY.md",
45
+ "docs/SECURITY.md",
46
+ "docs/PROVENANCE.json",
47
+ "docs/LICENSES.json",
48
+ "schemas",
49
+ "profile"
50
+ ],
51
+ "scripts": {
52
+ "build": "node scripts/build.mjs",
53
+ "test": "node --test --test-concurrency=1 tests/*.test.mjs",
54
+ "test:mutation": "node scripts/mutations.mjs",
55
+ "test:types": "tsc --noEmit --strict --target ES2022 --module NodeNext --moduleResolution NodeNext tests/consumer.mts",
56
+ "check": "npm run build && npm run check:consistency && npm test && npm run test:mutation",
57
+ "prepack": "npm run build",
58
+ "demo": "node examples/demo.mjs",
59
+ "preflight:dsh": "node scripts/preflight-dsh.mjs",
60
+ "check:consistency": "node scripts/check-consistency.mjs"
61
+ },
62
+ "dsh": {
63
+ "bundle": {
64
+ "patch": "./profile/cordis.patch.yml"
65
+ },
66
+ "client": {
67
+ "inject": [
68
+ "@deepseek-ai/dsh-client-ui-slots",
69
+ "@deepseek-ai/dsh-client-ui-settings",
70
+ "@deepseek-ai/dsh-client-locale"
71
+ ],
72
+ "platform": "web",
73
+ "external": [
74
+ "react"
75
+ ]
76
+ }
77
+ },
78
+ "dependencies": {
79
+ "zod": "4.5.4"
80
+ },
81
+ "peerDependencies": {
82
+ "@deepseek-ai/cordis": "4.0.4",
83
+ "@deepseek-ai/dsh-storage-domain": "0.2.0-rc.2",
84
+ "@deepseek-ai/schemastery": "3.18.4",
85
+ "@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
86
+ "@deepseek-ai/dsh-client-connection": "0.2.0-rc.2",
87
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
88
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
89
+ "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
90
+ "react": "18.3.1"
91
+ },
92
+ "hanamesh": {
93
+ "module": "app-host",
94
+ "contractVersion": 1,
95
+ "dshTarget": "0.2.0-rc.2",
96
+ "upstreamFilesModified": 0
97
+ },
98
+ "devDependencies": {
99
+ "@deepseek-ai/cordis": "4.0.4",
100
+ "@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
101
+ "@deepseek-ai/dsh-scope": "0.2.0-rc.2",
102
+ "@deepseek-ai/dsh-session": "0.2.0-rc.2",
103
+ "@deepseek-ai/dsh-session-persistence": "0.2.0-rc.2",
104
+ "@deepseek-ai/dsh-session-persistence-jsonl": "0.2.0-rc.2",
105
+ "@deepseek-ai/dsh-session-projection": "0.2.0-rc.2",
106
+ "@deepseek-ai/dsh-storage": "0.2.0-rc.2",
107
+ "@deepseek-ai/dsh-storage-domain": "0.2.0-rc.2",
108
+ "@deepseek-ai/dsh-storage-json": "0.2.0-rc.2",
109
+ "@deepseek-ai/schemastery": "3.18.4",
110
+ "typescript": "5.8.3"
111
+ }
112
+ }
@@ -0,0 +1,4 @@
1
+ - insert:
2
+ - id: hanamesh-app-host
3
+ name: '@hanamesh/dsh-app-host'
4
+ config: {}