dsh-zen-remote 2.3.5 → 2.3.7

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 (100) hide show
  1. package/AGENTS.md +15 -5
  2. package/CHANGELOG.md +71 -0
  3. package/README.md +2 -2
  4. package/README.zh-CN.md +2 -2
  5. package/docs/interface.md +12 -6
  6. package/docs/plugin-bridge.md +2 -2
  7. package/docs/remote-access.en.md +9 -3
  8. package/docs/remote-access.md +9 -3
  9. package/lan-gate.mjs +7 -0
  10. package/lib/adapters/dsh-better-sidebar/index.js +31 -2
  11. package/lib/adapters/dsh-better-sidebar/index.js.map +1 -1
  12. package/lib/client-pairing.js +10 -0
  13. package/lib/client-pairing.js.map +1 -1
  14. package/lib/client-routes.js +183 -94
  15. package/lib/client-routes.js.map +1 -1
  16. package/lib/client.js +589 -97
  17. package/lib/debug-redact.js +253 -0
  18. package/lib/debug-redact.js.map +1 -0
  19. package/lib/debug-report.js +60 -0
  20. package/lib/debug-report.js.map +1 -0
  21. package/lib/fetch-route-intercept.js +23 -0
  22. package/lib/fetch-route-intercept.js.map +1 -1
  23. package/lib/index.js +306 -45
  24. package/lib/index.js.map +1 -1
  25. package/lib/intercept.js +43 -1
  26. package/lib/intercept.js.map +1 -1
  27. package/lib/log-ring.js +76 -0
  28. package/lib/log-ring.js.map +1 -0
  29. package/lib/plugin-adapter-core.js +30 -1
  30. package/lib/plugin-adapter-core.js.map +1 -1
  31. package/lib/plugin-route-intercept.js +506 -11
  32. package/lib/plugin-route-intercept.js.map +1 -1
  33. package/lib/plugin-tunnel.js +210 -18
  34. package/lib/plugin-tunnel.js.map +1 -1
  35. package/lib/types/adapters/dsh-better-sidebar/index.d.ts +5 -2
  36. package/lib/types/adapters/dsh-better-sidebar/index.d.ts.map +1 -1
  37. package/lib/types/client/MobileSessionInfo.d.ts.map +1 -1
  38. package/lib/types/client/effects/remote-drop.d.ts +20 -8
  39. package/lib/types/client/effects/remote-drop.d.ts.map +1 -1
  40. package/lib/types/client/locales.d.ts +10 -1
  41. package/lib/types/client/locales.d.ts.map +1 -1
  42. package/lib/types/client/settings/SettingsSection.d.ts.map +1 -1
  43. package/lib/types/client/styles/content.css.d.ts +1 -1
  44. package/lib/types/client/styles/content.css.d.ts.map +1 -1
  45. package/lib/types/client/styles/layout.css.d.ts +1 -1
  46. package/lib/types/client/styles/layout.css.d.ts.map +1 -1
  47. package/lib/types/client/styles/misc.css.d.ts +1 -1
  48. package/lib/types/client/styles/misc.css.d.ts.map +1 -1
  49. package/lib/types/client-data/remote-drop.d.ts +64 -0
  50. package/lib/types/client-data/remote-drop.d.ts.map +1 -1
  51. package/lib/types/client-data/settings-form.d.ts +3 -0
  52. package/lib/types/client-data/settings-form.d.ts.map +1 -1
  53. package/lib/types/client-pairing.d.ts +8 -0
  54. package/lib/types/client-pairing.d.ts.map +1 -1
  55. package/lib/types/client-routes.d.ts +23 -0
  56. package/lib/types/client-routes.d.ts.map +1 -1
  57. package/lib/types/debug-redact.d.ts +68 -0
  58. package/lib/types/debug-redact.d.ts.map +1 -0
  59. package/lib/types/debug-report.d.ts +58 -0
  60. package/lib/types/debug-report.d.ts.map +1 -0
  61. package/lib/types/fetch-route-intercept.d.ts +26 -0
  62. package/lib/types/fetch-route-intercept.d.ts.map +1 -1
  63. package/lib/types/index.d.ts +7 -1
  64. package/lib/types/index.d.ts.map +1 -1
  65. package/lib/types/intercept.d.ts +6 -0
  66. package/lib/types/intercept.d.ts.map +1 -1
  67. package/lib/types/log-ring.d.ts +57 -0
  68. package/lib/types/log-ring.d.ts.map +1 -0
  69. package/lib/types/plugin-adapter-core.d.ts.map +1 -1
  70. package/lib/types/plugin-route-intercept.d.ts +8 -0
  71. package/lib/types/plugin-route-intercept.d.ts.map +1 -1
  72. package/lib/types/plugin-tunnel.d.ts +37 -2
  73. package/lib/types/plugin-tunnel.d.ts.map +1 -1
  74. package/package.json +3 -2
  75. package/pwa/app.css +13 -2
  76. package/scripts/check-debug-report.mjs +277 -0
  77. package/scripts/check-info-sheet-stacking.mjs +85 -0
  78. package/scripts/check-remote-drop.mjs +130 -0
  79. package/scripts/check-tablet-safe-area.mjs +49 -0
  80. package/src/adapters/dsh-better-sidebar/index.ts +31 -2
  81. package/src/client/MobileSessionInfo.tsx +29 -2
  82. package/src/client/effects/remote-drop.ts +271 -24
  83. package/src/client/locales.ts +24 -4
  84. package/src/client/settings/SettingsSection.tsx +120 -3
  85. package/src/client/styles/content.css.ts +44 -14
  86. package/src/client/styles/layout.css.ts +9 -3
  87. package/src/client/styles/misc.css.ts +38 -0
  88. package/src/client-data/remote-drop.ts +103 -0
  89. package/src/client-data/settings-form.ts +3 -0
  90. package/src/client-pairing.ts +11 -0
  91. package/src/client-routes.ts +196 -90
  92. package/src/debug-redact.ts +290 -0
  93. package/src/debug-report.ts +93 -0
  94. package/src/fetch-route-intercept.ts +29 -0
  95. package/src/index.ts +295 -43
  96. package/src/intercept.ts +46 -0
  97. package/src/log-ring.ts +101 -0
  98. package/src/plugin-adapter-core.ts +29 -2
  99. package/src/plugin-route-intercept.ts +516 -12
  100. package/src/plugin-tunnel.ts +230 -20
@@ -0,0 +1,93 @@
1
+ /**
2
+ * CU-2: the debug report's assembler (SPEC 方案 C). Pure module — no DSH
3
+ * imports, no I/O: everything dynamic (the log ring's snapshot, the resolved
4
+ * config, the status route's body, the gateway's summary, the profile name)
5
+ * arrives as plain input, so the check script and the tests can drive it
6
+ * with poisoned fixtures and assert nothing recoverable comes out.
7
+ *
8
+ * Two redaction layers meet here, per SPEC:
9
+ * 1. construction — the report's own fields are picked by NAME; nothing is
10
+ * ever spread into it. (The wiring in client-routes.ts picks the config
11
+ * summary fields; a secret that sneaks into `configSummary` anyway is
12
+ * still caught by layer 2.)
13
+ * 2. output — every string, at any depth, runs through `redactText`
14
+ * (debug-redact.ts). The two exceptions are `config.serverUrl` and
15
+ * `config.host`, which are not strings but SHAPES (`https://domain`,
16
+ * `http://lan-ip:3080`, `loopback`, `wildcard`) — assigning them after
17
+ * the deep pass keeps the shapers' own labels from being re-classified.
18
+ */
19
+
20
+ import { bindHostShape, redactText, redactValue, serverUrlShape } from './debug-redact.js'
21
+ import type { LogRingEntry } from './log-ring.js'
22
+
23
+ /** The `_meta` plate's scalars, all construction-time facts. */
24
+ export interface DebugReportMetaInput {
25
+ /** When the report was assembled (ISO string; the caller stamps it). */
26
+ generatedAt: string
27
+ /** This package's own version (module-load read in src/index.ts). */
28
+ pluginVersion: string
29
+ /** The host DSH's version (`resolveDshVersion`). */
30
+ dshVersion: string
31
+ /** e.g. `darwin arm64` — `process.platform` + `process.arch`. */
32
+ platform: string
33
+ /** The row's effective role: `'host'` or `'client'`. */
34
+ role: string
35
+ /** The profile context's display name, when the composition has one. */
36
+ profileName?: string
37
+ }
38
+
39
+ /** One debug report's input. `configSummary` is the PICKED config subset
40
+ * (field → value); `serverUrl` inside it is special-cased into a shape. */
41
+ export interface DebugReportInput {
42
+ meta: DebugReportMetaInput
43
+ configSummary: Record<string, unknown>
44
+ /** The `/client/status` diagnostics body, as the status route would have
45
+ * answered (the assembler only redacts it). */
46
+ statusBody: Record<string, unknown>
47
+ /** The gateway child's summary (host role only): liveness, port, device
48
+ * and share counts — counts, never tokens. */
49
+ gatewaySummary?: Record<string, unknown>
50
+ /** The log ring's snapshot, oldest first. */
51
+ logs: readonly LogRingEntry[]
52
+ /** The user home directory, the redactor's fold point for `~`. */
53
+ home: string
54
+ }
55
+
56
+ /**
57
+ * Assemble the report's five plates: `_meta`, `config`, `status`,
58
+ * `gateway` (only when a summary was supplied), `logs`. Every string is
59
+ * redacted; nothing in the output can carry a path (beyond a leaf), a
60
+ * hostname (beyond its address class), or a secret-shaped run.
61
+ */
62
+ export function assembleDebugReport(input: DebugReportInput): Record<string, unknown> {
63
+ const context = { home: input.home }
64
+ const config: Record<string, unknown> = {}
65
+ for (const [key, value] of Object.entries(input.configSummary)) {
66
+ if (key === 'serverUrl' || key === 'host') continue
67
+ config[key] = redactValue(value, context)
68
+ }
69
+ // Both addresses are SHAPES, assigned after the deep pass so the shapers'
70
+ // own labels are never re-classified: the bind host keeps only its class
71
+ // (a bare IP must not reach the report), serverUrl its scheme+class+port.
72
+ if ('host' in input.configSummary) config.host = bindHostShape(input.configSummary.host)
73
+ config.serverUrl = serverUrlShape(input.configSummary.serverUrl)
74
+ const report: Record<string, unknown> = {
75
+ _meta: {
76
+ generatedAt: redactText(input.meta.generatedAt, context),
77
+ pluginVersion: redactText(input.meta.pluginVersion, context),
78
+ dshVersion: redactText(input.meta.dshVersion, context),
79
+ platform: redactText(input.meta.platform, context),
80
+ role: redactText(input.meta.role, context),
81
+ ...(input.meta.profileName === undefined ? {} : { profile: redactText(input.meta.profileName, context) }),
82
+ },
83
+ config,
84
+ status: redactValue(input.statusBody, context),
85
+ ...(input.gatewaySummary === undefined ? {} : { gateway: redactValue(input.gatewaySummary, context) }),
86
+ logs: input.logs.map((entry) => ({
87
+ t: entry.t,
88
+ level: entry.level,
89
+ msg: redactText(entry.msg, context),
90
+ })),
91
+ }
92
+ return report
93
+ }
@@ -91,6 +91,35 @@ function isRecord(value: unknown): value is Record<string, unknown> {
91
91
  return typeof value === 'object' && value !== null
92
92
  }
93
93
 
94
+ /**
95
+ * Whether the FALLBACK install may fire on this tick (SPEC §2, the RD-6
96
+ * machine-local failure: `ctx.inject(['connection','fileUploads'])` silently
97
+ * stays PENDING on some compositions — the callback never runs, the wrap
98
+ * never installs, and every remote upload dies on the local backend with no
99
+ * diagnostic beyond "inject not seen"). All four facts must line up:
100
+ * - `injectSeen === false` — the inject callback has NOT fired (if it had,
101
+ * the primary path either installed or recorded a refusal itself);
102
+ * - `handleSet === false` — no install happened yet, via EITHER path (the
103
+ * double-install guard, checked again at the moment of installation);
104
+ * - `refused === false` — no install was refused yet (a refusal is a
105
+ * verdict, not a pending state; retrying it would only re-learn it);
106
+ * - `servicesPresent` — the reflection layer answers BOTH `connection` and
107
+ * `fileUploads`, i.e. the services exist and only the inject callback is
108
+ * stuck. Without them there is nothing to wrap and the inject may still
109
+ * be legitimately waiting (normal startup ordering) — the fallback keeps
110
+ * out of the way and inject stays the first choice.
111
+ * Pure judgment over injectable state, so the whole truth table is
112
+ * assertable in Node.
113
+ */
114
+ export function shouldFallbackInstall(state: {
115
+ injectSeen: boolean
116
+ handleSet: boolean
117
+ refused: boolean
118
+ servicesPresent: boolean
119
+ }): boolean {
120
+ return !state.injectSeen && !state.handleSet && !state.refused && state.servicesPresent
121
+ }
122
+
94
123
  /**
95
124
  * Check the RAW connection service instance against the shape the wrap
96
125
  * depends on. Pure inspection — nothing is mutated, so a failed check