@yadsh/dsh-qa-surface 0.6.1 → 0.7.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 (281) hide show
  1. package/README.md +136 -7
  2. package/capability-policy.json +1 -1
  3. package/lib/access/capability-catalog.js +144 -0
  4. package/lib/access/capability-catalog.js.map +1 -0
  5. package/lib/access/model.js +379 -0
  6. package/lib/access/model.js.map +1 -0
  7. package/lib/access/role-repository.js +195 -0
  8. package/lib/access/role-repository.js.map +1 -0
  9. package/lib/access/service.js +380 -0
  10. package/lib/access/service.js.map +1 -0
  11. package/lib/access/skill-metadata.js +234 -0
  12. package/lib/access/skill-metadata.js.map +1 -0
  13. package/lib/account-remotes.js +20 -10
  14. package/lib/account-remotes.js.map +1 -1
  15. package/lib/accounts/errors.js.map +1 -1
  16. package/lib/accounts/file.js.map +1 -1
  17. package/lib/accounts/store.js +202 -3
  18. package/lib/accounts/store.js.map +1 -1
  19. package/lib/admin/conversation-log.js +256 -0
  20. package/lib/admin/conversation-log.js.map +1 -0
  21. package/lib/admin/index.js +17 -0
  22. package/lib/admin/index.js.map +1 -0
  23. package/lib/admin/metrics.js +103 -0
  24. package/lib/admin/metrics.js.map +1 -0
  25. package/lib/admin/paging.js +23 -0
  26. package/lib/admin/paging.js.map +1 -0
  27. package/lib/admin/permissions.js +50 -0
  28. package/lib/admin/permissions.js.map +1 -0
  29. package/lib/admin/quality-store.js +485 -0
  30. package/lib/admin/quality-store.js.map +1 -0
  31. package/lib/admin/queue.js +107 -0
  32. package/lib/admin/queue.js.map +1 -0
  33. package/lib/admin/redaction.js +45 -0
  34. package/lib/admin/redaction.js.map +1 -0
  35. package/lib/admin/service.js +897 -0
  36. package/lib/admin/service.js.map +1 -0
  37. package/lib/admin/session-log.js +142 -0
  38. package/lib/admin/session-log.js.map +1 -0
  39. package/lib/cli.js +9 -6
  40. package/lib/cli.js.map +1 -1
  41. package/lib/client/QaSessionController.js +28 -2
  42. package/lib/client/QaSessionController.js.map +1 -1
  43. package/lib/client/QaSurface.js +143 -5
  44. package/lib/client/QaSurface.js.map +1 -1
  45. package/lib/client/QaTranscriptAdapter.js +1 -0
  46. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  47. package/lib/client/admin/QaAdmin.js +458 -0
  48. package/lib/client/admin/QaAdmin.js.map +1 -0
  49. package/lib/client/admin/format.js +177 -0
  50. package/lib/client/admin/format.js.map +1 -0
  51. package/lib/client/admin/pages/Conversations.js +114 -0
  52. package/lib/client/admin/pages/Conversations.js.map +1 -0
  53. package/lib/client/admin/pages/Overview.js +24 -0
  54. package/lib/client/admin/pages/Overview.js.map +1 -0
  55. package/lib/client/admin/pages/Quality.js +71 -0
  56. package/lib/client/admin/pages/Quality.js.map +1 -0
  57. package/lib/client/admin/pages/Review.js +93 -0
  58. package/lib/client/admin/pages/Review.js.map +1 -0
  59. package/lib/client/admin/pages/Users.js +95 -0
  60. package/lib/client/admin/pages/Users.js.map +1 -0
  61. package/lib/client/admin/routes.js +127 -0
  62. package/lib/client/admin/routes.js.map +1 -0
  63. package/lib/client/admin/shared.js +91 -0
  64. package/lib/client/admin/shared.js.map +1 -0
  65. package/lib/client/admin/styles.js +111 -0
  66. package/lib/client/admin/styles.js.map +1 -0
  67. package/lib/client/components/QaChangelog.js +35 -0
  68. package/lib/client/components/QaChangelog.js.map +1 -1
  69. package/lib/client/components/QaHeader.js +3 -3
  70. package/lib/client/components/QaHeader.js.map +1 -1
  71. package/lib/client/components/QaMessage.js +61 -2
  72. package/lib/client/components/QaMessage.js.map +1 -1
  73. package/lib/client/create-session.js +1 -1
  74. package/lib/client/create-session.js.map +1 -1
  75. package/lib/client/index.js +33 -1
  76. package/lib/client/index.js.map +1 -1
  77. package/lib/client/role/RoleSelector.js +31 -0
  78. package/lib/client/role/RoleSelector.js.map +1 -0
  79. package/lib/client/session-sources.js +37 -1
  80. package/lib/client/session-sources.js.map +1 -1
  81. package/lib/client/settings/card.js +2 -2
  82. package/lib/client/settings/card.js.map +1 -1
  83. package/lib/client/settings/sections.js +0 -1
  84. package/lib/client/settings/sections.js.map +1 -1
  85. package/lib/client/styles.js +31 -0
  86. package/lib/client/styles.js.map +1 -1
  87. package/lib/client/types.js.map +1 -1
  88. package/lib/client.js +9908 -4857
  89. package/lib/client.js.map +1 -1
  90. package/lib/config-resolvers/defaults.js +0 -2
  91. package/lib/config-resolvers/defaults.js.map +1 -1
  92. package/lib/config.js +0 -249
  93. package/lib/config.js.map +1 -1
  94. package/lib/enforcement/skill-policy.js +172 -0
  95. package/lib/enforcement/skill-policy.js.map +1 -0
  96. package/lib/enforcement/tool-grants.js +151 -0
  97. package/lib/enforcement/tool-grants.js.map +1 -0
  98. package/lib/index.js +224 -42
  99. package/lib/index.js.map +1 -1
  100. package/lib/personal-skills/service.js +10 -3
  101. package/lib/personal-skills/service.js.map +1 -1
  102. package/lib/qa-tools/index.js +4 -0
  103. package/lib/qa-tools/index.js.map +1 -1
  104. package/lib/resolve-config.js +0 -2
  105. package/lib/resolve-config.js.map +1 -1
  106. package/lib/secure-session.js +71 -17
  107. package/lib/secure-session.js.map +1 -1
  108. package/lib/typert.host.js +2237 -202
  109. package/lib/typert.remote-client.d.ts +49 -3
  110. package/lib/typert.remote-client.js +1863 -183
  111. package/lib/types/access/capability-catalog.d.ts +37 -0
  112. package/lib/types/access/model.d.ts +60 -0
  113. package/lib/types/access/role-repository.d.ts +32 -0
  114. package/lib/types/access/service.d.ts +57 -0
  115. package/lib/types/access/skill-metadata.d.ts +53 -0
  116. package/lib/types/account-remotes.d.ts +6 -0
  117. package/lib/types/accounts/errors.d.ts +1 -1
  118. package/lib/types/accounts/file.d.ts +16 -5
  119. package/lib/types/accounts/store.d.ts +83 -3
  120. package/lib/types/admin/conversation-log.d.ts +39 -0
  121. package/lib/types/admin/index.d.ts +24 -0
  122. package/lib/types/admin/metrics.d.ts +29 -0
  123. package/lib/types/admin/paging.d.ts +33 -0
  124. package/lib/types/admin/permissions.d.ts +10 -0
  125. package/lib/types/admin/quality-store.d.ts +82 -0
  126. package/lib/types/admin/queue.d.ts +21 -0
  127. package/lib/types/admin/redaction.d.ts +29 -0
  128. package/lib/types/admin/service.d.ts +105 -0
  129. package/lib/types/admin/session-log.d.ts +53 -0
  130. package/lib/types/client/QaSessionController.d.ts +12 -1
  131. package/lib/types/client/QaSurface.d.ts +7 -1
  132. package/lib/types/client/admin/QaAdmin.d.ts +17 -0
  133. package/lib/types/client/admin/format.d.ts +43 -0
  134. package/lib/types/client/admin/pages/Conversations.d.ts +21 -0
  135. package/lib/types/client/admin/pages/Overview.d.ts +13 -0
  136. package/lib/types/client/admin/pages/Quality.d.ts +18 -0
  137. package/lib/types/client/admin/pages/Review.d.ts +15 -0
  138. package/lib/types/client/admin/pages/Users.d.ts +22 -0
  139. package/lib/types/client/admin/routes.d.ts +50 -0
  140. package/lib/types/client/admin/shared.d.ts +53 -0
  141. package/lib/types/client/admin/styles.d.ts +11 -0
  142. package/lib/types/client/components/QaHeader.d.ts +5 -1
  143. package/lib/types/client/components/QaMessage.d.ts +14 -1
  144. package/lib/types/client/create-session.d.ts +2 -0
  145. package/lib/types/client/role/RoleSelector.d.ts +14 -0
  146. package/lib/types/client/session-sources.d.ts +9 -0
  147. package/lib/types/client/settings/sections.d.ts +0 -1
  148. package/lib/types/client/types.d.ts +39 -2
  149. package/lib/types/enforcement/skill-policy.d.ts +29 -0
  150. package/lib/types/enforcement/tool-grants.d.ts +84 -0
  151. package/lib/types/index.d.ts +62 -14
  152. package/lib/types/qa-tools/index.d.ts +2 -0
  153. package/lib/types/secure-session.d.ts +10 -1
  154. package/lib/types/types.d.ts +568 -5
  155. package/package.json +1 -1
  156. package/lib/client/settings/sections/documents.js +0 -88
  157. package/lib/client/settings/sections/documents.js.map +0 -1
  158. package/lib/documents/artifacts/ids.js +0 -43
  159. package/lib/documents/artifacts/ids.js.map +0 -1
  160. package/lib/documents/artifacts/manifest.js +0 -66
  161. package/lib/documents/artifacts/manifest.js.map +0 -1
  162. package/lib/documents/artifacts/store.js +0 -169
  163. package/lib/documents/artifacts/store.js.map +0 -1
  164. package/lib/documents/capabilities.js +0 -93
  165. package/lib/documents/capabilities.js.map +0 -1
  166. package/lib/documents/config.js +0 -302
  167. package/lib/documents/config.js.map +0 -1
  168. package/lib/documents/defaults.js +0 -78
  169. package/lib/documents/defaults.js.map +0 -1
  170. package/lib/documents/errors.js +0 -101
  171. package/lib/documents/errors.js.map +0 -1
  172. package/lib/documents/index.js +0 -80
  173. package/lib/documents/index.js.map +0 -1
  174. package/lib/documents/inspect/facts.js +0 -161
  175. package/lib/documents/inspect/facts.js.map +0 -1
  176. package/lib/documents/inspect/zip.js +0 -108
  177. package/lib/documents/inspect/zip.js.map +0 -1
  178. package/lib/documents/markdown/directives.js +0 -135
  179. package/lib/documents/markdown/directives.js.map +0 -1
  180. package/lib/documents/markdown/frontmatter.js +0 -35
  181. package/lib/documents/markdown/frontmatter.js.map +0 -1
  182. package/lib/documents/markdown/normalize.js +0 -113
  183. package/lib/documents/markdown/normalize.js.map +0 -1
  184. package/lib/documents/orchestrator/assets.js +0 -243
  185. package/lib/documents/orchestrator/assets.js.map +0 -1
  186. package/lib/documents/orchestrator/convert-document.js +0 -186
  187. package/lib/documents/orchestrator/convert-document.js.map +0 -1
  188. package/lib/documents/orchestrator/create-document.js +0 -292
  189. package/lib/documents/orchestrator/create-document.js.map +0 -1
  190. package/lib/documents/orchestrator/extract-document.js +0 -162
  191. package/lib/documents/orchestrator/extract-document.js.map +0 -1
  192. package/lib/documents/orchestrator/inspect-document.js +0 -89
  193. package/lib/documents/orchestrator/inspect-document.js.map +0 -1
  194. package/lib/documents/orchestrator/runtime-deps.js +0 -59
  195. package/lib/documents/orchestrator/runtime-deps.js.map +0 -1
  196. package/lib/documents/orchestrator/scope.js +0 -132
  197. package/lib/documents/orchestrator/scope.js.map +0 -1
  198. package/lib/documents/providers/docling.js +0 -247
  199. package/lib/documents/providers/docling.js.map +0 -1
  200. package/lib/documents/providers/libreoffice.js +0 -130
  201. package/lib/documents/providers/libreoffice.js.map +0 -1
  202. package/lib/documents/providers/markitdown.js +0 -89
  203. package/lib/documents/providers/markitdown.js.map +0 -1
  204. package/lib/documents/providers/pandoc.js +0 -161
  205. package/lib/documents/providers/pandoc.js.map +0 -1
  206. package/lib/documents/providers/process.js +0 -164
  207. package/lib/documents/providers/process.js.map +0 -1
  208. package/lib/documents/providers/registry.js +0 -152
  209. package/lib/documents/providers/registry.js.map +0 -1
  210. package/lib/documents/providers/shared.js +0 -75
  211. package/lib/documents/providers/shared.js.map +0 -1
  212. package/lib/documents/runtime.js +0 -114
  213. package/lib/documents/runtime.js.map +0 -1
  214. package/lib/documents/security/file-types.js +0 -188
  215. package/lib/documents/security/file-types.js.map +0 -1
  216. package/lib/documents/security/limits.js +0 -78
  217. package/lib/documents/security/limits.js.map +0 -1
  218. package/lib/documents/security/mime.js +0 -43
  219. package/lib/documents/security/mime.js.map +0 -1
  220. package/lib/documents/security/paths.js +0 -133
  221. package/lib/documents/security/paths.js.map +0 -1
  222. package/lib/documents/templates/registry.js +0 -147
  223. package/lib/documents/templates/registry.js.map +0 -1
  224. package/lib/documents/templates/resolver.js +0 -59
  225. package/lib/documents/templates/resolver.js.map +0 -1
  226. package/lib/documents/tools/convert.js +0 -125
  227. package/lib/documents/tools/convert.js.map +0 -1
  228. package/lib/documents/tools/create.js +0 -187
  229. package/lib/documents/tools/create.js.map +0 -1
  230. package/lib/documents/tools/index.js +0 -41
  231. package/lib/documents/tools/index.js.map +0 -1
  232. package/lib/documents/tools/inspect.js +0 -135
  233. package/lib/documents/tools/inspect.js.map +0 -1
  234. package/lib/documents/tools/shared.js +0 -88
  235. package/lib/documents/tools/shared.js.map +0 -1
  236. package/lib/documents/tools/to-markdown.js +0 -125
  237. package/lib/documents/tools/to-markdown.js.map +0 -1
  238. package/lib/documents/types.js +0 -12
  239. package/lib/documents/types.js.map +0 -1
  240. package/lib/types/client/settings/sections/documents.d.ts +0 -13
  241. package/lib/types/documents/artifacts/ids.d.ts +0 -14
  242. package/lib/types/documents/artifacts/manifest.d.ts +0 -32
  243. package/lib/types/documents/artifacts/store.d.ts +0 -67
  244. package/lib/types/documents/capabilities.d.ts +0 -32
  245. package/lib/types/documents/config.d.ts +0 -27
  246. package/lib/types/documents/defaults.d.ts +0 -161
  247. package/lib/types/documents/errors.d.ts +0 -42
  248. package/lib/types/documents/index.d.ts +0 -63
  249. package/lib/types/documents/inspect/facts.d.ts +0 -43
  250. package/lib/types/documents/inspect/zip.d.ts +0 -28
  251. package/lib/types/documents/markdown/directives.d.ts +0 -39
  252. package/lib/types/documents/markdown/frontmatter.d.ts +0 -15
  253. package/lib/types/documents/markdown/normalize.d.ts +0 -30
  254. package/lib/types/documents/orchestrator/assets.d.ts +0 -55
  255. package/lib/types/documents/orchestrator/convert-document.d.ts +0 -25
  256. package/lib/types/documents/orchestrator/create-document.d.ts +0 -18
  257. package/lib/types/documents/orchestrator/extract-document.d.ts +0 -24
  258. package/lib/types/documents/orchestrator/inspect-document.d.ts +0 -12
  259. package/lib/types/documents/orchestrator/runtime-deps.d.ts +0 -43
  260. package/lib/types/documents/orchestrator/scope.d.ts +0 -52
  261. package/lib/types/documents/providers/docling.d.ts +0 -54
  262. package/lib/types/documents/providers/libreoffice.d.ts +0 -40
  263. package/lib/types/documents/providers/markitdown.d.ts +0 -28
  264. package/lib/types/documents/providers/pandoc.d.ts +0 -42
  265. package/lib/types/documents/providers/process.d.ts +0 -54
  266. package/lib/types/documents/providers/registry.d.ts +0 -68
  267. package/lib/types/documents/providers/shared.d.ts +0 -27
  268. package/lib/types/documents/runtime.d.ts +0 -59
  269. package/lib/types/documents/security/file-types.d.ts +0 -39
  270. package/lib/types/documents/security/limits.d.ts +0 -24
  271. package/lib/types/documents/security/mime.d.ts +0 -13
  272. package/lib/types/documents/security/paths.d.ts +0 -38
  273. package/lib/types/documents/templates/registry.d.ts +0 -50
  274. package/lib/types/documents/templates/resolver.d.ts +0 -30
  275. package/lib/types/documents/tools/convert.d.ts +0 -9
  276. package/lib/types/documents/tools/create.d.ts +0 -14
  277. package/lib/types/documents/tools/index.d.ts +0 -33
  278. package/lib/types/documents/tools/inspect.d.ts +0 -9
  279. package/lib/types/documents/tools/shared.d.ts +0 -77
  280. package/lib/types/documents/tools/to-markdown.d.ts +0 -12
  281. package/lib/types/documents/types.d.ts +0 -294
@@ -0,0 +1,379 @@
1
+ import { normalizeSkillOverride, resolveSkillVisibility, skillHealth, } from "./skill-metadata.js";
2
+ const CAPABILITY_ID = /^[a-zA-Z0-9][a-zA-Z0-9._:/-]{0,199}$/u;
3
+ const SUBROLE_ID = /^[a-z0-9][a-z0-9-]{0,63}$/u;
4
+ function uniqueIds(values, label) {
5
+ const result = [
6
+ ...new Set(values.map((value) => {
7
+ if (typeof value !== "string") {
8
+ throw new TypeError(`${label} must contain strings`);
9
+ }
10
+ return value.trim();
11
+ })),
12
+ ].filter(Boolean);
13
+ if (result.some((value) => !CAPABILITY_ID.test(value))) {
14
+ throw new TypeError(`${label} contains an invalid capability id`);
15
+ }
16
+ return Object.freeze(result);
17
+ }
18
+ /**
19
+ * Normalize one Tool selection, accepting the pre-split flat list.
20
+ *
21
+ * A flat list predates skill grants and can only mean "always visible": the
22
+ * legacy reading is the narrower one, so an upgraded deployment never hands
23
+ * out a tool it did not hand out before.
24
+ * @param value - split selection, legacy string list, or nothing.
25
+ * @param label - prefix for validation errors.
26
+ */
27
+ export function normalizeToolSelection(value, label = "tools") {
28
+ if (Array.isArray(value)) {
29
+ return Object.freeze({
30
+ always: uniqueIds(value, label),
31
+ skillGrantable: Object.freeze([]),
32
+ });
33
+ }
34
+ const selection = value;
35
+ return Object.freeze({
36
+ always: uniqueIds(selection?.always ?? [], `${label}.always`),
37
+ skillGrantable: uniqueIds(selection?.skillGrantable ?? [], `${label}.skillGrantable`),
38
+ });
39
+ }
40
+ export function normalizeCapabilitySelection(value) {
41
+ return Object.freeze({
42
+ tools: normalizeToolSelection(value?.tools),
43
+ skills: uniqueIds(value?.skills ?? [], "skills"),
44
+ ...(value?.mcpServers === undefined
45
+ ? {}
46
+ : { mcpServers: uniqueIds(value.mcpServers, "mcpServers") }),
47
+ ...(value?.knowledgeSources === undefined
48
+ ? {}
49
+ : {
50
+ knowledgeSources: uniqueIds(value.knowledgeSources, "knowledgeSources"),
51
+ }),
52
+ ...(value?.promptAdditions === undefined
53
+ ? {}
54
+ : {
55
+ promptAdditions: Object.freeze(value.promptAdditions
56
+ .map((entry) => entry.trim())
57
+ .filter(Boolean)
58
+ .slice(0, 32)),
59
+ }),
60
+ });
61
+ }
62
+ export function normalizeSubrole(value) {
63
+ const id = value.id.trim().toLowerCase();
64
+ const name = value.name.trim();
65
+ const description = value.description?.trim();
66
+ if (!SUBROLE_ID.test(id)) {
67
+ throw new TypeError("subrole id must use lowercase letters, digits and hyphens");
68
+ }
69
+ if (name === "" || name.length > 100) {
70
+ throw new TypeError("subrole name must contain 1-100 characters");
71
+ }
72
+ if ((description?.length ?? 0) > 500) {
73
+ throw new TypeError("subrole description must be at most 500 characters");
74
+ }
75
+ const icon = value.ui?.icon?.trim();
76
+ const accent = value.ui?.accent?.trim();
77
+ return Object.freeze({
78
+ id,
79
+ name,
80
+ ...(description === undefined || description === "" ? {} : { description }),
81
+ enabled: value.enabled === true,
82
+ capabilities: normalizeCapabilitySelection(value.capabilities),
83
+ ...(icon === undefined && accent === undefined
84
+ ? {}
85
+ : {
86
+ ui: Object.freeze({
87
+ ...(icon === undefined || icon === "" ? {} : { icon }),
88
+ ...(accent === undefined || accent === "" ? {} : { accent }),
89
+ }),
90
+ }),
91
+ });
92
+ }
93
+ export function normalizeSkillOverrides(value) {
94
+ const overrides = (value ?? []).map(normalizeSkillOverride);
95
+ if (new Set(overrides.map(({ skillName }) => skillName)).size !==
96
+ overrides.length) {
97
+ throw new TypeError("a skill may have only one assignment override");
98
+ }
99
+ return Object.freeze(overrides);
100
+ }
101
+ export function normalizeCapabilityConfig(value) {
102
+ if (value.version !== 1 || !Array.isArray(value.subroles)) {
103
+ throw new TypeError("capability configuration version 1 is required");
104
+ }
105
+ const subroles = value.subroles.map(normalizeSubrole);
106
+ if (subroles.length === 0) {
107
+ throw new TypeError("at least one QA subrole is required");
108
+ }
109
+ if (new Set(subroles.map(({ id }) => id)).size !== subroles.length) {
110
+ throw new TypeError("subrole ids must be unique");
111
+ }
112
+ if (!subroles.some(({ enabled }) => enabled)) {
113
+ throw new TypeError("at least one QA subrole must be enabled");
114
+ }
115
+ return Object.freeze({
116
+ version: 1,
117
+ common: normalizeCapabilitySelection(value.common),
118
+ subroles: Object.freeze(subroles),
119
+ skillOverrides: normalizeSkillOverrides(value.skillOverrides),
120
+ });
121
+ }
122
+ export function defaultCapabilityConfig() {
123
+ return normalizeCapabilityConfig({
124
+ version: 1,
125
+ common: { tools: { always: [], skillGrantable: [] }, skills: [] },
126
+ subroles: [
127
+ {
128
+ id: "general",
129
+ name: "Общий",
130
+ description: "Базовый профиль QA-ассистента",
131
+ enabled: true,
132
+ capabilities: {
133
+ tools: { always: [], skillGrantable: [] },
134
+ skills: [],
135
+ },
136
+ },
137
+ ],
138
+ skillOverrides: [],
139
+ });
140
+ }
141
+ export function enabledSubroles(config) {
142
+ return config.subroles.filter(({ enabled }) => enabled);
143
+ }
144
+ export function enabledSubroleIds(config) {
145
+ return enabledSubroles(config).map(({ id }) => id);
146
+ }
147
+ /** The Common and subrole Tool selections that apply to one subrole. */
148
+ export function roleToolSelection(config, subroleId) {
149
+ const role = config.subroles.find((candidate) => candidate.id === subroleId && candidate.enabled);
150
+ if (role === undefined)
151
+ throw new TypeError("QA subrole is unavailable");
152
+ return Object.freeze({
153
+ always: uniqueIds([...config.common.tools.always, ...role.capabilities.tools.always], "tools.always"),
154
+ skillGrantable: uniqueIds([
155
+ ...config.common.tools.skillGrantable,
156
+ ...role.capabilities.tools.skillGrantable,
157
+ ], "tools.skillGrantable"),
158
+ });
159
+ }
160
+ /** The ceiling that bounds what one activated skill may add to the toolset. */
161
+ export function roleGrantCeiling(config, subroleId) {
162
+ return roleToolSelection(config, subroleId).skillGrantable;
163
+ }
164
+ /** Missing assignments migrate to the first enabled role, never to all roles. */
165
+ export function normalizeUserAccess(value, config) {
166
+ const enabled = enabledSubroles(config);
167
+ const enabledIds = new Set(enabled.map(({ id }) => id));
168
+ const fallback = enabled[0]?.id;
169
+ if (fallback === undefined)
170
+ throw new TypeError("no enabled QA subrole");
171
+ const allowed = [
172
+ ...new Set((value?.allowedSubroles ?? []).filter((id) => enabledIds.has(id))),
173
+ ];
174
+ if (allowed.length === 0)
175
+ allowed.push(fallback);
176
+ const requestedDefault = value?.defaultSubrole;
177
+ const defaultSubrole = requestedDefault !== undefined && allowed.includes(requestedDefault)
178
+ ? requestedDefault
179
+ : allowed[0];
180
+ return Object.freeze({
181
+ allowedSubroles: Object.freeze(allowed),
182
+ defaultSubrole,
183
+ });
184
+ }
185
+ function available(values, installed) {
186
+ return Object.freeze(values.filter((value) => installed.has(value)));
187
+ }
188
+ function missing(values, installed) {
189
+ return Object.freeze(values.filter((value) => !installed.has(value)));
190
+ }
191
+ /**
192
+ * Skills one subrole may see, and the reason each one is there.
193
+ *
194
+ * Declared skills come from their own SKILL.md audience, managed skills from
195
+ * the administrator's Common and role lists. Both are still subject to the
196
+ * administrator overlay, and an explicit withdrawal beats either source.
197
+ */
198
+ function resolveVisibleSkills(config, role, systemSkills, metadata) {
199
+ const overrides = new Map(config.skillOverrides.map((override) => [override.skillName, override]));
200
+ const enabled = enabledSubroleIds(config);
201
+ const declared = [];
202
+ const withdrawn = new Set();
203
+ for (const [name, descriptor] of metadata) {
204
+ const visibility = resolveSkillVisibility(descriptor, overrides.get(name), enabled);
205
+ if (visibility.visibleTo.includes(role.id))
206
+ declared.push(name);
207
+ if (visibility.disabled || visibility.removedByAdmin.includes(role.id)) {
208
+ withdrawn.add(name);
209
+ }
210
+ }
211
+ const managed = [
212
+ ...systemSkills,
213
+ ...config.common.skills,
214
+ ...role.capabilities.skills,
215
+ ];
216
+ return {
217
+ visible: [
218
+ ...new Set([...managed, ...declared].filter((name) => !withdrawn.has(name))),
219
+ ],
220
+ declared,
221
+ };
222
+ }
223
+ export function resolveCapabilityPolicy({ config, subroleId, systemTools, systemSkills, available: installed, skillMetadata, revision, }) {
224
+ const role = config.subroles.find((candidate) => candidate.id === subroleId && candidate.enabled);
225
+ if (role === undefined)
226
+ throw new TypeError("QA subrole is unavailable");
227
+ const systemToolIds = uniqueIds(systemTools, "system tools");
228
+ const systemSkillIds = uniqueIds(systemSkills, "system skills");
229
+ const selection = roleToolSelection(config, role.id);
230
+ const configuredBase = [...new Set([...systemToolIds, ...selection.always])];
231
+ const configuredGrantable = selection.skillGrantable;
232
+ const { visible: configuredSkills, declared: declaredSkills } = resolveVisibleSkills(config, role, systemSkillIds, skillMetadata ?? new Map());
233
+ const baseTools = [...available(configuredBase, installed.tools)];
234
+ const grantableTools = available(configuredGrantable.filter((name) => !baseTools.includes(name)), installed.tools);
235
+ const skills = available(configuredSkills, installed.skills);
236
+ const userSkills = available(configuredSkills, installed.userSkills ?? installed.skills);
237
+ // The filtered skill loader is transport for the selected skill set. It is
238
+ // made visible only when at least one model-invocable skill survived.
239
+ if (skills.length > 0 &&
240
+ installed.tools.has("skill") &&
241
+ !baseTools.includes("skill")) {
242
+ baseTools.push("skill");
243
+ }
244
+ return Object.freeze({
245
+ subroleId: role.id,
246
+ tools: Object.freeze([...new Set(baseTools)]),
247
+ grantableTools,
248
+ skills,
249
+ userSkills,
250
+ sources: Object.freeze({
251
+ systemTools: available(systemToolIds, installed.tools),
252
+ commonTools: available(config.common.tools.always, installed.tools),
253
+ roleTools: available(role.capabilities.tools.always, installed.tools),
254
+ commonGrantableTools: available(config.common.tools.skillGrantable, installed.tools),
255
+ roleGrantableTools: available(role.capabilities.tools.skillGrantable, installed.tools),
256
+ systemSkills: available(systemSkillIds, installed.skills),
257
+ commonSkills: available(config.common.skills, installed.skills),
258
+ roleSkills: available(role.capabilities.skills, installed.skills),
259
+ declaredSkills: available(declaredSkills, installed.skills),
260
+ }),
261
+ missingTools: missing([...new Set([...configuredBase, ...configuredGrantable])], installed.tools),
262
+ missingSkills: missing(configuredSkills, installed.userSkills ?? installed.skills),
263
+ policyRevision: revision ?? "",
264
+ });
265
+ }
266
+ function roleGrants(input, name, descriptor, visibleTo) {
267
+ const overrides = new Map(input.config.skillOverrides.map((override) => [
268
+ override.skillName,
269
+ override,
270
+ ]));
271
+ const enabled = enabledSubroleIds(input.config);
272
+ return enabled.map((roleId) => {
273
+ const visibility = resolveSkillVisibility(descriptor, overrides.get(name), enabled);
274
+ const ceiling = new Set(roleGrantCeiling(input.config, roleId));
275
+ const grantable = descriptor.requiredTools.filter((tool) => ceiling.has(tool) && input.installedTools.has(tool));
276
+ const unavailable = descriptor.requiredTools.filter((tool) => !grantable.includes(tool));
277
+ return Object.freeze({
278
+ roleId,
279
+ visible: visibleTo.includes(roleId),
280
+ declared: visibility.declaredTo.includes(roleId),
281
+ addedByAdmin: visibility.addedByAdmin.includes(roleId),
282
+ removedByAdmin: visibility.removedByAdmin.includes(roleId),
283
+ disabled: visibility.disabled,
284
+ grantableTools: Object.freeze(grantable),
285
+ unavailableTools: Object.freeze(unavailable),
286
+ });
287
+ });
288
+ }
289
+ /**
290
+ * Project every skill for the administration surface.
291
+ *
292
+ * The declared audience is reported next to the effective one, so an
293
+ * administrator can see which roles a skill asked for and which it got.
294
+ * @param input - configuration, resolved metadata and the installed catalog.
295
+ */
296
+ export function resolveSkillAccess(input) {
297
+ const rowByName = new Map(input.rows.map((row) => [row.id, row]));
298
+ const enabled = enabledSubroleIds(input.config);
299
+ const overrides = new Map(input.config.skillOverrides.map((override) => [
300
+ override.skillName,
301
+ override,
302
+ ]));
303
+ const names = [
304
+ ...new Set([...input.descriptors.keys(), ...rowByName.keys()]),
305
+ ].sort((left, right) => left.localeCompare(right));
306
+ const access = names.map((name) => {
307
+ const descriptor = input.descriptors.get(name);
308
+ const row = rowByName.get(name);
309
+ const overridesEntry = overrides.get(name);
310
+ if (descriptor === undefined) {
311
+ // Retained selection: the skill is configured but no longer discovered.
312
+ const empty = Object.freeze({
313
+ name,
314
+ audience: Object.freeze({ type: "unassigned" }),
315
+ requiredTools: Object.freeze([]),
316
+ requireAll: false,
317
+ lifecycle: "session",
318
+ schemaVersion: 0,
319
+ declared: false,
320
+ warnings: Object.freeze([]),
321
+ });
322
+ return Object.freeze({
323
+ name,
324
+ ...(row?.description === undefined
325
+ ? {}
326
+ : { description: row.description }),
327
+ source: row?.source ?? { kind: "plugin" },
328
+ status: "missing",
329
+ descriptor: empty,
330
+ visibleTo: Object.freeze([]),
331
+ disabled: overridesEntry?.disabled === true,
332
+ forceCommon: overridesEntry?.forceCommon === true,
333
+ overridden: overridesEntry !== undefined,
334
+ health: "unassigned",
335
+ tools: Object.freeze([]),
336
+ roles: Object.freeze([]),
337
+ });
338
+ }
339
+ const visibility = resolveSkillVisibility(descriptor, overridesEntry, enabled);
340
+ const grants = roleGrants(input, name, descriptor, visibility.visibleTo);
341
+ const toolIds = [...new Set(descriptor.requiredTools)];
342
+ const tools = toolIds.map((id) => {
343
+ const installed = input.installedTools.has(id);
344
+ const grantableBy = grants
345
+ .filter(({ visible, grantableTools }) => visible && grantableTools.includes(id))
346
+ .map(({ roleId }) => roleId);
347
+ const blockedFor = grants
348
+ .filter(({ visible, grantableTools }) => visible && !grantableTools.includes(id))
349
+ .map(({ roleId }) => roleId);
350
+ return Object.freeze({
351
+ id,
352
+ installed,
353
+ grantableBy: Object.freeze(grantableBy),
354
+ blockedFor: Object.freeze(blockedFor),
355
+ });
356
+ });
357
+ return Object.freeze({
358
+ name,
359
+ ...(row?.description === undefined
360
+ ? {}
361
+ : { description: row.description }),
362
+ source: row?.source ?? { kind: "runtime" },
363
+ status: row?.status ?? "available",
364
+ descriptor,
365
+ visibleTo: visibility.visibleTo,
366
+ disabled: visibility.disabled,
367
+ forceCommon: overridesEntry?.forceCommon === true,
368
+ overridden: visibility.overridden,
369
+ health: skillHealth(descriptor, tools.filter(({ grantableBy }) => grantableBy.length > 0).length, tools.filter(({ grantableBy }) => grantableBy.length === 0).length, visibility.visibleTo),
370
+ tools: Object.freeze(tools),
371
+ roles: grants,
372
+ });
373
+ });
374
+ // Skills that already have an audience come first; the rest is alphabetical.
375
+ return Object.freeze(access.sort((left, right) => Number(left.health === "unassigned") -
376
+ Number(right.health === "unassigned") ||
377
+ left.name.localeCompare(right.name)));
378
+ }
379
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/access/model.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,195 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { mkdirSync, readFileSync, renameSync, statSync, writeFileSync, } from "node:fs";
3
+ import path from "node:path";
4
+ import { defaultCapabilityConfig, normalizeCapabilityConfig, normalizeCapabilitySelection, normalizeSubrole, } from "./model.js";
5
+ import { normalizeSkillOverride } from "./skill-metadata.js";
6
+ const MAX_AUDIT_EVENTS = 1_000;
7
+ function auditSnapshot(value) {
8
+ return JSON.stringify(value);
9
+ }
10
+ export function defaultCapabilityFilePath() {
11
+ const home = process.env.DSH_HOME?.trim();
12
+ return path.join(home !== undefined && home !== "" ? home : process.cwd(), "qa-capability-policies.json");
13
+ }
14
+ function stamp(filePath) {
15
+ const stat = statSync(filePath);
16
+ return { mtimeMs: stat.mtimeMs, size: stat.size };
17
+ }
18
+ function same(left, right) {
19
+ return left?.mtimeMs === right.mtimeMs && left.size === right.size;
20
+ }
21
+ function initialFile() {
22
+ return { version: 1, config: defaultCapabilityConfig(), audit: [] };
23
+ }
24
+ /** Atomic, externally reloadable source of truth for roles and their audit. */
25
+ export class QaRoleRepository {
26
+ filePath;
27
+ file;
28
+ fileStamp;
29
+ constructor(filePath = defaultCapabilityFilePath()) {
30
+ this.filePath = filePath;
31
+ this.file = this.load();
32
+ }
33
+ snapshot() {
34
+ this.reload();
35
+ return this.file.config;
36
+ }
37
+ audit() {
38
+ this.reload();
39
+ return this.file.audit;
40
+ }
41
+ create(actorId, input) {
42
+ const role = normalizeSubrole(input);
43
+ const before = this.snapshot();
44
+ if (before.subroles.some(({ id }) => id === role.id)) {
45
+ throw new TypeError(`QA subrole "${role.id}" already exists`);
46
+ }
47
+ this.replace(actorId, "subrole.created", role.id, before, normalizeCapabilityConfig({
48
+ ...before,
49
+ subroles: [...before.subroles, role],
50
+ }));
51
+ return role;
52
+ }
53
+ update(actorId, id, input) {
54
+ const role = normalizeSubrole(input);
55
+ if (role.id !== id)
56
+ throw new TypeError("subrole id is immutable");
57
+ const before = this.snapshot();
58
+ if (!before.subroles.some((candidate) => candidate.id === id)) {
59
+ throw new TypeError(`QA subrole "${id}" does not exist`);
60
+ }
61
+ const after = normalizeCapabilityConfig({
62
+ ...before,
63
+ subroles: before.subroles.map((candidate) => candidate.id === id ? role : candidate),
64
+ });
65
+ this.replace(actorId, "subrole.updated", id, before, after);
66
+ return role;
67
+ }
68
+ delete(actorId, id) {
69
+ const before = this.snapshot();
70
+ if (!before.subroles.some((candidate) => candidate.id === id)) {
71
+ throw new TypeError(`QA subrole "${id}" does not exist`);
72
+ }
73
+ const after = normalizeCapabilityConfig({
74
+ ...before,
75
+ subroles: before.subroles.filter((candidate) => candidate.id !== id),
76
+ });
77
+ this.replace(actorId, "subrole.deleted", id, before, after);
78
+ }
79
+ updateCommon(actorId, input) {
80
+ const before = this.snapshot();
81
+ const common = normalizeCapabilitySelection(input);
82
+ const after = normalizeCapabilityConfig({ ...before, common });
83
+ this.replace(actorId, "common.updated", undefined, before, after);
84
+ return common;
85
+ }
86
+ /**
87
+ * Replace one skill's administrator overlay.
88
+ *
89
+ * An overlay with nothing left to declare is removed outright, so clearing a
90
+ * row in the administration surface leaves the file as if it was never set.
91
+ * @param actorId - the administrator performing the change.
92
+ * @param input - the overlay as edited in the browser.
93
+ * @returns every overlay in force after the change.
94
+ */
95
+ updateSkillOverride(actorId, input) {
96
+ const before = this.snapshot();
97
+ const override = normalizeSkillOverride(input);
98
+ const cleared = override.addToSubroles === undefined &&
99
+ override.removeFromSubroles === undefined &&
100
+ override.forceCommon !== true &&
101
+ override.disabled !== true;
102
+ const remaining = before.skillOverrides.filter(({ skillName }) => skillName !== override.skillName);
103
+ const after = normalizeCapabilityConfig({
104
+ ...before,
105
+ skillOverrides: cleared ? remaining : [...remaining, override],
106
+ });
107
+ this.replace(actorId, "skill.assignment-updated", override.skillName, before, after);
108
+ return after.skillOverrides;
109
+ }
110
+ recordAssignment(actorId, targetId, before, after) {
111
+ this.reload();
112
+ this.persist({
113
+ ...this.file,
114
+ audit: this.appendAudit("assignment.updated", actorId, targetId, before, after),
115
+ });
116
+ }
117
+ replace(actorId, action, targetId, before, after) {
118
+ this.persist({
119
+ version: 1,
120
+ config: after,
121
+ audit: this.appendAudit(action, actorId, targetId, before, after),
122
+ });
123
+ }
124
+ appendAudit(action, actorId, targetId, before, after) {
125
+ return [
126
+ ...this.file.audit,
127
+ {
128
+ timestamp: new Date().toISOString(),
129
+ actorId,
130
+ action,
131
+ ...(targetId === undefined ? {} : { targetId }),
132
+ before: auditSnapshot(before),
133
+ after: auditSnapshot(after),
134
+ },
135
+ ].slice(-MAX_AUDIT_EVENTS);
136
+ }
137
+ reload() {
138
+ let current;
139
+ try {
140
+ current = stamp(this.filePath);
141
+ }
142
+ catch {
143
+ return;
144
+ }
145
+ if (same(this.fileStamp, current))
146
+ return;
147
+ this.file = this.load();
148
+ }
149
+ load() {
150
+ try {
151
+ const parsed = JSON.parse(readFileSync(this.filePath, "utf8"));
152
+ if (parsed.version !== 1 || !Array.isArray(parsed.audit)) {
153
+ throw new TypeError("unrecognized QA capability policy file");
154
+ }
155
+ this.fileStamp = stamp(this.filePath);
156
+ return {
157
+ version: 1,
158
+ config: normalizeCapabilityConfig(parsed.config),
159
+ audit: Object.freeze(parsed.audit.map((event) => ({
160
+ ...event,
161
+ ...(event.before === undefined
162
+ ? {}
163
+ : {
164
+ before: typeof event.before === "string"
165
+ ? event.before
166
+ : auditSnapshot(event.before),
167
+ }),
168
+ ...(event.after === undefined
169
+ ? {}
170
+ : {
171
+ after: typeof event.after === "string"
172
+ ? event.after
173
+ : auditSnapshot(event.after),
174
+ }),
175
+ }))),
176
+ };
177
+ }
178
+ catch (error) {
179
+ if (error.code !== "ENOENT")
180
+ throw error;
181
+ const created = initialFile();
182
+ this.persist(created);
183
+ return created;
184
+ }
185
+ }
186
+ persist(file) {
187
+ mkdirSync(path.dirname(this.filePath), { recursive: true });
188
+ const temporary = `${this.filePath}.${process.pid}.${randomUUID()}.tmp`;
189
+ writeFileSync(temporary, `${JSON.stringify(file, null, 2)}\n`, "utf8");
190
+ renameSync(temporary, this.filePath);
191
+ this.file = file;
192
+ this.fileStamp = stamp(this.filePath);
193
+ }
194
+ }
195
+ //# sourceMappingURL=role-repository.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"role-repository.js","sourceRoot":"","sources":["../../src/access/role-repository.ts"],"names":[],"mappings":"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"}