@sequenceholdings/orm 2.6.2 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1459,14 +1459,21 @@ function normalizeCanonical(definition) {
1459
1459
  var BUILTIN_SQL_READ_HASH = "sha256:a50c477c952a5e0fe68ed158a4530e4aab573c09bcbb1a8ac454dc88a39a6258";
1460
1460
 
1461
1461
  // src/ir/index.ts
1462
- var IR_VERSION = 5;
1462
+ var IR_VERSION = 6;
1463
1463
  var LEGACY_IR_VERSION = 1;
1464
1464
  var GUARDED_IR_VERSION = 2;
1465
1465
  var COMPOSED_IR_VERSION = 3;
1466
1466
  var SQL_IR_VERSION = 4;
1467
1467
  var RUNTIME_SQL_IR_VERSION = 5;
1468
- var irVersionSchema = z.union([z.literal(LEGACY_IR_VERSION), z.literal(GUARDED_IR_VERSION), z.literal(COMPOSED_IR_VERSION), z.literal(SQL_IR_VERSION), z.literal(RUNTIME_SQL_IR_VERSION)]);
1468
+ var SERVICE_PRINCIPAL_IR_VERSION = 6;
1469
+ var irVersionSchema = z.union([z.literal(LEGACY_IR_VERSION), z.literal(GUARDED_IR_VERSION), z.literal(COMPOSED_IR_VERSION), z.literal(SQL_IR_VERSION), z.literal(RUNTIME_SQL_IR_VERSION), z.literal(SERVICE_PRINCIPAL_IR_VERSION)]);
1469
1470
  var operationVersionSchema = z.object({ irVersion: irVersionSchema });
1471
+ function usesServicePrincipal(value) {
1472
+ if (value === null || typeof value !== "object") return false;
1473
+ if (Array.isArray(value)) return value.some(usesServicePrincipal);
1474
+ const row = value;
1475
+ return row.kind === "servicePrincipal" || Object.values(row).some(usesServicePrincipal);
1476
+ }
1470
1477
  function requiredArtifactIrVersion(operations) {
1471
1478
  let required = LEGACY_IR_VERSION;
1472
1479
  for (const operation of operations) {
@@ -1526,6 +1533,7 @@ var predIrSchema = z.lazy(
1526
1533
  z.object({ kind: z.literal("capability"), key: z.string(), namespace: z.string().optional() }),
1527
1534
  z.object({ kind: z.literal("role"), key: z.string(), namespace: z.string().optional() }),
1528
1535
  z.object({ kind: z.literal("dynamicFilter"), slot: z.string() }),
1536
+ z.object({ kind: z.literal("servicePrincipal") }).strict(),
1529
1537
  z.object({ kind: z.literal("const"), value: z.boolean() })
1530
1538
  ])
1531
1539
  );
@@ -1751,7 +1759,7 @@ var variableIrSchema = z.object({
1751
1759
  /** Absent = no default declared; see {@link variableDefaultIrSchema}. */
1752
1760
  defaultValue: variableDefaultIrSchema.optional()
1753
1761
  });
1754
- var sqlColumnSchema = z.object({ name: z.string(), type: z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz"]), nullable: z.boolean() });
1762
+ var sqlColumnSchema = z.object({ name: z.string(), type: z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz", "jsonb"]), nullable: z.boolean() });
1755
1763
  var compiledOperationSchema = z.object({
1756
1764
  language: z.literal("sql").optional(),
1757
1765
  /** Server-compiled object catalog and permission ceiling, never caller SQL. */
@@ -1789,6 +1797,9 @@ var compiledOperationSchema = z.object({
1789
1797
  tableSet: z.array(z.string()).min(1),
1790
1798
  roots: z.array(rootIrSchema)
1791
1799
  }).superRefine((operation, ctx) => {
1800
+ if (operation.irVersion < SERVICE_PRINCIPAL_IR_VERSION && usesServicePrincipal(operation.roots)) {
1801
+ ctx.addIssue({ code: "custom", message: "servicePrincipal() requires IR v6" });
1802
+ }
1792
1803
  if (operation.language === "sql") {
1793
1804
  const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
1794
1805
  const builtin = operation.name === "BuiltinSqlRead" && operation.opHash === BUILTIN_SQL_READ_HASH && operation.requires === null;
@@ -1921,6 +1932,9 @@ var compiledArtifactSchema = z.object({
1921
1932
  tables: z.record(z.string(), tableMetaIrSchema),
1922
1933
  operations: z.record(z.string(), compiledOperationSchema)
1923
1934
  }).superRefine((artifact, ctx) => {
1935
+ if (artifact.irVersion < SERVICE_PRINCIPAL_IR_VERSION && usesServicePrincipal(artifact)) {
1936
+ ctx.addIssue({ code: "custom", message: "servicePrincipal() requires IR v6" });
1937
+ }
1924
1938
  if (Object.keys(artifact.dependencies ?? {}).length > 0 && artifact.irVersion < COMPOSED_IR_VERSION) {
1925
1939
  ctx.addIssue({ code: "custom", path: ["irVersion"], message: "cross-namespace dependencies require IR v3" });
1926
1940
  }
@@ -2229,6 +2243,12 @@ var Parser2 = class {
2229
2243
  }
2230
2244
  return node;
2231
2245
  }
2246
+ if (this.peekKeyword("servicePrincipal") && this.tokens[this.index + 1]?.kind === "lparen") {
2247
+ this.advance();
2248
+ this.expect("lparen", "'(' after servicePrincipal");
2249
+ this.expect("rparen", "')' closing servicePrincipal()");
2250
+ return { kind: "servicePrincipal" };
2251
+ }
2232
2252
  if (this.peekKeyword("exists")) return this.parseExists();
2233
2253
  if (this.peekKeyword("visible") && this.tokens[this.index + 1]?.kind === "lparen") return this.parseVisible();
2234
2254
  return this.parseComparison();
@@ -2441,6 +2461,8 @@ var PolicyCompiler = class _PolicyCompiler {
2441
2461
  return { kind: "capability", key: node.key };
2442
2462
  case "role":
2443
2463
  return { kind: "role", key: node.key };
2464
+ case "servicePrincipal":
2465
+ return { kind: "servicePrincipal" };
2444
2466
  case "exists":
2445
2467
  return this.compileExists(node.path, node.where, table, depth);
2446
2468
  case "visible":
@@ -3105,7 +3127,10 @@ function platformUserMeta() {
3105
3127
  { name: "role", columnName: "role", type: "text", nullable: true },
3106
3128
  { name: "managerId", columnName: "manager_id", type: "text", nullable: true },
3107
3129
  // NOT NULL DEFAULT true on chat.users, so non-null through the view.
3108
- { name: "accountEnabled", columnName: "account_enabled", type: "boolean", nullable: false }
3130
+ { name: "accountEnabled", columnName: "account_enabled", type: "boolean", nullable: false },
3131
+ { name: "canonicalSub", columnName: "canonical_sub", type: "text", nullable: false },
3132
+ { name: "normalizedEmail", columnName: "normalized_email", type: "text", nullable: true },
3133
+ { name: "emailDomain", columnName: "email_domain", type: "text", nullable: true }
3109
3134
  ];
3110
3135
  return {
3111
3136
  table: "users_directory",
@@ -5092,7 +5117,7 @@ function compileNamespace({ canonical, sdl, documents }) {
5092
5117
  }
5093
5118
  }
5094
5119
  operations[restricted.name] = {
5095
- irVersion: canonical.imports?.length ? COMPOSED_IR_VERSION : roots.some((root) => root.kind === "mutation" && root.assertAffectedRows !== void 0) ? GUARDED_IR_VERSION : LEGACY_IR_VERSION,
5120
+ irVersion: usesServicePrincipal(roots) ? SERVICE_PRINCIPAL_IR_VERSION : canonical.imports?.length ? COMPOSED_IR_VERSION : roots.some((root) => root.kind === "mutation" && root.assertAffectedRows !== void 0) ? GUARDED_IR_VERSION : LEGACY_IR_VERSION,
5096
5121
  name: restricted.name,
5097
5122
  opHash: computeOpHash({ definition: flattened, schemaHash }),
5098
5123
  kind: restricted.kind,
@@ -5119,7 +5144,7 @@ function compileNamespace({ canonical, sdl, documents }) {
5119
5144
  }
5120
5145
  if (diagnostics.some((d) => d.severity === "error")) return { ok: false, diagnostics };
5121
5146
  const artifact = {
5122
- irVersion: canonical.imports?.length ? COMPOSED_IR_VERSION : requiredArtifactIrVersion(Object.values(operations)),
5147
+ irVersion: usesServicePrincipal([...ctx.readPolicies.values(), ...ctx.writePolicies.values(), ...ctx.insertPolicies.values(), ...ctx.updatePolicies.values(), ...Object.values(operations)]) ? SERVICE_PRINCIPAL_IR_VERSION : canonical.imports?.length ? COMPOSED_IR_VERSION : requiredArtifactIrVersion(Object.values(operations)),
5123
5148
  namespace: ctx.namespace,
5124
5149
  schemaHash,
5125
5150
  ownSchemaHash: computeSchemaHash(localContract(canonical)),
@@ -5173,6 +5198,8 @@ function compilePredIrToSql(pred, options = {}) {
5173
5198
  return `(NOT ${compilePredIrToSql(pred.operand, options)})`;
5174
5199
  case "cmp":
5175
5200
  return compileCmp(pred.op, pred.column, pred.value, options);
5201
+ case "servicePrincipal":
5202
+ return `coalesce(${claimExpression("servicePrincipal")} = 'true', false)`;
5176
5203
  case "capability":
5177
5204
  return `(${options.statementClaimChecks ? "SELECT " : ""}${capabilityExpression(pred.key, pred.namespace ?? options.namespace)})`;
5178
5205
  case "role":
@@ -5275,6 +5302,39 @@ function compileArrayValue(value, columnType, _options) {
5275
5302
  return columnType ? `${array}::${sqlTypeName(columnType)}[]` : array;
5276
5303
  }
5277
5304
 
5305
+ // src/compiler/static-policy-sql.ts
5306
+ function compileStaticPolicySql({ table, predicate, tables, namespace, alias, rootRelation, statementClaimChecks, onRead }) {
5307
+ let sequence = 0;
5308
+ const aliases = new Set([alias, rootRelation].filter((value) => value !== void 0));
5309
+ const column = (meta, qualifier, name2) => {
5310
+ const found = meta.columns.find((c) => c.name === name2 || c.columnName === name2);
5311
+ if (!found) throw new OrmDefinitionError("Static policy relationship column is unavailable");
5312
+ return `${quoteIdentifier(qualifier)}.${quoteIdentifier(found.columnName)}`;
5313
+ };
5314
+ const render = (meta, pred, qualifier, outerRelation) => compilePredIrToSql(pred, {
5315
+ alias: qualifier,
5316
+ namespace: meta.namespace ?? namespace,
5317
+ statementClaimChecks,
5318
+ columnNames: Object.fromEntries(meta.columns.map((c) => [c.name, c.columnName])),
5319
+ columnTypes: Object.fromEntries(meta.columns.map((c) => [c.name, c.type])),
5320
+ exists: (node) => {
5321
+ const link = meta.links.find((candidate) => candidate.name === node.link);
5322
+ const target = link?.target ? tables[link.target] : void 0;
5323
+ const parent = qualifier ?? outerRelation;
5324
+ if (!link || !target || !parent) throw new OrmDefinitionError("Static policy relationship metadata is unavailable");
5325
+ onRead?.(target);
5326
+ let child;
5327
+ do {
5328
+ child = `policy_${++sequence}`;
5329
+ } while (aliases.has(child));
5330
+ aliases.add(child);
5331
+ const join5 = link.kind === "toMany" ? `${column(target, child, link.on)} = ${column(meta, parent, link.references)}` : `${column(meta, parent, link.on)} = ${column(target, child, link.references)}`;
5332
+ return `EXISTS (SELECT 1 FROM ${quoteIdentifier(target.schema)}.${quoteIdentifier(target.table)} AS ${quoteIdentifier(child)} WHERE ${join5} AND (${render(target, node.where, child)}))`;
5333
+ }
5334
+ });
5335
+ return render(table, predicate, alias, rootRelation);
5336
+ }
5337
+
5278
5338
  // src/sql/catalog.ts
5279
5339
  function sqlHash(value) {
5280
5340
  return `sha256:${createHash("sha256").update(value).digest("hex")}`;
@@ -5295,27 +5355,6 @@ function createSqlCatalog({ canonical, publishedObjects, executionTarget }) {
5295
5355
  const meta = Object.values(ctx.tables).find((table) => refOf(table) === ref);
5296
5356
  if (!meta || internal.has(ref) || meta.namespace !== canonical.namespace && !meta.exportRead) throw new Error(`SQL object not published: ${ref}`);
5297
5357
  const reads = /* @__PURE__ */ new Set([ref]);
5298
- let sequence = 0;
5299
- const predicate = (table, pred, alias) => compilePredIrToSql(pred, {
5300
- alias,
5301
- namespace: table.namespace ?? canonical.namespace,
5302
- columnNames: Object.fromEntries(table.columns.map((c) => [c.name, c.columnName])),
5303
- columnTypes: Object.fromEntries(table.columns.map((c) => [c.name, c.type])),
5304
- exists: (node) => {
5305
- const link = table.links.find((candidate) => candidate.name === node.link);
5306
- const target = link?.target ? ctx.tables[link.target] : void 0;
5307
- if (!link || !target) throw new Error("SQL policy link is unavailable");
5308
- reads.add(refOf(target));
5309
- const child = `p${++sequence}`;
5310
- const col = (t2, a, name2) => {
5311
- const c = t2.columns.find((c2) => c2.name === name2 || c2.columnName === name2);
5312
- if (!c) throw new Error("SQL policy column is unavailable");
5313
- return `${quoteIdentifier(a)}.${quoteIdentifier(c.columnName)}`;
5314
- };
5315
- const join5 = link.kind === "toMany" ? `${col(target, child, link.on)} = ${col(table, alias, link.references)}` : `${col(table, alias, link.on)} = ${col(target, child, link.references)}`;
5316
- return `EXISTS (SELECT 1 FROM ${quoteIdentifier(target.schema)}.${quoteIdentifier(target.table)} AS ${quoteIdentifier(child)} WHERE ${join5} AND (${predicate(target, node.where, child)}))`;
5317
- }
5318
- });
5319
5358
  const columns = meta.columns.filter((c) => meta.filterable.includes(c.name)).map((c) => ({
5320
5359
  name: c.name,
5321
5360
  type: typeof c.type === "string" ? c.type : "text",
@@ -5326,7 +5365,7 @@ function createSqlCatalog({ canonical, publishedObjects, executionTarget }) {
5326
5365
  return `${quoteIdentifier("p0")}.${quoteIdentifier(physical.columnName)}${typeof physical.type === "object" ? "::text" : ""} AS ${quoteIdentifier(c.name)}`;
5327
5366
  }).join(", ");
5328
5367
  const policy = ctx.readPolicies.get(meta.table) ?? { kind: "const", value: true };
5329
- const scan = `SELECT ${projection} FROM ${quoteIdentifier(meta.schema)}.${quoteIdentifier(meta.table)} AS ${quoteIdentifier("p0")} WHERE ${predicate(meta, policy, "p0")}`;
5368
+ const scan = `SELECT ${projection} FROM ${quoteIdentifier(meta.schema)}.${quoteIdentifier(meta.table)} AS ${quoteIdentifier("p0")} WHERE ${compileStaticPolicySql({ table: meta, predicate: policy, tables: ctx.tables, namespace: canonical.namespace, alias: "p0", onRead: (target) => reads.add(refOf(target)) })}`;
5330
5369
  return { ref, table: meta.table, columns, scan, read: [...reads].sort() };
5331
5370
  });
5332
5371
  return { identity, objects };
@@ -5950,7 +5989,7 @@ async function managedViewDiagnostics(canonical) {
5950
5989
  }
5951
5990
 
5952
5991
  // src/sql/codegen.ts
5953
- var typeOf = (type) => ["integer", "double"].includes(type) ? "number" : type === "boolean" ? "boolean" : "string";
5992
+ var typeOf = (type) => ["integer", "double"].includes(type) ? "number" : type === "boolean" ? "boolean" : type === "jsonb" ? "unknown" : "string";
5954
5993
  function generateSqlOperations({ artifact }) {
5955
5994
  const dynamic = Object.values(artifact.operations).some((op) => op.sqlQuery);
5956
5995
  const lines = [
@@ -5987,6 +6026,15 @@ ${variables}
5987
6026
  return `${lines.join("\n").trimEnd()}
5988
6027
  `;
5989
6028
  }
6029
+
6030
+ // src/runtime-capabilities.ts
6031
+ function assertServicePrincipalRuntime(value) {
6032
+ const row = value !== null && typeof value === "object" ? value : {};
6033
+ const predicates = row.policyPredicates;
6034
+ if (typeof row.maxIrVersion !== "number" || row.maxIrVersion < 6 || !Array.isArray(predicates) || !predicates.includes("servicePrincipal")) {
6035
+ throw new Error("The target ORM runtime does not support servicePrincipal() / IR v6; deploy the reviewed runtime before applying this namespace");
6036
+ }
6037
+ }
5990
6038
  var ENUM_BRAND = "seq-enum";
5991
6039
  function isEnumRef(value) {
5992
6040
  return typeof value === "object" && value !== null && value.kind === ENUM_BRAND;
@@ -11962,6 +12010,10 @@ async function applyV2Command(rest, dir) {
11962
12010
  }
11963
12011
  const { loaded, sdl, documents, manifest } = compiled.project;
11964
12012
  const namespace = loaded.canonical.namespace;
12013
+ if (compiled.project.artifact.irVersion >= SERVICE_PRINCIPAL_IR_VERSION || usesServicePrincipal(compiled.project.artifact)) {
12014
+ const support = await apiRequestStrict("GET", "/api/orm/runtime-capabilities");
12015
+ assertServicePrincipalRuntime(support);
12016
+ }
11965
12017
  const workspace = await readMigrationWorkspace(dir, namespace);
11966
12018
  const migration = await loadCommittedTipMigrationV2({ dir, loaded, workspace });
11967
12019
  const registered = await apiRequestStrict("POST", "/api/orm/namespaces", {