@segmentstream-cloud/ontology 0.22.0 → 0.24.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 (56) hide show
  1. package/README.md +27 -2
  2. package/dist/aggregate-routes.d.ts +46 -9
  3. package/dist/aggregate-routes.js +186 -20
  4. package/dist/analyze.d.ts +12 -1
  5. package/dist/analyze.js +3 -1
  6. package/dist/diagnostics.d.ts +3 -3
  7. package/dist/diagnostics.js +2 -0
  8. package/dist/index.d.ts +3 -2
  9. package/dist/index.js +2 -1
  10. package/dist/manifest.d.ts +113 -2
  11. package/dist/manifest.js +33 -2
  12. package/dist/measure.d.ts +57 -6
  13. package/dist/measure.js +7 -2
  14. package/dist/migrate/apply.js +2 -1
  15. package/dist/migrate/model.d.ts +22 -0
  16. package/dist/migrate/plan.js +9 -1
  17. package/dist/migrate/storage.d.ts +3 -0
  18. package/dist/migrate/storage.js +10 -0
  19. package/dist/model-measures.d.ts +22 -0
  20. package/dist/model-measures.js +543 -0
  21. package/dist/ontology.d.ts +5 -4
  22. package/dist/permissions.d.ts +3 -0
  23. package/dist/permissions.js +8 -1
  24. package/dist/render.d.ts +15 -3
  25. package/dist/render.js +56 -3
  26. package/dist/runtime/history.d.ts +22 -0
  27. package/dist/runtime/history.js +2 -0
  28. package/dist/runtime/pipeline.js +6 -2
  29. package/dist/runtime/principals.d.ts +2 -0
  30. package/dist/runtime/principals.js +55 -0
  31. package/dist/runtime/reads.js +9 -1
  32. package/dist/runtime/service-binding.js +2 -1
  33. package/dist/runtime/workload.d.ts +23 -0
  34. package/dist/runtime/workload.js +22 -0
  35. package/dist/runtime/writes.js +7 -1
  36. package/dist/runtime.d.ts +3 -0
  37. package/dist/service/authentication.d.ts +11 -0
  38. package/dist/service/authentication.js +114 -5
  39. package/dist/service/catalog.d.ts +2 -1
  40. package/dist/service/catalog.js +7 -3
  41. package/dist/service/config.d.ts +4 -0
  42. package/dist/service/config.js +11 -0
  43. package/dist/service/handlers.js +2 -1
  44. package/dist/service/mcp/server.js +10 -6
  45. package/dist/service/mcp/tools.js +25 -10
  46. package/dist/service/operations.d.ts +25 -5
  47. package/dist/service/runtime-contract.d.ts +1 -0
  48. package/dist/service/schemas.d.ts +143 -0
  49. package/dist/service/schemas.js +11 -2
  50. package/dist/storage/attachments.js +4 -4
  51. package/dist/storage/authorization.d.ts +1 -1
  52. package/dist/storage/authorization.js +9 -4
  53. package/dist/storage/sessions.js +3 -3
  54. package/dist/storage/writes.js +1 -1
  55. package/dist/warehouse-backed.js +4 -0
  56. package/package.json +1 -1
@@ -13,9 +13,11 @@ import { type SignInOptions, type SignInPolicy } from "./sign-in.js";
13
13
  * a relationship with a warehouse-backed end carries `on` and omits `optional` and `onDelete`.
14
14
  * Version 6 adds the `countDistinct` measure operator and lets stored entities declare `measures`,
15
15
  * whose columns name the stored properties' replication view columns. Version 7 adds the avg, min,
16
- * max and filtered measure operators and balanceOver on measures.
16
+ * max and filtered measure operators and balanceOver on measures. Version 8 adds the top-level
17
+ * `measures`, the measures of the model, written only when the ontology declares some: each combines
18
+ * measures of entities, named `entity.measure`, with its inputs and its alignment.
17
19
  */
18
- export declare const MANIFEST_VERSION = 7;
20
+ export declare const MANIFEST_VERSION = 8;
19
21
  /** The phrase used for a direction the author did not phrase. */
20
22
  export declare const DEFAULT_PHRASE = "has";
21
23
  export declare const SelectOptionManifest: Schema.Struct<{
@@ -146,6 +148,27 @@ export declare const MeasureManifest: Schema.Struct<{
146
148
  readonly balanceOver: Schema.optionalKey<Schema.String>;
147
149
  }>;
148
150
  export type MeasureManifest = typeof MeasureManifest.Type;
151
+ /**
152
+ * A measure of the model, `defineOntology({ measures })`. Its expression is an entity measure's
153
+ * arithmetic whose `measure` nodes name `entity.measure`, with references to other model measures
154
+ * expanded. Names are wire names throughout.
155
+ */
156
+ export declare const ModelMeasureManifest: Schema.Struct<{
157
+ readonly name: Schema.String;
158
+ readonly label: Schema.String;
159
+ readonly description: Schema.String;
160
+ readonly unit: Schema.Literals<readonly ["number", "currency", "ratio", "percent"]>;
161
+ readonly format: Schema.Literals<readonly ["decimal", "currency", "percent"]>;
162
+ readonly expression: Schema.Codec<Schema.Json, Schema.Json, never, never>;
163
+ /** The entity measures the expression reads, `entity.measure`, each once, in reading order. */
164
+ readonly inputs: Schema.$Array<Schema.String>;
165
+ /**
166
+ * Groups of properties that stand for one another: each names every entity the measure reads,
167
+ * with a property or `null` for an entity without a counterpart.
168
+ */
169
+ readonly align: Schema.$Array<Schema.$Record<Schema.String, Schema.NullOr<Schema.String>>>;
170
+ }>;
171
+ export type ModelMeasureManifest = typeof ModelMeasureManifest.Type;
149
172
  export declare const EntityManifest: Schema.Struct<{
150
173
  readonly source: Schema.optionalKey<Schema.Struct<{
151
174
  readonly asset: Schema.String;
@@ -426,6 +449,7 @@ export declare const OntologyManifestWire: Schema.encodeKeys<Schema.Struct<{
426
449
  }>, {
427
450
  readonly builtIn: "built_in";
428
451
  }>>;
452
+ readonly runtimeCapabilities: Schema.optionalKey<Schema.$Array<Schema.String>>;
429
453
  readonly version: Schema.Int;
430
454
  /** `sha256:` and the hex digest of the canonical JSON of the manifest without `hash`. */
431
455
  readonly hash: Schema.String;
@@ -438,6 +462,25 @@ export declare const OntologyManifestWire: Schema.encodeKeys<Schema.Struct<{
438
462
  readonly key: Schema.String;
439
463
  readonly description: Schema.String;
440
464
  }>>>;
465
+ /**
466
+ * The measures of the model, since version 8. Written only when there are some; absent reads as
467
+ * none.
468
+ */
469
+ readonly measures: Schema.optionalKey<Schema.$Array<Schema.Struct<{
470
+ readonly name: Schema.String;
471
+ readonly label: Schema.String;
472
+ readonly description: Schema.String;
473
+ readonly unit: Schema.Literals<readonly ["number", "currency", "ratio", "percent"]>;
474
+ readonly format: Schema.Literals<readonly ["decimal", "currency", "percent"]>;
475
+ readonly expression: Schema.Codec<Schema.Json, Schema.Json, never, never>;
476
+ /** The entity measures the expression reads, `entity.measure`, each once, in reading order. */
477
+ readonly inputs: Schema.$Array<Schema.String>;
478
+ /**
479
+ * Groups of properties that stand for one another: each names every entity the measure reads,
480
+ * with a property or `null` for an entity without a counterpart.
481
+ */
482
+ readonly align: Schema.$Array<Schema.$Record<Schema.String, Schema.NullOr<Schema.String>>>;
483
+ }>>>;
441
484
  }>, {
442
485
  readonly signIn: "sign_in";
443
486
  }>;
@@ -577,6 +620,7 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
577
620
  }>, {
578
621
  readonly builtIn: "built_in";
579
622
  }>>;
623
+ readonly runtimeCapabilities: Schema.optionalKey<Schema.$Array<Schema.String>>;
580
624
  readonly version: Schema.Int;
581
625
  /** `sha256:` and the hex digest of the canonical JSON of the manifest without `hash`. */
582
626
  readonly hash: Schema.String;
@@ -589,9 +633,29 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
589
633
  readonly key: Schema.String;
590
634
  readonly description: Schema.String;
591
635
  }>>>;
636
+ /**
637
+ * The measures of the model, since version 8. Written only when there are some; absent reads as
638
+ * none.
639
+ */
640
+ readonly measures: Schema.optionalKey<Schema.$Array<Schema.Struct<{
641
+ readonly name: Schema.String;
642
+ readonly label: Schema.String;
643
+ readonly description: Schema.String;
644
+ readonly unit: Schema.Literals<readonly ["number", "currency", "ratio", "percent"]>;
645
+ readonly format: Schema.Literals<readonly ["decimal", "currency", "percent"]>;
646
+ readonly expression: Schema.Codec<Schema.Json, Schema.Json, never, never>;
647
+ /** The entity measures the expression reads, `entity.measure`, each once, in reading order. */
648
+ readonly inputs: Schema.$Array<Schema.String>;
649
+ /**
650
+ * Groups of properties that stand for one another: each names every entity the measure reads,
651
+ * with a property or `null` for an entity without a counterpart.
652
+ */
653
+ readonly align: Schema.$Array<Schema.$Record<Schema.String, Schema.NullOr<Schema.String>>>;
654
+ }>>>;
592
655
  }>, {
593
656
  readonly signIn: "sign_in";
594
657
  }>, Schema.Struct<{
658
+ readonly runtimeCapabilities: Schema.optionalKey<Schema.$Array<Schema.String>>;
595
659
  readonly version: Schema.Int;
596
660
  /** `sha256:` and the hex digest of the canonical JSON of the manifest without `hash`. */
597
661
  readonly hash: Schema.String;
@@ -731,6 +795,25 @@ export declare const OntologyManifest: Schema.Union<readonly [Schema.encodeKeys<
731
795
  readonly key: Schema.String;
732
796
  readonly description: Schema.String;
733
797
  }>>>;
798
+ /**
799
+ * The measures of the model, since version 8. Written only when there are some; absent reads as
800
+ * none.
801
+ */
802
+ readonly measures: Schema.optionalKey<Schema.$Array<Schema.Struct<{
803
+ readonly name: Schema.String;
804
+ readonly label: Schema.String;
805
+ readonly description: Schema.String;
806
+ readonly unit: Schema.Literals<readonly ["number", "currency", "ratio", "percent"]>;
807
+ readonly format: Schema.Literals<readonly ["decimal", "currency", "percent"]>;
808
+ readonly expression: Schema.Codec<Schema.Json, Schema.Json, never, never>;
809
+ /** The entity measures the expression reads, `entity.measure`, each once, in reading order. */
810
+ readonly inputs: Schema.$Array<Schema.String>;
811
+ /**
812
+ * Groups of properties that stand for one another: each names every entity the measure reads,
813
+ * with a property or `null` for an entity without a counterpart.
814
+ */
815
+ readonly align: Schema.$Array<Schema.$Record<Schema.String, Schema.NullOr<Schema.String>>>;
816
+ }>>>;
734
817
  }>]>;
735
818
  export type OntologyManifest = typeof OntologyManifest.Type;
736
819
  /** Retain the complete document when decoding a persisted or published manifest. */
@@ -833,10 +916,23 @@ export declare const decodeManifestDocument: (value: unknown) => Effect.Effect<{
833
916
  }[];
834
917
  readonly version: number;
835
918
  readonly hash: string;
919
+ readonly measures?: readonly {
920
+ readonly name: string;
921
+ readonly label: string;
922
+ readonly description: string;
923
+ readonly unit: "number" | "currency" | "ratio" | "percent";
924
+ readonly format: "decimal" | "currency" | "percent";
925
+ readonly expression: Schema.Json;
926
+ readonly inputs: readonly string[];
927
+ readonly align: readonly {
928
+ readonly [x: string]: string | null;
929
+ }[];
930
+ }[] | undefined;
836
931
  readonly connections?: readonly {
837
932
  readonly key: string;
838
933
  readonly description: string;
839
934
  }[] | undefined;
935
+ readonly runtimeCapabilities?: readonly string[] | undefined;
840
936
  readonly signIn?: {
841
937
  readonly policy: string;
842
938
  } | undefined;
@@ -939,10 +1035,23 @@ export declare const decodeManifestDocument: (value: unknown) => Effect.Effect<{
939
1035
  }[];
940
1036
  readonly version: number;
941
1037
  readonly hash: string;
1038
+ readonly measures?: readonly {
1039
+ readonly name: string;
1040
+ readonly label: string;
1041
+ readonly description: string;
1042
+ readonly unit: "number" | "currency" | "ratio" | "percent";
1043
+ readonly format: "decimal" | "currency" | "percent";
1044
+ readonly expression: Schema.Json;
1045
+ readonly inputs: readonly string[];
1046
+ readonly align: readonly {
1047
+ readonly [x: string]: string | null;
1048
+ }[];
1049
+ }[] | undefined;
942
1050
  readonly connections?: readonly {
943
1051
  readonly key: string;
944
1052
  readonly description: string;
945
1053
  }[] | undefined;
1054
+ readonly runtimeCapabilities?: readonly string[] | undefined;
946
1055
  readonly signIn?: {
947
1056
  readonly policy: string;
948
1057
  } | undefined;
@@ -973,6 +1082,8 @@ export declare function buildManifest(input: {
973
1082
  readonly roles: ReadonlyArray<Role>;
974
1083
  readonly signIn: SignInOptions;
975
1084
  readonly connections?: ReadonlyArray<ResolvedConnection>;
1085
+ /** The measures of the model, resolved to their manifest form. */
1086
+ readonly measures?: ReadonlyArray<ModelMeasureManifest>;
976
1087
  }): OntologyManifest;
977
1088
  /** The keys of every connection the manifest's actions call, without duplicates. */
978
1089
  export declare function actionConnectionKeys(manifest: Pick<OntologyManifest, "entities">): Array<string>;
package/dist/manifest.js CHANGED
@@ -16,9 +16,11 @@ import { DEFAULT_SIGN_IN_POLICY, isSignInPolicy, } from "./sign-in.js";
16
16
  * a relationship with a warehouse-backed end carries `on` and omits `optional` and `onDelete`.
17
17
  * Version 6 adds the `countDistinct` measure operator and lets stored entities declare `measures`,
18
18
  * whose columns name the stored properties' replication view columns. Version 7 adds the avg, min,
19
- * max and filtered measure operators and balanceOver on measures.
19
+ * max and filtered measure operators and balanceOver on measures. Version 8 adds the top-level
20
+ * `measures`, the measures of the model, written only when the ontology declares some: each combines
21
+ * measures of entities, named `entity.measure`, with its inputs and its alignment.
20
22
  */
21
- export const MANIFEST_VERSION = 7;
23
+ export const MANIFEST_VERSION = 8;
22
24
  /** The first version whose documents use snake_case names on the wire. */
23
25
  const WIRE_MANIFEST_VERSION = 4;
24
26
  /** The phrase used for a direction the author did not phrase. */
@@ -139,6 +141,26 @@ export const MeasureManifest = Schema.Struct({
139
141
  */
140
142
  balanceOver: Schema.optionalKey(Schema.String),
141
143
  });
144
+ /**
145
+ * A measure of the model, `defineOntology({ measures })`. Its expression is an entity measure's
146
+ * arithmetic whose `measure` nodes name `entity.measure`, with references to other model measures
147
+ * expanded. Names are wire names throughout.
148
+ */
149
+ export const ModelMeasureManifest = Schema.Struct({
150
+ name: Schema.String,
151
+ label: Schema.String,
152
+ description: Schema.String,
153
+ unit: Schema.Literals(["number", "currency", "ratio", "percent"]),
154
+ format: Schema.Literals(["decimal", "currency", "percent"]),
155
+ expression: Schema.Json,
156
+ /** The entity measures the expression reads, `entity.measure`, each once, in reading order. */
157
+ inputs: Schema.Array(Schema.String),
158
+ /**
159
+ * Groups of properties that stand for one another: each names every entity the measure reads,
160
+ * with a property or `null` for an entity without a counterpart.
161
+ */
162
+ align: Schema.Array(Schema.Record(Schema.String, Schema.NullOr(Schema.String))),
163
+ });
142
164
  export const EntityManifest = Schema.Struct({
143
165
  source: Schema.optionalKey(Schema.Struct({
144
166
  asset: Schema.String,
@@ -191,6 +213,7 @@ export const SignInManifest = Schema.Struct({
191
213
  * `onDelete`) are validated because the migration planner must map every value to storage.
192
214
  */
193
215
  const OntologyManifestModel = Schema.Struct({
216
+ runtimeCapabilities: Schema.optionalKey(Schema.Array(Schema.String)),
194
217
  version: Schema.Int,
195
218
  /** `sha256:` and the hex digest of the canonical JSON of the manifest without `hash`. */
196
219
  hash: Schema.String,
@@ -200,6 +223,11 @@ const OntologyManifestModel = Schema.Struct({
200
223
  signIn: Schema.optionalKey(SignInManifest),
201
224
  /** The connections the actions call. Written only when there are some; absent reads as none. */
202
225
  connections: Schema.optionalKey(Schema.Array(ConnectionManifest)),
226
+ /**
227
+ * The measures of the model, since version 8. Written only when there are some; absent reads as
228
+ * none.
229
+ */
230
+ measures: Schema.optionalKey(Schema.Array(ModelMeasureManifest)),
203
231
  });
204
232
  const PropertyManifestWire = PropertyManifest.pipe(Schema.encodeKeys({
205
233
  renamedFrom: "renamed_from",
@@ -429,11 +457,13 @@ function entityManifest(input) {
429
457
  /** Builds the manifest of a resolved ontology that passed `check`. */
430
458
  export function buildManifest(input) {
431
459
  const connections = input.connections ?? [];
460
+ const measures = input.measures ?? [];
432
461
  const warehouseBacked = new Set(input.entities
433
462
  .filter((candidate) => candidate.entity.definition.source !== undefined)
434
463
  .map((candidate) => candidate.name));
435
464
  const body = {
436
465
  version: MANIFEST_VERSION,
466
+ runtimeCapabilities: ["pipeline-workload-tokens-v1"],
437
467
  entities: input.entities.map((candidate) => entityManifest({ resolved: candidate, warehouseBacked })),
438
468
  roles: input.roles.map((candidate) => ({
439
469
  name: candidate.name,
@@ -450,6 +480,7 @@ export function buildManifest(input) {
450
480
  })),
451
481
  }
452
482
  : {}),
483
+ ...(measures.length > 0 ? { measures } : {}),
453
484
  };
454
485
  return { ...body, hash: manifestHash(encodeManifest({ ...body, hash: "" })) };
455
486
  }
package/dist/measure.d.ts CHANGED
@@ -71,12 +71,62 @@ export type Measure = MeasureExpression & Partial<MeasureOptions> & {
71
71
  readonly where?: ReadonlyArray<MeasureCondition | MeasureColumnCondition>;
72
72
  /** An aggregate's balance property, as its builder's `balanceOver` option declares it. */
73
73
  readonly balanceOver?: string;
74
+ /** A measure of an entity reads that entity's rows only: alignment is for model measures. */
75
+ readonly align?: never;
74
76
  };
75
77
  export type Measures = Readonly<Record<string, Measure>>;
78
+ /**
79
+ * One group of a model measure's alignment: every entity the measure reads, by its TypeScript name,
80
+ * with its property that stands for the others', or `null` when the entity has no counterpart, as a
81
+ * current snapshot has no date.
82
+ */
83
+ export type AlignmentGroup = Readonly<Record<string, string | null>>;
84
+ /** The options of a model measure: a measure's options and how its entities' properties align. */
85
+ export interface ModelMeasureOptions extends MeasureOptions {
86
+ /**
87
+ * At most 5 groups of properties that stand for one another across the entities the measure
88
+ * reads, such as a sales date and a plan month. A request that groups or filters by one member of
89
+ * a group reads each entity through its own member. Properties of one group share a type, and a
90
+ * property appears in one group at most.
91
+ */
92
+ readonly align?: ReadonlyArray<AlignmentGroup>;
93
+ }
94
+ /**
95
+ * A measure of the model, declared in `defineOntology({ measures })`: arithmetic over measures of
96
+ * entities, `m.ref("entity.measure")`, and over other model measures, `m.ref("name")`. It reads
97
+ * entity measures and aggregates no rows of its own.
98
+ */
99
+ export type ModelMeasure = MeasureExpression & Partial<MeasureOptions> & {
100
+ readonly align?: ReadonlyArray<AlignmentGroup>;
101
+ };
102
+ export type ModelMeasures = Readonly<Record<string, ModelMeasure>>;
103
+ /** A model measure's options that declare an alignment, which only model measures take. */
104
+ type AlignedOptions = ModelMeasureOptions & {
105
+ readonly align: ReadonlyArray<AlignmentGroup>;
106
+ };
107
+ /**
108
+ * An argument of arithmetic: any expression but one that declares an alignment, which belongs on
109
+ * the model measure itself.
110
+ */
111
+ type Argument = MeasureExpression & {
112
+ readonly align?: never;
113
+ };
114
+ /** Arithmetic of two expressions; with `align` among its options, a model measure. */
115
+ interface Arithmetic {
116
+ (left: Argument, right: Argument, options: AlignedOptions): ModelMeasure;
117
+ (left: Argument, right: Argument, options?: MeasureOptions): Measure;
118
+ }
119
+ /** A reference to another measure; with `align` among its options, a model measure. */
120
+ interface Reference {
121
+ (name: string, options: AlignedOptions): ModelMeasure;
122
+ (name: string, options?: MeasureOptions): Measure;
123
+ }
76
124
  /**
77
125
  * Arithmetic combines aggregates; references name another measure of the same entity. Every
78
126
  * aggregate takes `where`, conditions on properties of the entity that the rows it reads must meet,
79
- * and `balanceOver`, the date its rows are snapshots over.
127
+ * and `balanceOver`, the date its rows are snapshots over. In `defineOntology({ measures })`,
128
+ * references name measures of entities, `m.ref("sales.revenue")`, or other model measures, and
129
+ * arithmetic and references take `align`.
80
130
  */
81
131
  export declare const m: {
82
132
  readonly count: (options?: AggregateOptions) => Measure;
@@ -93,12 +143,12 @@ export declare const m: {
93
143
  readonly min: (property: string, options?: AggregateOptions) => Measure;
94
144
  /** The greatest value of an integer or number property. Maximums do not add up. */
95
145
  readonly max: (property: string, options?: AggregateOptions) => Measure;
96
- readonly ref: (name: string, options?: MeasureOptions) => Measure;
146
+ readonly ref: Reference;
97
147
  readonly literal: (value: number | string, options?: MeasureOptions) => Measure;
98
- readonly add: (left: MeasureExpression, right: MeasureExpression, options?: MeasureOptions) => Measure;
99
- readonly subtract: (left: MeasureExpression, right: MeasureExpression, options?: MeasureOptions) => Measure;
100
- readonly multiply: (left: MeasureExpression, right: MeasureExpression, options?: MeasureOptions) => Measure;
101
- readonly divide: (left: MeasureExpression, right: MeasureExpression, options?: MeasureOptions) => Measure;
148
+ readonly add: Arithmetic;
149
+ readonly subtract: Arithmetic;
150
+ readonly multiply: Arithmetic;
151
+ readonly divide: Arithmetic;
102
152
  };
103
153
  /** The conditions an expression declares: an aggregate's `where` option, or a `filtered` node's. */
104
154
  export declare function conditionsOf(value: Measure | MeasureExpression): ReadonlyArray<MeasureCondition | MeasureColumnCondition> | undefined;
@@ -119,3 +169,4 @@ export declare function conditionProperty(condition: object): unknown;
119
169
  * naming columns too.
120
170
  */
121
171
  export declare function measureExpression(value: MeasureExpression, columns: ReadonlyMap<string, string>): MeasureExpression;
172
+ export {};
package/dist/measure.js CHANGED
@@ -3,6 +3,9 @@ export const MEASURE_AGGREGATES = ["count", "sum", "countDistinct", "avg", "min"
3
3
  function binary(op) {
4
4
  return (left, right, options) => ({ op, args: [left, right], ...options });
5
5
  }
6
+ function reference(name, options) {
7
+ return { op: "measure", name, ...options };
8
+ }
6
9
  /** An aggregate of one property of the entity. */
7
10
  function aggregate(op) {
8
11
  return (property, options) => ({
@@ -14,7 +17,9 @@ function aggregate(op) {
14
17
  /**
15
18
  * Arithmetic combines aggregates; references name another measure of the same entity. Every
16
19
  * aggregate takes `where`, conditions on properties of the entity that the rows it reads must meet,
17
- * and `balanceOver`, the date its rows are snapshots over.
20
+ * and `balanceOver`, the date its rows are snapshots over. In `defineOntology({ measures })`,
21
+ * references name measures of entities, `m.ref("sales.revenue")`, or other model measures, and
22
+ * arithmetic and references take `align`.
18
23
  */
19
24
  export const m = {
20
25
  count: (options) => ({ op: "count", ...options }),
@@ -31,7 +36,7 @@ export const m = {
31
36
  min: aggregate("min"),
32
37
  /** The greatest value of an integer or number property. Maximums do not add up. */
33
38
  max: aggregate("max"),
34
- ref: (name, options) => ({ op: "measure", name, ...options }),
39
+ ref: reference,
35
40
  literal: (value, options) => ({
36
41
  op: "literal",
37
42
  value: String(value),
@@ -7,7 +7,7 @@ import { REPLICATION_DDL, REPLICATION_SCHEMA_VERSION, replicationEntityDdl, } fr
7
7
  import { replicationMigrationRefusals } from "../replication/migrate.js";
8
8
  import { ATTACHMENTS_TABLE } from "../storage/tables.js";
9
9
  import { resolveReplicationSelection, } from "../replication/model.js";
10
- import { AGENT_TABLES, API_KEYS_TABLE, CATALOG_TABLE, OAUTH_TABLES, USER_ROLES_TABLE, quoteIdentifier, quoteLiteral, } from "./storage.js";
10
+ import { ACTION_ATTRIBUTION_TABLE, AGENT_TABLES, API_KEYS_TABLE, CATALOG_TABLE, OAUTH_TABLES, USER_ROLES_TABLE, quoteIdentifier, quoteLiteral, } from "./storage.js";
11
11
  const CATALOG = quoteIdentifier(CATALOG_TABLE);
12
12
  /** Serializes migrations of one database; transaction-scoped, so it ends with the transaction. */
13
13
  const MIGRATION_LOCK = "segmentstream.ontology.migration";
@@ -180,6 +180,7 @@ export const applyMigration = (plan, options) => Effect.gen(function* () {
180
180
  */
181
181
  /** The runtime's tables, beside the catalog and the entity tables. */
182
182
  export const RUNTIME_TABLES = [
183
+ ACTION_ATTRIBUTION_TABLE,
183
184
  USER_ROLES_TABLE,
184
185
  API_KEYS_TABLE,
185
186
  ...OAUTH_TABLES,
@@ -152,6 +152,7 @@ export declare const MigrationPlan: Schema.Struct<{
152
152
  }>, {
153
153
  readonly builtIn: "built_in";
154
154
  }>>;
155
+ readonly runtimeCapabilities: Schema.optionalKey<Schema.$Array<Schema.String>>;
155
156
  readonly version: Schema.Int;
156
157
  readonly hash: Schema.String;
157
158
  readonly signIn: Schema.optionalKey<Schema.Struct<{
@@ -161,9 +162,20 @@ export declare const MigrationPlan: Schema.Struct<{
161
162
  readonly key: Schema.String;
162
163
  readonly description: Schema.String;
163
164
  }>>>;
165
+ readonly measures: Schema.optionalKey<Schema.$Array<Schema.Struct<{
166
+ readonly name: Schema.String;
167
+ readonly label: Schema.String;
168
+ readonly description: Schema.String;
169
+ readonly unit: Schema.Literals<readonly ["number", "currency", "ratio", "percent"]>;
170
+ readonly format: Schema.Literals<readonly ["decimal", "currency", "percent"]>;
171
+ readonly expression: Schema.Codec<Schema.Json, Schema.Json, never, never>;
172
+ readonly inputs: Schema.$Array<Schema.String>;
173
+ readonly align: Schema.$Array<Schema.$Record<Schema.String, Schema.NullOr<Schema.String>>>;
174
+ }>>>;
164
175
  }>, {
165
176
  readonly signIn: "sign_in";
166
177
  }>, Schema.Struct<{
178
+ readonly runtimeCapabilities: Schema.optionalKey<Schema.$Array<Schema.String>>;
167
179
  readonly version: Schema.Int;
168
180
  readonly hash: Schema.String;
169
181
  readonly entities: Schema.$Array<Schema.Struct<{
@@ -267,6 +279,16 @@ export declare const MigrationPlan: Schema.Struct<{
267
279
  readonly key: Schema.String;
268
280
  readonly description: Schema.String;
269
281
  }>>>;
282
+ readonly measures: Schema.optionalKey<Schema.$Array<Schema.Struct<{
283
+ readonly name: Schema.String;
284
+ readonly label: Schema.String;
285
+ readonly description: Schema.String;
286
+ readonly unit: Schema.Literals<readonly ["number", "currency", "ratio", "percent"]>;
287
+ readonly format: Schema.Literals<readonly ["decimal", "currency", "percent"]>;
288
+ readonly expression: Schema.Codec<Schema.Json, Schema.Json, never, never>;
289
+ readonly inputs: Schema.$Array<Schema.String>;
290
+ readonly align: Schema.$Array<Schema.$Record<Schema.String, Schema.NullOr<Schema.String>>>;
291
+ }>>>;
270
292
  }>]>;
271
293
  /** Non-transactional steps first, then the steps of the one transaction, in execution order. */
272
294
  readonly steps: Schema.$Array<Schema.Struct<{
@@ -1,7 +1,7 @@
1
1
  import { isValueMatched, } from "../manifest.js";
2
2
  import { ATTACHMENTS_TABLE, ATTACHMENT_TABLES_DDL, BLOB_TABLES_DDL } from "../storage/tables.js";
3
3
  import { SNAKE_CASE_NAME, isSystemProperty, toSnakeCase } from "../names.js";
4
- import { AGENT_TABLES, AGENT_TABLES_DDL, 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";
4
+ import { ACTION_ATTRIBUTION_TABLE, ACTION_ATTRIBUTION_DDL, AGENT_TABLES, AGENT_TABLES_DDL, 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";
5
5
  const GLOBAL_KINDS = new Set(["table", "type", "index"]);
6
6
  function step(input) {
7
7
  return {
@@ -77,6 +77,14 @@ export function planMigration(input) {
77
77
  else {
78
78
  // A database an earlier SDK migrated lacks the tables added since; each set arrives on its own.
79
79
  const lacks = (tables) => tables.some((table) => input.existingTables?.has(table) === false);
80
+ if (lacks([ACTION_ATTRIBUTION_TABLE])) {
81
+ draft.runtimeTables.push(step({
82
+ kind: "createCatalog",
83
+ classification: "additive",
84
+ description: "Create the runtime's verified pipeline action attribution table.",
85
+ sql: ACTION_ATTRIBUTION_DDL,
86
+ }));
87
+ }
80
88
  if (lacks(OAUTH_TABLES)) {
81
89
  draft.runtimeTables.push(step({
82
90
  kind: "createCatalog",
@@ -180,6 +180,9 @@ export declare const AGENT_TABLES_DDL: ReadonlyArray<string>;
180
180
  * The runtime's own tables beside the catalog. They are created with it, after the entity tables
181
181
  * because they refer to the built-in user table, and every statement is idempotent.
182
182
  */
183
+ export declare const ACTION_ATTRIBUTION_TABLE = "_ontology_action_attribution";
184
+ /** Runtime audit metadata deliberately has no foreign key: deleted records retain their history. */
185
+ export declare const ACTION_ATTRIBUTION_DDL: ReadonlyArray<string>;
183
186
  export declare const RUNTIME_TABLES_DDL: ReadonlyArray<string>;
184
187
  export declare function columnDefinition(column: ColumnStorage): string;
185
188
  export declare function constraintDefinition(constraint: {
@@ -575,7 +575,17 @@ export const AGENT_TABLES_DDL = [
575
575
  * The runtime's own tables beside the catalog. They are created with it, after the entity tables
576
576
  * because they refer to the built-in user table, and every statement is idempotent.
577
577
  */
578
+ export const ACTION_ATTRIBUTION_TABLE = "_ontology_action_attribution";
579
+ /** Runtime audit metadata deliberately has no foreign key: deleted records retain their history. */
580
+ export const ACTION_ATTRIBUTION_DDL = [
581
+ `CREATE TABLE IF NOT EXISTS "${ACTION_ATTRIBUTION_TABLE}" (
582
+ "action_id" uuid PRIMARY KEY,
583
+ "execution" jsonb NOT NULL,
584
+ "at" timestamptz NOT NULL DEFAULT now()
585
+ )`,
586
+ ];
578
587
  export const RUNTIME_TABLES_DDL = [
588
+ ...ACTION_ATTRIBUTION_DDL,
579
589
  [
580
590
  `CREATE TABLE IF NOT EXISTS ${quoteIdentifier(USER_ROLES_TABLE)} (`,
581
591
  ` "user_id" uuid NOT NULL,`,
@@ -0,0 +1,22 @@
1
+ import type { ResolvedEntity } from "./analyze.js";
2
+ import type { Diagnostic, DiagnosticCode } from "./diagnostics.js";
3
+ import type { ModelMeasureManifest } from "./manifest.js";
4
+ type Report = (code: DiagnosticCode, path: string, message: string, severity?: Diagnostic["severity"]) => void;
5
+ /** The most measures a model declares. */
6
+ export declare const MAXIMUM_MODEL_MEASURES = 50;
7
+ /** The most distinct entity measures one model measure reads, references expanded. */
8
+ export declare const MAXIMUM_MODEL_MEASURE_INPUTS = 10;
9
+ /** The most alignment groups one model measure declares. */
10
+ export declare const MAXIMUM_ALIGNMENT_GROUPS = 5;
11
+ /**
12
+ * Resolves and checks the measures of the model, `defineOntology({ measures })`, against the
13
+ * resolved entities, whose measures were checked first (docs/ontology-aggregates-release-3-spec.md,
14
+ * "Declaring model measures"). Returns the manifest form of each measure that passed, in declaration
15
+ * order: references expanded, names on the wire, inputs in reading order.
16
+ */
17
+ export declare function resolveModelMeasures(input: {
18
+ readonly measures: unknown;
19
+ readonly entities: ReadonlyArray<ResolvedEntity>;
20
+ readonly report: Report;
21
+ }): ReadonlyArray<ModelMeasureManifest>;
22
+ export {};