@yadsh/dsh-qa-surface 0.7.4 → 0.9.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.
- package/README.md +169 -12
- package/compatibility.json +5 -0
- package/lib/access/capability-catalog.js +32 -3
- package/lib/access/capability-catalog.js.map +1 -1
- package/lib/access/model.js +24 -4
- package/lib/access/model.js.map +1 -1
- package/lib/access/role-repository.js +199 -91
- package/lib/access/role-repository.js.map +1 -1
- package/lib/access/service.js +223 -7
- package/lib/access/service.js.map +1 -1
- package/lib/account-remotes.js +2 -4
- package/lib/account-remotes.js.map +1 -1
- package/lib/accounts/database.js +447 -0
- package/lib/accounts/database.js.map +1 -0
- package/lib/accounts/errors.js.map +1 -1
- package/lib/accounts/file.js +27 -90
- package/lib/accounts/file.js.map +1 -1
- package/lib/accounts/store.js +224 -59
- package/lib/accounts/store.js.map +1 -1
- package/lib/admin/permissions.js +4 -0
- package/lib/admin/permissions.js.map +1 -1
- package/lib/admin/quality-store.js +270 -54
- package/lib/admin/quality-store.js.map +1 -1
- package/lib/admin/service.js +145 -7
- package/lib/admin/service.js.map +1 -1
- package/lib/admin/session-log.js +66 -5
- package/lib/admin/session-log.js.map +1 -1
- package/lib/cli.js +2 -1
- package/lib/cli.js.map +1 -1
- package/lib/client/QaSessionController.js +379 -39
- package/lib/client/QaSessionController.js.map +1 -1
- package/lib/client/QaSurface.js +94 -34
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/QaTranscriptAdapter.js +40 -0
- package/lib/client/QaTranscriptAdapter.js.map +1 -1
- package/lib/client/admin/QaAdmin.js +26 -8
- package/lib/client/admin/QaAdmin.js.map +1 -1
- package/lib/client/admin/{format.js → copy.js} +1 -1
- package/lib/client/admin/copy.js.map +1 -0
- package/lib/client/admin/pages/Conversations.js +34 -8
- package/lib/client/admin/pages/Conversations.js.map +1 -1
- package/lib/client/admin/pages/Overview.js +1 -1
- package/lib/client/admin/pages/Overview.js.map +1 -1
- package/lib/client/admin/pages/Quality.js +1 -1
- package/lib/client/admin/pages/Quality.js.map +1 -1
- package/lib/client/admin/pages/Review.js +1 -1
- package/lib/client/admin/pages/Review.js.map +1 -1
- package/lib/client/admin/pages/Users.js +6 -2
- package/lib/client/admin/pages/Users.js.map +1 -1
- package/lib/client/admin/shared.js +10 -1
- package/lib/client/admin/shared.js.map +1 -1
- package/lib/client/admin/styles.js +2 -0
- package/lib/client/admin/styles.js.map +1 -1
- package/lib/client/audit/QaAuditDialog.js +74 -0
- package/lib/client/audit/QaAuditDialog.js.map +1 -0
- package/lib/client/audit/QaAuditRowBadge.js +17 -0
- package/lib/client/audit/QaAuditRowBadge.js.map +1 -0
- package/lib/client/audit/controller.js +39 -0
- package/lib/client/audit/controller.js.map +1 -0
- package/lib/client/audit/types.js +36 -0
- package/lib/client/audit/types.js.map +1 -0
- package/lib/client/audit/use-chat-audits.js +139 -0
- package/lib/client/audit/use-chat-audits.js.map +1 -0
- package/lib/client/components/Markdown.js +14 -206
- package/lib/client/components/Markdown.js.map +1 -1
- package/lib/client/components/QaChangelog.js +91 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/components/QaComposer.js +63 -3
- package/lib/client/components/QaComposer.js.map +1 -1
- package/lib/client/components/QaHeader.js +1 -3
- package/lib/client/components/QaHeader.js.map +1 -1
- package/lib/client/components/QaMessage.js +25 -4
- package/lib/client/components/QaMessage.js.map +1 -1
- package/lib/client/components/QaQuestions.js +1 -1
- package/lib/client/components/QaQuestions.js.map +1 -1
- package/lib/client/components/QaSidebar.js +17 -3
- package/lib/client/components/QaSidebar.js.map +1 -1
- package/lib/client/components/QaSourcesPanel.js +3 -18
- package/lib/client/components/QaSourcesPanel.js.map +1 -1
- package/lib/client/components/QaWorkGroup.js +4 -8
- package/lib/client/components/QaWorkGroup.js.map +1 -1
- package/lib/client/components/source-icon.js +26 -0
- package/lib/client/components/source-icon.js.map +1 -0
- package/lib/client/components/thinking-phrases.js +2 -11
- package/lib/client/components/thinking-phrases.js.map +1 -1
- package/lib/client/components/use-now.js +21 -0
- package/lib/client/components/use-now.js.map +1 -0
- package/lib/client/index.js +33 -5
- package/lib/client/index.js.map +1 -1
- package/lib/client/lineage.js +18 -0
- package/lib/client/lineage.js.map +1 -0
- package/lib/client/markdown/CodeBlock.js +28 -0
- package/lib/client/markdown/CodeBlock.js.map +1 -0
- package/lib/client/markdown/blocks.js +342 -0
- package/lib/client/markdown/blocks.js.map +1 -0
- package/lib/client/markdown/highlight.js +1089 -0
- package/lib/client/markdown/highlight.js.map +1 -0
- package/lib/client/markdown/inline.js +377 -0
- package/lib/client/markdown/inline.js.map +1 -0
- package/lib/client/markdown/render.js +147 -0
- package/lib/client/markdown/render.js.map +1 -0
- package/lib/client/markdown/source-chip.js +55 -0
- package/lib/client/markdown/source-chip.js.map +1 -0
- package/lib/client/markdown/use-transient-flag.js +27 -0
- package/lib/client/markdown/use-transient-flag.js.map +1 -0
- package/lib/client/project-session-state.js +15 -2
- package/lib/client/project-session-state.js.map +1 -1
- package/lib/client/prompt-content.js +26 -0
- package/lib/client/prompt-content.js.map +1 -1
- package/lib/client/role/RoleSelector.js +11 -2
- package/lib/client/role/RoleSelector.js.map +1 -1
- package/lib/client/role/preview.js +123 -0
- package/lib/client/role/preview.js.map +1 -0
- package/lib/client/settings/card.js +2 -2
- package/lib/client/settings/card.js.map +1 -1
- package/lib/client/settings/sections/lockdown.js +1 -6
- package/lib/client/settings/sections/lockdown.js.map +1 -1
- package/lib/client/settings/sections/slash.js +57 -0
- package/lib/client/settings/sections/slash.js.map +1 -0
- package/lib/client/settings/sections/status.js +9 -1
- package/lib/client/settings/sections/status.js.map +1 -1
- package/lib/client/settings/sections.js +1 -0
- package/lib/client/settings/sections.js.map +1 -1
- package/lib/client/slash/SlashPalette.js +48 -0
- package/lib/client/slash/SlashPalette.js.map +1 -0
- package/lib/client/slash/copy.js +54 -0
- package/lib/client/slash/copy.js.map +1 -0
- package/lib/client/slash/slash-router.js +49 -0
- package/lib/client/slash/slash-router.js.map +1 -0
- package/lib/client/slash/useSlashNavigation.js +95 -0
- package/lib/client/slash/useSlashNavigation.js.map +1 -0
- package/lib/client/styles.js +124 -20
- package/lib/client/styles.js.map +1 -1
- package/lib/client/types.js +11 -0
- package/lib/client/types.js.map +1 -1
- package/lib/client.js +7615 -1567
- package/lib/client.js.map +1 -1
- package/lib/config-resolvers/accounts.js +15 -0
- package/lib/config-resolvers/accounts.js.map +1 -1
- package/lib/config-resolvers/basics.js +11 -2
- package/lib/config-resolvers/basics.js.map +1 -1
- package/lib/config-resolvers/defaults.js +30 -0
- package/lib/config-resolvers/defaults.js.map +1 -1
- package/lib/config-resolvers/lockdown.js +8 -2
- package/lib/config-resolvers/lockdown.js.map +1 -1
- package/lib/config-resolvers/slash-commands.js +60 -0
- package/lib/config-resolvers/slash-commands.js.map +1 -0
- package/lib/config-resolvers/sources.js +16 -0
- package/lib/config-resolvers/sources.js.map +1 -1
- package/lib/config.js +118 -2
- package/lib/config.js.map +1 -1
- package/lib/index.js +183 -11
- package/lib/index.js.map +1 -1
- package/lib/lockdown-policy.js +19 -0
- package/lib/lockdown-policy.js.map +1 -1
- package/lib/personal-skills/service.js +16 -3
- package/lib/personal-skills/service.js.map +1 -1
- package/lib/provenance/host-store.js +25 -4
- package/lib/provenance/host-store.js.map +1 -1
- package/lib/provenance/retention.js +25 -0
- package/lib/provenance/retention.js.map +1 -0
- package/lib/provenance/snapshot-store.js +290 -35
- package/lib/provenance/snapshot-store.js.map +1 -1
- package/lib/questions.js +98 -38
- package/lib/questions.js.map +1 -1
- package/lib/resolve-config.js +5 -0
- package/lib/resolve-config.js.map +1 -1
- package/lib/secure-session.js +139 -21
- package/lib/secure-session.js.map +1 -1
- package/lib/slash/catalog.js +77 -0
- package/lib/slash/catalog.js.map +1 -0
- package/lib/slash/matcher.js +100 -0
- package/lib/slash/matcher.js.map +1 -0
- package/lib/slash/parser.js +79 -0
- package/lib/slash/parser.js.map +1 -0
- package/lib/slash/policy.js +72 -0
- package/lib/slash/policy.js.map +1 -0
- package/lib/slash/remotes.js +272 -0
- package/lib/slash/remotes.js.map +1 -0
- package/lib/typert.host.js +348 -56
- package/lib/typert.remote-client.d.ts +7 -1
- package/lib/typert.remote-client.js +274 -51
- package/lib/types/access/capability-catalog.d.ts +28 -1
- package/lib/types/access/role-repository.d.ts +38 -7
- package/lib/types/access/service.d.ts +106 -3
- package/lib/types/account-remotes.d.ts +8 -4
- package/lib/types/accounts/database.d.ts +84 -0
- package/lib/types/accounts/errors.d.ts +7 -1
- package/lib/types/accounts/file.d.ts +17 -39
- package/lib/types/accounts/store.d.ts +110 -19
- package/lib/types/admin/quality-store.d.ts +38 -2
- package/lib/types/admin/service.d.ts +34 -2
- package/lib/types/admin/session-log.d.ts +65 -1
- package/lib/types/client/QaSessionController.d.ts +84 -2
- package/lib/types/client/QaSurface.d.ts +14 -1
- package/lib/types/client/admin/{format.d.ts → copy.d.ts} +1 -1
- package/lib/types/client/admin/pages/Conversations.d.ts +4 -0
- package/lib/types/client/audit/QaAuditDialog.d.ts +21 -0
- package/lib/types/client/audit/QaAuditRowBadge.d.ts +18 -0
- package/lib/types/client/audit/controller.d.ts +27 -0
- package/lib/types/client/audit/types.d.ts +72 -0
- package/lib/types/client/audit/use-chat-audits.d.ts +20 -0
- package/lib/types/client/components/Markdown.d.ts +7 -8
- package/lib/types/client/components/QaComposer.d.ts +12 -2
- package/lib/types/client/components/QaQuestions.d.ts +7 -0
- package/lib/types/client/components/QaSidebar.d.ts +11 -1
- package/lib/types/client/components/QaSourcesPanel.d.ts +1 -3
- package/lib/types/client/components/source-icon.d.ts +12 -0
- package/lib/types/client/components/use-now.d.ts +8 -0
- package/lib/types/client/lineage.d.ts +15 -0
- package/lib/types/client/markdown/CodeBlock.d.ts +14 -0
- package/lib/types/client/markdown/blocks.d.ts +74 -0
- package/lib/types/client/markdown/highlight.d.ts +29 -0
- package/lib/types/client/markdown/inline.d.ts +40 -0
- package/lib/types/client/markdown/render.d.ts +13 -0
- package/lib/types/client/markdown/source-chip.d.ts +32 -0
- package/lib/types/client/markdown/use-transient-flag.d.ts +12 -0
- package/lib/types/client/project-session-state.d.ts +3 -1
- package/lib/types/client/prompt-content.d.ts +9 -1
- package/lib/types/client/role/RoleSelector.d.ts +11 -1
- package/lib/types/client/role/preview.d.ts +109 -0
- package/lib/types/client/settings/sections/slash.d.ts +16 -0
- package/lib/types/client/settings/sections.d.ts +1 -0
- package/lib/types/client/slash/SlashPalette.d.ts +24 -0
- package/lib/types/client/slash/copy.d.ts +30 -0
- package/lib/types/client/slash/slash-router.d.ts +67 -0
- package/lib/types/client/slash/useSlashNavigation.d.ts +47 -0
- package/lib/types/client/styles.d.ts +9 -0
- package/lib/types/client/types.d.ts +16 -1
- package/lib/types/config-resolvers/slash-commands.d.ts +20 -0
- package/lib/types/index.d.ts +83 -2
- package/lib/types/lockdown-policy.d.ts +16 -0
- package/lib/types/personal-skills/service.d.ts +5 -0
- package/lib/types/provenance/host-store.d.ts +20 -3
- package/lib/types/provenance/retention.d.ts +46 -0
- package/lib/types/provenance/snapshot-store.d.ts +63 -7
- package/lib/types/questions.d.ts +13 -0
- package/lib/types/secure-session.d.ts +27 -1
- package/lib/types/slash/catalog.d.ts +56 -0
- package/lib/types/slash/matcher.d.ts +51 -0
- package/lib/types/slash/parser.d.ts +46 -0
- package/lib/types/slash/policy.d.ts +40 -0
- package/lib/types/slash/remotes.d.ts +35 -0
- package/lib/types/types.d.ts +254 -5
- package/package.json +9 -5
- package/scripts/attach-workspace-sessions.mjs +472 -0
- package/lib/client/admin/format.js.map +0 -1
|
@@ -1,42 +1,107 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import path from "node:path";
|
|
1
|
+
import { readFileSync, renameSync } from "node:fs";
|
|
2
|
+
import { SqliteDatabase, } from "@yadsh/dsh-plugin-kit/sqlite";
|
|
4
3
|
import { defaultCapabilityConfig, normalizeCapabilityConfig, normalizeCapabilitySelection, normalizeSubrole, } from "./model.js";
|
|
5
4
|
import { normalizeSkillOverride } from "./skill-metadata.js";
|
|
6
5
|
const MAX_AUDIT_EVENTS = 1_000;
|
|
6
|
+
const MIGRATIONS = [
|
|
7
|
+
{
|
|
8
|
+
version: 1,
|
|
9
|
+
up: `
|
|
10
|
+
CREATE TABLE role_config (
|
|
11
|
+
id INTEGER PRIMARY KEY CHECK (id = 1),
|
|
12
|
+
json TEXT NOT NULL
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
-- One row per policy change. The trail is bounded by count and not by
|
|
16
|
+
-- age: policies change rarely, and who granted what to whom is worth
|
|
17
|
+
-- keeping exactly as long as the store it replaces did.
|
|
18
|
+
CREATE TABLE role_audit (
|
|
19
|
+
seq INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
20
|
+
timestamp TEXT NOT NULL,
|
|
21
|
+
actor_id TEXT NOT NULL,
|
|
22
|
+
action TEXT NOT NULL,
|
|
23
|
+
target_id TEXT,
|
|
24
|
+
before TEXT,
|
|
25
|
+
after TEXT
|
|
26
|
+
);
|
|
27
|
+
`,
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
/** SQLite hands back null-prototype records; the row shapes describe them. */
|
|
31
|
+
function asRows(value) {
|
|
32
|
+
return value;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* One audit payload as text. Absent or unserializable values become NULL: the
|
|
36
|
+
* trail records that there was nothing to compare, and SQLite has no
|
|
37
|
+
* `undefined` to bind.
|
|
38
|
+
*/
|
|
7
39
|
function auditSnapshot(value) {
|
|
8
|
-
return JSON.stringify(value);
|
|
40
|
+
return JSON.stringify(value) ?? null;
|
|
9
41
|
}
|
|
10
|
-
|
|
42
|
+
function defaultBasePath() {
|
|
11
43
|
const home = process.env.DSH_HOME?.trim();
|
|
12
|
-
return
|
|
44
|
+
return home !== undefined && home !== "" ? home : process.cwd();
|
|
13
45
|
}
|
|
14
|
-
function
|
|
15
|
-
|
|
16
|
-
return { mtimeMs: stat.mtimeMs, size: stat.size };
|
|
46
|
+
export function defaultCapabilityFilePath() {
|
|
47
|
+
return `${defaultBasePath()}/qa-capability-policies.db`;
|
|
17
48
|
}
|
|
18
|
-
|
|
19
|
-
|
|
49
|
+
/** The `.json` sibling of a `.db` path: what a deployment upgraded from. */
|
|
50
|
+
function legacySiblingOf(filePath) {
|
|
51
|
+
return filePath.endsWith(".db")
|
|
52
|
+
? `${filePath.slice(0, -".db".length)}.json`
|
|
53
|
+
: undefined;
|
|
20
54
|
}
|
|
21
|
-
|
|
22
|
-
|
|
55
|
+
/** The pre-SQLite policy file, imported once on first use. */
|
|
56
|
+
export function defaultLegacyCapabilityFilePath() {
|
|
57
|
+
return `${defaultBasePath()}/qa-capability-policies.json`;
|
|
23
58
|
}
|
|
24
|
-
/**
|
|
59
|
+
/**
|
|
60
|
+
* Atomic, externally reloadable source of truth for roles and their audit.
|
|
61
|
+
*
|
|
62
|
+
* The policy is one row and a change appends one row beside it, so an edit
|
|
63
|
+
* writes what it changed instead of rewriting a growing document — the cost of
|
|
64
|
+
* an administrative change no longer depends on how long the deployment has
|
|
65
|
+
* been administering anything.
|
|
66
|
+
*
|
|
67
|
+
* Only the configuration is cached. An audit trail carries the full policy
|
|
68
|
+
* that preceded each change, so reading it is reserved for the callers that
|
|
69
|
+
* ask for it, and dropped whenever another process writes.
|
|
70
|
+
*/
|
|
25
71
|
export class QaRoleRepository {
|
|
26
72
|
filePath;
|
|
27
|
-
|
|
28
|
-
|
|
73
|
+
storage;
|
|
74
|
+
config;
|
|
75
|
+
auditCache;
|
|
76
|
+
observedDataVersion;
|
|
29
77
|
constructor(filePath = defaultCapabilityFilePath()) {
|
|
30
78
|
this.filePath = filePath;
|
|
31
|
-
this.
|
|
79
|
+
this.storage = new SqliteDatabase(filePath, MIGRATIONS);
|
|
80
|
+
this.observedDataVersion = this.readDataVersion();
|
|
81
|
+
try {
|
|
82
|
+
// The pre-SQLite file sat beside the database, so it is looked for as
|
|
83
|
+
// the `.json` sibling of the path this repository was given.
|
|
84
|
+
this.importLegacyFile(legacySiblingOf(filePath) ?? defaultLegacyCapabilityFilePath());
|
|
85
|
+
this.config = this.readConfig();
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
// A store that cannot start must not hold the database open: the caller
|
|
89
|
+
// may retry, and a held handle blocks cleaning up after the failure.
|
|
90
|
+
this.storage.close();
|
|
91
|
+
throw error;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
close() {
|
|
95
|
+
this.storage.close();
|
|
32
96
|
}
|
|
33
97
|
snapshot() {
|
|
34
|
-
this.
|
|
35
|
-
return this.
|
|
98
|
+
this.refresh();
|
|
99
|
+
return this.config;
|
|
36
100
|
}
|
|
37
101
|
audit() {
|
|
38
|
-
this.
|
|
39
|
-
|
|
102
|
+
this.refresh();
|
|
103
|
+
this.auditCache ??= this.readAudit();
|
|
104
|
+
return this.auditCache;
|
|
40
105
|
}
|
|
41
106
|
create(actorId, input) {
|
|
42
107
|
const role = normalizeSubrole(input);
|
|
@@ -87,7 +152,7 @@ export class QaRoleRepository {
|
|
|
87
152
|
* Replace one skill's administrator overlay.
|
|
88
153
|
*
|
|
89
154
|
* An overlay with nothing left to declare is removed outright, so clearing a
|
|
90
|
-
* row in the administration surface leaves the
|
|
155
|
+
* row in the administration surface leaves the store as if it was never set.
|
|
91
156
|
* @param actorId - the administrator performing the change.
|
|
92
157
|
* @param input - the overlay as edited in the browser.
|
|
93
158
|
* @returns every overlay in force after the change.
|
|
@@ -108,88 +173,131 @@ export class QaRoleRepository {
|
|
|
108
173
|
return after.skillOverrides;
|
|
109
174
|
}
|
|
110
175
|
recordAssignment(actorId, targetId, before, after) {
|
|
111
|
-
this.
|
|
112
|
-
this.
|
|
113
|
-
|
|
114
|
-
audit: this.appendAudit("assignment.updated", actorId, targetId, before, after),
|
|
176
|
+
this.refresh();
|
|
177
|
+
this.storage.transaction(() => {
|
|
178
|
+
this.appendAudit("assignment.updated", actorId, targetId, before, after);
|
|
115
179
|
});
|
|
116
180
|
}
|
|
117
181
|
replace(actorId, action, targetId, before, after) {
|
|
118
|
-
this.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
182
|
+
this.storage.transaction(() => {
|
|
183
|
+
this.writeConfig(after);
|
|
184
|
+
this.appendAudit(action, actorId, targetId, before, after);
|
|
185
|
+
this.config = after;
|
|
122
186
|
});
|
|
123
187
|
}
|
|
188
|
+
/** Append one change and trim the trail to its newest events. */
|
|
124
189
|
appendAudit(action, actorId, targetId, before, after) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
190
|
+
this.storage.db
|
|
191
|
+
.prepare(`INSERT INTO role_audit
|
|
192
|
+
(timestamp, actor_id, action, target_id, before, after)
|
|
193
|
+
VALUES (?, ?, ?, ?, ?, ?)`)
|
|
194
|
+
.run(new Date().toISOString(), actorId, action, targetId ?? null, auditSnapshot(before), auditSnapshot(after));
|
|
195
|
+
this.storage.db
|
|
196
|
+
.prepare("DELETE FROM role_audit WHERE seq <= (SELECT MAX(seq) - ? FROM role_audit)")
|
|
197
|
+
.run(MAX_AUDIT_EVENTS);
|
|
198
|
+
this.auditCache = undefined;
|
|
199
|
+
}
|
|
200
|
+
writeConfig(config) {
|
|
201
|
+
this.storage.db
|
|
202
|
+
.prepare(`INSERT INTO role_config (id, json) VALUES (1, ?)
|
|
203
|
+
ON CONFLICT(id) DO UPDATE SET json = excluded.json`)
|
|
204
|
+
.run(JSON.stringify(config));
|
|
205
|
+
}
|
|
206
|
+
readConfig() {
|
|
207
|
+
const row = this.storage.db
|
|
208
|
+
.prepare("SELECT json FROM role_config WHERE id = 1")
|
|
209
|
+
.get();
|
|
210
|
+
return row === undefined
|
|
211
|
+
? defaultCapabilityConfig()
|
|
212
|
+
: normalizeCapabilityConfig(JSON.parse(row.json));
|
|
213
|
+
}
|
|
214
|
+
readAudit() {
|
|
215
|
+
return Object.freeze(asRows(this.storage.db.prepare("SELECT * FROM role_audit ORDER BY seq").all()).map((row) => ({
|
|
216
|
+
timestamp: row.timestamp,
|
|
217
|
+
actorId: row.actor_id,
|
|
218
|
+
action: row.action,
|
|
219
|
+
...(row.target_id === null ? {} : { targetId: row.target_id }),
|
|
220
|
+
...(row.before === null ? {} : { before: row.before }),
|
|
221
|
+
...(row.after === null ? {} : { after: row.after }),
|
|
222
|
+
})));
|
|
223
|
+
}
|
|
224
|
+
readDataVersion() {
|
|
225
|
+
const row = this.storage.db.prepare("PRAGMA data_version").get();
|
|
226
|
+
return row.data_version;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Re-read the policy when another process wrote it. The `qa-admin` surfaces
|
|
230
|
+
* and this store share one database, so a configuration an administrator
|
|
231
|
+
* just saved must be the one the next policy resolution sees.
|
|
232
|
+
*/
|
|
233
|
+
refresh() {
|
|
234
|
+
const version = this.readDataVersion();
|
|
235
|
+
if (version === this.observedDataVersion)
|
|
146
236
|
return;
|
|
147
|
-
this.
|
|
237
|
+
this.observedDataVersion = version;
|
|
238
|
+
this.config = this.readConfig();
|
|
239
|
+
this.auditCache = undefined;
|
|
148
240
|
}
|
|
149
|
-
|
|
241
|
+
/**
|
|
242
|
+
* Import a pre-SQLite `qa-capability-policies.json` exactly once, then rename
|
|
243
|
+
* it aside. A configuration the database already holds wins: a leftover file
|
|
244
|
+
* must not silently revert an administrator's policy.
|
|
245
|
+
*/
|
|
246
|
+
importLegacyFile(legacyFilePath) {
|
|
247
|
+
let raw;
|
|
150
248
|
try {
|
|
151
|
-
|
|
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
|
-
};
|
|
249
|
+
raw = readFileSync(legacyFilePath, "utf8");
|
|
177
250
|
}
|
|
178
251
|
catch (error) {
|
|
179
|
-
if (error.code
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
252
|
+
if (error.code === "ENOENT")
|
|
253
|
+
return;
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
const parsed = JSON.parse(raw);
|
|
257
|
+
if (typeof parsed !== "object" ||
|
|
258
|
+
parsed === null ||
|
|
259
|
+
parsed.version !== 1 ||
|
|
260
|
+
!Array.isArray(parsed.audit)) {
|
|
261
|
+
throw new Error(`qa-capability-policies: ${legacyFilePath} is not a recognizable policy file; refusing to import it`);
|
|
184
262
|
}
|
|
263
|
+
const file = parsed;
|
|
264
|
+
const existing = this.storage.db
|
|
265
|
+
.prepare("SELECT json FROM role_config WHERE id = 1")
|
|
266
|
+
.get();
|
|
267
|
+
if (existing !== undefined)
|
|
268
|
+
return;
|
|
269
|
+
this.storage.transaction(() => {
|
|
270
|
+
this.writeConfig(normalizeCapabilityConfig(file.config));
|
|
271
|
+
const insert = this.storage.db.prepare(`INSERT INTO role_audit
|
|
272
|
+
(timestamp, actor_id, action, target_id, before, after)
|
|
273
|
+
VALUES (?, ?, ?, ?, ?, ?)`);
|
|
274
|
+
for (const event of file.audit) {
|
|
275
|
+
insert.run(event.timestamp, event.actorId, event.action, event.targetId ?? null, event.before === undefined ? null : String(event.before), event.after === undefined ? null : String(event.after));
|
|
276
|
+
}
|
|
277
|
+
this.assertImportArrived(file.audit.length);
|
|
278
|
+
});
|
|
279
|
+
this.config = this.readConfig();
|
|
280
|
+
this.auditCache = undefined;
|
|
281
|
+
this.observedDataVersion = this.readDataVersion();
|
|
282
|
+
renameSync(legacyFilePath, `${legacyFilePath}.migrated-${new Date().toISOString().replace(/[:.]/gu, "-")}`);
|
|
185
283
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
284
|
+
assertImportArrived(expectedAudit) {
|
|
285
|
+
const config = this.storage.db
|
|
286
|
+
.prepare("SELECT COUNT(*) AS count FROM role_config")
|
|
287
|
+
.get();
|
|
288
|
+
const audit = this.storage.db
|
|
289
|
+
.prepare("SELECT COUNT(*) AS count FROM role_audit")
|
|
290
|
+
.get();
|
|
291
|
+
const expectedEvents = Math.min(expectedAudit, MAX_AUDIT_EVENTS);
|
|
292
|
+
const problems = [];
|
|
293
|
+
if (config.count !== 1)
|
|
294
|
+
problems.push("the policy did not arrive");
|
|
295
|
+
if (audit.count !== expectedEvents) {
|
|
296
|
+
problems.push(`expected ${expectedEvents} audit events, imported ${audit.count}`);
|
|
297
|
+
}
|
|
298
|
+
if (problems.length > 0) {
|
|
299
|
+
throw new Error(`qa-capability-policies: importing the pre-SQLite file failed verification (${problems.join("; ")}); the file is left in place and the import was rolled back`);
|
|
300
|
+
}
|
|
193
301
|
}
|
|
194
302
|
}
|
|
195
303
|
//# sourceMappingURL=role-repository.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-repository.js","sourceRoot":"","sources":["../../src/access/role-repository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"role-repository.js","sourceRoot":"","sources":["../../src/access/role-repository.ts"],"names":[],"mappings":"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"}
|