@heybox/hb-sdk 0.7.3-alpha.2 → 0.7.4-alpha.1

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 (43) hide show
  1. package/CHANGELOG.md +36 -1
  2. package/README.md +5 -0
  3. package/dist/cli-chunks/{build-SCCCDtC6.cjs → build-Cej8ObyY.cjs} +2 -2
  4. package/dist/cli-chunks/{context-dika4R3J.cjs → context-DATgeHkI.cjs} +6 -19
  5. package/dist/cli-chunks/{create-DK9-wP6G.cjs → create-LXHV_lW5.cjs} +1 -1
  6. package/dist/cli-chunks/{dev-B0vo5N0U.cjs → dev-CDuVyGm9.cjs} +798 -139
  7. package/dist/cli-chunks/{doctor-BfVm18BY.cjs → doctor-BqmQrPaV.cjs} +1 -1
  8. package/dist/cli-chunks/{index-CXeFMwHy.cjs → index-BCd2vU5D.cjs} +24 -21
  9. package/dist/cli-chunks/{index-BxnwvZsl.cjs → index-Ck7X1LRP.cjs} +1 -1
  10. package/dist/cli-chunks/{login-DRgv4TGG.cjs → login-BLTILOf-.cjs} +2 -2
  11. package/dist/cli-chunks/{project-vite-BxuI2_2-.cjs → project-vite-BtIYxLkt.cjs} +1 -1
  12. package/dist/cli-chunks/{remote-BqHHAon9.cjs → remote-Bp9SK8C3.cjs} +4 -4
  13. package/dist/cli-chunks/{session-DZsk79k0.cjs → session-9ZWPGpqB.cjs} +1 -1
  14. package/dist/cli.cjs +1 -1
  15. package/dist/devtools/{mock-host → browser-dev-host}/index.html +3 -7
  16. package/dist/devtools/browser-dev-host/main.js +9657 -0
  17. package/dist/index.cjs.js +40 -118
  18. package/dist/index.esm.js +40 -118
  19. package/dist/protocol.cjs.js +71 -346
  20. package/dist/protocol.esm.js +72 -342
  21. package/dist/vite.cjs.js +1 -4
  22. package/dist/vite.esm.js +1 -4
  23. package/package.json +26 -9
  24. package/skill/SKILL.md +5 -5
  25. package/skill/references/api-protocol.md +102 -114
  26. package/skill/references/api-root.md +1 -1
  27. package/skill/references/cli.md +4 -2
  28. package/skill/references/safety-boundaries.md +1 -0
  29. package/skill/scripts/sync-references.mjs +5 -1
  30. package/skill/skill.json +4 -4
  31. package/types/core/network-sanitize.d.ts +1 -1
  32. package/types/modules/auth/index.d.ts +3 -1
  33. package/types/modules/user/types.d.ts +2 -53
  34. package/types/protocol/capabilities.d.ts +2 -352
  35. package/types/protocol/constants.d.ts +1 -14
  36. package/types/protocol/dev-session.d.ts +3 -3
  37. package/types/protocol/guards.d.ts +1 -8
  38. package/types/protocol/runtime-permissions.d.ts +2 -41
  39. package/types/protocol/types.d.ts +3 -150
  40. package/types/protocol.d.ts +8 -23
  41. package/dist/devtools/mock-host/main.js +0 -7751
  42. package/types/protocol/network-policy.d.ts +0 -10
  43. package/types/protocol/trusted-user-gesture.d.ts +0 -6
@@ -1,291 +1,30 @@
1
- /** 小程序沙盒通信命名空间,父容器与 iframe 内 SDK 必须保持一致。 */
2
- const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
3
- /** 小程序沙盒通信协议版本。 */
4
- const MINI_PROGRAM_MESSAGE_VERSION = 2;
5
- /** 父容器注入到小程序 URL 上的通信 nonce 参数名。 */
6
- const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
7
- /** SDK 初始化时发给父容器的握手方法名。 */
8
- const SDK_HANDSHAKE_METHOD = 'sdk.handshake';
9
- /** Runtime 主动探测 SDK 当前文档地址的内部方法名。 */
10
- const RUNTIME_LOCATION_PROBE_METHOD = 'runtime.location.probe';
11
- /** SDK 向 Runtime 报告当前文档地址的内部方法名。 */
12
- const SDK_LOCATION_REPORT_METHOD = 'sdk.location.report';
13
- /** SDK 向 Runtime 报告 CSP 违规的内部方法名。 */
14
- const SDK_CSP_VIOLATION_METHOD = 'sdk.csp.violation';
15
-
16
- /**
17
- * 判断未知数据是否符合小程序 bridge 消息信封。
18
- *
19
- * @param value 待判断的未知数据。
20
- * @returns 当数据满足小程序 bridge 消息基础结构时返回 `true`。
21
- */
22
- function isMiniProgramBridgeMessage(value) {
23
- if (!value || typeof value !== 'object') {
24
- return false;
25
- }
26
- const message = value;
27
- return (message.namespace === MINI_PROGRAM_MESSAGE_NAMESPACE &&
28
- (message.version === 1 || message.version === 2) &&
29
- typeof message.nonce === 'string' &&
30
- typeof message.type === 'string');
31
- }
32
-
33
- function readBrowserEnvironment() {
34
- try {
35
- return {
36
- activeElement: globalThis.document?.activeElement ?? null,
37
- userActivation: globalThis.navigator?.userActivation,
38
- };
39
- }
40
- catch {
41
- return { activeElement: null };
42
- }
43
- }
44
- /** 按当前浏览器消息、用户激活和目标 iframe 焦点生成请求级可信手势快照。 */
45
- function computeTrustedIframeUserGesture(event, iframe, environment = readBrowserEnvironment()) {
46
- return (event.isTrusted === true
47
- && environment.userActivation?.isActive === true
48
- && environment.activeElement === iframe);
49
- }
50
-
51
- const MANAGED_RUNTIME_PERMISSION_KEYS = new Set(['network.request']);
52
- /**
53
- * 判断 permission key 是否由 Runtime 权限快照管理。
54
- *
55
- * @param key 待判断的 permission key。
56
- * @returns 该 key 需要读取 Runtime 权限快照时返回 `true`。
57
- */
58
- function isManagedMiniProgramRuntimePermissionKey(key) {
59
- return MANAGED_RUNTIME_PERMISSION_KEYS.has(key);
60
- }
61
- /**
62
- * 解析服务端权限快照;格式不完整时整份快照失效并 fail closed。
63
- *
64
- * @param snapshot 待校验的服务端权限快照。
65
- * @returns 解析状态和通过校验的受管权限。
66
- */
67
- function parseMiniProgramRuntimePermissions(snapshot) {
68
- if (!isRecord(snapshot) || snapshot.schema_version !== 1 || !Array.isArray(snapshot.entries)) {
69
- return { valid: false, permissions: {} };
70
- }
71
- if (snapshot.revision !== undefined && (typeof snapshot.revision !== 'number' || !Number.isInteger(snapshot.revision) || snapshot.revision < 0)) {
72
- return { valid: false, permissions: {} };
73
- }
74
- const seenKeys = new Set();
75
- const permissions = {};
76
- for (const rawEntry of snapshot.entries) {
77
- if (!isRecord(rawEntry) || typeof rawEntry.key !== 'string' || !rawEntry.key.trim()) {
78
- return { valid: false, permissions: {} };
79
- }
80
- const key = rawEntry.key.trim();
81
- if (seenKeys.has(key) || (rawEntry.status !== 'enabled' && rawEntry.status !== 'disabled') || !isRecord(rawEntry.config)) {
82
- return { valid: false, permissions: {} };
83
- }
84
- seenKeys.add(key);
85
- if (!isManagedMiniProgramRuntimePermissionKey(key)) {
86
- continue;
87
- }
88
- if (key === 'network.request' && typeof rawEntry.config.useOfficialDomain !== 'boolean') {
89
- return { valid: false, permissions: {} };
90
- }
91
- permissions[key] = {
92
- key,
93
- status: rawEntry.status,
94
- config: { useOfficialDomain: rawEntry.config.useOfficialDomain },
95
- };
96
- }
97
- return { valid: true, permissions };
98
- }
99
- function isRecord(value) {
100
- return typeof value === 'object' && value !== null && !Array.isArray(value);
101
- }
102
-
103
- const OFFICIAL_MINI_PROGRAM_NETWORK_ROOT_DOMAINS = [
104
- 'xiaoheihe.cn',
105
- 'max-c.com',
106
- 'debugmode.cn',
107
- 'maxjia.com',
108
- ];
109
- /** Runtime / Host 在 `network.request` 分发前拒绝的小程序服务端私有路径前缀。 */
110
- const MINI_PROGRAM_NETWORK_PROTECTED_PATHS = [
111
- '/user_miniprogram/runtime/auth',
112
- '/user_miniprogram/openapi/v1',
113
- ];
114
- const NETWORK_REQUEST_PATHNAME_MAX_DECODE_ROUNDS = 4;
115
- /** 使用 URL 解析后的 hostname 判断黑盒官方根域及其子域。 */
116
- function isOfficialMiniProgramNetworkUrl(value) {
117
- try {
118
- const url = new URL(value);
119
- if (url.protocol !== 'http:' && url.protocol !== 'https:') {
120
- return false;
121
- }
122
- const hostname = url.hostname.toLowerCase().replace(/\.$/, '');
123
- return OFFICIAL_MINI_PROGRAM_NETWORK_ROOT_DOMAINS.some(rootDomain => hostname === rootDomain || hostname.endsWith(`.${rootDomain}`));
124
- }
125
- catch {
126
- return false;
127
- }
128
- }
129
- /**
130
- * 规范化并判断 pathname 是否命中 Runtime Auth / OpenAPI 保护前缀。
131
- * 解码失败或仍可继续解码时视为不安全路径。
132
- */
133
- function isProtectedMiniProgramNetworkPath(pathname) {
134
- const normalized = normalizeMiniProgramNetworkPathname(pathname);
135
- if (normalized === null) {
136
- return true;
137
- }
138
- return MINI_PROGRAM_NETWORK_PROTECTED_PATHS.some(prefix => normalized === prefix || normalized.startsWith(`${prefix}/`));
139
- }
140
- function normalizeMiniProgramNetworkPathname(pathname) {
141
- let decoded = pathname;
142
- for (let round = 0; round < NETWORK_REQUEST_PATHNAME_MAX_DECODE_ROUNDS; round += 1) {
143
- let next;
144
- try {
145
- next = decodeURIComponent(decoded);
146
- }
147
- catch {
148
- return null;
149
- }
150
- if (next === decoded) {
151
- return normalizeDecodedNetworkPathname(decoded);
152
- }
153
- decoded = next;
154
- }
155
- try {
156
- if (decodeURIComponent(decoded) !== decoded) {
157
- return null;
158
- }
159
- }
160
- catch {
161
- return null;
162
- }
163
- return normalizeDecodedNetworkPathname(decoded);
164
- }
165
- function normalizeDecodedNetworkPathname(decoded) {
166
- const segments = [];
167
- for (const segment of decoded.replace(/\\/g, '/').split('/')) {
168
- if (!segment || segment === '.') {
169
- continue;
170
- }
171
- if (segment === '..') {
172
- segments.pop();
173
- continue;
174
- }
175
- segments.push(segment);
176
- }
177
- return `/${segments.join('/')}`;
178
- }
179
-
180
- /**
181
- * 登录授权能力方法名。
182
- *
183
- * @remarks
184
- * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
185
- */
186
1
  const AUTH_LOGIN_METHOD = 'auth.login';
187
- /** 读取当前登录态、授权状态和已获准披露资料的 bridge method 标识。 */
188
2
  const USER_GET_INFO_METHOD = 'user.getInfo';
189
- /** 撤销当前用户授予本小程序授权的 bridge method 标识。 */
190
3
  const USER_REVOKE_AUTHORIZATION_METHOD = 'user.revokeAuthorization';
191
- /** 读取当前已登录用户 Steam 游戏库的 bridge method 标识。 */
192
4
  const USER_GET_STEAM_GAME_LIST_METHOD = 'user.getSteamGameList';
193
- /**
194
- * 展示分享面板能力方法名。
195
- *
196
- * @remarks
197
- * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
198
- */
199
5
  const SHARE_SHOW_SHARE_MENU_METHOD = 'share.showShareMenu';
200
- /**
201
- * 截图分享能力方法名。
202
- *
203
- * @remarks
204
- * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
205
- */
206
6
  const SHARE_SCREENSHOT_METHOD = 'share.screenshot';
207
- /**
208
- * 视口窗口信息能力方法名。
209
- *
210
- * @remarks
211
- * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
212
- */
213
7
  const VIEWPORT_GET_WINDOW_INFO_METHOD = 'viewport.getWindowInfo';
214
- /**
215
- * 设置导航栏样式能力方法名。
216
- *
217
- * @remarks
218
- * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
219
- */
220
8
  const VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD = 'viewport.setNavigationBarStyle';
221
- /**
222
- * 读取小程序隔离 storage 能力方法名。
223
- *
224
- * @remarks
225
- * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
226
- */
227
9
  const STORAGE_GET_STORAGE_METHOD = 'storage.getStorage';
228
- /**
229
- * 写入小程序隔离 storage 能力方法名。
230
- *
231
- * @remarks
232
- * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
233
- */
234
10
  const STORAGE_SET_STORAGE_METHOD = 'storage.setStorage';
235
- /**
236
- * 发起网络请求能力方法名。
237
- *
238
- * @remarks
239
- * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
240
- */
241
11
  const NETWORK_REQUEST_METHOD = 'network.request';
242
- /** 展示 toast 能力方法名。 */
243
12
  const UI_SHOW_TOAST_METHOD = 'ui.showToast';
244
- /** 展示全局 loading 能力方法名。 */
245
13
  const UI_SHOW_LOADING_METHOD = 'ui.showLoading';
246
- /** 隐藏全局 loading 能力方法名。 */
247
14
  const UI_HIDE_LOADING_METHOD = 'ui.hideLoading';
248
- /** 震动反馈能力方法名。 */
249
15
  const DEVICE_VIBRATE_METHOD = 'device.vibrate';
250
- /** 写入文本剪贴板能力方法名。 */
251
16
  const DEVICE_SET_CLIPBOARD_METHOD = 'device.setClipboard';
252
- /** 关闭当前小程序容器能力方法名。 */
253
17
  const NAVIGATION_CLOSE_METHOD = 'navigation.close';
254
- /** 重载当前小程序容器能力方法名。 */
255
18
  const NAVIGATION_RELOAD_METHOD = 'navigation.reload';
256
- /** 打开黑盒 App 页面能力方法名。 */
257
19
  const NAVIGATION_OPEN_APP_PAGE_METHOD = 'navigation.openAppPage';
258
- /** 提交当前用户排行榜分数能力方法名。 */
259
20
  const CLOUD_LEADERBOARD_SUBMIT_METHOD = 'cloud.leaderboard.submit';
260
- /** 读取排行榜列表能力方法名。 */
261
21
  const CLOUD_LEADERBOARD_GET_LIST_METHOD = 'cloud.leaderboard.getList';
262
- /** 读取当前用户排行榜记录能力方法名。 */
263
22
  const CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD = 'cloud.leaderboard.getCurrentUserEntry';
264
- /** 删除当前用户排行榜记录能力方法名。 */
265
23
  const CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD = 'cloud.leaderboard.deleteCurrentUserEntry';
266
- /** 读取排行榜基础信息能力方法名。 */
267
24
  const CLOUD_LEADERBOARD_GET_INFO_METHOD = 'cloud.leaderboard.getInfo';
268
- /**
269
- * 小程序开放能力目录。
270
- *
271
- * @remarks
272
- * 新增 bridge method 时应先更新这里,再分别补齐 SDK 模块、runtime handler 与测试。
273
- */
274
25
  const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
275
- {
276
- method: AUTH_LOGIN_METHOD,
277
- module: 'auth',
278
- capability: AUTH_LOGIN_METHOD,
279
- permission: 'auth.login',
280
- risk: 'medium',
281
- },
282
- {
283
- method: USER_GET_INFO_METHOD,
284
- module: 'user',
285
- capability: USER_GET_INFO_METHOD,
286
- permission: 'user.getInfo',
287
- risk: 'medium',
288
- },
26
+ { method: AUTH_LOGIN_METHOD, module: 'auth', capability: AUTH_LOGIN_METHOD, permission: 'auth.login', risk: 'medium' },
27
+ { method: USER_GET_INFO_METHOD, module: 'user', capability: USER_GET_INFO_METHOD, permission: 'user.getInfo', risk: 'medium' },
289
28
  {
290
29
  method: USER_REVOKE_AUTHORIZATION_METHOD,
291
30
  module: 'user',
@@ -300,20 +39,8 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
300
39
  permission: 'user.platformAccount.steam',
301
40
  risk: 'high',
302
41
  },
303
- {
304
- method: SHARE_SHOW_SHARE_MENU_METHOD,
305
- module: 'share',
306
- capability: SHARE_SHOW_SHARE_MENU_METHOD,
307
- permission: 'share.basic',
308
- risk: 'low',
309
- },
310
- {
311
- method: SHARE_SCREENSHOT_METHOD,
312
- module: 'share',
313
- capability: SHARE_SCREENSHOT_METHOD,
314
- permission: 'share.screenshot',
315
- risk: 'medium',
316
- },
42
+ { method: SHARE_SHOW_SHARE_MENU_METHOD, module: 'share', capability: SHARE_SHOW_SHARE_MENU_METHOD, permission: 'share.basic', risk: 'low' },
43
+ { method: SHARE_SCREENSHOT_METHOD, module: 'share', capability: SHARE_SCREENSHOT_METHOD, permission: 'share.screenshot', risk: 'medium' },
317
44
  {
318
45
  method: VIEWPORT_GET_WINDOW_INFO_METHOD,
319
46
  module: 'viewport',
@@ -328,55 +55,13 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
328
55
  permission: 'viewport.navigationBarStyle',
329
56
  risk: 'low',
330
57
  },
331
- {
332
- method: STORAGE_GET_STORAGE_METHOD,
333
- module: 'storage',
334
- capability: STORAGE_GET_STORAGE_METHOD,
335
- permission: 'storage.read',
336
- risk: 'low',
337
- },
338
- {
339
- method: STORAGE_SET_STORAGE_METHOD,
340
- module: 'storage',
341
- capability: STORAGE_SET_STORAGE_METHOD,
342
- permission: 'storage.write',
343
- risk: 'medium',
344
- },
345
- {
346
- method: NETWORK_REQUEST_METHOD,
347
- module: 'network',
348
- capability: NETWORK_REQUEST_METHOD,
349
- permission: 'network.request',
350
- risk: 'high',
351
- },
352
- {
353
- method: UI_SHOW_TOAST_METHOD,
354
- module: 'ui',
355
- capability: UI_SHOW_TOAST_METHOD,
356
- permission: 'ui.toast',
357
- risk: 'low',
358
- },
359
- {
360
- method: UI_SHOW_LOADING_METHOD,
361
- module: 'ui',
362
- capability: UI_SHOW_LOADING_METHOD,
363
- permission: 'ui.loading',
364
- risk: 'low',
365
- },
366
- {
367
- method: UI_HIDE_LOADING_METHOD,
368
- module: 'ui',
369
- capability: UI_HIDE_LOADING_METHOD,
370
- permission: 'ui.loading',
371
- risk: 'low',
372
- },
373
- {
374
- method: DEVICE_VIBRATE_METHOD,
375
- module: 'device',
376
- capability: DEVICE_VIBRATE_METHOD,
377
- permission: 'device.vibrate',
378
- risk: 'low',
379
- },
58
+ { method: STORAGE_GET_STORAGE_METHOD, module: 'storage', capability: STORAGE_GET_STORAGE_METHOD, permission: 'storage.read', risk: 'low' },
59
+ { method: STORAGE_SET_STORAGE_METHOD, module: 'storage', capability: STORAGE_SET_STORAGE_METHOD, permission: 'storage.write', risk: 'medium' },
60
+ { method: NETWORK_REQUEST_METHOD, module: 'network', capability: NETWORK_REQUEST_METHOD, permission: 'network.request', risk: 'high' },
61
+ { method: UI_SHOW_TOAST_METHOD, module: 'ui', capability: UI_SHOW_TOAST_METHOD, permission: 'ui.toast', risk: 'low' },
62
+ { method: UI_SHOW_LOADING_METHOD, module: 'ui', capability: UI_SHOW_LOADING_METHOD, permission: 'ui.loading', risk: 'low' },
63
+ { method: UI_HIDE_LOADING_METHOD, module: 'ui', capability: UI_HIDE_LOADING_METHOD, permission: 'ui.loading', risk: 'low' },
64
+ { method: DEVICE_VIBRATE_METHOD, module: 'device', capability: DEVICE_VIBRATE_METHOD, permission: 'device.vibrate', risk: 'low' },
380
65
  {
381
66
  method: DEVICE_SET_CLIPBOARD_METHOD,
382
67
  module: 'device',
@@ -384,20 +69,8 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
384
69
  permission: 'device.clipboard.write',
385
70
  risk: 'medium',
386
71
  },
387
- {
388
- method: NAVIGATION_CLOSE_METHOD,
389
- module: 'navigation',
390
- capability: NAVIGATION_CLOSE_METHOD,
391
- permission: 'navigation.close',
392
- risk: 'medium',
393
- },
394
- {
395
- method: NAVIGATION_RELOAD_METHOD,
396
- module: 'navigation',
397
- capability: NAVIGATION_RELOAD_METHOD,
398
- permission: 'navigation.reload',
399
- risk: 'medium',
400
- },
72
+ { method: NAVIGATION_CLOSE_METHOD, module: 'navigation', capability: NAVIGATION_CLOSE_METHOD, permission: 'navigation.close', risk: 'medium' },
73
+ { method: NAVIGATION_RELOAD_METHOD, module: 'navigation', capability: NAVIGATION_RELOAD_METHOD, permission: 'navigation.reload', risk: 'medium' },
401
74
  {
402
75
  method: NAVIGATION_OPEN_APP_PAGE_METHOD,
403
76
  module: 'navigation',
@@ -442,7 +115,64 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
442
115
  },
443
116
  ];
444
117
 
445
- /** 当前用户信息能力支持的完整 scope 目录。新增 scope 时必须更新这里。 */
118
+ const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
119
+ const MINI_PROGRAM_MESSAGE_VERSION = 2;
120
+ const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
121
+ const SDK_HANDSHAKE_METHOD = 'sdk.handshake';
122
+ const RUNTIME_LOCATION_PROBE_METHOD = 'runtime.location.probe';
123
+ const SDK_LOCATION_REPORT_METHOD = 'sdk.location.report';
124
+ const SDK_CSP_VIOLATION_METHOD = 'sdk.csp.violation';
125
+
126
+ function isMiniProgramBridgeMessage(value) {
127
+ if (!value || typeof value !== 'object')
128
+ return false;
129
+ const message = value;
130
+ return (message.namespace === MINI_PROGRAM_MESSAGE_NAMESPACE &&
131
+ (message.version === 1 || message.version === 2) &&
132
+ typeof message.nonce === 'string' &&
133
+ typeof message.type === 'string');
134
+ }
135
+
136
+ /** 当前用户信息与登录能力支持的完整 scope 目录。 */
446
137
  const USER_INFO_AUTHORIZATION_SCOPES = ['identity', 'profile'];
447
138
 
448
- export { AUTH_LOGIN_METHOD, CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_INFO_METHOD, CLOUD_LEADERBOARD_GET_LIST_METHOD, CLOUD_LEADERBOARD_SUBMIT_METHOD, DEVICE_SET_CLIPBOARD_METHOD, DEVICE_VIBRATE_METHOD, MINI_PROGRAM_BRIDGE_NONCE_PARAM, MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_MESSAGE_VERSION, MINI_PROGRAM_NETWORK_PROTECTED_PATHS, MINI_PROGRAM_PROTOCOL_CAPABILITIES, NAVIGATION_CLOSE_METHOD, NAVIGATION_OPEN_APP_PAGE_METHOD, NAVIGATION_RELOAD_METHOD, NETWORK_REQUEST_METHOD, RUNTIME_LOCATION_PROBE_METHOD, SDK_CSP_VIOLATION_METHOD, SDK_HANDSHAKE_METHOD, SDK_LOCATION_REPORT_METHOD, SHARE_SCREENSHOT_METHOD, SHARE_SHOW_SHARE_MENU_METHOD, STORAGE_GET_STORAGE_METHOD, STORAGE_SET_STORAGE_METHOD, UI_HIDE_LOADING_METHOD, UI_SHOW_LOADING_METHOD, UI_SHOW_TOAST_METHOD, USER_GET_INFO_METHOD, USER_GET_STEAM_GAME_LIST_METHOD, USER_INFO_AUTHORIZATION_SCOPES, USER_REVOKE_AUTHORIZATION_METHOD, VIEWPORT_GET_WINDOW_INFO_METHOD, VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD, computeTrustedIframeUserGesture, isManagedMiniProgramRuntimePermissionKey, isMiniProgramBridgeMessage, isOfficialMiniProgramNetworkUrl, isProtectedMiniProgramNetworkPath, normalizeMiniProgramNetworkPathname, parseMiniProgramRuntimePermissions };
139
+ const MANAGED_RUNTIME_PERMISSION_KEYS = new Set(['network.request']);
140
+ function isManagedMiniProgramRuntimePermissionKey(key) {
141
+ return MANAGED_RUNTIME_PERMISSION_KEYS.has(key);
142
+ }
143
+ function parseMiniProgramRuntimePermissions(snapshot) {
144
+ if (!isRecord(snapshot) || snapshot.schema_version !== 1 || !Array.isArray(snapshot.entries)) {
145
+ return { valid: false, permissions: {} };
146
+ }
147
+ if (snapshot.revision !== undefined && (typeof snapshot.revision !== 'number' || !Number.isInteger(snapshot.revision) || snapshot.revision < 0)) {
148
+ return { valid: false, permissions: {} };
149
+ }
150
+ const seenKeys = new Set();
151
+ const permissions = {};
152
+ for (const rawEntry of snapshot.entries) {
153
+ if (!isRecord(rawEntry) || typeof rawEntry.key !== 'string' || !rawEntry.key.trim()) {
154
+ return { valid: false, permissions: {} };
155
+ }
156
+ const key = rawEntry.key.trim();
157
+ if (seenKeys.has(key) || (rawEntry.status !== 'enabled' && rawEntry.status !== 'disabled') || !isRecord(rawEntry.config)) {
158
+ return { valid: false, permissions: {} };
159
+ }
160
+ seenKeys.add(key);
161
+ if (!isManagedMiniProgramRuntimePermissionKey(key))
162
+ continue;
163
+ if (key === 'network.request' && typeof rawEntry.config.useOfficialDomain !== 'boolean') {
164
+ return { valid: false, permissions: {} };
165
+ }
166
+ permissions[key] = {
167
+ key,
168
+ status: rawEntry.status,
169
+ config: { useOfficialDomain: rawEntry.config.useOfficialDomain },
170
+ };
171
+ }
172
+ return { valid: true, permissions };
173
+ }
174
+ function isRecord(value) {
175
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
176
+ }
177
+
178
+ export { AUTH_LOGIN_METHOD, CLOUD_LEADERBOARD_DELETE_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_CURRENT_USER_ENTRY_METHOD, CLOUD_LEADERBOARD_GET_INFO_METHOD, CLOUD_LEADERBOARD_GET_LIST_METHOD, CLOUD_LEADERBOARD_SUBMIT_METHOD, DEVICE_SET_CLIPBOARD_METHOD, DEVICE_VIBRATE_METHOD, MINI_PROGRAM_BRIDGE_NONCE_PARAM, MINI_PROGRAM_MESSAGE_NAMESPACE, MINI_PROGRAM_MESSAGE_VERSION, MINI_PROGRAM_PROTOCOL_CAPABILITIES, NAVIGATION_CLOSE_METHOD, NAVIGATION_OPEN_APP_PAGE_METHOD, NAVIGATION_RELOAD_METHOD, NETWORK_REQUEST_METHOD, RUNTIME_LOCATION_PROBE_METHOD, SDK_CSP_VIOLATION_METHOD, SDK_HANDSHAKE_METHOD, SDK_LOCATION_REPORT_METHOD, SHARE_SCREENSHOT_METHOD, SHARE_SHOW_SHARE_MENU_METHOD, STORAGE_GET_STORAGE_METHOD, STORAGE_SET_STORAGE_METHOD, UI_HIDE_LOADING_METHOD, UI_SHOW_LOADING_METHOD, UI_SHOW_TOAST_METHOD, USER_GET_INFO_METHOD, USER_GET_STEAM_GAME_LIST_METHOD, USER_INFO_AUTHORIZATION_SCOPES, USER_REVOKE_AUTHORIZATION_METHOD, VIEWPORT_GET_WINDOW_INFO_METHOD, VIEWPORT_SET_NAVIGATION_BAR_STYLE_METHOD, isManagedMiniProgramRuntimePermissionKey, isMiniProgramBridgeMessage, parseMiniProgramRuntimePermissions };
package/dist/vite.cjs.js CHANGED
@@ -8,7 +8,7 @@ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentS
8
8
  /** 构建时替换为当前发布包的实际版本。 */
9
9
  const HB_SDK_VERSION = typeof undefined === 'string'
10
10
  ? undefined
11
- : '0.7.3-alpha.2';
11
+ : '0.7.4-alpha.1';
12
12
 
13
13
  var re = {exports: {}};
14
14
 
@@ -11301,11 +11301,8 @@ function parse(html, options) {
11301
11301
  return Parser.parse(html, options);
11302
11302
  }
11303
11303
 
11304
- /** 小程序沙盒通信命名空间,父容器与 iframe 内 SDK 必须保持一致。 */
11305
11304
  const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
11306
- /** 小程序沙盒通信协议版本。 */
11307
11305
  const MINI_PROGRAM_MESSAGE_VERSION = 2;
11308
- /** 父容器注入到小程序 URL 上的通信 nonce 参数名。 */
11309
11306
  const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
11310
11307
 
11311
11308
  const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
package/dist/vite.esm.js CHANGED
@@ -5,7 +5,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
5
5
  /** 构建时替换为当前发布包的实际版本。 */
6
6
  const HB_SDK_VERSION = typeof undefined === 'string'
7
7
  ? undefined
8
- : '0.7.3-alpha.2';
8
+ : '0.7.4-alpha.1';
9
9
 
10
10
  var re = {exports: {}};
11
11
 
@@ -11298,11 +11298,8 @@ function parse(html, options) {
11298
11298
  return Parser.parse(html, options);
11299
11299
  }
11300
11300
 
11301
- /** 小程序沙盒通信命名空间,父容器与 iframe 内 SDK 必须保持一致。 */
11302
11301
  const MINI_PROGRAM_MESSAGE_NAMESPACE = 'heybox:miniprogram';
11303
- /** 小程序沙盒通信协议版本。 */
11304
11302
  const MINI_PROGRAM_MESSAGE_VERSION = 2;
11305
- /** 父容器注入到小程序 URL 上的通信 nonce 参数名。 */
11306
11303
  const MINI_PROGRAM_BRIDGE_NONCE_PARAM = 'hb_mini_bridge_nonce';
11307
11304
 
11308
11305
  const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@heybox/hb-sdk",
3
- "version": "0.7.3-alpha.2",
3
+ "version": "0.7.4-alpha.1",
4
4
  "sideEffects": [
5
5
  "./src/index.ts",
6
6
  "./src/core/singleton.ts",
@@ -54,7 +54,8 @@
54
54
  "license": "ISC",
55
55
  "dependencies": {
56
56
  "parse5": "^7.3.0",
57
- "undici": "^7.28.0"
57
+ "undici": "^7.28.0",
58
+ "@heybox/hb-sdk-protocol": "0.7.4-alpha.1"
58
59
  },
59
60
  "peerDependencies": {
60
61
  "vite": ">=5"
@@ -95,7 +96,8 @@
95
96
  "vue": "^2.7.16",
96
97
  "vite": "^8.0.12",
97
98
  "vitest": "^3.2.4",
98
- "@heybox/hb-api": "~1.25.18"
99
+ "@heybox/hb-sdk-runtime": "~0.7.4-alpha.1",
100
+ "@heybox/hb-api": "~1.25.20"
99
101
  },
100
102
  "publishConfig": {
101
103
  "registry": "https://registry.npmjs.org/",
@@ -105,11 +107,18 @@
105
107
  "targets": {
106
108
  "build:package": {
107
109
  "inputs": [
108
- "{projectRoot}/src/**/*"
110
+ "{projectRoot}/src/**/*",
111
+ "{projectRoot}/devtools/browser-dev-host/**/*",
112
+ "{projectRoot}/scripts/copy-browser-dev-host.cjs",
113
+ "{projectRoot}/rollup.config.ts",
114
+ "{projectRoot}/tsconfig*.json",
115
+ "{workspaceRoot}/packages/hb-sdk-runtime/src/**/*",
116
+ "{workspaceRoot}/packages/hb-sdk-runtime/package.json",
117
+ "{workspaceRoot}/packages/hb-sdk-runtime/rollup.config.ts"
109
118
  ],
110
119
  "outputs": [
111
- "{workspaceRoot}/vue.config.js",
112
- "{workspaceRoot}/vue2-plugin.js"
120
+ "{projectRoot}/dist",
121
+ "{projectRoot}/types"
113
122
  ],
114
123
  "cache": true
115
124
  }
@@ -126,20 +135,28 @@
126
135
  "build:lib": "pnpm run build:hb-api-contract && pnpm run build:lib:bundle",
127
136
  "build:lib:bundle": "rollup -c rollup.config.ts --configPlugin 'typescript={\"tsconfig\":\"tsconfig.build.json\"}'",
128
137
  "build:cli": "pnpm run build:hb-api-contract && pnpm run build:cli:bundle",
129
- "build:cli:bundle": "rollup -c rollup.config.ts --environment HB_SDK_BUILD:cli --configPlugin 'typescript={\"tsconfig\":\"tsconfig.build.json\"}' && pnpm run build:mock-host",
130
- "build:mock-host": "node scripts/copy-mock-host.cjs",
138
+ "build:cli:bundle": "rollup -c rollup.config.ts --environment HB_SDK_BUILD:cli --configPlugin 'typescript={\"tsconfig\":\"tsconfig.build.json\"}' && pnpm run build:browser-dev-host",
139
+ "build:browser-dev-host": "node scripts/copy-browser-dev-host.cjs",
131
140
  "build:templates": "node scripts/copy-cli-templates.cjs",
132
141
  "build:types": "tsc -p tsconfig.dts.json",
133
142
  "check:boundary": "node scripts/check-boundary.cjs",
134
143
  "check:docs-sync": "pnpm -w exec hbexec hb-sdk check",
135
144
  "clean": "rimraf ./dist && rimraf ./types",
136
145
  "test:unit": "NODE_OPTIONS='--conditions=heybox' vitest run",
146
+ "test:types:characterization": "tsc -p tsconfig.characterization.json --noEmit --pretty false",
147
+ "test:types:browser-dev-host": "tsc -p tsconfig.browser-dev-host.json --noEmit --pretty false",
148
+ "test:types": "pnpm run test:types:characterization && pnpm run test:types:browser-dev-host",
149
+ "test:e2e:browser-dev-host": "pnpm run build:browser-dev-host && NODE_OPTIONS='--conditions=heybox' vitest run --config vitest.browser-dev-host-e2e.config.ts",
137
150
  "test:unit:coverage": "NODE_OPTIONS='--conditions=heybox' vitest run --coverage",
138
151
  "test:vite": "pnpm run build:hb-api-contract && vitest run --config vitest.vite.config.ts",
139
152
  "test:watch": "NODE_OPTIONS='--conditions=heybox' vitest",
140
153
  "changelog:draft": "node scripts/changelog-draft.cjs",
141
154
  "check:changelog": "node scripts/check-changelog.cjs",
155
+ "test:release": "node --test scripts/release-family.test.cjs ../../ops/jobs/publish-changed-packages/publish.test.cjs",
142
156
  "release:prepare": "node scripts/release-prepare.cjs",
143
- "release:tag": "node scripts/release-tag.cjs"
157
+ "release:tag": "node scripts/release-tag.cjs",
158
+ "release:family:dry-run": "node ../../ops/jobs/publish-changed-packages/publish.cjs --dry-run",
159
+ "release:family:promote": "node ../../ops/jobs/publish-changed-packages/publish.cjs --family-action promote",
160
+ "release:family:rollback": "node ../../ops/jobs/publish-changed-packages/publish.cjs --family-action rollback"
144
161
  }
145
162
  }
package/skill/SKILL.md CHANGED
@@ -10,7 +10,7 @@ Apply these instructions when writing, reviewing, or debugging code that consume
10
10
  ## Step 1: Classify the task
11
11
 
12
12
  1. If the task is workshop mini-program business code, use the root package import path `@heybox/hb-sdk`.
13
- 2. If the task is parent-container runtime, bridge-server, protocol contract, or `@heybox/hb-sdk-runtime` work, use `@heybox/hb-sdk/protocol` only for shared constants and types.
13
+ 2. If the task is new protocol or `@heybox/hb-sdk-runtime` graph maintenance, import wire contracts directly from `@heybox/hb-sdk-protocol`. Existing released Host consumers continue to use the compatibility entry `@heybox/hb-sdk/protocol` until the synchronized hard cut is published.
14
14
  3. If the task is project scaffolding, local startup, production build, browser Mock, device debugging, CLI login, Agent Skill diagnosis, or CLI troubleshooting, use the `hb-sdk` CLI workflow.
15
15
  4. If the task is reviewing a mini-program for submission, listing, audit, publishing, content compliance, data/privacy compliance, runtime quality, or icon/cover design requirements, use the online publishing rules workflow.
16
16
  5. If the task asks for direct login-state extraction, cookies, tokens, raw Heybox client protocols, or internal hb-sdk package paths, refuse that approach and use the public SDK or CLI boundary instead.
@@ -32,7 +32,7 @@ Apply these instructions when writing, reviewing, or debugging code that consume
32
32
  ## Step 3: Follow import rules
33
33
 
34
34
  1. Import app-facing SDK APIs from `@heybox/hb-sdk`.
35
- 2. Import protocol contracts from `@heybox/hb-sdk/protocol` only in host/runtime/protocol-maintenance code.
35
+ 2. Import protocol contracts from `@heybox/hb-sdk-protocol` in the new Runtime/protocol graph. Use `@heybox/hb-sdk/protocol` only when maintaining an existing released Host consumer that still targets the compatibility entry.
36
36
  3. Never import from internal hb-sdk implementation paths; only use the documented package entrypoints.
37
37
  4. Prefer named imports for focused code and the default `hbSDK` singleton for compact page-level examples.
38
38
 
@@ -55,7 +55,7 @@ Apply these instructions when writing, reviewing, or debugging code that consume
55
55
 
56
56
  1. Use `hb-sdk create <project-name>` to scaffold a workshop mini-program.
57
57
  2. Use `hb-sdk dev` for browser, Mac App, or mobile App debugging. These entries remain available without CLI login or project binding, but managed capabilities are denied by default.
58
- 3. Use `--port`, `--mock-port`, and `--no-open` when the default local ports or browser opening behavior need to be controlled.
58
+ 3. Use `--port`, `--browser-dev-host-port`, and `--no-open` when the default local ports or browser opening behavior need to be controlled.
59
59
  4. Use `hb-sdk build [--env <name>] [--verbose]` as the recommended production build entry. It directly owns the Vite build, always cleans and writes `dist/`, and works without CLI login, project binding, or network access.
60
60
  5. Keep `miniappManifest()` explicitly enabled in `vite.config.ts`; `hb-sdk build` must fail when the required Manifest or Runtime gate output is missing.
61
61
  6. Keep project typechecking in `scripts.build`, for example `vue-tsc --noEmit && hb-sdk build`; `hb-sdk build` does not run typechecking or invoke `scripts.build` itself.
@@ -97,7 +97,7 @@ For CLI and local development:
97
97
 
98
98
  For host/runtime/protocol-maintenance code:
99
99
 
100
- 1. Use `@heybox/hb-sdk/protocol` for shared constants and type contracts.
100
+ 1. Treat `@heybox/hb-sdk-protocol` as the wire contract owner; existing consumers continue to use the public compatibility entry `@heybox/hb-sdk/protocol` until the synchronized hard cut is released.
101
101
  2. Keep raw protocol details inside the host/runtime boundary; do not leak them into app-facing SDK examples or workshop mini-program business code.
102
102
  3. Preserve compatibility with existing SDK clients.
103
103
 
@@ -107,7 +107,7 @@ For host/runtime/protocol-maintenance code:
107
107
  2. When modifying docs, skill instructions, CLI guidance, or public agent-skill sync points, start with:
108
108
  - `pnpm --filter @heybox/hb-sdk run check:docs-sync`
109
109
  - `cat packages/hb-sdk/DOC_SYNC_CHECKLIST.md`
110
- 3. When preparing a package release, run `pnpm --filter @heybox/hb-sdk run release:prepare -- --bump patch` or `pnpm --filter @heybox/hb-sdk run release:prepare -- --version <x.y.z>`. The release assistant updates both package versions, inserts `packages/hb-sdk/CHANGELOG.md`, and runs `check:changelog`. Use `--ai-command "<command>"` or `HB_SDK_CHANGELOG_AI_COMMAND` when an AI writer should rewrite the Conventional Commit draft. Review the entry for Mini-program developers and Host/Runtime integration maintainers, and do not expose Runtime internal adapter, state-machine, or security-policy details.
110
+ 3. When preparing a package release, run `pnpm --filter @heybox/hb-sdk run release:prepare -- --bump patch` or `pnpm --filter @heybox/hb-sdk run release:prepare -- --version <x.y.z>`. The release assistant updates the Protocol/Runtime/SDK family versions, inserts `packages/hb-sdk/CHANGELOG.md`, and runs `check:changelog`. Use `--ai-command "<command>"` or `HB_SDK_CHANGELOG_AI_COMMAND` when an AI writer should rewrite the Conventional Commit draft. Review the entry for Mini-program developers and Host/Runtime integration maintainers, and do not expose Runtime internal adapter, state-machine, or security-policy details.
111
111
  4. When modifying this repo's source skill at `packages/hb-sdk/skill` and preparing distributable artifacts, also run:
112
112
  - `node packages/hb-sdk/skill/scripts/package-skill.mjs`
113
113
  5. When modifying CLI, local debugging, package exports, or package dependency direction, also run: