@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,313 @@
1
+ import type { SyncSummary } from '../catalog/sync.js';
2
+ import type { SecretBox } from '../crypto/index.js';
3
+ import type { Db } from '../db/index.js';
4
+ import { pluginInstances, plugins } from '../db/schema.js';
5
+ import type { CoreEvents } from '../events.js';
6
+ import type { InstanceRuntime } from '../gate/pipeline.js';
7
+ import type { InstanceStatus } from '../plugins/supervisor.js';
8
+ import type { InstanceSettings } from './settings.js';
9
+ /**
10
+ * Instance lifecycle (design §4, §10): creation and connection config (secrets encrypted), one
11
+ * supervised plugin child per enabled instance, and catalog/registry sync scheduling.
12
+ */
13
+ export declare const AUTH_MODES: readonly ["external", "bearer", "oauth", "bearer+oauth"];
14
+ export type AuthMode = (typeof AUTH_MODES)[number];
15
+ type InstanceRow = typeof pluginInstances.$inferSelect;
16
+ type PluginRow = typeof plugins.$inferSelect;
17
+ export interface ManagerOptions {
18
+ db: Db;
19
+ secrets: SecretBox;
20
+ events: CoreEvents;
21
+ now?: () => Date;
22
+ /** Test hooks: faster restarts and shorter RPC/init timeouts. */
23
+ supervisor?: {
24
+ backoff?: {
25
+ initialMs: number;
26
+ maxMs: number;
27
+ };
28
+ initTimeoutMs?: number;
29
+ rpcTimeoutMs?: number;
30
+ };
31
+ /** How often a live session may trigger the cheap upstream version check. */
32
+ versionCheckIntervalMs?: number;
33
+ }
34
+ export interface CreateInstanceInput {
35
+ pluginId: string;
36
+ slug: string;
37
+ displayName?: string;
38
+ /** Config and secrets together, as the connection form submits them. */
39
+ connection: Record<string, unknown>;
40
+ authMode?: AuthMode | null;
41
+ settings?: unknown;
42
+ enabled?: boolean;
43
+ }
44
+ export interface Actor {
45
+ userId?: string;
46
+ }
47
+ export declare class InstanceManager {
48
+ private readonly opts;
49
+ private readonly live;
50
+ private readonly db;
51
+ private readonly now;
52
+ constructor(opts: ManagerOptions);
53
+ private row;
54
+ private plugin;
55
+ /** Resolves a plugin by row id or by manifest id (`truenas`). */
56
+ private pluginByAnyId;
57
+ list(): {
58
+ id: string;
59
+ slug: string;
60
+ displayName: string;
61
+ enabled: boolean;
62
+ authMode: "external" | "bearer" | "oauth" | "bearer+oauth" | null;
63
+ status: "stopped" | "starting" | "ready" | "error";
64
+ statusError: string | null;
65
+ upstreamVersion: string | null;
66
+ sourceRef: string | null;
67
+ lastSyncedAt: Date | null;
68
+ lastSyncStatus: string | null;
69
+ settings: {
70
+ approvalTimeoutMs: number;
71
+ formElicitationApprovals: "off" | "writes";
72
+ executePerMinute: number;
73
+ writesPerMinute: number;
74
+ sandbox: {
75
+ timeoutMs: number;
76
+ memoryMb: number;
77
+ maxResultBytes: number;
78
+ };
79
+ extraRedactKeys: string[];
80
+ syncMaxAgeMs: number;
81
+ memoryMb: number;
82
+ };
83
+ plugin: {
84
+ id: string;
85
+ pluginId: string;
86
+ name: string;
87
+ enabled: boolean;
88
+ status: "ok" | "invalid" | "incompatible";
89
+ labels: {
90
+ operation: string;
91
+ operations: string;
92
+ } | undefined;
93
+ attestation: boolean;
94
+ };
95
+ }[];
96
+ get(id: string): {
97
+ id: string;
98
+ slug: string;
99
+ displayName: string;
100
+ enabled: boolean;
101
+ authMode: "external" | "bearer" | "oauth" | "bearer+oauth" | null;
102
+ status: "stopped" | "starting" | "ready" | "error";
103
+ statusError: string | null;
104
+ upstreamVersion: string | null;
105
+ sourceRef: string | null;
106
+ lastSyncedAt: Date | null;
107
+ lastSyncStatus: string | null;
108
+ settings: {
109
+ approvalTimeoutMs: number;
110
+ formElicitationApprovals: "off" | "writes";
111
+ executePerMinute: number;
112
+ writesPerMinute: number;
113
+ sandbox: {
114
+ timeoutMs: number;
115
+ memoryMb: number;
116
+ maxResultBytes: number;
117
+ };
118
+ extraRedactKeys: string[];
119
+ syncMaxAgeMs: number;
120
+ memoryMb: number;
121
+ };
122
+ plugin: {
123
+ id: string;
124
+ pluginId: string;
125
+ name: string;
126
+ enabled: boolean;
127
+ status: "ok" | "invalid" | "incompatible";
128
+ labels: {
129
+ operation: string;
130
+ operations: string;
131
+ } | undefined;
132
+ attestation: boolean;
133
+ };
134
+ };
135
+ bySlug(slug: string): {
136
+ instance: InstanceRow;
137
+ plugin: PluginRow;
138
+ } | undefined;
139
+ private describe;
140
+ /** Whether the instance's endpoint should serve: instance and plugin enabled, plugin healthy. */
141
+ isServing(instance: InstanceRow, plugin: PluginRow): boolean;
142
+ settingsOf(instance: InstanceRow): InstanceSettings;
143
+ /**
144
+ * Scrubs an instance's secret values out of plugin/upstream error text before it is stored, audited
145
+ * or sent to notification channels (an init error can echo a config value or token).
146
+ */
147
+ private scrubError;
148
+ /** Startup step: removes stored instance settings fields the current schema rejects. */
149
+ normalizeStoredSettings(): string[];
150
+ /** Everything the gate needs for one instance. */
151
+ runtime(instanceId: string): InstanceRuntime;
152
+ status(instanceId: string): InstanceStatus;
153
+ private readSecrets;
154
+ private sealSecrets;
155
+ create(input: CreateInstanceInput, actor?: Actor): Promise<{
156
+ id: string;
157
+ slug: string;
158
+ displayName: string;
159
+ enabled: boolean;
160
+ authMode: "external" | "bearer" | "oauth" | "bearer+oauth" | null;
161
+ status: "stopped" | "starting" | "ready" | "error";
162
+ statusError: string | null;
163
+ upstreamVersion: string | null;
164
+ sourceRef: string | null;
165
+ lastSyncedAt: Date | null;
166
+ lastSyncStatus: string | null;
167
+ settings: {
168
+ approvalTimeoutMs: number;
169
+ formElicitationApprovals: "off" | "writes";
170
+ executePerMinute: number;
171
+ writesPerMinute: number;
172
+ sandbox: {
173
+ timeoutMs: number;
174
+ memoryMb: number;
175
+ maxResultBytes: number;
176
+ };
177
+ extraRedactKeys: string[];
178
+ syncMaxAgeMs: number;
179
+ memoryMb: number;
180
+ };
181
+ plugin: {
182
+ id: string;
183
+ pluginId: string;
184
+ name: string;
185
+ enabled: boolean;
186
+ status: "ok" | "invalid" | "incompatible";
187
+ labels: {
188
+ operation: string;
189
+ operations: string;
190
+ } | undefined;
191
+ attestation: boolean;
192
+ };
193
+ }>;
194
+ update(id: string, patch: {
195
+ displayName?: string;
196
+ slug?: string;
197
+ enabled?: boolean;
198
+ authMode?: AuthMode | null;
199
+ settings?: unknown;
200
+ }, actor?: Actor): Promise<{
201
+ id: string;
202
+ slug: string;
203
+ displayName: string;
204
+ enabled: boolean;
205
+ authMode: "external" | "bearer" | "oauth" | "bearer+oauth" | null;
206
+ status: "stopped" | "starting" | "ready" | "error";
207
+ statusError: string | null;
208
+ upstreamVersion: string | null;
209
+ sourceRef: string | null;
210
+ lastSyncedAt: Date | null;
211
+ lastSyncStatus: string | null;
212
+ settings: {
213
+ approvalTimeoutMs: number;
214
+ formElicitationApprovals: "off" | "writes";
215
+ executePerMinute: number;
216
+ writesPerMinute: number;
217
+ sandbox: {
218
+ timeoutMs: number;
219
+ memoryMb: number;
220
+ maxResultBytes: number;
221
+ };
222
+ extraRedactKeys: string[];
223
+ syncMaxAgeMs: number;
224
+ memoryMb: number;
225
+ };
226
+ plugin: {
227
+ id: string;
228
+ pluginId: string;
229
+ name: string;
230
+ enabled: boolean;
231
+ status: "ok" | "invalid" | "incompatible";
232
+ labels: {
233
+ operation: string;
234
+ operations: string;
235
+ } | undefined;
236
+ attestation: boolean;
237
+ };
238
+ }>;
239
+ remove(id: string, confirmSlug: string, actor?: Actor): Promise<void>;
240
+ getConnection(id: string): {
241
+ config: Record<string, unknown>;
242
+ secrets: Record<string, import("./connection.js").SecretSummary>;
243
+ schema: Record<string, unknown>;
244
+ ui: Record<string, {
245
+ widget?: "number" | "text" | "url" | "diff" | "select" | "secret" | "prefix" | "range" | "bool" | "multiselect" | "registry-picker" | undefined;
246
+ help?: string | undefined;
247
+ placeholder?: string | undefined;
248
+ optionsSource?: string | undefined;
249
+ showWhen?: {
250
+ field: string;
251
+ in: (string | number | boolean)[];
252
+ } | undefined;
253
+ }>;
254
+ help: string | undefined;
255
+ };
256
+ /** Replaces non-secret config; secrets follow the merge rules in `mergeSecrets`. Restarts the child. */
257
+ updateConnection(id: string, input: {
258
+ config: Record<string, unknown>;
259
+ secrets?: Record<string, string | null>;
260
+ }, actor?: Actor): Promise<{
261
+ config: Record<string, unknown>;
262
+ secrets: Record<string, import("./connection.js").SecretSummary>;
263
+ schema: Record<string, unknown>;
264
+ ui: Record<string, {
265
+ widget?: "number" | "text" | "url" | "diff" | "select" | "secret" | "prefix" | "range" | "bool" | "multiselect" | "registry-picker" | undefined;
266
+ help?: string | undefined;
267
+ placeholder?: string | undefined;
268
+ optionsSource?: string | undefined;
269
+ showWhen?: {
270
+ field: string;
271
+ in: (string | number | boolean)[];
272
+ } | undefined;
273
+ }>;
274
+ help: string | undefined;
275
+ }>;
276
+ /**
277
+ * "Test connection": runs `testConnection` in a throwaway child, so an unsaved candidate config
278
+ * can be tried without disturbing the running instance. Omitted secrets fall back to stored ones.
279
+ */
280
+ testConnection(id: string, candidate?: {
281
+ config: Record<string, unknown>;
282
+ secrets?: Record<string, string | null>;
283
+ }): Promise<{
284
+ ok: boolean;
285
+ message?: string | undefined;
286
+ upstreamVersion?: string | undefined;
287
+ }>;
288
+ setPluginEnabled(pluginRowId: string, enabled: boolean, actor?: Actor): Promise<void>;
289
+ /** Stops every running instance of a plugin (before its files are replaced). */
290
+ stopPlugin(pluginRowId: string): Promise<void>;
291
+ /** Starts every servable instance of a plugin and resyncs its catalog (after an install or update). */
292
+ startPlugin(pluginRowId: string): Promise<void>;
293
+ startAll(): Promise<void>;
294
+ stopAll(): Promise<void>;
295
+ private setStatus;
296
+ private start;
297
+ private stop;
298
+ private scheduleSync;
299
+ /** Full catalog (+ registry) sync. Concurrent callers share one run (per-instance mutex). */
300
+ syncNow(instanceId: string): Promise<SyncSummary>;
301
+ /**
302
+ * Called before serving MCP traffic (session start, and cheaply on each tool call):
303
+ * - never synced → sync now; failure means the endpoint can't serve (TN §2.2, per instance);
304
+ * - stale beyond `syncMaxAgeMs` → sync, but keep serving the last catalog if it fails;
305
+ * - otherwise compare the upstream version (throttled) and sync on a mismatch.
306
+ */
307
+ ensureFresh(instanceId: string, opts?: {
308
+ forceVersionCheck?: boolean;
309
+ }): Promise<void>;
310
+ /** Daily backstop (design §10): sync anything that hasn't synced in 24 h. */
311
+ syncStale(maxAgeMs?: number): Promise<void>;
312
+ }
313
+ export {};