@sequenceholdings/orm 2.1.1 → 2.3.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 (68) hide show
  1. package/README.md +3 -1
  2. package/dist/authoring.cjs +284 -99
  3. package/dist/authoring.cjs.map +1 -1
  4. package/dist/authoring.d.cts +31 -8
  5. package/dist/authoring.d.ts +31 -8
  6. package/dist/authoring.js +282 -100
  7. package/dist/authoring.js.map +1 -1
  8. package/dist/canonical.cjs +51 -3
  9. package/dist/canonical.cjs.map +1 -1
  10. package/dist/canonical.d.cts +838 -12
  11. package/dist/canonical.d.ts +838 -12
  12. package/dist/canonical.js +47 -4
  13. package/dist/canonical.js.map +1 -1
  14. package/dist/cli.cjs +5876 -4198
  15. package/dist/cli.cjs.map +1 -1
  16. package/dist/cli.js +5876 -4198
  17. package/dist/cli.js.map +1 -1
  18. package/dist/client.cjs +49 -32
  19. package/dist/client.cjs.map +1 -1
  20. package/dist/client.d.cts +49 -6
  21. package/dist/client.d.ts +49 -6
  22. package/dist/client.js +49 -32
  23. package/dist/client.js.map +1 -1
  24. package/dist/compiler.cjs +1275 -264
  25. package/dist/compiler.cjs.map +1 -1
  26. package/dist/compiler.d.cts +57 -3
  27. package/dist/compiler.d.ts +57 -3
  28. package/dist/compiler.js +1268 -265
  29. package/dist/compiler.js.map +1 -1
  30. package/dist/{constants-YoFGjIBM.d.cts → constants-C6EG6Wq7.d.cts} +1 -1
  31. package/dist/{constants-YoFGjIBM.d.ts → constants-C6EG6Wq7.d.ts} +1 -1
  32. package/dist/definition-DjfC7Lll.d.cts +91 -0
  33. package/dist/definition-DjfC7Lll.d.ts +91 -0
  34. package/dist/dynamic-input.cjs +2 -1
  35. package/dist/dynamic-input.cjs.map +1 -1
  36. package/dist/dynamic-input.d.cts +9 -2
  37. package/dist/dynamic-input.d.ts +9 -2
  38. package/dist/dynamic-input.js +2 -1
  39. package/dist/dynamic-input.js.map +1 -1
  40. package/dist/index.cjs +1103 -322
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +479 -19
  43. package/dist/index.d.ts +479 -19
  44. package/dist/index.js +1090 -323
  45. package/dist/index.js.map +1 -1
  46. package/dist/ir.cjs +93 -11
  47. package/dist/ir.cjs.map +1 -1
  48. package/dist/ir.d.cts +226 -15
  49. package/dist/ir.d.ts +226 -15
  50. package/dist/ir.js +88 -12
  51. package/dist/ir.js.map +1 -1
  52. package/dist/predicate-v2.cjs +116 -10
  53. package/dist/predicate-v2.cjs.map +1 -1
  54. package/dist/predicate-v2.d.cts +11 -3
  55. package/dist/predicate-v2.d.ts +11 -3
  56. package/dist/predicate-v2.js +116 -10
  57. package/dist/predicate-v2.js.map +1 -1
  58. package/dist/sdl.cjs +158 -22
  59. package/dist/sdl.cjs.map +1 -1
  60. package/dist/sdl.d.cts +8 -1
  61. package/dist/sdl.d.ts +8 -1
  62. package/dist/sdl.js +158 -22
  63. package/dist/sdl.js.map +1 -1
  64. package/package.json +5 -4
  65. package/src/codegen-gql/server-fns.cjs +2 -2
  66. package/templates/orm-namespace/AGENTS.md +10 -0
  67. package/templates/orm-namespace/CLAUDE.md +1 -84
  68. package/templates/orm-namespace/package.json +1 -1
@@ -34,6 +34,7 @@ var PolicyCompileError = class extends Error {
34
34
  var COLUMN_IDENTIFIER_PATTERN = /^_?[a-z][a-z0-9_]*$/;
35
35
  var MAX_IDENTIFIER_LENGTH = 63;
36
36
  var CAPABILITY_KEY_PATTERN = /^(?:org\/|app\/[a-z][a-z0-9-]{0,63}\/)?[a-z0-9-]{1,64}$/;
37
+ var QUALIFIED_TABLE_PATTERN = /^[a-z][a-z0-9_]{0,62}\.[a-z][a-z0-9_]{0,62}$/;
37
38
  var CELL_PARTS = ["at", "by", "rev", "source", "conflicts"];
38
39
  var CELL_PART_SUFFIX = {
39
40
  at: "__at",
@@ -563,6 +564,8 @@ var canonicalLinkSchema = zod.z.object({
563
564
  kind: zod.z.enum(["toOne", "toMany", "toPlatformUser"]),
564
565
  /** Target table name (namespace-local). Absent for toPlatformUser. */
565
566
  target: identifier2.optional(),
567
+ /** Owning namespace of an imported target; omitted for local links. */
568
+ namespace: identifier2.max(41).optional(),
566
569
  /** FK column on the owning side (toOne/toPlatformUser: on this table; toMany: on the target). */
567
570
  on: columnIdentifier,
568
571
  /** Referenced column on the target (default: target's PK / platform user `sub`). */
@@ -664,11 +667,12 @@ var canonicalForeignKeySchema = zod.z.object({
664
667
  }).strict();
665
668
  var canonicalTableSchema = zod.z.object({
666
669
  table: identifier2,
670
+ displayName: zod.z.string().trim().min(1).max(120).optional(),
667
671
  description: zod.z.string().max(2e3).optional(),
668
672
  /** Table-level rename hint (new in v2). */
669
673
  renamedFrom: identifier2.optional(),
670
- /** Synced/reflected read-only tables (`source: gold.*`) — v1 semantics. */
671
- source: zod.z.string().regex(/^gold\.[a-z][a-z0-9_]*$/).optional(),
674
+ /** Synced/reflected read-only tables (`source: schema.table`) — v1 semantics. */
675
+ source: zod.z.string().regex(QUALIFIED_TABLE_PATTERN).optional(),
672
676
  columns: zod.z.array(canonicalColumnSchema).default([]),
673
677
  primaryKey: zod.z.array(columnIdentifier).min(1).max(8).optional(),
674
678
  links: zod.z.array(canonicalLinkSchema).default([]),
@@ -821,7 +825,9 @@ function validateCellMetadata(table, index, ctx) {
821
825
  }
822
826
  }
823
827
  }
824
- zod.z.object({
828
+ var exportGateSchema = zod.z.union([zod.z.literal(true), zod.z.object({ capability: zod.z.string().min(1) }).strict(), zod.z.object({ role: zod.z.string().min(1) }).strict()]);
829
+ var relationExportSchema = zod.z.object({ read: exportGateSchema, write: exportGateSchema.optional() }).strict();
830
+ var localDefinitionSchema = zod.z.object({
825
831
  definition_format: zod.z.literal(CANONICAL_FORMAT),
826
832
  namespace: identifier2.max(41),
827
833
  description: zod.z.string().max(2e3).optional(),
@@ -829,6 +835,8 @@ zod.z.object({
829
835
  tables: zod.z.array(canonicalTableSchema).min(0).max(500),
830
836
  /** Optional to preserve byte-identical hashes for pre-view canonical v2 documents. */
831
837
  views: zod.z.array(canonicalViewSchema).max(500).optional(),
838
+ /** Target-owned cross-namespace access contract, using existing namespace grants. */
839
+ exports: zod.z.record(identifier2, relationExportSchema).optional(),
832
840
  /** Verbatim custom-roles grammar (@sequenceholdings/custom-roles-manifest). */
833
841
  capabilities: zod.z.object({
834
842
  roles: zod.z.unknown().optional(),
@@ -855,7 +863,16 @@ zod.z.object({
855
863
  }
856
864
  }
857
865
  const fkTables = new Map(definition.tables.map((table) => [table.table, table]));
866
+ const relations = /* @__PURE__ */ new Set([...fkTables.keys(), ...(definition.views ?? []).map((view) => view.view)]);
867
+ for (const name of Object.keys(definition.exports ?? {})) {
868
+ if (!relations.has(name)) ctx.addIssue({ code: "custom", path: ["exports", name], message: `export '${name}' is not a local object` });
869
+ }
858
870
  for (const [tableIndex, table] of definition.tables.entries()) {
871
+ for (const [linkIndex, link] of table.links.entries()) {
872
+ if (link.enforce && link.namespace !== void 0 && link.namespace !== definition.namespace) {
873
+ ctx.addIssue({ code: "custom", path: ["tables", tableIndex, "links", linkIndex], message: "physical foreign keys require a local target; use an ORM link without enforce" });
874
+ }
875
+ }
859
876
  const names = /* @__PURE__ */ new Set([
860
877
  ...table.primaryKey?.length ? [`${table.table}_pkey`] : [],
861
878
  ...table.columns.filter((column) => column.unique && !(table.primaryKey?.length === 1 && table.primaryKey[0] === column.columnName)).map((column) => `${table.table}_${column.columnName}_unique`),
@@ -1025,23 +1042,36 @@ zod.z.object({
1025
1042
  };
1026
1043
  for (const view of views) visit(view.view, []);
1027
1044
  });
1045
+ localDefinitionSchema.safeExtend({
1046
+ /** Flattened, pinned snapshots. Imported relations never participate in this namespace's DDL. */
1047
+ imports: zod.z.array(localDefinitionSchema).max(32).optional()
1048
+ });
1028
1049
 
1029
1050
  // src/ir/index.ts
1030
- var IR_VERSION = 2;
1031
1051
  var LEGACY_IR_VERSION = 1;
1032
- var irVersionSchema = zod.z.union([zod.z.literal(LEGACY_IR_VERSION), zod.z.literal(IR_VERSION)]);
1052
+ var GUARDED_IR_VERSION = 2;
1053
+ var COMPOSED_IR_VERSION = 3;
1054
+ var SQL_IR_VERSION = 4;
1055
+ var RUNTIME_SQL_IR_VERSION = 5;
1056
+ var irVersionSchema = zod.z.union([zod.z.literal(LEGACY_IR_VERSION), zod.z.literal(GUARDED_IR_VERSION), zod.z.literal(COMPOSED_IR_VERSION), zod.z.literal(SQL_IR_VERSION), zod.z.literal(RUNTIME_SQL_IR_VERSION)]);
1033
1057
  zod.z.object({ irVersion: irVersionSchema });
1034
1058
  var CLAIMS_CONTRACT = {
1035
1059
  sub: "string",
1036
1060
  org: "string?",
1061
+ ext_subject: "string?",
1062
+ ext_email: "string?",
1037
1063
  roles: "string[]",
1038
1064
  capabilities: "string[]"
1039
1065
  };
1066
+ var EXTERNAL_POLICY_CLAIM_KEYS = ["ext_subject", "ext_email"];
1067
+ function isExternalPolicyClaimKey(key) {
1068
+ return EXTERNAL_POLICY_CLAIM_KEYS.includes(key);
1069
+ }
1040
1070
  var scalarLiteral = zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean(), zod.z.null()]);
1041
1071
  var valueIrSchema = zod.z.discriminatedUnion("kind", [
1042
1072
  zod.z.object({ kind: zod.z.literal("literal"), value: zod.z.union([scalarLiteral, zod.z.array(scalarLiteral)]) }),
1043
1073
  zod.z.object({ kind: zod.z.literal("variable"), name: zod.z.string() }),
1044
- zod.z.object({ kind: zod.z.literal("claim"), key: zod.z.enum(["sub", "org"]) })
1074
+ zod.z.object({ kind: zod.z.literal("claim"), key: zod.z.enum(["sub", "org", ...EXTERNAL_POLICY_CLAIM_KEYS]) })
1045
1075
  ]);
1046
1076
  var CMP_OPS = [
1047
1077
  "eq",
@@ -1073,8 +1103,8 @@ var predIrSchema = zod.z.lazy(
1073
1103
  value: zod.z.number(),
1074
1104
  where: predIrSchema.optional()
1075
1105
  }),
1076
- zod.z.object({ kind: zod.z.literal("capability"), key: zod.z.string() }),
1077
- zod.z.object({ kind: zod.z.literal("role"), key: zod.z.string() }),
1106
+ zod.z.object({ kind: zod.z.literal("capability"), key: zod.z.string(), namespace: zod.z.string().optional() }),
1107
+ zod.z.object({ kind: zod.z.literal("role"), key: zod.z.string(), namespace: zod.z.string().optional() }),
1078
1108
  zod.z.object({ kind: zod.z.literal("dynamicFilter"), slot: zod.z.string() }),
1079
1109
  zod.z.object({ kind: zod.z.literal("const"), value: zod.z.boolean() })
1080
1110
  ])
@@ -1301,7 +1331,31 @@ var variableIrSchema = zod.z.object({
1301
1331
  /** Absent = no default declared; see {@link variableDefaultIrSchema}. */
1302
1332
  defaultValue: variableDefaultIrSchema.optional()
1303
1333
  });
1334
+ var sqlColumnSchema = zod.z.object({ name: zod.z.string(), type: zod.z.enum(["text", "boolean", "integer", "bigint", "numeric", "double", "uuid", "date", "timestamptz"]), nullable: zod.z.boolean() });
1304
1335
  var compiledOperationSchema = zod.z.object({
1336
+ language: zod.z.literal("sql").optional(),
1337
+ /** Server-compiled object catalog and permission ceiling, never caller SQL. */
1338
+ sqlQuery: zod.z.object({
1339
+ catalog: zod.z.object({
1340
+ identity: zod.z.string(),
1341
+ objects: zod.z.array(zod.z.object({
1342
+ ref: zod.z.string(),
1343
+ table: zod.z.string(),
1344
+ columns: zod.z.array(sqlColumnSchema.extend({ type: zod.z.string() })).min(1),
1345
+ scan: zod.z.string().min(1),
1346
+ read: zod.z.array(zod.z.string()).min(1)
1347
+ }).strict()).min(1).max(256)
1348
+ }).strict(),
1349
+ read: zod.z.array(zod.z.string()).min(1).max(256),
1350
+ maxRows: zod.z.number().int().min(1).max(1e4)
1351
+ }).strict().optional(),
1352
+ sql: zod.z.object({
1353
+ text: zod.z.string().min(1).max(1048576),
1354
+ columns: zod.z.array(sqlColumnSchema).min(1).max(256),
1355
+ parameters: zod.z.array(zod.z.string()).max(128),
1356
+ read: zod.z.array(zod.z.string()).min(1).max(256),
1357
+ maxRows: zod.z.number().int().min(1).max(1e4)
1358
+ }).strict().optional(),
1305
1359
  irVersion: irVersionSchema,
1306
1360
  name: zod.z.string(),
1307
1361
  opHash: zod.z.string().regex(/^sha256:[0-9a-f]{64}$/),
@@ -1313,8 +1367,16 @@ var compiledOperationSchema = zod.z.object({
1313
1367
  variables: zod.z.array(variableIrSchema),
1314
1368
  /** Every table the op touches — data-token scoping + audit. */
1315
1369
  tableSet: zod.z.array(zod.z.string()).min(1),
1316
- roots: zod.z.array(rootIrSchema).min(1)
1370
+ roots: zod.z.array(rootIrSchema)
1317
1371
  }).superRefine((operation, ctx) => {
1372
+ if (operation.language === "sql") {
1373
+ const validPlan = operation.sqlQuery ? !operation.sql && operation.irVersion === RUNTIME_SQL_IR_VERSION : !!operation.sql && operation.irVersion === SQL_IR_VERSION;
1374
+ if (!validPlan || operation.kind !== "query" || operation.roots.length !== 0 || !operation.requires?.capability) {
1375
+ ctx.addIssue({ code: "custom", message: "SQL operations require a query-only v4 plan or v5 runtime contract, capability, and no GraphQL roots" });
1376
+ }
1377
+ } else if (operation.sql || operation.sqlQuery || operation.roots.length === 0) {
1378
+ ctx.addIssue({ code: "custom", message: "GraphQL operations require roots and cannot carry SQL" });
1379
+ }
1318
1380
  for (const [index, root] of operation.roots.entries()) {
1319
1381
  if (root.kind !== "mutation" || root.assertAffectedRows === void 0) continue;
1320
1382
  if (operation.irVersion < 2 || operation.kind !== "mutation" || root.includeIf !== void 0) {
@@ -1361,11 +1423,16 @@ var resolvedMetaIrSchema = zod.z.object({
1361
1423
  });
1362
1424
  var tableMetaIrSchema = zod.z.object({
1363
1425
  table: zod.z.string(),
1426
+ namespace: zod.z.string().optional(),
1427
+ dependencies: zod.z.array(zod.z.string()).optional(),
1428
+ foreignReferences: zod.z.array(zod.z.object({ column: zod.z.string(), target: zod.z.string(), targetColumn: zod.z.string() })).optional(),
1429
+ exportRead: zod.z.union([zod.z.literal(true), zod.z.object({ capability: zod.z.string() }), zod.z.object({ role: zod.z.string() })]).optional(),
1430
+ exportWrite: zod.z.union([zod.z.literal(true), zod.z.object({ capability: zod.z.string() }), zod.z.object({ role: zod.z.string() })]).optional(),
1364
1431
  schema: zod.z.string(),
1365
1432
  typename: zod.z.string(),
1366
1433
  /**
1367
1434
  * True when statements over this relation evaluate a claims-gated synced
1368
- * view: synced twins (`source: gold.*`) materialize as views whose baked
1435
+ * view: synced twins (`source: schema.table`) materialize as views whose baked
1369
1436
  * policy reads `current_setting('request.jwt.claims')`, and namespace views
1370
1437
  * inherit the gate transitively through their declared dependencies. The
1371
1438
  * executor must stamp that GUC (transaction-scoped) before any statement
@@ -1424,10 +1491,18 @@ zod.z.object({
1424
1491
  irVersion: irVersionSchema,
1425
1492
  namespace: zod.z.string(),
1426
1493
  schemaHash: zod.z.string(),
1494
+ ownSchemaHash: zod.z.string().optional(),
1495
+ dependencies: zod.z.record(zod.z.string(), zod.z.string()).optional(),
1496
+ readPolicies: zod.z.record(zod.z.string(), predIrSchema).optional(),
1427
1497
  opsHash: zod.z.string(),
1498
+ /** Apply-observed synced objects without a serving backing; not part of the authored schema hash. */
1499
+ unbackedTables: zod.z.array(zod.z.string()).optional(),
1428
1500
  tables: zod.z.record(zod.z.string(), tableMetaIrSchema),
1429
1501
  operations: zod.z.record(zod.z.string(), compiledOperationSchema)
1430
1502
  }).superRefine((artifact, ctx) => {
1503
+ if (Object.keys(artifact.dependencies ?? {}).length > 0 && artifact.irVersion < COMPOSED_IR_VERSION) {
1504
+ ctx.addIssue({ code: "custom", path: ["irVersion"], message: "cross-namespace dependencies require IR v3" });
1505
+ }
1431
1506
  for (const [name, operation] of Object.entries(artifact.operations)) {
1432
1507
  if (operation.irVersion > artifact.irVersion) {
1433
1508
  ctx.addIssue({ code: "custom", path: ["operations", name, "irVersion"], message: "operation requires a newer IR version than its artifact" });
@@ -1746,6 +1821,7 @@ var PolicyCompiler = class {
1746
1821
  case "or":
1747
1822
  return { kind: node.kind, operands: node.operands.map((operand) => this.compile(operand, table, depth)) };
1748
1823
  case "not":
1824
+ assertNoNegatedExternalClaim(node.operand);
1749
1825
  return { kind: "not", operand: this.compile(node.operand, table, depth) };
1750
1826
  case "capability":
1751
1827
  return { kind: "capability", key: node.key };
@@ -1825,6 +1901,9 @@ var PolicyCompiler = class {
1825
1901
  columnCandidates(info)
1826
1902
  );
1827
1903
  }
1904
+ if (valueSide.kind === "claim" && isExternalPolicyClaimKey(valueSide.key)) {
1905
+ assertExternalClaimComparison({ op, key: valueSide.key, column: info.columns.find((c) => c.name === column) });
1906
+ }
1828
1907
  let cmp = this.buildCmp(op, column, valueSide);
1829
1908
  for (let i = links.length - 1; i >= 0; i -= 1) {
1830
1909
  cmp = { kind: "exists", link: links[i].name, where: cmp };
@@ -1845,6 +1924,33 @@ var PolicyCompiler = class {
1845
1924
  return { kind: "cmp", op: CMP_BY_OP[op], column, value };
1846
1925
  }
1847
1926
  };
1927
+ function assertExternalClaimComparison({ op, key, column }) {
1928
+ if (op !== "=") {
1929
+ throw new PolicyCompileError(
1930
+ `claim('${key}') supports = comparisons only, got '${op}'`,
1931
+ "unsupported-comparison"
1932
+ );
1933
+ }
1934
+ if (column?.type !== "text") {
1935
+ const actual = column?.type === void 0 ? "of unknown type" : typeof column.type === "string" ? column.type : "an enum";
1936
+ throw new PolicyCompileError(
1937
+ `claim('${key}') is text and compares to a text column only \u2014 '${column?.name ?? "?"}' is ${actual}`,
1938
+ "claim-type-mismatch"
1939
+ );
1940
+ }
1941
+ }
1942
+ function assertNoNegatedExternalClaim(operand) {
1943
+ walkPolicy(operand, (node) => {
1944
+ if (node.kind !== "compare") return;
1945
+ const claim = [node.left, node.right].find((side) => side.kind === "claim" && isExternalPolicyClaimKey(side.key));
1946
+ if (claim?.kind === "claim") {
1947
+ throw new PolicyCompileError(
1948
+ `claim('${claim.key}') cannot appear under not(): a negated borrower comparison admits other borrowers' rows`,
1949
+ "unsupported-comparison"
1950
+ );
1951
+ }
1952
+ });
1953
+ }
1848
1954
  function compilePredicateV2({ expression, table, resolver, maxLinkDepth }) {
1849
1955
  const parsed = typeof expression === "string" ? parsePolicy(expression) : expression;
1850
1956
  const compiler = new PolicyCompiler({ resolver, maxLinkDepth: maxLinkDepth ?? POLICY_MAX_LINK_DEPTH });