@yadsh/dsh-qa-surface 0.1.1 → 0.2.0

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 (89) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/README.md +162 -14
  3. package/SPEC-dsh-qa-surface.md +600 -96
  4. package/capability-policy.json +5 -0
  5. package/compatibility.json +7 -1
  6. package/cordis.patch.yml +11 -0
  7. package/docs/ARCHITECTURE.md +49 -7
  8. package/docs/COMPATIBILITY.md +5 -4
  9. package/docs/CONFIGURATION.md +96 -2
  10. package/lib/attestation.js +10 -0
  11. package/lib/attestation.js.map +1 -0
  12. package/lib/client/QaConfigController.js +111 -4
  13. package/lib/client/QaConfigController.js.map +1 -1
  14. package/lib/client/QaSessionController.js +501 -119
  15. package/lib/client/QaSessionController.js.map +1 -1
  16. package/lib/client/QaSurface.js +137 -20
  17. package/lib/client/QaSurface.js.map +1 -1
  18. package/lib/client/QaTranscriptAdapter.js +534 -45
  19. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  20. package/lib/client/attestation.js +60 -0
  21. package/lib/client/attestation.js.map +1 -0
  22. package/lib/client/chat-index.js +86 -0
  23. package/lib/client/chat-index.js.map +1 -0
  24. package/lib/client/components/Markdown.js +75 -5
  25. package/lib/client/components/Markdown.js.map +1 -1
  26. package/lib/client/components/QaAgentsDrawer.js +40 -0
  27. package/lib/client/components/QaAgentsDrawer.js.map +1 -0
  28. package/lib/client/components/QaComposer.js +132 -15
  29. package/lib/client/components/QaComposer.js.map +1 -1
  30. package/lib/client/components/QaMessage.js +184 -10
  31. package/lib/client/components/QaMessage.js.map +1 -1
  32. package/lib/client/components/QaSidebar.js +124 -0
  33. package/lib/client/components/QaSidebar.js.map +1 -0
  34. package/lib/client/components/QaSourcesDrawer.js +46 -0
  35. package/lib/client/components/QaSourcesDrawer.js.map +1 -0
  36. package/lib/client/components/QaWorkGroup.js +135 -0
  37. package/lib/client/components/QaWorkGroup.js.map +1 -0
  38. package/lib/client/components/VariantSwitcher.js +29 -0
  39. package/lib/client/components/VariantSwitcher.js.map +1 -0
  40. package/lib/client/components/format.js +48 -0
  41. package/lib/client/components/format.js.map +1 -0
  42. package/lib/client/index.js +77 -34
  43. package/lib/client/index.js.map +1 -1
  44. package/lib/client/styles.js +308 -43
  45. package/lib/client/styles.js.map +1 -1
  46. package/lib/client/types.js +13 -0
  47. package/lib/client/types.js.map +1 -0
  48. package/lib/client/wait-for.js +49 -0
  49. package/lib/client/wait-for.js.map +1 -0
  50. package/lib/client.js +8228 -383
  51. package/lib/client.js.map +1 -1
  52. package/lib/config.js +61 -9
  53. package/lib/config.js.map +1 -1
  54. package/lib/index.js +166 -70
  55. package/lib/index.js.map +1 -1
  56. package/lib/lockdown-policy.js +20 -0
  57. package/lib/lockdown-policy.js.map +1 -0
  58. package/lib/resolve-config.js +122 -10
  59. package/lib/resolve-config.js.map +1 -1
  60. package/lib/secure-session.js +170 -0
  61. package/lib/secure-session.js.map +1 -0
  62. package/lib/typert.host.d.ts +3 -0
  63. package/lib/typert.host.js +191 -0
  64. package/lib/typert.remote-client.d.ts +24 -0
  65. package/lib/typert.remote-client.js +129 -0
  66. package/lib/types/attestation.d.ts +17 -0
  67. package/lib/types/client/QaConfigController.d.ts +34 -2
  68. package/lib/types/client/QaSessionController.d.ts +106 -19
  69. package/lib/types/client/QaSurface.d.ts +5 -4
  70. package/lib/types/client/QaTranscriptAdapter.d.ts +17 -2
  71. package/lib/types/client/attestation.d.ts +25 -0
  72. package/lib/types/client/chat-index.d.ts +28 -0
  73. package/lib/types/client/components/Markdown.d.ts +7 -3
  74. package/lib/types/client/components/QaAgentsDrawer.d.ts +25 -0
  75. package/lib/types/client/components/QaComposer.d.ts +12 -2
  76. package/lib/types/client/components/QaMessage.d.ts +14 -1
  77. package/lib/types/client/components/QaSidebar.d.ts +41 -0
  78. package/lib/types/client/components/QaSourcesDrawer.d.ts +8 -0
  79. package/lib/types/client/components/QaWorkGroup.d.ts +19 -0
  80. package/lib/types/client/components/VariantSwitcher.d.ts +19 -0
  81. package/lib/types/client/components/format.d.ts +9 -0
  82. package/lib/types/client/index.d.ts +1 -5
  83. package/lib/types/client/types.d.ts +29 -0
  84. package/lib/types/client/wait-for.d.ts +11 -0
  85. package/lib/types/index.d.ts +22 -6
  86. package/lib/types/lockdown-policy.d.ts +18 -0
  87. package/lib/types/secure-session.d.ts +22 -0
  88. package/lib/types/types.d.ts +148 -1
  89. package/package.json +29 -3
package/lib/config.js CHANGED
@@ -10,25 +10,28 @@ const configSchema = z.object({
10
10
  .default({ path: "/qa", matchChildren: true }),
11
11
  branding: z
12
12
  .object({
13
- title: z.string().default("Assistant"),
13
+ title: z.string().default("Помощник"),
14
14
  subtitle: z.string().default(""),
15
- welcomeMessage: z.string().default("How can I help?"),
16
- placeholder: z.string().default("Ask a question..."),
15
+ welcomeMessage: z.string().default("Чем могу помочь?"),
16
+ placeholder: z.string().default("Задайте вопрос…"),
17
17
  logoUrl: nullableString.default(null),
18
+ disclaimer: nullableString.default("Диалоги могут быть видны другим пользователям сервера и используются для улучшения качества ответов."),
18
19
  })
19
20
  .default({
20
- title: "Assistant",
21
+ title: "Помощник",
21
22
  subtitle: "",
22
- welcomeMessage: "How can I help?",
23
- placeholder: "Ask a question...",
23
+ welcomeMessage: "Чем могу помочь?",
24
+ placeholder: "Задайте вопрос…",
24
25
  logoUrl: null,
26
+ disclaimer: "Диалоги могут быть видны другим пользователям сервера и используются для улучшения качества ответов.",
25
27
  }),
26
28
  session: z
27
29
  .object({
28
30
  policy: z
29
31
  .union(["browser-persistent", "new-on-load", "fixed"])
30
32
  .default("browser-persistent"),
31
- storageKey: z.string().default("dsh-qa-surface"),
33
+ storageKey: z.string().default("dsh-qa-surface.session"),
34
+ cwd: nullableString.default(null),
32
35
  workspaceId: nullableString.default(null),
33
36
  fixedSessionId: nullableString.default(null),
34
37
  agentPreset: nullableString.default(null),
@@ -38,7 +41,8 @@ const configSchema = z.object({
38
41
  })
39
42
  .default({
40
43
  policy: "browser-persistent",
41
- storageKey: "dsh-qa-surface",
44
+ storageKey: "dsh-qa-surface.session",
45
+ cwd: null,
42
46
  workspaceId: null,
43
47
  fixedSessionId: null,
44
48
  agentPreset: null,
@@ -56,6 +60,7 @@ const configSchema = z.object({
56
60
  showReasoning: z.boolean().default(false),
57
61
  renderMarkdown: z.boolean().default(true),
58
62
  maxContentWidth: z.number().step(1).min(480).max(1600).default(900),
63
+ showSessionList: z.boolean().default(false),
59
64
  })
60
65
  .default({
61
66
  showHeader: true,
@@ -66,14 +71,61 @@ const configSchema = z.object({
66
71
  showReasoning: false,
67
72
  renderMarkdown: true,
68
73
  maxContentWidth: 900,
74
+ showSessionList: false,
69
75
  }),
70
- suggestedQuestions: z.array(z.string()).default([]),
76
+ suggestedQuestions: z
77
+ .array(z.string())
78
+ .default([
79
+ "Что ты умеешь?",
80
+ "С чего начать?",
81
+ "Помоги разобраться с ошибкой",
82
+ ]),
71
83
  interaction: z
72
84
  .object({
73
85
  approvals: z.union(["blocked"]).default("blocked"),
74
86
  questions: z.union(["unsupported"]).default("unsupported"),
75
87
  })
76
88
  .default({ approvals: "blocked", questions: "unsupported" }),
89
+ lockdown: z
90
+ .object({
91
+ enabled: z.boolean().default(true),
92
+ enforceFixedAgentPreset: z.boolean().default(true),
93
+ enforceFixedWorkspace: z.boolean().default(true),
94
+ enforceFixedModel: z.boolean().default(true),
95
+ sandboxMode: z.union(["read-only"]).default("read-only"),
96
+ approvalPolicy: z.union(["never"]).default("never"),
97
+ permissionPreset: z.string().default("qa-read-only"),
98
+ allowPermissionChanges: z.const(false).default(false),
99
+ allowSlashCommands: z.const(false).default(false),
100
+ allowSettingsMutation: z.const(false).default(false),
101
+ allowSessionReset: z.boolean().default(false),
102
+ allowSessionRename: z.const(false).default(false),
103
+ allowSessionDelete: z.const(false).default(false),
104
+ allowArbitrarySessionOpen: z.const(false).default(false),
105
+ toolPolicy: z
106
+ .object({
107
+ mode: z.union(["allow-list"]).default("allow-list"),
108
+ allow: z.array(z.string()).default([]),
109
+ })
110
+ .default({ mode: "allow-list", allow: [] }),
111
+ })
112
+ .default({
113
+ enabled: true,
114
+ enforceFixedAgentPreset: true,
115
+ enforceFixedWorkspace: true,
116
+ enforceFixedModel: true,
117
+ sandboxMode: "read-only",
118
+ approvalPolicy: "never",
119
+ permissionPreset: "qa-read-only",
120
+ allowPermissionChanges: false,
121
+ allowSlashCommands: false,
122
+ allowSettingsMutation: false,
123
+ allowSessionReset: false,
124
+ allowSessionRename: false,
125
+ allowSessionDelete: false,
126
+ allowArbitrarySessionOpen: false,
127
+ toolPolicy: { mode: "allow-list", allow: [] },
128
+ }),
77
129
  embedding: z
78
130
  .object({ frameAncestors: nullableString.default(null) })
79
131
  .default({ frameAncestors: null }),
package/lib/config.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
package/lib/index.js CHANGED
@@ -1,83 +1,179 @@
1
- import { Service } from "@deepseek-ai/cordis";
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ import { Remote, TypertRemoteService } from "@deepseek-ai/dsh-typert-protocol";
2
36
  import { installSettingsSection, settingsNamespace, } from "@deepseek-ai/dsh-settings";
3
37
  import { createHostLoggerSink, getPluginLogger, } from "@yadsh/dsh-plugin-log";
4
38
  import { ConfigSchema, resolveConfig } from "./config.js";
39
+ import { QaAttestationError } from "./attestation.js";
5
40
  import { registerQaNavigationRoute } from "./host-route.js";
41
+ import { QaPolicyAdmission } from "./secure-session.js";
6
42
  export const name = "qa-surface";
7
- export const inject = [];
43
+ export const inject = [
44
+ "agents",
45
+ "agentPresets",
46
+ "permissionPresets",
47
+ "tools",
48
+ "workspaceRegistry",
49
+ ];
8
50
  export const QA_SURFACE_SETTINGS_NAMESPACE = settingsNamespace("qa-surface");
9
51
  export const Config = ConfigSchema;
10
- /** Small Host companion: validates config and exposes it through DSH settings. */
11
- export class QaSurface extends Service {
12
- static inject = inject;
13
- static Config = ConfigSchema;
14
- source;
15
- logger;
16
- webServer;
17
- disposeRoute;
18
- routeKey;
19
- constructor(ctx, entry = {}) {
20
- super(ctx, "qaSurface");
21
- const resolvedEntry = resolveConfig(entry);
22
- this.source = () => resolvedEntry;
23
- this.logger = getPluginLogger({
24
- pluginId: "dsh-qa-surface",
25
- consoleSink: createHostLoggerSink(ctx.logger),
26
- });
27
- ctx.effect(() => async () => this.logger.close(), "dsh-qa-surface.logger");
28
- installSettingsSection(ctx, QA_SURFACE_SETTINGS_NAMESPACE, ConfigSchema, entry, {
29
- setSource: (source) => {
30
- this.source = source;
31
- },
32
- onChange: () => {
33
- const config = this.getConfig();
52
+ const CONFIGURATION_ERROR = "Assistant configuration is unavailable.";
53
+ /** Host companion: validates config, owns the admission boundary and the route. */
54
+ let QaSurface = (() => {
55
+ let _classSuper = TypertRemoteService;
56
+ let _instanceExtraInitializers = [];
57
+ let _describe_decorators;
58
+ let _secureSession_decorators;
59
+ return class QaSurface extends _classSuper {
60
+ static {
61
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
62
+ _describe_decorators = [Remote("describe")];
63
+ _secureSession_decorators = [Remote("secureSession")];
64
+ __esDecorate(this, null, _describe_decorators, { kind: "method", name: "describe", static: false, private: false, access: { has: obj => "describe" in obj, get: obj => obj.describe }, metadata: _metadata }, null, _instanceExtraInitializers);
65
+ __esDecorate(this, null, _secureSession_decorators, { kind: "method", name: "secureSession", static: false, private: false, access: { has: obj => "secureSession" in obj, get: obj => obj.secureSession }, metadata: _metadata }, null, _instanceExtraInitializers);
66
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
67
+ }
68
+ static inject = inject;
69
+ static Config = ConfigSchema;
70
+ source = __runInitializers(this, _instanceExtraInitializers);
71
+ logger;
72
+ admission;
73
+ webServer;
74
+ disposeRoute;
75
+ routeKey;
76
+ constructor(ctx, entry = {}) {
77
+ super(ctx, "qaSurface", { namespace: "qaSurface" });
78
+ const resolvedEntry = resolveConfig(entry);
79
+ this.source = () => resolvedEntry;
80
+ this.logger = getPluginLogger({
81
+ pluginId: "dsh-qa-surface",
82
+ consoleSink: createHostLoggerSink(ctx.logger),
83
+ });
84
+ this.admission = new QaPolicyAdmission(ctx, () => this.getConfig(), this.logger);
85
+ ctx.effect(() => async () => this.logger.close(), "dsh-qa-surface.logger");
86
+ ctx.effect(() => () => this.admission.dispose(), "dsh-qa-surface.lockdown-policies");
87
+ installSettingsSection(ctx, QA_SURFACE_SETTINGS_NAMESPACE, ConfigSchema, entry, {
88
+ setSource: (source) => {
89
+ this.source = source;
90
+ },
91
+ onChange: () => {
92
+ const config = this.getConfig();
93
+ this.refreshRoute();
94
+ this.logger.info("config.updated", {
95
+ enabled: config.enabled,
96
+ route: config.route.path,
97
+ sessionPolicy: config.session.policy,
98
+ });
99
+ },
100
+ validate: (value) => {
101
+ resolveConfig(value);
102
+ },
103
+ });
104
+ ctx.inject(["webServer"], (webContext) => {
105
+ this.webServer = webContext.webServer;
34
106
  this.refreshRoute();
35
- this.logger.info("config.updated", {
36
- enabled: config.enabled,
37
- route: config.route.path,
38
- sessionPolicy: config.session.policy,
107
+ webContext.effect(() => () => {
108
+ this.disposeRoute?.();
109
+ this.disposeRoute = undefined;
110
+ this.routeKey = undefined;
111
+ this.webServer = undefined;
112
+ }, "dsh-qa-surface.navigation-route");
113
+ });
114
+ this.logger.info("plugin.ready", {
115
+ enabled: resolvedEntry.enabled,
116
+ route: resolvedEntry.route.path,
117
+ sessionPolicy: resolvedEntry.session.policy,
118
+ });
119
+ }
120
+ getConfig() {
121
+ return resolveConfig(this.source());
122
+ }
123
+ /**
124
+ * Serve the effective QA configuration to the browser. The DSH gateway pins
125
+ * settings RPCs to loopback, so a browser served over the LAN always sees
126
+ * the settings namespace as unavailable; this method is the config channel
127
+ * such a browser falls back to. It is read-only projection — the admission
128
+ * boundary stays in {@link secureSession}.
129
+ */
130
+ describe() {
131
+ return this.getConfig();
132
+ }
133
+ /** Pin and attest the effective policy. The browser supplies identity only. */
134
+ secureSession(sessionId) {
135
+ try {
136
+ return this.admission.secureSession(sessionId);
137
+ }
138
+ catch (error) {
139
+ // The carrier empties error.details, so the coarse reason rides the
140
+ // wire message for the browser console; the specific mismatch facts
141
+ // stay in this log only.
142
+ const reason = error instanceof QaAttestationError
143
+ ? error.reason
144
+ : "attestation-failed";
145
+ this.logger.error("lockdown.rejected", {
146
+ sessionId,
147
+ reason,
148
+ error: error instanceof Error ? error.message : String(error),
39
149
  });
40
- },
41
- validate: (value) => {
42
- resolveConfig(value);
43
- },
44
- });
45
- ctx.inject(["webServer"], (webContext) => {
46
- this.webServer = webContext.webServer;
47
- this.refreshRoute();
48
- webContext.effect(() => () => {
49
- this.disposeRoute?.();
50
- this.disposeRoute = undefined;
51
- this.routeKey = undefined;
52
- this.webServer = undefined;
53
- }, "dsh-qa-surface.navigation-route");
54
- });
55
- this.logger.info("plugin.ready", {
56
- enabled: resolvedEntry.enabled,
57
- route: resolvedEntry.route.path,
58
- sessionPolicy: resolvedEntry.session.policy,
59
- });
60
- }
61
- getConfig() {
62
- return resolveConfig(this.source());
63
- }
64
- refreshRoute() {
65
- const config = this.getConfig();
66
- const key = config.enabled
67
- ? `${config.route.path}:${config.route.matchChildren}`
68
- : undefined;
69
- if (key === this.routeKey)
70
- return;
71
- this.disposeRoute?.();
72
- this.disposeRoute = undefined;
73
- this.routeKey = undefined;
74
- if (key === undefined || this.webServer === undefined)
75
- return;
76
- this.disposeRoute = registerQaNavigationRoute(this.webServer, config);
77
- this.routeKey = key;
78
- }
79
- }
150
+ throw new Error(`${CONFIGURATION_ERROR} (reason: ${reason})`, {
151
+ cause: error,
152
+ });
153
+ }
154
+ }
155
+ refreshRoute() {
156
+ const config = this.getConfig();
157
+ const key = config.enabled
158
+ ? `${config.route.path}:${config.route.matchChildren}`
159
+ : undefined;
160
+ if (key === this.routeKey)
161
+ return;
162
+ this.disposeRoute?.();
163
+ this.disposeRoute = undefined;
164
+ this.routeKey = undefined;
165
+ if (key === undefined || this.webServer === undefined)
166
+ return;
167
+ this.disposeRoute = registerQaNavigationRoute(this.webServer, config);
168
+ this.routeKey = key;
169
+ }
170
+ };
171
+ })();
172
+ export { QaSurface };
80
173
  export { ConfigSchema, DEFAULT_QA_SURFACE_CONFIG, normalizeRoutePath, resolveConfig, } from "./config.js";
174
+ export { QaAttestationError } from "./attestation.js";
81
175
  export { registerQaNavigationRoute } from "./host-route.js";
176
+ export { qaToolDenial, qaToolPolicyPlan } from "./lockdown-policy.js";
177
+ export { QaPolicyAdmission } from "./secure-session.js";
82
178
  export default QaSurface;
83
179
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ const TOOL_DENIAL = "This tool is not available in the QA execution profile.";
2
+ /**
3
+ * Validate an allow-list against the complete agent-scoped view.
4
+ *
5
+ * Preset tools live on an ancestor scope, not necessarily in the global tool
6
+ * layer. The restriction must therefore retain the configured names verbatim;
7
+ * deriving it from the global view would hide every preset-owned tool after a
8
+ * successful first attestation and make the next attestation fail.
9
+ */
10
+ export function qaToolPolicyPlan(allow, isMounted) {
11
+ return {
12
+ allow: [...allow],
13
+ unknown: allow.filter((toolName) => !isMounted(toolName)),
14
+ };
15
+ }
16
+ /** Monotonic execution decision shared by inherited, scoped and transport tools. */
17
+ export function qaToolDenial(allowed, toolName) {
18
+ return allowed.has(toolName) ? undefined : TOOL_DENIAL;
19
+ }
20
+ //# sourceMappingURL=lockdown-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lockdown-policy.js","sourceRoot":"","sources":["../src/lockdown-policy.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,GAAG,yDAAyD,CAAC;AAS9E;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAwB,EACxB,SAAwC;IAExC,OAAO;QACL,KAAK,EAAE,CAAC,GAAG,KAAK,CAAC;QACjB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;KAC1D,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,YAAY,CAC1B,OAA4B,EAC5B,QAAgB;IAEhB,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;AACzD,CAAC"}
@@ -2,15 +2,17 @@ export const DEFAULT_QA_SURFACE_CONFIG = Object.freeze({
2
2
  enabled: true,
3
3
  route: Object.freeze({ path: "/qa", matchChildren: true }),
4
4
  branding: Object.freeze({
5
- title: "Assistant",
5
+ title: "Помощник",
6
6
  subtitle: "",
7
- welcomeMessage: "How can I help?",
8
- placeholder: "Ask a question...",
7
+ welcomeMessage: "Чем могу помочь?",
8
+ placeholder: "Задайте вопрос…",
9
9
  logoUrl: null,
10
+ disclaimer: "Диалоги могут быть видны другим пользователям сервера и используются для улучшения качества ответов.",
10
11
  }),
11
12
  session: Object.freeze({
12
13
  policy: "browser-persistent",
13
- storageKey: "dsh-qa-surface",
14
+ storageKey: "dsh-qa-surface.session",
15
+ cwd: null,
14
16
  workspaceId: null,
15
17
  fixedSessionId: null,
16
18
  agentPreset: null,
@@ -20,19 +22,44 @@ export const DEFAULT_QA_SURFACE_CONFIG = Object.freeze({
20
22
  }),
21
23
  ui: Object.freeze({
22
24
  showHeader: true,
23
- showReset: true,
25
+ showReset: false,
24
26
  showStop: true,
25
27
  showTimestamps: false,
26
28
  showToolActivity: false,
27
29
  showReasoning: false,
28
30
  renderMarkdown: true,
29
31
  maxContentWidth: 900,
32
+ showSessionList: false,
30
33
  }),
31
- suggestedQuestions: Object.freeze([]),
34
+ suggestedQuestions: Object.freeze([
35
+ "Что ты умеешь?",
36
+ "С чего начать?",
37
+ "Помоги разобраться с ошибкой",
38
+ ]),
32
39
  interaction: Object.freeze({
33
40
  approvals: "blocked",
34
41
  questions: "unsupported",
35
42
  }),
43
+ lockdown: Object.freeze({
44
+ enabled: true,
45
+ enforceFixedAgentPreset: true,
46
+ enforceFixedWorkspace: true,
47
+ enforceFixedModel: true,
48
+ sandboxMode: "read-only",
49
+ approvalPolicy: "never",
50
+ permissionPreset: "qa-read-only",
51
+ allowPermissionChanges: false,
52
+ allowSlashCommands: false,
53
+ allowSettingsMutation: false,
54
+ allowSessionReset: false,
55
+ allowSessionRename: false,
56
+ allowSessionDelete: false,
57
+ allowArbitrarySessionOpen: false,
58
+ toolPolicy: Object.freeze({
59
+ mode: "allow-list",
60
+ allow: Object.freeze([]),
61
+ }),
62
+ }),
36
63
  embedding: Object.freeze({ frameAncestors: null }),
37
64
  });
38
65
  function optionalText(value) {
@@ -65,6 +92,15 @@ function uniqueQuestions(values) {
65
92
  }
66
93
  return Object.freeze(questions);
67
94
  }
95
+ function uniqueToolNames(values) {
96
+ const names = [
97
+ ...new Set(values.map((value) => value.trim()).filter(Boolean)),
98
+ ];
99
+ if (names.some((value) => value.length > 200)) {
100
+ throw new TypeError("dsh-qa-surface: lockdown.toolPolicy.allow names must be at most 200 characters");
101
+ }
102
+ return Object.freeze(names);
103
+ }
68
104
  /** Materialize defaults and enforce route/session/model safety constraints. */
69
105
  export function resolveConfig(input = {}) {
70
106
  const routePath = normalizeRoutePath(input.route?.path ?? DEFAULT_QA_SURFACE_CONFIG.route.path);
@@ -73,6 +109,16 @@ export function resolveConfig(input = {}) {
73
109
  if (policy === "fixed" && fixedSessionId === null) {
74
110
  throw new TypeError("dsh-qa-surface: session.fixedSessionId is required for fixed policy");
75
111
  }
112
+ // The cwd pin is the no-registry alternative to workspaceId; both pin the
113
+ // session to one directory, so together they are a configuration error.
114
+ const cwd = optionalText(input.session?.cwd);
115
+ if (cwd !== null && !/^([a-zA-Z]:[/\\]|\/)/u.test(cwd)) {
116
+ throw new TypeError("dsh-qa-surface: session.cwd must be an absolute directory path");
117
+ }
118
+ const workspaceId = optionalText(input.session?.workspaceId);
119
+ if (workspaceId !== null && cwd !== null) {
120
+ throw new TypeError("dsh-qa-surface: session.workspaceId and session.cwd are mutually exclusive");
121
+ }
76
122
  const provider = optionalText(input.session?.provider);
77
123
  const model = optionalText(input.session?.model);
78
124
  if ((provider === null) !== (model === null)) {
@@ -89,8 +135,43 @@ export function resolveConfig(input = {}) {
89
135
  maxContentWidth > 1600) {
90
136
  throw new TypeError("dsh-qa-surface: ui.maxContentWidth must be an integer from 480 to 1600");
91
137
  }
92
- if (input.ui?.showReasoning === true) {
93
- throw new TypeError("dsh-qa-surface: ui.showReasoning is not supported by the safe MVP surface");
138
+ const lockdownEnabled = input.lockdown?.enabled ?? DEFAULT_QA_SURFACE_CONFIG.lockdown.enabled;
139
+ const rawLockdown = input.lockdown;
140
+ const forbiddenCapabilityFlags = [
141
+ ["allowPermissionChanges", rawLockdown?.allowPermissionChanges],
142
+ ["allowSlashCommands", rawLockdown?.allowSlashCommands],
143
+ ["allowSettingsMutation", rawLockdown?.allowSettingsMutation],
144
+ ["allowSessionRename", rawLockdown?.allowSessionRename],
145
+ ["allowSessionDelete", rawLockdown?.allowSessionDelete],
146
+ ["allowArbitrarySessionOpen", rawLockdown?.allowArbitrarySessionOpen],
147
+ ];
148
+ const weakenedFlag = forbiddenCapabilityFlags.find(([, value]) => value === true);
149
+ if (weakenedFlag !== undefined) {
150
+ throw new TypeError(`dsh-qa-surface: lockdown.${weakenedFlag[0]} cannot be enabled`);
151
+ }
152
+ if (input.lockdown?.sandboxMode !== undefined &&
153
+ input.lockdown.sandboxMode !== "read-only") {
154
+ throw new TypeError("dsh-qa-surface: lockdown.sandboxMode must be read-only");
155
+ }
156
+ if (input.lockdown?.approvalPolicy !== undefined &&
157
+ input.lockdown.approvalPolicy !== "never") {
158
+ throw new TypeError("dsh-qa-surface: lockdown.approvalPolicy must be never");
159
+ }
160
+ if (input.lockdown?.toolPolicy?.mode !== undefined &&
161
+ input.lockdown.toolPolicy.mode !== "allow-list") {
162
+ throw new TypeError("dsh-qa-surface: lockdown.toolPolicy.mode must be allow-list");
163
+ }
164
+ const permissionPreset = input.lockdown?.permissionPreset?.trim() ??
165
+ DEFAULT_QA_SURFACE_CONFIG.lockdown.permissionPreset;
166
+ if (lockdownEnabled && permissionPreset === "") {
167
+ throw new TypeError("dsh-qa-surface: lockdown.permissionPreset is required when lockdown is enabled");
168
+ }
169
+ const allowSessionReset = input.lockdown?.allowSessionReset ??
170
+ DEFAULT_QA_SURFACE_CONFIG.lockdown.allowSessionReset;
171
+ if (lockdownEnabled &&
172
+ (input.ui?.showReset ?? DEFAULT_QA_SURFACE_CONFIG.ui.showReset) &&
173
+ !allowSessionReset) {
174
+ throw new TypeError("dsh-qa-surface: ui.showReset requires lockdown.allowSessionReset");
94
175
  }
95
176
  return Object.freeze({
96
177
  enabled: input.enabled ?? DEFAULT_QA_SURFACE_CONFIG.enabled,
@@ -108,10 +189,16 @@ export function resolveConfig(input = {}) {
108
189
  placeholder: input.branding?.placeholder?.trim() ||
109
190
  DEFAULT_QA_SURFACE_CONFIG.branding.placeholder,
110
191
  logoUrl: optionalText(input.branding?.logoUrl),
192
+ // Undefined falls back to the default notice; an explicit null or
193
+ // empty string hides the plate entirely.
194
+ disclaimer: input.branding?.disclaimer === undefined
195
+ ? DEFAULT_QA_SURFACE_CONFIG.branding.disclaimer
196
+ : (optionalText(input.branding.disclaimer) ?? ""),
111
197
  }),
112
198
  session: Object.freeze({
113
199
  policy,
114
200
  storageKey,
201
+ cwd,
115
202
  workspaceId: optionalText(input.session?.workspaceId),
116
203
  fixedSessionId,
117
204
  agentPreset: optionalText(input.session?.agentPreset),
@@ -126,15 +213,40 @@ export function resolveConfig(input = {}) {
126
213
  showTimestamps: input.ui?.showTimestamps ?? DEFAULT_QA_SURFACE_CONFIG.ui.showTimestamps,
127
214
  showToolActivity: input.ui?.showToolActivity ??
128
215
  DEFAULT_QA_SURFACE_CONFIG.ui.showToolActivity,
129
- showReasoning: false,
216
+ showReasoning: input.ui?.showReasoning ?? DEFAULT_QA_SURFACE_CONFIG.ui.showReasoning,
130
217
  renderMarkdown: input.ui?.renderMarkdown ?? DEFAULT_QA_SURFACE_CONFIG.ui.renderMarkdown,
131
218
  maxContentWidth,
219
+ showSessionList: input.ui?.showSessionList ??
220
+ DEFAULT_QA_SURFACE_CONFIG.ui.showSessionList,
132
221
  }),
133
- suggestedQuestions: uniqueQuestions(input.suggestedQuestions ?? []),
222
+ suggestedQuestions: uniqueQuestions(input.suggestedQuestions ?? DEFAULT_QA_SURFACE_CONFIG.suggestedQuestions),
134
223
  interaction: Object.freeze({
135
224
  approvals: "blocked",
136
225
  questions: "unsupported",
137
226
  }),
227
+ lockdown: Object.freeze({
228
+ enabled: lockdownEnabled,
229
+ enforceFixedAgentPreset: input.lockdown?.enforceFixedAgentPreset ??
230
+ DEFAULT_QA_SURFACE_CONFIG.lockdown.enforceFixedAgentPreset,
231
+ enforceFixedWorkspace: input.lockdown?.enforceFixedWorkspace ??
232
+ DEFAULT_QA_SURFACE_CONFIG.lockdown.enforceFixedWorkspace,
233
+ enforceFixedModel: input.lockdown?.enforceFixedModel ??
234
+ DEFAULT_QA_SURFACE_CONFIG.lockdown.enforceFixedModel,
235
+ sandboxMode: "read-only",
236
+ approvalPolicy: "never",
237
+ permissionPreset,
238
+ allowPermissionChanges: false,
239
+ allowSlashCommands: false,
240
+ allowSettingsMutation: false,
241
+ allowSessionReset,
242
+ allowSessionRename: false,
243
+ allowSessionDelete: false,
244
+ allowArbitrarySessionOpen: false,
245
+ toolPolicy: Object.freeze({
246
+ mode: "allow-list",
247
+ allow: uniqueToolNames(input.lockdown?.toolPolicy?.allow ?? []),
248
+ }),
249
+ }),
138
250
  embedding: Object.freeze({
139
251
  frameAncestors: optionalText(input.embedding?.frameAncestors),
140
252
  }),