@synoikia/core 0.1.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 (209) hide show
  1. package/LICENSE +21 -0
  2. package/dist/app.d.ts +79 -0
  3. package/dist/app.js +155 -0
  4. package/dist/app.js.map +1 -0
  5. package/dist/approvals/links.d.ts +23 -0
  6. package/dist/approvals/links.js +49 -0
  7. package/dist/approvals/links.js.map +1 -0
  8. package/dist/approvals/service.d.ts +110 -0
  9. package/dist/approvals/service.js +182 -0
  10. package/dist/approvals/service.js.map +1 -0
  11. package/dist/audit-query.d.ts +52 -0
  12. package/dist/audit-query.js +116 -0
  13. package/dist/audit-query.js.map +1 -0
  14. package/dist/audit.d.ts +5 -0
  15. package/dist/audit.js +8 -0
  16. package/dist/audit.js.map +1 -0
  17. package/dist/auth/mcp-auth.d.ts +50 -0
  18. package/dist/auth/mcp-auth.js +160 -0
  19. package/dist/auth/mcp-auth.js.map +1 -0
  20. package/dist/auth/mcp-tokens.d.ts +57 -0
  21. package/dist/auth/mcp-tokens.js +143 -0
  22. package/dist/auth/mcp-tokens.js.map +1 -0
  23. package/dist/auth/oauth.d.ts +188 -0
  24. package/dist/auth/oauth.js +470 -0
  25. package/dist/auth/oauth.js.map +1 -0
  26. package/dist/auth/oidc.d.ts +110 -0
  27. package/dist/auth/oidc.js +221 -0
  28. package/dist/auth/oidc.js.map +1 -0
  29. package/dist/auth/sessions.d.ts +34 -0
  30. package/dist/auth/sessions.js +83 -0
  31. package/dist/auth/sessions.js.map +1 -0
  32. package/dist/auth/throttle.d.ts +31 -0
  33. package/dist/auth/throttle.js +52 -0
  34. package/dist/auth/throttle.js.map +1 -0
  35. package/dist/auth/tokens.d.ts +7 -0
  36. package/dist/auth/tokens.js +40 -0
  37. package/dist/auth/tokens.js.map +1 -0
  38. package/dist/auth/totp.d.ts +14 -0
  39. package/dist/auth/totp.js +81 -0
  40. package/dist/auth/totp.js.map +1 -0
  41. package/dist/auth/users.d.ts +70 -0
  42. package/dist/auth/users.js +296 -0
  43. package/dist/auth/users.js.map +1 -0
  44. package/dist/catalog/groups.d.ts +102 -0
  45. package/dist/catalog/groups.js +363 -0
  46. package/dist/catalog/groups.js.map +1 -0
  47. package/dist/catalog/registry.d.ts +25 -0
  48. package/dist/catalog/registry.js +80 -0
  49. package/dist/catalog/registry.js.map +1 -0
  50. package/dist/catalog/rules.d.ts +128 -0
  51. package/dist/catalog/rules.js +178 -0
  52. package/dist/catalog/rules.js.map +1 -0
  53. package/dist/catalog/sync.d.ts +29 -0
  54. package/dist/catalog/sync.js +222 -0
  55. package/dist/catalog/sync.js.map +1 -0
  56. package/dist/cli.d.ts +3 -0
  57. package/dist/cli.js +83 -0
  58. package/dist/cli.js.map +1 -0
  59. package/dist/config/env.d.ts +40 -0
  60. package/dist/config/env.js +71 -0
  61. package/dist/config/env.js.map +1 -0
  62. package/dist/crypto/index.d.ts +28 -0
  63. package/dist/crypto/index.js +88 -0
  64. package/dist/crypto/index.js.map +1 -0
  65. package/dist/crypto/rotate.d.ts +15 -0
  66. package/dist/crypto/rotate.js +61 -0
  67. package/dist/crypto/rotate.js.map +1 -0
  68. package/dist/db/index.d.ts +17 -0
  69. package/dist/db/index.js +29 -0
  70. package/dist/db/index.js.map +1 -0
  71. package/dist/db/schema.d.ts +4389 -0
  72. package/dist/db/schema.js +372 -0
  73. package/dist/db/schema.js.map +1 -0
  74. package/dist/endpoints/slug.d.ts +3 -0
  75. package/dist/endpoints/slug.js +7 -0
  76. package/dist/endpoints/slug.js.map +1 -0
  77. package/dist/errors.d.ts +16 -0
  78. package/dist/errors.js +29 -0
  79. package/dist/errors.js.map +1 -0
  80. package/dist/events.d.ts +43 -0
  81. package/dist/events.js +16 -0
  82. package/dist/events.js.map +1 -0
  83. package/dist/gate/access.d.ts +47 -0
  84. package/dist/gate/access.js +48 -0
  85. package/dist/gate/access.js.map +1 -0
  86. package/dist/gate/attestation.d.ts +23 -0
  87. package/dist/gate/attestation.js +33 -0
  88. package/dist/gate/attestation.js.map +1 -0
  89. package/dist/gate/canonical.d.ts +3 -0
  90. package/dist/gate/canonical.js +11 -0
  91. package/dist/gate/canonical.js.map +1 -0
  92. package/dist/gate/match.d.ts +67 -0
  93. package/dist/gate/match.js +133 -0
  94. package/dist/gate/match.js.map +1 -0
  95. package/dist/gate/pipeline.d.ts +61 -0
  96. package/dist/gate/pipeline.js +284 -0
  97. package/dist/gate/pipeline.js.map +1 -0
  98. package/dist/gate/preapproval.d.ts +24 -0
  99. package/dist/gate/preapproval.js +48 -0
  100. package/dist/gate/preapproval.js.map +1 -0
  101. package/dist/gate/rate-limit.d.ts +35 -0
  102. package/dist/gate/rate-limit.js +82 -0
  103. package/dist/gate/rate-limit.js.map +1 -0
  104. package/dist/gate/redact.d.ts +23 -0
  105. package/dist/gate/redact.js +87 -0
  106. package/dist/gate/redact.js.map +1 -0
  107. package/dist/http/admin/auth.d.ts +33 -0
  108. package/dist/http/admin/auth.js +338 -0
  109. package/dist/http/admin/auth.js.map +1 -0
  110. package/dist/http/admin/instances.d.ts +5 -0
  111. package/dist/http/admin/instances.js +193 -0
  112. package/dist/http/admin/instances.js.map +1 -0
  113. package/dist/http/admin/system.d.ts +5 -0
  114. package/dist/http/admin/system.js +225 -0
  115. package/dist/http/admin/system.js.map +1 -0
  116. package/dist/http/admin-app.d.ts +9 -0
  117. package/dist/http/admin-app.js +51 -0
  118. package/dist/http/admin-app.js.map +1 -0
  119. package/dist/http/common.d.ts +32 -0
  120. package/dist/http/common.js +80 -0
  121. package/dist/http/common.js.map +1 -0
  122. package/dist/http/mcp/approval-routes.d.ts +11 -0
  123. package/dist/http/mcp/approval-routes.js +117 -0
  124. package/dist/http/mcp/approval-routes.js.map +1 -0
  125. package/dist/http/mcp/endpoint.d.ts +32 -0
  126. package/dist/http/mcp/endpoint.js +293 -0
  127. package/dist/http/mcp/endpoint.js.map +1 -0
  128. package/dist/http/mcp/oauth-routes.d.ts +29 -0
  129. package/dist/http/mcp/oauth-routes.js +465 -0
  130. package/dist/http/mcp/oauth-routes.js.map +1 -0
  131. package/dist/http/mcp/pages.d.ts +63 -0
  132. package/dist/http/mcp/pages.js +200 -0
  133. package/dist/http/mcp/pages.js.map +1 -0
  134. package/dist/http/mcp-app.d.ts +7 -0
  135. package/dist/http/mcp-app.js +30 -0
  136. package/dist/http/mcp-app.js.map +1 -0
  137. package/dist/instances/connection.d.ts +37 -0
  138. package/dist/instances/connection.js +109 -0
  139. package/dist/instances/connection.js.map +1 -0
  140. package/dist/instances/manager.d.ts +313 -0
  141. package/dist/instances/manager.js +600 -0
  142. package/dist/instances/manager.js.map +1 -0
  143. package/dist/instances/settings.d.ts +42 -0
  144. package/dist/instances/settings.js +57 -0
  145. package/dist/instances/settings.js.map +1 -0
  146. package/dist/lenient.d.ts +16 -0
  147. package/dist/lenient.js +51 -0
  148. package/dist/lenient.js.map +1 -0
  149. package/dist/lock.d.ts +28 -0
  150. package/dist/lock.js +77 -0
  151. package/dist/lock.js.map +1 -0
  152. package/dist/main.d.ts +1 -0
  153. package/dist/main.js +38 -0
  154. package/dist/main.js.map +1 -0
  155. package/dist/maintenance.d.ts +10 -0
  156. package/dist/maintenance.js +48 -0
  157. package/dist/maintenance.js.map +1 -0
  158. package/dist/notify/service.d.ts +149 -0
  159. package/dist/notify/service.js +358 -0
  160. package/dist/notify/service.js.map +1 -0
  161. package/dist/plugins/discovery.d.ts +39 -0
  162. package/dist/plugins/discovery.js +157 -0
  163. package/dist/plugins/discovery.js.map +1 -0
  164. package/dist/plugins/minisign.d.ts +25 -0
  165. package/dist/plugins/minisign.js +49 -0
  166. package/dist/plugins/minisign.js.map +1 -0
  167. package/dist/plugins/process.d.ts +55 -0
  168. package/dist/plugins/process.js +162 -0
  169. package/dist/plugins/process.js.map +1 -0
  170. package/dist/plugins/repos.d.ts +198 -0
  171. package/dist/plugins/repos.js +612 -0
  172. package/dist/plugins/repos.js.map +1 -0
  173. package/dist/plugins/supervisor.d.ts +50 -0
  174. package/dist/plugins/supervisor.js +125 -0
  175. package/dist/plugins/supervisor.js.map +1 -0
  176. package/dist/runtime/index.d.ts +28 -0
  177. package/dist/runtime/index.js +248 -0
  178. package/dist/runtime/index.js.map +1 -0
  179. package/dist/sandbox/index.d.ts +53 -0
  180. package/dist/sandbox/index.js +197 -0
  181. package/dist/sandbox/index.js.map +1 -0
  182. package/dist/server.d.ts +16 -0
  183. package/dist/server.js +36 -0
  184. package/dist/server.js.map +1 -0
  185. package/dist/settings.d.ts +43 -0
  186. package/dist/settings.js +99 -0
  187. package/dist/settings.js.map +1 -0
  188. package/dist/testing/index.d.ts +73 -0
  189. package/dist/testing/index.js +174 -0
  190. package/dist/testing/index.js.map +1 -0
  191. package/dist/version.d.ts +2 -0
  192. package/dist/version.js +4 -0
  193. package/dist/version.js.map +1 -0
  194. package/drizzle/0000_init.sql +334 -0
  195. package/drizzle/0001_totp_last_step.sql +1 -0
  196. package/drizzle/0002_access_levels.sql +16 -0
  197. package/drizzle/0003_drop_exclusion_flags.sql +2 -0
  198. package/drizzle/0004_grant_instance_ids.sql +1 -0
  199. package/drizzle/0005_rule_strict_miss.sql +1 -0
  200. package/drizzle/0006_attestation_waived.sql +1 -0
  201. package/drizzle/meta/0000_snapshot.json +2318 -0
  202. package/drizzle/meta/0001_snapshot.json +2325 -0
  203. package/drizzle/meta/0002_snapshot.json +2348 -0
  204. package/drizzle/meta/0003_snapshot.json +2332 -0
  205. package/drizzle/meta/0004_snapshot.json +2339 -0
  206. package/drizzle/meta/0005_snapshot.json +2346 -0
  207. package/drizzle/meta/0006_snapshot.json +2354 -0
  208. package/drizzle/meta/_journal.json +55 -0
  209. package/package.json +58 -0
@@ -0,0 +1,174 @@
1
+ import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import path from 'node:path';
4
+ import { parseManifest } from '@synoikia/plugin-sdk';
5
+ import { and, eq } from 'drizzle-orm';
6
+ import { createAppContext } from '../app.js';
7
+ import { setGroupLevel, updateOperation } from '../catalog/groups.js';
8
+ import { createRule } from '../catalog/rules.js';
9
+ import { loadConfig } from '../config/env.js';
10
+ import { ConflictError } from '../errors.js';
11
+ import { secretFieldNames } from '../instances/connection.js';
12
+ import { auditLog, operations, pendingApprovals, plugins, registryEntries } from '../db/schema.js';
13
+ import { executeCode, searchCode } from '../runtime/index.js';
14
+ /** Copies what a release ships (manifest, package.json, the entry's top-level path) into `root/<id>`. */
15
+ function stagePlugin(pluginDir, manifest, root) {
16
+ const entry = path.join(pluginDir, manifest.entry);
17
+ if (!existsSync(entry)) {
18
+ throw new Error(`${manifest.id}: entry ${manifest.entry} not found in ${pluginDir}. Build the plugin first.`);
19
+ }
20
+ const dest = path.join(root, manifest.id);
21
+ mkdirSync(dest, { recursive: true });
22
+ const top = path.normalize(manifest.entry).split(path.sep)[0];
23
+ for (const name of new Set(['manifest.json', 'package.json', top])) {
24
+ const from = path.join(pluginDir, name);
25
+ if (existsSync(from))
26
+ cpSync(from, path.join(dest, name), { recursive: true });
27
+ }
28
+ return dest;
29
+ }
30
+ export async function startPluginHarness(opts) {
31
+ const manifest = parseManifest(JSON.parse(readFileSync(path.join(opts.pluginDir, 'manifest.json'), 'utf8')));
32
+ const work = mkdtempSync(path.join(tmpdir(), `synoikia-harness-${manifest.id}-`));
33
+ let ctx;
34
+ try {
35
+ const pluginsDir = path.join(work, 'plugins');
36
+ stagePlugin(opts.pluginDir, manifest, pluginsDir);
37
+ ctx = await createAppContext(loadConfig({
38
+ DATA_DIR: path.join(work, 'data'),
39
+ CORE_PLUGINS_DIR: pluginsDir,
40
+ CORE_PLUGINS_AUTOENABLE: 'true',
41
+ }), { memoryDb: true, supervisor: opts.supervisor ?? { initTimeoutMs: 5000, rpcTimeoutMs: 10_000 } });
42
+ const row = ctx.db.select().from(plugins).where(eq(plugins.pluginId, manifest.id)).get();
43
+ if (row?.status !== 'ok') {
44
+ throw new Error(`${manifest.id} was not loaded: ${row ? `${row.status}: ${row.statusError}` : 'not discovered'}`);
45
+ }
46
+ const instanceId = (await ctx.instances.create({ pluginId: manifest.id, slug: opts.slug ?? manifest.id, connection: opts.connection })).id;
47
+ if (opts.sync ?? true)
48
+ await ctx.instances.syncNow(instanceId);
49
+ return harness(ctx, manifest, instanceId, work);
50
+ }
51
+ catch (err) {
52
+ await ctx?.stop();
53
+ rmSync(work, { recursive: true, force: true });
54
+ throw err;
55
+ }
56
+ }
57
+ function harness(ctx, manifest, instanceId, work) {
58
+ const approvalErrors = [];
59
+ const operation = (key) => {
60
+ const op = ctx.db
61
+ .select()
62
+ .from(operations)
63
+ .where(and(eq(operations.instanceId, instanceId), eq(operations.key, key)))
64
+ .get();
65
+ if (!op)
66
+ throw new Error(`No operation ${key} in the synced catalog`);
67
+ return op;
68
+ };
69
+ const caller = (opts = {}) => {
70
+ const onApproval = opts.onApproval;
71
+ return {
72
+ client: { kind: 'mcp_client', id: 'harness' },
73
+ principal: { ceiling: 'write' },
74
+ mcpSessionId: 'harness-session',
75
+ prompts: onApproval
76
+ ? {
77
+ url: async (req) => {
78
+ // Decide after the prompt returns, as a human on the approval page would.
79
+ setTimeout(() => void decide(req.approvalId, req.message, onApproval), 10);
80
+ return { action: 'accept' };
81
+ },
82
+ }
83
+ : undefined,
84
+ };
85
+ };
86
+ const decide = async (id, message, onApproval) => {
87
+ const pending = ctx.db.select().from(pendingApprovals).where(eq(pendingApprovals.id, id)).get();
88
+ const operationKey = ctx.db.select().from(operations).where(eq(operations.id, pending.operationId)).get().key;
89
+ let decided = false;
90
+ const approval = {
91
+ id,
92
+ operationKey,
93
+ message,
94
+ pending,
95
+ approve(confirm) {
96
+ ctx.approvals.decide(id, { approve: true, confirm, decidedBy: 'harness' });
97
+ decided = true;
98
+ },
99
+ deny() {
100
+ ctx.approvals.decide(id, { approve: false, decidedBy: 'harness' });
101
+ decided = true;
102
+ },
103
+ };
104
+ try {
105
+ await onApproval(approval);
106
+ if (!decided)
107
+ throw new Error(`onApproval left approval ${id} (${operationKey}) open`);
108
+ }
109
+ catch (err) {
110
+ approvalErrors.push(err);
111
+ if (!decided)
112
+ ctx.approvals.decide(id, { approve: false, decidedBy: 'harness' });
113
+ }
114
+ };
115
+ return {
116
+ ctx,
117
+ instanceId,
118
+ manifest,
119
+ approvalErrors,
120
+ execute: (code, opts) => executeCode(ctx.gateDeps(), ctx.instances.runtime(instanceId), caller(opts), code),
121
+ search: (code) => searchCode(ctx.gateDeps(), ctx.instances.runtime(instanceId), caller(), code),
122
+ setGroupLevel(group, level) {
123
+ try {
124
+ setGroupLevel(ctx.db, instanceId, group, level);
125
+ }
126
+ catch (err) {
127
+ // Raising to write must acknowledge the writes it lets through: take the list core offers,
128
+ // as an admin confirming the portal's dialog does.
129
+ if (!(err instanceof ConflictError) || err.code !== 'acknowledgement_mismatch')
130
+ throw err;
131
+ const expected = err.details.expected.map((o) => o.id);
132
+ setGroupLevel(ctx.db, instanceId, group, level, { acknowledge: expected });
133
+ }
134
+ },
135
+ setOperationLevel(key, level) {
136
+ updateOperation(ctx.db, instanceId, operation(key).id, { level });
137
+ },
138
+ addRule({ operation: key, match, reason }) {
139
+ return createRule(ctx.db, ctx.instances.runtime(instanceId).manifest, instanceId, {
140
+ operationId: operation(key).id,
141
+ match,
142
+ reason,
143
+ });
144
+ },
145
+ operation,
146
+ operations: () => ctx.db.select().from(operations).where(eq(operations.instanceId, instanceId)).all(),
147
+ registry: () => ctx.db.select().from(registryEntries).where(eq(registryEntries.instanceId, instanceId)).all(),
148
+ audit(filter = {}) {
149
+ const rows = ctx.db.select().from(auditLog).where(eq(auditLog.instanceId, instanceId)).all();
150
+ return filter.operationKey ? rows.filter((a) => a.operationKey === filter.operationKey) : rows;
151
+ },
152
+ instance: () => ctx.instances.get(instanceId),
153
+ testConnection: (connection) => ctx.instances.testConnection(instanceId, splitConnection(manifest, connection)),
154
+ syncNow: () => ctx.instances.syncNow(instanceId),
155
+ async stop() {
156
+ await ctx.stop();
157
+ rmSync(work, { recursive: true, force: true });
158
+ },
159
+ };
160
+ }
161
+ /** `testConnection` takes config and secrets apart; the manifest's `writeOnly` fields are the secrets. */
162
+ function splitConnection(manifest, connection) {
163
+ const secretNames = new Set(secretFieldNames(manifest));
164
+ const config = {};
165
+ const secrets = {};
166
+ for (const [k, v] of Object.entries(connection)) {
167
+ if (secretNames.has(k))
168
+ secrets[k] = String(v);
169
+ else
170
+ config[k] = v;
171
+ }
172
+ return { config, secrets };
173
+ }
174
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ /** The core's own version, from package.json (src/ and dist/ both sit one level below it). */
2
+ export declare const CORE_VERSION: string;
@@ -0,0 +1,4 @@
1
+ import { readFileSync } from 'node:fs';
2
+ /** The core's own version, from package.json (src/ and dist/ both sit one level below it). */
3
+ export const CORE_VERSION = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
4
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,8FAA8F;AAC9F,MAAM,CAAC,MAAM,YAAY,GACvB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAC7E,CAAC,OAAO,CAAC"}
@@ -0,0 +1,334 @@
1
+ CREATE TABLE `approval_links` (
2
+ `token_hash` text PRIMARY KEY NOT NULL,
3
+ `approval_id` text NOT NULL,
4
+ `action` text NOT NULL,
5
+ `expires_at` integer NOT NULL,
6
+ `used_at` integer,
7
+ FOREIGN KEY (`approval_id`) REFERENCES `pending_approvals`(`id`) ON UPDATE no action ON DELETE cascade
8
+ );
9
+ --> statement-breakpoint
10
+ CREATE TABLE `audit_log` (
11
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
12
+ `at` integer NOT NULL,
13
+ `kind` text NOT NULL,
14
+ `instance_id` text,
15
+ `operation_key` text,
16
+ `classification` text,
17
+ `decision` text,
18
+ `actor_kind` text NOT NULL,
19
+ `actor_id` text,
20
+ `decided_by` text,
21
+ `decided_via` text,
22
+ `params` text,
23
+ `resolved_targets` text,
24
+ `result_status` text,
25
+ `duration_ms` integer,
26
+ `detail` text
27
+ );
28
+ --> statement-breakpoint
29
+ CREATE INDEX `audit_at_idx` ON `audit_log` (`at`);--> statement-breakpoint
30
+ CREATE INDEX `audit_instance_at_idx` ON `audit_log` (`instance_id`,`at`);--> statement-breakpoint
31
+ CREATE TABLE `guides` (
32
+ `id` text PRIMARY KEY NOT NULL,
33
+ `instance_id` text NOT NULL,
34
+ `operation_id` text NOT NULL,
35
+ `version` text NOT NULL,
36
+ `content` text NOT NULL,
37
+ `fetched_at` integer NOT NULL,
38
+ FOREIGN KEY (`instance_id`) REFERENCES `plugin_instances`(`id`) ON UPDATE no action ON DELETE cascade,
39
+ FOREIGN KEY (`operation_id`) REFERENCES `operations`(`id`) ON UPDATE no action ON DELETE cascade
40
+ );
41
+ --> statement-breakpoint
42
+ CREATE TABLE `mcp_tokens` (
43
+ `id` text PRIMARY KEY NOT NULL,
44
+ `name` text NOT NULL,
45
+ `token_hash` text NOT NULL,
46
+ `scope` text NOT NULL,
47
+ `created_by` text,
48
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
49
+ `expires_at` integer,
50
+ `last_used_at` integer,
51
+ `revoked_at` integer,
52
+ FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
53
+ );
54
+ --> statement-breakpoint
55
+ CREATE UNIQUE INDEX `mcp_tokens_token_hash_unique` ON `mcp_tokens` (`token_hash`);--> statement-breakpoint
56
+ CREATE TABLE `notifier_channels` (
57
+ `id` text PRIMARY KEY NOT NULL,
58
+ `kind` text NOT NULL,
59
+ `name` text NOT NULL,
60
+ `config` text NOT NULL,
61
+ `secrets_enc` blob,
62
+ `events` text NOT NULL,
63
+ `instance_filter` text,
64
+ `enabled` integer DEFAULT true NOT NULL,
65
+ `last_sent_at` integer,
66
+ `last_error` text
67
+ );
68
+ --> statement-breakpoint
69
+ CREATE TABLE `oauth_clients` (
70
+ `id` text PRIMARY KEY NOT NULL,
71
+ `client_id` text NOT NULL,
72
+ `client_secret_hash` text,
73
+ `name` text NOT NULL,
74
+ `redirect_uris` text NOT NULL,
75
+ `registered_via` text NOT NULL,
76
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
77
+ `revoked_at` integer
78
+ );
79
+ --> statement-breakpoint
80
+ CREATE UNIQUE INDEX `oauth_clients_client_id_unique` ON `oauth_clients` (`client_id`);--> statement-breakpoint
81
+ CREATE TABLE `oauth_codes` (
82
+ `code_hash` text PRIMARY KEY NOT NULL,
83
+ `grant_id` text NOT NULL,
84
+ `code_challenge` text NOT NULL,
85
+ `redirect_uri` text NOT NULL,
86
+ `resources` text NOT NULL,
87
+ `expires_at` integer NOT NULL,
88
+ `used_at` integer,
89
+ FOREIGN KEY (`grant_id`) REFERENCES `oauth_grants`(`id`) ON UPDATE no action ON DELETE cascade
90
+ );
91
+ --> statement-breakpoint
92
+ CREATE TABLE `oauth_grants` (
93
+ `id` text PRIMARY KEY NOT NULL,
94
+ `client_id` text NOT NULL,
95
+ `user_id` text NOT NULL,
96
+ `resources` text NOT NULL,
97
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
98
+ `revoked_at` integer,
99
+ FOREIGN KEY (`client_id`) REFERENCES `oauth_clients`(`id`) ON UPDATE no action ON DELETE cascade,
100
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
101
+ );
102
+ --> statement-breakpoint
103
+ CREATE TABLE `oauth_tokens` (
104
+ `token_hash` text PRIMARY KEY NOT NULL,
105
+ `grant_id` text NOT NULL,
106
+ `kind` text NOT NULL,
107
+ `family_id` text NOT NULL,
108
+ `resources` text NOT NULL,
109
+ `expires_at` integer NOT NULL,
110
+ `revoked_at` integer,
111
+ FOREIGN KEY (`grant_id`) REFERENCES `oauth_grants`(`id`) ON UPDATE no action ON DELETE cascade
112
+ );
113
+ --> statement-breakpoint
114
+ CREATE TABLE `oidc_config` (
115
+ `id` integer PRIMARY KEY NOT NULL,
116
+ `issuer` text NOT NULL,
117
+ `client_id` text NOT NULL,
118
+ `client_secret_enc` blob,
119
+ `scopes` text DEFAULT 'openid email profile' NOT NULL,
120
+ `allow_policy` text,
121
+ `auto_provision` integer DEFAULT false NOT NULL,
122
+ `enabled` integer DEFAULT false NOT NULL
123
+ );
124
+ --> statement-breakpoint
125
+ CREATE TABLE `operation_group_aliases` (
126
+ `instance_id` text NOT NULL,
127
+ `plugin_group` text NOT NULL,
128
+ `group_key` text NOT NULL,
129
+ FOREIGN KEY (`instance_id`) REFERENCES `plugin_instances`(`id`) ON UPDATE no action ON DELETE cascade
130
+ );
131
+ --> statement-breakpoint
132
+ CREATE UNIQUE INDEX `operation_group_aliases_idx` ON `operation_group_aliases` (`instance_id`,`plugin_group`);--> statement-breakpoint
133
+ CREATE TABLE `operation_groups` (
134
+ `id` text PRIMARY KEY NOT NULL,
135
+ `instance_id` text NOT NULL,
136
+ `key` text NOT NULL,
137
+ `label` text NOT NULL,
138
+ `level` text DEFAULT 'read' NOT NULL,
139
+ `level_changed_at` integer,
140
+ `level_changed_by` text,
141
+ `first_seen_at` integer NOT NULL,
142
+ `stale` integer DEFAULT false NOT NULL,
143
+ FOREIGN KEY (`instance_id`) REFERENCES `plugin_instances`(`id`) ON UPDATE no action ON DELETE cascade,
144
+ FOREIGN KEY (`level_changed_by`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
145
+ );
146
+ --> statement-breakpoint
147
+ CREATE UNIQUE INDEX `operation_groups_instance_key_idx` ON `operation_groups` (`instance_id`,`key`);--> statement-breakpoint
148
+ CREATE TABLE `operations` (
149
+ `id` text PRIMARY KEY NOT NULL,
150
+ `instance_id` text NOT NULL,
151
+ `key` text NOT NULL,
152
+ `display_name` text,
153
+ `kind` text NOT NULL,
154
+ `plugin_group` text NOT NULL,
155
+ `group_id` text NOT NULL,
156
+ `tag` text,
157
+ `classification` text NOT NULL,
158
+ `classification_source` text NOT NULL,
159
+ `inferred_classification` text NOT NULL,
160
+ `inferred_reason` text NOT NULL,
161
+ `locked` integer DEFAULT false NOT NULL,
162
+ `excluded` integer DEFAULT false NOT NULL,
163
+ `locked_opt_in` integer DEFAULT false NOT NULL,
164
+ `write_acknowledged` integer DEFAULT false NOT NULL,
165
+ `acknowledged_at` integer,
166
+ `acknowledged_by` text,
167
+ `typed_confirmation` integer DEFAULT false NOT NULL,
168
+ `attestation_required` integer DEFAULT false NOT NULL,
169
+ `needs_review` integer DEFAULT false NOT NULL,
170
+ `match_profile` text,
171
+ `params_schema` text,
172
+ `docs` text,
173
+ `first_seen_at` integer NOT NULL,
174
+ `last_seen_at` integer NOT NULL,
175
+ `stale` integer DEFAULT false NOT NULL,
176
+ FOREIGN KEY (`instance_id`) REFERENCES `plugin_instances`(`id`) ON UPDATE no action ON DELETE cascade,
177
+ FOREIGN KEY (`group_id`) REFERENCES `operation_groups`(`id`) ON UPDATE no action ON DELETE no action,
178
+ FOREIGN KEY (`acknowledged_by`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
179
+ );
180
+ --> statement-breakpoint
181
+ CREATE UNIQUE INDEX `operations_instance_key_idx` ON `operations` (`instance_id`,`key`);--> statement-breakpoint
182
+ CREATE INDEX `operations_group_idx` ON `operations` (`group_id`);--> statement-breakpoint
183
+ CREATE TABLE `pending_approvals` (
184
+ `id` text PRIMARY KEY NOT NULL,
185
+ `instance_id` text NOT NULL,
186
+ `operation_id` text NOT NULL,
187
+ `params_display` text,
188
+ `params_hash` text NOT NULL,
189
+ `resolved_targets` text,
190
+ `summary` text NOT NULL,
191
+ `confirm_literal` text,
192
+ `diff` text,
193
+ `expected_hash` text,
194
+ `client_kind` text,
195
+ `client_id` text,
196
+ `mcp_session_id` text,
197
+ `requested_at` integer NOT NULL,
198
+ `expires_at` integer NOT NULL,
199
+ `status` text DEFAULT 'pending' NOT NULL,
200
+ `decided_by` text,
201
+ `decided_via` text,
202
+ `decided_at` integer,
203
+ FOREIGN KEY (`instance_id`) REFERENCES `plugin_instances`(`id`) ON UPDATE no action ON DELETE no action,
204
+ FOREIGN KEY (`operation_id`) REFERENCES `operations`(`id`) ON UPDATE no action ON DELETE no action
205
+ );
206
+ --> statement-breakpoint
207
+ CREATE TABLE `plugin_instances` (
208
+ `id` text PRIMARY KEY NOT NULL,
209
+ `plugin_id` text NOT NULL,
210
+ `slug` text NOT NULL,
211
+ `display_name` text NOT NULL,
212
+ `enabled` integer DEFAULT true NOT NULL,
213
+ `config` text DEFAULT '{}' NOT NULL,
214
+ `secrets_enc` blob,
215
+ `auth_mode` text,
216
+ `settings` text DEFAULT '{}' NOT NULL,
217
+ `status` text DEFAULT 'stopped' NOT NULL,
218
+ `status_error` text,
219
+ `upstream_version` text,
220
+ `source_ref` text,
221
+ `last_synced_at` integer,
222
+ `last_sync_status` text,
223
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
224
+ FOREIGN KEY (`plugin_id`) REFERENCES `plugins`(`id`) ON UPDATE no action ON DELETE no action
225
+ );
226
+ --> statement-breakpoint
227
+ CREATE UNIQUE INDEX `plugin_instances_slug_unique` ON `plugin_instances` (`slug`);--> statement-breakpoint
228
+ CREATE TABLE `plugin_repos` (
229
+ `id` text PRIMARY KEY NOT NULL,
230
+ `url` text NOT NULL,
231
+ `name` text,
232
+ `signing_mode` text NOT NULL,
233
+ `public_key` text,
234
+ `key_fingerprint` text,
235
+ `key_status` text DEFAULT 'ok' NOT NULL,
236
+ `index_cache` text,
237
+ `last_fetched_at` integer,
238
+ `last_fetch_error` text
239
+ );
240
+ --> statement-breakpoint
241
+ CREATE UNIQUE INDEX `plugin_repos_url_unique` ON `plugin_repos` (`url`);--> statement-breakpoint
242
+ CREATE TABLE `plugins` (
243
+ `id` text PRIMARY KEY NOT NULL,
244
+ `plugin_id` text NOT NULL,
245
+ `version` text NOT NULL,
246
+ `source` text NOT NULL,
247
+ `repo_id` text,
248
+ `path` text NOT NULL,
249
+ `sha256` text,
250
+ `signature_verified` integer DEFAULT false NOT NULL,
251
+ `manifest` text NOT NULL,
252
+ `status` text NOT NULL,
253
+ `status_error` text,
254
+ `enabled` integer DEFAULT false NOT NULL,
255
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
256
+ FOREIGN KEY (`repo_id`) REFERENCES `plugin_repos`(`id`) ON UPDATE no action ON DELETE no action
257
+ );
258
+ --> statement-breakpoint
259
+ CREATE UNIQUE INDEX `plugins_plugin_id_unique` ON `plugins` (`plugin_id`);--> statement-breakpoint
260
+ CREATE TABLE `pre_approval_hits` (
261
+ `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
262
+ `rule_id` text NOT NULL,
263
+ `occurred_at` integer NOT NULL,
264
+ FOREIGN KEY (`rule_id`) REFERENCES `pre_approval_rules`(`id`) ON UPDATE no action ON DELETE cascade
265
+ );
266
+ --> statement-breakpoint
267
+ CREATE INDEX `hits_rule_time_idx` ON `pre_approval_hits` (`rule_id`,`occurred_at`);--> statement-breakpoint
268
+ CREATE TABLE `pre_approval_rules` (
269
+ `id` text PRIMARY KEY NOT NULL,
270
+ `instance_id` text NOT NULL,
271
+ `operation_id` text NOT NULL,
272
+ `match` text DEFAULT '[]' NOT NULL,
273
+ `rate_limit` integer,
274
+ `window_seconds` integer,
275
+ `expires_at` integer,
276
+ `reason` text NOT NULL,
277
+ `enabled` integer DEFAULT true NOT NULL,
278
+ `created_by` text,
279
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
280
+ `updated_at` integer,
281
+ `last_triggered_at` integer,
282
+ FOREIGN KEY (`instance_id`) REFERENCES `plugin_instances`(`id`) ON UPDATE no action ON DELETE cascade,
283
+ FOREIGN KEY (`operation_id`) REFERENCES `operations`(`id`) ON UPDATE no action ON DELETE no action,
284
+ FOREIGN KEY (`created_by`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE no action
285
+ );
286
+ --> statement-breakpoint
287
+ CREATE TABLE `registry_entries` (
288
+ `id` text PRIMARY KEY NOT NULL,
289
+ `instance_id` text NOT NULL,
290
+ `kind` text NOT NULL,
291
+ `ext_id` text NOT NULL,
292
+ `name` text NOT NULL,
293
+ `parent_ext_id` text,
294
+ `domain` text,
295
+ `attrs` text,
296
+ `stale` integer DEFAULT false NOT NULL,
297
+ `last_synced_at` integer NOT NULL,
298
+ FOREIGN KEY (`instance_id`) REFERENCES `plugin_instances`(`id`) ON UPDATE no action ON DELETE cascade
299
+ );
300
+ --> statement-breakpoint
301
+ CREATE UNIQUE INDEX `registry_instance_kind_ext_idx` ON `registry_entries` (`instance_id`,`kind`,`ext_id`);--> statement-breakpoint
302
+ CREATE TABLE `sessions` (
303
+ `id_hash` text PRIMARY KEY NOT NULL,
304
+ `user_id` text NOT NULL,
305
+ `kind` text NOT NULL,
306
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
307
+ `last_seen_at` integer NOT NULL,
308
+ `expires_at` integer NOT NULL,
309
+ `ip` text,
310
+ `user_agent` text,
311
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
312
+ );
313
+ --> statement-breakpoint
314
+ CREATE INDEX `sessions_user_idx` ON `sessions` (`user_id`);--> statement-breakpoint
315
+ CREATE TABLE `settings` (
316
+ `key` text PRIMARY KEY NOT NULL,
317
+ `value` text NOT NULL
318
+ );
319
+ --> statement-breakpoint
320
+ CREATE TABLE `users` (
321
+ `id` text PRIMARY KEY NOT NULL,
322
+ `username` text NOT NULL,
323
+ `password_hash` text,
324
+ `totp_secret_enc` blob,
325
+ `totp_enabled` integer DEFAULT false NOT NULL,
326
+ `recovery_codes_hash` text,
327
+ `oidc_issuer` text,
328
+ `oidc_subject` text,
329
+ `created_at` integer DEFAULT (unixepoch() * 1000) NOT NULL,
330
+ `last_login_at` integer,
331
+ `disabled` integer DEFAULT false NOT NULL
332
+ );
333
+ --> statement-breakpoint
334
+ CREATE UNIQUE INDEX `users_username_unique` ON `users` (`username`);
@@ -0,0 +1 @@
1
+ ALTER TABLE `users` ADD `totp_last_step` integer;
@@ -0,0 +1,16 @@
1
+ ALTER TABLE `mcp_tokens` ADD `access` text DEFAULT 'read' NOT NULL;--> statement-breakpoint
2
+ ALTER TABLE `oauth_grants` ADD `access` text DEFAULT 'read' NOT NULL;--> statement-breakpoint
3
+ ALTER TABLE `operations` ADD `level_override` text;--> statement-breakpoint
4
+ -- Tokens and grants issued before access ceilings existed keep their read & write reach.
5
+ UPDATE `mcp_tokens` SET `access` = 'write';--> statement-breakpoint
6
+ UPDATE `oauth_grants` SET `access` = 'write';--> statement-breakpoint
7
+ -- Exclusions become an explicit `none` level.
8
+ UPDATE `operations` SET `level_override` = 'none' WHERE `excluded` = 1;--> statement-breakpoint
9
+ -- Opted-in locked ops were callable (with approval) only while their group was at `write`.
10
+ UPDATE `operations` SET `level_override` = 'ask'
11
+ WHERE `locked_opt_in` = 1 AND `excluded` = 0
12
+ AND `group_id` IN (SELECT `id` FROM `operation_groups` WHERE `level` = 'write');--> statement-breakpoint
13
+ -- The old `write` level asked for approval on every write: that is now `ask`. Nothing starts auto-running.
14
+ UPDATE `operation_groups` SET `level` = 'ask' WHERE `level` = 'write';--> statement-breakpoint
15
+ -- Approvals decided in the removed portal inbox or via notification links were all made on a signed-in page.
16
+ UPDATE `pending_approvals` SET `decided_via` = 'url' WHERE `decided_via` IN ('portal', 'link');
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `operations` DROP COLUMN `excluded`;--> statement-breakpoint
2
+ ALTER TABLE `operations` DROP COLUMN `locked_opt_in`;
@@ -0,0 +1 @@
1
+ ALTER TABLE `oauth_grants` ADD `instance_ids` text;
@@ -0,0 +1 @@
1
+ ALTER TABLE `pre_approval_rules` ADD `strict_miss_at` integer;
@@ -0,0 +1 @@
1
+ ALTER TABLE `operations` ADD `attestation_waived` integer DEFAULT false NOT NULL;