@segmentstream-cloud/ontology 0.9.0 → 0.11.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 (90) hide show
  1. package/dist/action.d.ts +19 -0
  2. package/dist/action.js +1 -0
  3. package/dist/analyze.d.ts +3 -1
  4. package/dist/analyze.js +97 -2
  5. package/dist/bin/migrate.js +3 -2
  6. package/dist/blob.d.ts +39 -0
  7. package/dist/blob.js +49 -0
  8. package/dist/diagnostics.d.ts +3 -3
  9. package/dist/diagnostics.js +1 -0
  10. package/dist/entity.d.ts +5 -3
  11. package/dist/index.d.ts +9 -4
  12. package/dist/index.js +6 -1
  13. package/dist/manifest.d.ts +71 -7
  14. package/dist/manifest.js +18 -1
  15. package/dist/migrate/apply.d.ts +7 -0
  16. package/dist/migrate/apply.js +18 -1
  17. package/dist/migrate/index.d.ts +1 -1
  18. package/dist/migrate/index.js +1 -1
  19. package/dist/migrate/model.d.ts +15 -2
  20. package/dist/migrate/plan.d.ts +6 -0
  21. package/dist/migrate/plan.js +35 -3
  22. package/dist/migrate/storage.d.ts +14 -0
  23. package/dist/migrate/storage.js +95 -0
  24. package/dist/names.d.ts +9 -1
  25. package/dist/names.js +11 -0
  26. package/dist/nitro.d.ts +13 -0
  27. package/dist/nitro.js +18 -0
  28. package/dist/property.d.ts +10 -1
  29. package/dist/property.js +12 -1
  30. package/dist/query.js +6 -1
  31. package/dist/runtime/generated-actions.d.ts +3 -0
  32. package/dist/runtime/generated-actions.js +10 -5
  33. package/dist/runtime/history.d.ts +3 -0
  34. package/dist/runtime/oauth.d.ts +9 -0
  35. package/dist/runtime/oauth.js +165 -0
  36. package/dist/runtime/pipeline.d.ts +5 -1
  37. package/dist/runtime/pipeline.js +87 -3
  38. package/dist/runtime/principals.d.ts +5 -0
  39. package/dist/runtime/principals.js +15 -0
  40. package/dist/runtime/records.js +9 -0
  41. package/dist/runtime/service-binding.d.ts +2 -1
  42. package/dist/runtime/service-binding.js +15 -2
  43. package/dist/runtime/writes.js +17 -3
  44. package/dist/service/api.js +19 -10
  45. package/dist/service/authentication.d.ts +27 -1
  46. package/dist/service/authentication.js +48 -26
  47. package/dist/service/config.d.ts +8 -0
  48. package/dist/service/config.js +18 -0
  49. package/dist/service/descriptions.d.ts +8 -0
  50. package/dist/service/descriptions.js +15 -0
  51. package/dist/service/errors.d.ts +5 -1
  52. package/dist/service/errors.js +6 -2
  53. package/dist/service/handlers.d.ts +1 -4
  54. package/dist/service/handlers.js +59 -203
  55. package/dist/service/mcp/server.d.ts +24 -0
  56. package/dist/service/mcp/server.js +370 -0
  57. package/dist/service/mcp/tools.d.ts +47 -0
  58. package/dist/service/mcp/tools.js +218 -0
  59. package/dist/service/oauth/protocol.d.ts +52 -0
  60. package/dist/service/oauth/protocol.js +110 -0
  61. package/dist/service/oauth/server.d.ts +27 -0
  62. package/dist/service/oauth/server.js +576 -0
  63. package/dist/service/operations.d.ts +114 -0
  64. package/dist/service/operations.js +218 -0
  65. package/dist/service/runtime-contract.d.ts +98 -0
  66. package/dist/service/schemas.d.ts +18 -2
  67. package/dist/service/schemas.js +18 -2
  68. package/dist/service/service.d.ts +3 -3
  69. package/dist/service/service.js +27 -7
  70. package/dist/storage/api.d.ts +4 -0
  71. package/dist/storage/api.js +39 -0
  72. package/dist/storage/authorization.d.ts +8 -0
  73. package/dist/storage/authorization.js +30 -0
  74. package/dist/storage/maintenance-auth.d.ts +20 -0
  75. package/dist/storage/maintenance-auth.js +24 -0
  76. package/dist/storage/maintenance.d.ts +7 -0
  77. package/dist/storage/maintenance.js +50 -0
  78. package/dist/storage/neon.d.ts +3 -0
  79. package/dist/storage/neon.js +212 -0
  80. package/dist/storage/operator.d.ts +10 -0
  81. package/dist/storage/operator.js +30 -0
  82. package/dist/storage/provider.d.ts +80 -0
  83. package/dist/storage/provider.js +20 -0
  84. package/dist/storage/sessions.d.ts +87 -0
  85. package/dist/storage/sessions.js +341 -0
  86. package/dist/storage/tables.d.ts +2 -0
  87. package/dist/storage/tables.js +55 -0
  88. package/dist/storage/writes.d.ts +7 -0
  89. package/dist/storage/writes.js +88 -0
  90. package/package.json +8 -1
@@ -21,7 +21,7 @@ export declare const PropertyManifest: Schema.Struct<{
21
21
  readonly column: Schema.optionalKey<Schema.String>;
22
22
  readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
23
23
  readonly name: Schema.String;
24
- readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
24
+ readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
25
25
  readonly label: Schema.String;
26
26
  readonly description: Schema.optionalKey<Schema.String>;
27
27
  readonly optional: Schema.Boolean;
@@ -33,6 +33,8 @@ export declare const PropertyManifest: Schema.Struct<{
33
33
  readonly min: Schema.optionalKey<Schema.Number>;
34
34
  readonly max: Schema.optionalKey<Schema.Number>;
35
35
  readonly maxLength: Schema.optionalKey<Schema.Number>;
36
+ readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
37
+ readonly maxBytes: Schema.optionalKey<Schema.Number>;
36
38
  readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
37
39
  readonly value: Schema.String;
38
40
  readonly label: Schema.String;
@@ -83,6 +85,14 @@ export declare const ActionManifest: Schema.Struct<{
83
85
  * when there are some; absent reads as none.
84
86
  */
85
87
  readonly connections: Schema.optionalKey<Schema.$Array<Schema.String>>;
88
+ /**
89
+ * How the action behaves, as MCP tool annotations tell agents. Written only when the action
90
+ * declares hints; absent reads as destructive and not idempotent.
91
+ */
92
+ readonly hints: Schema.optionalKey<Schema.Struct<{
93
+ readonly destructive: Schema.optionalKey<Schema.Boolean>;
94
+ readonly idempotent: Schema.optionalKey<Schema.Boolean>;
95
+ }>>;
86
96
  }>;
87
97
  export type ActionManifest = typeof ActionManifest.Type;
88
98
  /**
@@ -126,7 +136,7 @@ export declare const EntityManifest: Schema.Struct<{
126
136
  readonly column: Schema.optionalKey<Schema.String>;
127
137
  readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
128
138
  readonly name: Schema.String;
129
- readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
139
+ readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
130
140
  readonly label: Schema.String;
131
141
  readonly description: Schema.optionalKey<Schema.String>;
132
142
  readonly optional: Schema.Boolean;
@@ -138,6 +148,8 @@ export declare const EntityManifest: Schema.Struct<{
138
148
  readonly min: Schema.optionalKey<Schema.Number>;
139
149
  readonly max: Schema.optionalKey<Schema.Number>;
140
150
  readonly maxLength: Schema.optionalKey<Schema.Number>;
151
+ readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
152
+ readonly maxBytes: Schema.optionalKey<Schema.Number>;
141
153
  readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
142
154
  readonly value: Schema.String;
143
155
  readonly label: Schema.String;
@@ -182,6 +194,14 @@ export declare const EntityManifest: Schema.Struct<{
182
194
  * when there are some; absent reads as none.
183
195
  */
184
196
  readonly connections: Schema.optionalKey<Schema.$Array<Schema.String>>;
197
+ /**
198
+ * How the action behaves, as MCP tool annotations tell agents. Written only when the action
199
+ * declares hints; absent reads as destructive and not idempotent.
200
+ */
201
+ readonly hints: Schema.optionalKey<Schema.Struct<{
202
+ readonly destructive: Schema.optionalKey<Schema.Boolean>;
203
+ readonly idempotent: Schema.optionalKey<Schema.Boolean>;
204
+ }>>;
185
205
  }>>;
186
206
  /** Always written; absent from version 1 manifests. */
187
207
  readonly permissions: Schema.optionalKey<Schema.Struct<{
@@ -227,7 +247,7 @@ export declare const OntologyManifestWire: Schema.encodeKeys<Schema.Struct<{
227
247
  readonly column: Schema.optionalKey<Schema.String>;
228
248
  readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
229
249
  readonly name: Schema.String;
230
- readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
250
+ readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
231
251
  readonly label: Schema.String;
232
252
  readonly description: Schema.optionalKey<Schema.String>;
233
253
  readonly optional: Schema.Boolean;
@@ -239,6 +259,8 @@ export declare const OntologyManifestWire: Schema.encodeKeys<Schema.Struct<{
239
259
  readonly min: Schema.optionalKey<Schema.Number>;
240
260
  readonly max: Schema.optionalKey<Schema.Number>;
241
261
  readonly maxLength: Schema.optionalKey<Schema.Number>;
262
+ readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
263
+ readonly maxBytes: Schema.optionalKey<Schema.Number>;
242
264
  readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
243
265
  readonly value: Schema.String;
244
266
  readonly label: Schema.String;
@@ -247,6 +269,7 @@ export declare const OntologyManifestWire: Schema.encodeKeys<Schema.Struct<{
247
269
  }>, {
248
270
  readonly renamedFrom: "renamed_from";
249
271
  readonly maxLength: "max_length";
272
+ readonly maxBytes: "max_bytes";
250
273
  }>>;
251
274
  readonly relationships: Schema.$Array<Schema.encodeKeys<Schema.Struct<{
252
275
  readonly on: Schema.optionalKey<Schema.encodeKeys<Schema.Struct<{
@@ -311,6 +334,14 @@ export declare const OntologyManifestWire: Schema.encodeKeys<Schema.Struct<{
311
334
  * when there are some; absent reads as none.
312
335
  */
313
336
  readonly connections: Schema.optionalKey<Schema.$Array<Schema.String>>;
337
+ /**
338
+ * How the action behaves, as MCP tool annotations tell agents. Written only when the action
339
+ * declares hints; absent reads as destructive and not idempotent.
340
+ */
341
+ readonly hints: Schema.optionalKey<Schema.Struct<{
342
+ readonly destructive: Schema.optionalKey<Schema.Boolean>;
343
+ readonly idempotent: Schema.optionalKey<Schema.Boolean>;
344
+ }>>;
314
345
  }>>;
315
346
  /** Always written; absent from version 1 manifests. */
316
347
  readonly permissions: Schema.optionalKey<Schema.Struct<{
@@ -359,7 +390,7 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
359
390
  readonly column: Schema.optionalKey<Schema.String>;
360
391
  readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
361
392
  readonly name: Schema.String;
362
- readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
393
+ readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
363
394
  readonly label: Schema.String;
364
395
  readonly description: Schema.optionalKey<Schema.String>;
365
396
  readonly optional: Schema.Boolean;
@@ -371,6 +402,8 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
371
402
  readonly min: Schema.optionalKey<Schema.Number>;
372
403
  readonly max: Schema.optionalKey<Schema.Number>;
373
404
  readonly maxLength: Schema.optionalKey<Schema.Number>;
405
+ readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
406
+ readonly maxBytes: Schema.optionalKey<Schema.Number>;
374
407
  readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
375
408
  readonly value: Schema.String;
376
409
  readonly label: Schema.String;
@@ -379,6 +412,7 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
379
412
  }>, {
380
413
  readonly renamedFrom: "renamed_from";
381
414
  readonly maxLength: "max_length";
415
+ readonly maxBytes: "max_bytes";
382
416
  }>>;
383
417
  readonly relationships: Schema.$Array<Schema.encodeKeys<Schema.Struct<{
384
418
  readonly on: Schema.optionalKey<Schema.encodeKeys<Schema.Struct<{
@@ -443,6 +477,14 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
443
477
  * when there are some; absent reads as none.
444
478
  */
445
479
  readonly connections: Schema.optionalKey<Schema.$Array<Schema.String>>;
480
+ /**
481
+ * How the action behaves, as MCP tool annotations tell agents. Written only when the action
482
+ * declares hints; absent reads as destructive and not idempotent.
483
+ */
484
+ readonly hints: Schema.optionalKey<Schema.Struct<{
485
+ readonly destructive: Schema.optionalKey<Schema.Boolean>;
486
+ readonly idempotent: Schema.optionalKey<Schema.Boolean>;
487
+ }>>;
446
488
  }>>;
447
489
  /** Always written; absent from version 1 manifests. */
448
490
  readonly permissions: Schema.optionalKey<Schema.Struct<{
@@ -514,7 +556,7 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
514
556
  readonly column: Schema.optionalKey<Schema.String>;
515
557
  readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
516
558
  readonly name: Schema.String;
517
- readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
559
+ readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
518
560
  readonly label: Schema.String;
519
561
  readonly description: Schema.optionalKey<Schema.String>;
520
562
  readonly optional: Schema.Boolean;
@@ -526,6 +568,8 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
526
568
  readonly min: Schema.optionalKey<Schema.Number>;
527
569
  readonly max: Schema.optionalKey<Schema.Number>;
528
570
  readonly maxLength: Schema.optionalKey<Schema.Number>;
571
+ readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
572
+ readonly maxBytes: Schema.optionalKey<Schema.Number>;
529
573
  readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
530
574
  readonly value: Schema.String;
531
575
  readonly label: Schema.String;
@@ -570,6 +614,14 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
570
614
  * when there are some; absent reads as none.
571
615
  */
572
616
  readonly connections: Schema.optionalKey<Schema.$Array<Schema.String>>;
617
+ /**
618
+ * How the action behaves, as MCP tool annotations tell agents. Written only when the action
619
+ * declares hints; absent reads as destructive and not idempotent.
620
+ */
621
+ readonly hints: Schema.optionalKey<Schema.Struct<{
622
+ readonly destructive: Schema.optionalKey<Schema.Boolean>;
623
+ readonly idempotent: Schema.optionalKey<Schema.Boolean>;
624
+ }>>;
573
625
  }>>;
574
626
  /** Always written; absent from version 1 manifests. */
575
627
  readonly permissions: Schema.optionalKey<Schema.Struct<{
@@ -617,13 +669,17 @@ export declare const decodeManifestDocument: (value: unknown) => Effect.Effect<{
617
669
  };
618
670
  readonly permission?: string | undefined;
619
671
  readonly connections?: readonly string[] | undefined;
672
+ readonly hints?: {
673
+ readonly destructive?: boolean | undefined;
674
+ readonly idempotent?: boolean | undefined;
675
+ } | undefined;
620
676
  }[];
621
677
  readonly title: string;
622
678
  readonly properties: readonly {
623
679
  readonly optional: boolean;
624
680
  readonly name: string;
625
681
  readonly label: string;
626
- readonly type: "number" | "boolean" | "text" | "integer" | "date" | "timestamp" | "select" | "email" | "url" | "json";
682
+ readonly type: "number" | "boolean" | "text" | "integer" | "date" | "timestamp" | "select" | "email" | "url" | "json" | "blob";
627
683
  readonly unique: boolean;
628
684
  readonly managed: boolean;
629
685
  readonly column?: string | undefined;
@@ -640,6 +696,8 @@ export declare const decodeManifestDocument: (value: unknown) => Effect.Effect<{
640
696
  }[] | undefined;
641
697
  readonly renamedFrom?: string | undefined;
642
698
  readonly display?: string | undefined;
699
+ readonly accept?: readonly string[] | undefined;
700
+ readonly maxBytes?: number | undefined;
643
701
  }[];
644
702
  readonly relationships: readonly {
645
703
  readonly name: string;
@@ -715,13 +773,17 @@ export declare const decodeManifestDocument: (value: unknown) => Effect.Effect<{
715
773
  };
716
774
  readonly permission?: string | undefined;
717
775
  readonly connections?: readonly string[] | undefined;
776
+ readonly hints?: {
777
+ readonly destructive?: boolean | undefined;
778
+ readonly idempotent?: boolean | undefined;
779
+ } | undefined;
718
780
  }[];
719
781
  readonly title: string;
720
782
  readonly properties: readonly {
721
783
  readonly optional: boolean;
722
784
  readonly name: string;
723
785
  readonly label: string;
724
- readonly type: "number" | "boolean" | "text" | "integer" | "date" | "timestamp" | "select" | "email" | "url" | "json";
786
+ readonly type: "number" | "boolean" | "text" | "integer" | "date" | "timestamp" | "select" | "email" | "url" | "json" | "blob";
725
787
  readonly unique: boolean;
726
788
  readonly managed: boolean;
727
789
  readonly column?: string | undefined;
@@ -738,6 +800,8 @@ export declare const decodeManifestDocument: (value: unknown) => Effect.Effect<{
738
800
  }[] | undefined;
739
801
  readonly renamedFrom?: string | undefined;
740
802
  readonly display?: string | undefined;
803
+ readonly accept?: readonly string[] | undefined;
804
+ readonly maxBytes?: number | undefined;
741
805
  }[];
742
806
  readonly relationships: readonly {
743
807
  readonly name: string;
package/dist/manifest.js CHANGED
@@ -36,6 +36,8 @@ export const PropertyManifest = Schema.Struct({
36
36
  min: Schema.optionalKey(Schema.Number),
37
37
  max: Schema.optionalKey(Schema.Number),
38
38
  maxLength: Schema.optionalKey(Schema.Number),
39
+ accept: Schema.optionalKey(Schema.Array(Schema.String)),
40
+ maxBytes: Schema.optionalKey(Schema.Number),
39
41
  options: Schema.optionalKey(Schema.Array(SelectOptionManifest)),
40
42
  });
41
43
  /**
@@ -77,6 +79,14 @@ export const ActionManifest = Schema.Struct({
77
79
  * when there are some; absent reads as none.
78
80
  */
79
81
  connections: Schema.optionalKey(Schema.Array(Schema.String)),
82
+ /**
83
+ * How the action behaves, as MCP tool annotations tell agents. Written only when the action
84
+ * declares hints; absent reads as destructive and not idempotent.
85
+ */
86
+ hints: Schema.optionalKey(Schema.Struct({
87
+ destructive: Schema.optionalKey(Schema.Boolean),
88
+ idempotent: Schema.optionalKey(Schema.Boolean),
89
+ })),
80
90
  });
81
91
  /**
82
92
  * The permissions of an entity's reads and generated actions, so that readers need not rebuild the
@@ -160,7 +170,11 @@ const OntologyManifestModel = Schema.Struct({
160
170
  /** The connections the actions call. Written only when there are some; absent reads as none. */
161
171
  connections: Schema.optionalKey(Schema.Array(ConnectionManifest)),
162
172
  });
163
- const PropertyManifestWire = PropertyManifest.pipe(Schema.encodeKeys({ renamedFrom: "renamed_from", maxLength: "max_length" }));
173
+ const PropertyManifestWire = PropertyManifest.pipe(Schema.encodeKeys({
174
+ renamedFrom: "renamed_from",
175
+ maxLength: "max_length",
176
+ maxBytes: "max_bytes",
177
+ }));
164
178
  const OnDeleteWire = Schema.Literals(["set_null", "cascade", "restrict"]).pipe(Schema.decodeTo(Schema.Literals(ON_DELETE), SchemaTransformation.transform({
165
179
  decode: (value) => (value === "set_null" ? "setNull" : value),
166
180
  encode: (value) => (value === "setNull" ? "set_null" : value),
@@ -265,6 +279,8 @@ function propertyManifest({ name, definition }) {
265
279
  ...(definition.min !== undefined ? { min: definition.min } : {}),
266
280
  ...(definition.max !== undefined ? { max: definition.max } : {}),
267
281
  ...(definition.maxLength !== undefined ? { maxLength: definition.maxLength } : {}),
282
+ ...(definition.accept !== undefined ? { accept: definition.accept } : {}),
283
+ ...(definition.maxBytes !== undefined ? { maxBytes: definition.maxBytes } : {}),
268
284
  ...(definition.options !== undefined
269
285
  ? {
270
286
  options: definition.options.map((option) => ({
@@ -344,6 +360,7 @@ function entityManifest(resolved) {
344
360
  permission: action.permission,
345
361
  input: action.input ?? {},
346
362
  ...(action.connections.length > 0 ? { connections: [...action.connections] } : {}),
363
+ ...(action.hints !== undefined ? { hints: { ...action.hints } } : {}),
347
364
  })),
348
365
  permissions: { ...resolved.permissions },
349
366
  };
@@ -54,6 +54,13 @@ export declare const applyMigration: (plan: MigrationPlan, options: ApplyMigrati
54
54
  * workspace database first as a dry run, then on production: the plan is made against each database's
55
55
  * own catalog.
56
56
  */
57
+ /** The runtime's tables, beside the catalog and the entity tables. */
58
+ export declare const RUNTIME_TABLES: ReadonlyArray<string>;
59
+ /**
60
+ * The runtime tables the database has, for `planMigration`'s `existingTables`: a database that an
61
+ * earlier SDK migrated lacks the tables added since.
62
+ */
63
+ export declare const readRuntimeTables: (input: CatalogInput) => Effect.Effect<ReadonlySet<string>, SqlError>;
57
64
  export declare const migrate: (input: MigrateInput) => Effect.Effect<{
58
65
  readonly plan: MigrationPlan;
59
66
  readonly result: MigrationResult;
@@ -3,7 +3,7 @@ import { canonicalJson, decodeManifestDocument, encodeManifest, manifestHash, }
3
3
  import { CatalogInvalid, CatalogMismatch, MigrationFailed, MigrationRefused } from "./errors.js";
4
4
  import { isNoopMigration } from "./model.js";
5
5
  import { planMigration } from "./plan.js";
6
- import { CATALOG_TABLE, quoteIdentifier } from "./storage.js";
6
+ import { API_KEYS_TABLE, CATALOG_TABLE, OAUTH_TABLES, USER_ROLES_TABLE, quoteIdentifier, quoteLiteral, } from "./storage.js";
7
7
  const CATALOG = quoteIdentifier(CATALOG_TABLE);
8
8
  /** Serializes migrations of one database; transaction-scoped, so it ends with the transaction. */
9
9
  const MIGRATION_LOCK = "segmentstream.ontology.migration";
@@ -133,11 +133,28 @@ export const applyMigration = (plan, options) => Effect.gen(function* () {
133
133
  * workspace database first as a dry run, then on production: the plan is made against each database's
134
134
  * own catalog.
135
135
  */
136
+ /** The runtime's tables, beside the catalog and the entity tables. */
137
+ export const RUNTIME_TABLES = [
138
+ USER_ROLES_TABLE,
139
+ API_KEYS_TABLE,
140
+ ...OAUTH_TABLES,
141
+ ];
142
+ /**
143
+ * The runtime tables the database has, for `planMigration`'s `existingTables`: a database that an
144
+ * earlier SDK migrated lacks the tables added since.
145
+ */
146
+ export const readRuntimeTables = (input) => input.sql
147
+ .unsafe(`SELECT "tablename" AS "name" FROM "pg_catalog"."pg_tables" ` +
148
+ `WHERE "schemaname" = current_schema() ` +
149
+ `AND "tablename" IN (${RUNTIME_TABLES.map(quoteLiteral).join(", ")})`)
150
+ .pipe(Effect.map((rows) => new Set(rows.map((row) => row.name))));
136
151
  export const migrate = (input) => Effect.gen(function* () {
137
152
  const current = yield* readCatalog({ sql: input.sql });
153
+ const existingTables = yield* readRuntimeTables({ sql: input.sql });
138
154
  const plan = planMigration({
139
155
  current,
140
156
  target: input.target,
157
+ existingTables,
141
158
  ...(input.options === undefined ? {} : { options: input.options }),
142
159
  });
143
160
  const result = yield* applyMigration(plan, input);
@@ -1,4 +1,4 @@
1
- export { applyMigration, migrate, readCatalog } from "./apply.js";
1
+ export { applyMigration, migrate, readCatalog, readRuntimeTables, RUNTIME_TABLES, } from "./apply.js";
2
2
  export type { ApplyMigrationError, ApplyMigrationOptions, CatalogInput, MigrateInput, MigrationResult, } from "./apply.js";
3
3
  export { CatalogInvalid, CatalogMismatch, MigrationFailed, MigrationRefused } from "./errors.js";
4
4
  export { isNoopMigration, MIGRATION_REFUSAL_CODES, MIGRATION_STEP_CLASSIFICATIONS, MIGRATION_STEP_KINDS, MigrationPlan, MigrationRefusal, MigrationStep, } from "./model.js";
@@ -1,4 +1,4 @@
1
- export { applyMigration, migrate, readCatalog } from "./apply.js";
1
+ export { applyMigration, migrate, readCatalog, readRuntimeTables, RUNTIME_TABLES, } from "./apply.js";
2
2
  export { CatalogInvalid, CatalogMismatch, MigrationFailed, MigrationRefused } from "./errors.js";
3
3
  export { isNoopMigration, MIGRATION_REFUSAL_CODES, MIGRATION_STEP_CLASSIFICATIONS, MIGRATION_STEP_KINDS, MigrationPlan, MigrationRefusal, MigrationStep, } from "./model.js";
4
4
  export { planMigration } from "./plan.js";
@@ -48,7 +48,7 @@ export declare const MigrationPlan: Schema.Struct<{
48
48
  readonly column: Schema.optionalKey<Schema.String>;
49
49
  readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
50
50
  readonly name: Schema.String;
51
- readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
51
+ readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
52
52
  readonly label: Schema.String;
53
53
  readonly description: Schema.optionalKey<Schema.String>;
54
54
  readonly optional: Schema.Boolean;
@@ -60,6 +60,8 @@ export declare const MigrationPlan: Schema.Struct<{
60
60
  readonly min: Schema.optionalKey<Schema.Number>;
61
61
  readonly max: Schema.optionalKey<Schema.Number>;
62
62
  readonly maxLength: Schema.optionalKey<Schema.Number>;
63
+ readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
64
+ readonly maxBytes: Schema.optionalKey<Schema.Number>;
63
65
  readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
64
66
  readonly value: Schema.String;
65
67
  readonly label: Schema.String;
@@ -68,6 +70,7 @@ export declare const MigrationPlan: Schema.Struct<{
68
70
  }>, {
69
71
  readonly renamedFrom: "renamed_from";
70
72
  readonly maxLength: "max_length";
73
+ readonly maxBytes: "max_bytes";
71
74
  }>>;
72
75
  readonly relationships: Schema.$Array<Schema.encodeKeys<Schema.Struct<{
73
76
  readonly on: Schema.optionalKey<Schema.encodeKeys<Schema.Struct<{
@@ -120,6 +123,10 @@ export declare const MigrationPlan: Schema.Struct<{
120
123
  readonly permission: Schema.optionalKey<Schema.String>;
121
124
  readonly input: Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>;
122
125
  readonly connections: Schema.optionalKey<Schema.$Array<Schema.String>>;
126
+ readonly hints: Schema.optionalKey<Schema.Struct<{
127
+ readonly destructive: Schema.optionalKey<Schema.Boolean>;
128
+ readonly idempotent: Schema.optionalKey<Schema.Boolean>;
129
+ }>>;
123
130
  }>>;
124
131
  readonly permissions: Schema.optionalKey<Schema.Struct<{
125
132
  readonly read: Schema.String;
@@ -182,7 +189,7 @@ export declare const MigrationPlan: Schema.Struct<{
182
189
  readonly column: Schema.optionalKey<Schema.String>;
183
190
  readonly scope: Schema.optionalKey<Schema.$Array<Schema.String>>;
184
191
  readonly name: Schema.String;
185
- readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json"]>;
192
+ readonly type: Schema.Literals<readonly ["text", "email", "url", "integer", "number", "boolean", "date", "timestamp", "select", "json", "blob"]>;
186
193
  readonly label: Schema.String;
187
194
  readonly description: Schema.optionalKey<Schema.String>;
188
195
  readonly optional: Schema.Boolean;
@@ -194,6 +201,8 @@ export declare const MigrationPlan: Schema.Struct<{
194
201
  readonly min: Schema.optionalKey<Schema.Number>;
195
202
  readonly max: Schema.optionalKey<Schema.Number>;
196
203
  readonly maxLength: Schema.optionalKey<Schema.Number>;
204
+ readonly accept: Schema.optionalKey<Schema.$Array<Schema.String>>;
205
+ readonly maxBytes: Schema.optionalKey<Schema.Number>;
197
206
  readonly options: Schema.optionalKey<Schema.$Array<Schema.Struct<{
198
207
  readonly value: Schema.String;
199
208
  readonly label: Schema.String;
@@ -225,6 +234,10 @@ export declare const MigrationPlan: Schema.Struct<{
225
234
  readonly permission: Schema.optionalKey<Schema.String>;
226
235
  readonly input: Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>;
227
236
  readonly connections: Schema.optionalKey<Schema.$Array<Schema.String>>;
237
+ readonly hints: Schema.optionalKey<Schema.Struct<{
238
+ readonly destructive: Schema.optionalKey<Schema.Boolean>;
239
+ readonly idempotent: Schema.optionalKey<Schema.Boolean>;
240
+ }>>;
228
241
  }>>;
229
242
  readonly permissions: Schema.optionalKey<Schema.Struct<{
230
243
  readonly read: Schema.String;
@@ -12,6 +12,12 @@ export interface PlanMigrationInput {
12
12
  readonly current: OntologyManifest | undefined;
13
13
  readonly target: OntologyManifest;
14
14
  readonly options?: MigrationOptions;
15
+ /**
16
+ * The runtime tables the database has, from `readRuntimeTables`. A database migrated by an earlier
17
+ * SDK lacks the tables added since, and the plan creates them. Without it, the plan assumes the
18
+ * database has every runtime table.
19
+ */
20
+ readonly existingTables?: ReadonlySet<string>;
15
21
  }
16
22
  /**
17
23
  * Plans the migration from the applied manifest to the target. It is pure: the same manifests always
@@ -1,5 +1,6 @@
1
+ import { BLOB_TABLES_DDL } from "../storage/tables.js";
1
2
  import { SNAKE_CASE_NAME, isSystemProperty, toSnakeCase } from "../names.js";
2
- import { CATALOG_TABLE_DDL, MAX_IDENTIFIER_LENGTH, USER_TABLE, addConstraintStatement, columnDefinition, constraintDefinition, createEnumStatement, createIndexStatement, createTableStatement, defaultExpression, entityStorage, enumTypeName, fieldColumnName, joinTable, propertyCheck, propertyColumn, propertyEnum, quoteIdentifier, quoteLiteral, relationshipColumn, RUNTIME_TABLES_DDL, relationshipForeignKey, SYSTEM_COLUMNS, tableName, } from "./storage.js";
3
+ import { CATALOG_TABLE_DDL, MAX_IDENTIFIER_LENGTH, OAUTH_TABLES, OAUTH_TABLES_DDL, USER_TABLE, addConstraintStatement, columnDefinition, constraintDefinition, createEnumStatement, createIndexStatement, createTableStatement, defaultExpression, entityStorage, enumTypeName, fieldColumnName, joinTable, propertyCheck, blobForeignKey, propertyColumn, propertyEnum, quoteIdentifier, quoteLiteral, relationshipColumn, RUNTIME_TABLES_DDL, relationshipForeignKey, SYSTEM_COLUMNS, tableName, } from "./storage.js";
3
4
  const GLOBAL_KINDS = new Set(["table", "type", "index"]);
4
5
  function step(input) {
5
6
  return {
@@ -68,10 +69,27 @@ export function planMigration(input) {
68
69
  draft.runtimeTables.push(step({
69
70
  kind: "createCatalog",
70
71
  classification: "additive",
71
- description: "Create the runtime's role assignment and API key tables.",
72
+ description: "Create the runtime's role assignment, API key and OAuth tables.",
72
73
  sql: RUNTIME_TABLES_DDL,
73
74
  }));
74
75
  }
76
+ else if (OAUTH_TABLES.some((table) => input.existingTables?.has(table) === false)) {
77
+ draft.runtimeTables.push(step({
78
+ kind: "createCatalog",
79
+ classification: "additive",
80
+ description: "Create the runtime's OAuth tables, which connect agents to the MCP server.",
81
+ sql: OAUTH_TABLES_DDL,
82
+ }));
83
+ }
84
+ if (storedTargets.some((entity) => entity.properties.some((property) => property.type === "blob")) &&
85
+ !current?.entities.some((entity) => entity.properties.some((property) => property.type === "blob"))) {
86
+ draft.runtimeTables.push(step({
87
+ kind: "createCatalog",
88
+ classification: "additive",
89
+ description: "Create the ontology's file revision and upload tables.",
90
+ sql: BLOB_TABLES_DDL,
91
+ }));
92
+ }
75
93
  planDrops({ pairs, removedEntities, addedEntities, allowDrops, draft });
76
94
  const renamed = planRenames({ pairs, draft });
77
95
  const appliedNames = new Set(storageObjects(currentEntities)
@@ -573,6 +591,12 @@ function logicalRenames(pairs, refusals) {
573
591
  path: `${pair.target.name}.properties.${to}`,
574
592
  description: `Rename property ${pair.target.name}.${from} to ${to}.`,
575
593
  apply: (model) => renameProperty(model, pair.target.id, from, to),
594
+ ...(pair.current.properties.some((property) => property.name === from && property.type === "blob")
595
+ ? {
596
+ metadataSql: ["_blobs", "_blob_uploads", "_blob_references"].map((table) => `UPDATE ${quoteIdentifier(table)} SET property_id = ${quoteLiteral(to)} ` +
597
+ `WHERE entity_id = ${quoteLiteral(pair.target.id)} AND property_id = ${quoteLiteral(from)}`),
598
+ }
599
+ : {}),
576
600
  });
577
601
  }
578
602
  }
@@ -595,7 +619,7 @@ function planRenames(input) {
595
619
  kind: rename.kind,
596
620
  classification: "rename",
597
621
  description: rename.description,
598
- sql: statements,
622
+ sql: [...statements, ...(rename.metadataSql ?? [])],
599
623
  }));
600
624
  model = next;
601
625
  }
@@ -893,6 +917,14 @@ function planEntityChanges(input) {
893
917
  }
894
918
  }
895
919
  for (const property of pair.addedProperties) {
920
+ if (property.type === "blob") {
921
+ draft.foreignKeys.push(step({
922
+ kind: "addProperty",
923
+ classification: "additive",
924
+ description: `Reference the file revision for ${entity}.${property.name}.`,
925
+ sql: [addConstraintStatement(table, blobForeignKey(entity, property))],
926
+ }));
927
+ }
896
928
  const enumStorage = propertyEnum(entity, property);
897
929
  const check = propertyCheck(entity, property);
898
930
  const column = propertyColumn(entity, property);
@@ -30,6 +30,7 @@ export declare const COLUMN_TYPES: {
30
30
  readonly date: "date";
31
31
  readonly timestamp: "timestamptz";
32
32
  readonly json: "jsonb";
33
+ readonly blob: "uuid";
33
34
  };
34
35
  export interface ColumnStorage {
35
36
  readonly name: string;
@@ -130,6 +131,7 @@ export declare function checkExpression(property: PropertyManifest): string | un
130
131
  export declare function propertyColumn(entity: string, property: PropertyManifest): ColumnStorage;
131
132
  export declare function propertyCheck(entity: string, property: PropertyManifest): ConstraintStorage | undefined;
132
133
  export declare function propertyEnum(entity: string, property: PropertyManifest): EnumStorage | undefined;
134
+ export declare function blobForeignKey(entity: string, property: PropertyManifest): ConstraintStorage;
133
135
  /** The key column of a `rel.one`. */
134
136
  export declare function relationshipColumn(relationship: RelationshipManifest): ColumnStorage;
135
137
  /** The foreign key of a `rel.one`, with its `onDelete` action. */
@@ -149,6 +151,18 @@ export declare const USER_ROLES_TABLE = "_user_roles";
149
151
  * secret only as a salted PBKDF2 hash.
150
152
  */
151
153
  export declare const API_KEYS_TABLE = "_api_keys";
154
+ /** OAuth clients that registered themselves to connect agents to the MCP server. */
155
+ export declare const OAUTH_CLIENTS_TABLE = "_oauth_clients";
156
+ /** Authorization requests waiting for a member's consent, for a few minutes. */
157
+ export declare const OAUTH_REQUESTS_TABLE = "_oauth_requests";
158
+ /** What a member allowed a client to do: revoking a grant stops its tokens. */
159
+ export declare const OAUTH_GRANTS_TABLE = "_oauth_grants";
160
+ /** Authorization codes, access tokens and refresh tokens, stored only as SHA-256 hashes. */
161
+ export declare const OAUTH_TOKENS_TABLE = "_oauth_tokens";
162
+ /** The OAuth tables, in the order they are created. */
163
+ export declare const OAUTH_TABLES: ReadonlyArray<string>;
164
+ /** The OAuth tables of the MCP server's authorization server. Every statement is idempotent. */
165
+ export declare const OAUTH_TABLES_DDL: ReadonlyArray<string>;
152
166
  /**
153
167
  * The runtime's own tables beside the catalog. They are created with it, after the entity tables
154
168
  * because they refer to the built-in user table, and every statement is idempotent.