@goodandready/dsh-approval-gate 0.1.27 → 0.1.28
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.
- package/CHANGELOG.md +4 -0
- package/lib/compat.js +55 -22
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.28
|
|
4
|
+
|
|
5
|
+
- Fix: Безопасное чтение версии хоста в lib/compat.js через ctx.get(version) и защищенный доступ без падений на строгих Proxy-контекстах Cordis при отсутствии инжекции version (Refs: #184).
|
|
6
|
+
|
|
3
7
|
## 0.1.27
|
|
4
8
|
|
|
5
9
|
- Feature: Интерактивный визуальный редактор правил и белых списков путей (ApprovalGateSettingsCard в lib/client.js, TimelineService endpoints /rules в lib/timeline-service.js, слот settings.plugin.item) (Refs: #49).
|
package/lib/compat.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// lib/compat.js
|
|
2
|
-
// Host compatibility checks and polyfills across DeepSeek Harness minor versions (#106).
|
|
2
|
+
// Host compatibility checks and polyfills across DeepSeek Harness minor versions (#106, #184).
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Detects available runtime capabilities and services in the Cordis host context (#106).
|
|
5
|
+
* Detects available runtime capabilities and services in the Cordis host context (#106, #184).
|
|
6
|
+
* Safely accesses properties via ctx.get() and guarded property lookup to avoid
|
|
7
|
+
* throwing in strict Cordis contexts where uninjected property access is forbidden.
|
|
6
8
|
*
|
|
7
9
|
* @param {any} ctx - Cordis / DSH host context
|
|
8
10
|
* @returns {{
|
|
@@ -11,7 +13,7 @@
|
|
|
11
13
|
* hasPreExecuteHook: boolean,
|
|
12
14
|
* hasProvideApi: boolean,
|
|
13
15
|
* hasLocaleService: boolean,
|
|
14
|
-
* harnessVersion: string
|
|
16
|
+
* harnessVersion: string
|
|
15
17
|
* }}
|
|
16
18
|
*/
|
|
17
19
|
export function detectHarnessCapabilities(ctx) {
|
|
@@ -22,39 +24,48 @@ export function detectHarnessCapabilities(ctx) {
|
|
|
22
24
|
hasPreExecuteHook: false,
|
|
23
25
|
hasProvideApi: false,
|
|
24
26
|
hasLocaleService: false,
|
|
25
|
-
harnessVersion:
|
|
27
|
+
harnessVersion: "unknown",
|
|
26
28
|
};
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
const
|
|
31
|
+
const safeGet = (name) => {
|
|
30
32
|
try {
|
|
31
33
|
if (typeof ctx.get === "function") return ctx.get(name);
|
|
32
34
|
} catch {
|
|
33
35
|
// ignore
|
|
34
36
|
}
|
|
35
|
-
|
|
37
|
+
try {
|
|
38
|
+
return ctx[name];
|
|
39
|
+
} catch {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
36
42
|
};
|
|
37
43
|
|
|
38
|
-
const tools =
|
|
39
|
-
const locale =
|
|
44
|
+
const tools = safeGet("tools");
|
|
45
|
+
const locale = safeGet("locale");
|
|
46
|
+
const onFn = safeGet("on");
|
|
47
|
+
const provideFn = safeGet("provide");
|
|
48
|
+
|
|
49
|
+
const rawVersion = safeGet("version");
|
|
40
50
|
|
|
41
51
|
const harnessVersion =
|
|
42
|
-
(typeof
|
|
43
|
-
(typeof
|
|
44
|
-
|
|
52
|
+
(typeof rawVersion === "string" && rawVersion.trim()) ||
|
|
53
|
+
(rawVersion && typeof rawVersion === "object" && typeof rawVersion.version === "string" && rawVersion.version.trim()) ||
|
|
54
|
+
(typeof process.env.DSH_VERSION === "string" && process.env.DSH_VERSION.trim()) ||
|
|
55
|
+
"unknown";
|
|
45
56
|
|
|
46
57
|
return {
|
|
47
58
|
hasContext: true,
|
|
48
59
|
hasToolsService: Boolean(tools),
|
|
49
|
-
hasPreExecuteHook: typeof
|
|
50
|
-
hasProvideApi: typeof
|
|
60
|
+
hasPreExecuteHook: typeof onFn === "function",
|
|
61
|
+
hasProvideApi: typeof provideFn === "function",
|
|
51
62
|
hasLocaleService: Boolean(locale && typeof locale.register === "function"),
|
|
52
63
|
harnessVersion,
|
|
53
64
|
};
|
|
54
65
|
}
|
|
55
66
|
|
|
56
67
|
/**
|
|
57
|
-
* Asserts host compatibility and identifies missing optional or required features (#106).
|
|
68
|
+
* Asserts host compatibility and identifies missing optional or required features (#106, #184).
|
|
58
69
|
*
|
|
59
70
|
* @param {any} ctx
|
|
60
71
|
* @param {{ requireTools?: boolean }} [options]
|
|
@@ -80,7 +91,7 @@ export function assertHarnessCompatibility(ctx, options = {}) {
|
|
|
80
91
|
}
|
|
81
92
|
|
|
82
93
|
/**
|
|
83
|
-
* Safely provides a service to the host context with backward-compatible polyfill (#106).
|
|
94
|
+
* Safely provides a service to the host context with backward-compatible polyfill (#106, #184).
|
|
84
95
|
*
|
|
85
96
|
* @param {any} ctx
|
|
86
97
|
* @param {string} serviceName
|
|
@@ -90,21 +101,32 @@ export function assertHarnessCompatibility(ctx, options = {}) {
|
|
|
90
101
|
export function provideServicePolyfill(ctx, serviceName, serviceInstance) {
|
|
91
102
|
if (!ctx || typeof ctx !== "object" || !serviceName) return false;
|
|
92
103
|
|
|
93
|
-
|
|
104
|
+
let provideFn = undefined;
|
|
105
|
+
try {
|
|
106
|
+
provideFn = ctx.provide;
|
|
107
|
+
} catch {
|
|
108
|
+
// ignore
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (typeof provideFn === "function") {
|
|
94
112
|
try {
|
|
95
|
-
|
|
113
|
+
provideFn.call(ctx, serviceName, serviceInstance);
|
|
96
114
|
return true;
|
|
97
115
|
} catch {
|
|
98
116
|
// fallback to property assignment below
|
|
99
117
|
}
|
|
100
118
|
}
|
|
101
119
|
|
|
102
|
-
|
|
103
|
-
|
|
120
|
+
try {
|
|
121
|
+
ctx[serviceName] = serviceInstance;
|
|
122
|
+
return true;
|
|
123
|
+
} catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
104
126
|
}
|
|
105
127
|
|
|
106
128
|
/**
|
|
107
|
-
* Safely attaches an event hook to the host context with error boundary (#106).
|
|
129
|
+
* Safely attaches an event hook to the host context with error boundary (#106, #184).
|
|
108
130
|
*
|
|
109
131
|
* @param {any} ctx
|
|
110
132
|
* @param {string} event
|
|
@@ -112,12 +134,23 @@ export function provideServicePolyfill(ctx, serviceName, serviceInstance) {
|
|
|
112
134
|
* @returns {(() => void) | null} Unsubscribe dispose function or null
|
|
113
135
|
*/
|
|
114
136
|
export function registerHookPolyfill(ctx, event, handler) {
|
|
115
|
-
if (!ctx || typeof ctx
|
|
137
|
+
if (!ctx || typeof ctx !== "object" || typeof handler !== "function") {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
let onFn = undefined;
|
|
142
|
+
try {
|
|
143
|
+
onFn = ctx.on;
|
|
144
|
+
} catch {
|
|
145
|
+
// ignore
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (typeof onFn !== "function") {
|
|
116
149
|
return null;
|
|
117
150
|
}
|
|
118
151
|
|
|
119
152
|
try {
|
|
120
|
-
return
|
|
153
|
+
return onFn.call(ctx, event, handler);
|
|
121
154
|
} catch {
|
|
122
155
|
return null;
|
|
123
156
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-approval-gate",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.28",
|
|
4
4
|
"description": "Host-only command safety gate for DeepSeek Harness: blocks recognized dangerous operations and requests DSH approval when a command cannot be inspected.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|