@sequenceholdings/orm 2.3.0 → 2.4.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.cjs +100 -66
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +100 -66
- package/dist/cli.js.map +1 -1
- package/dist/compiler.cjs +107 -38
- package/dist/compiler.cjs.map +1 -1
- package/dist/compiler.d.cts +6 -4
- package/dist/compiler.d.ts +6 -4
- package/dist/compiler.js +107 -38
- package/dist/compiler.js.map +1 -1
- package/dist/predicate-v2.cjs +95 -19
- package/dist/predicate-v2.cjs.map +1 -1
- package/dist/predicate-v2.d.cts +40 -3
- package/dist/predicate-v2.d.ts +40 -3
- package/dist/predicate-v2.js +95 -19
- package/dist/predicate-v2.js.map +1 -1
- package/package.json +1 -1
package/dist/compiler.d.cts
CHANGED
|
@@ -2,7 +2,7 @@ import { CanonicalEnum, CanonicalDefinition } from './canonical.cjs';
|
|
|
2
2
|
import { ClaimKey, PredIr, RootIr, InputRefKind, TableMetaIr, CompiledOperation, CompiledArtifact, VariableIr, OrderIr, SelectionIr } from './ir.cjs';
|
|
3
3
|
import { DocumentNode, OperationDefinitionNode, FragmentDefinitionNode, GraphQLSchema, ValueNode, SelectionSetNode } from 'graphql';
|
|
4
4
|
export { DynamicInputIssue, DynamicInputResult, NormalizedBoolExp, NormalizedOnConflict, NormalizedOrderBy, NormalizedRow, ORDER_BY_DIRECTIONS, ScalarKind, allowedBoolExpOperators, allowedOps, validateAppendInput, validateBoolExpInput, validateInsertInput, validateOnConflictInput, validateOrderByInput, validateSelectColumns, validateSetInput } from './dynamic-input.cjs';
|
|
5
|
-
export { CompilePolicyInput, CompilePredicateInput, POLICY_COMPARE_OPS, POLICY_MAX_LINK_DEPTH, ParsedPolicy, PolicyColumnInfo, PolicyCompareOp, PolicyCompileError, PolicyCompileErrorCode, PolicyLinkInfo, PolicyNode, PolicyOperand, PolicyParseError, PolicyResolver, PolicyTableInfo, assertClaimsOnlyWhen, compilePolicy, compilePredicateV2, parsePolicy, walkPolicy } from './predicate-v2.cjs';
|
|
5
|
+
export { CompilePolicyInput, CompilePredicateInput, POLICY_COMPARE_OPS, POLICY_MAX_LINK_DEPTH, ParsedPolicy, PolicyAccess, PolicyColumnInfo, PolicyCompareOp, PolicyCompileError, PolicyCompileErrorCode, PolicyLinkInfo, PolicyNode, PolicyOperand, PolicyParseError, PolicyResolver, PolicyTableInfo, assertClaimsOnlyWhen, compilePolicy, compilePredicateV2, parsePolicy, walkPolicy } from './predicate-v2.cjs';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
export { P as PLATFORM_USER_TYPENAME, c as camelCase, g as enumTypeName, p as pascalCase } from './naming-CU9ThP_E.cjs';
|
|
8
8
|
export { S as SqlOperationDefinition, d as defineOperation, s as sqlOperationDefinitionSchema } from './definition-DjfC7Lll.cjs';
|
|
@@ -50,9 +50,11 @@ declare class NamespaceCompileError extends Error {
|
|
|
50
50
|
* - document-authored relationship predicates (exists/aggPredicate) get the
|
|
51
51
|
* TARGET table's read policy injected too, so filtering through a link
|
|
52
52
|
* can't become an existence oracle on rows the caller can't read;
|
|
53
|
-
* - write policy AND-ed into update/delete row filters,
|
|
54
|
-
*
|
|
55
|
-
* exists
|
|
53
|
+
* - write policy AND-ed into update/delete row filters, set as the insert
|
|
54
|
+
* check for inserts, and re-checked against the NEW rows of every update.
|
|
55
|
+
* Link-traversing (exists/visible) write policies are evaluated by the data
|
|
56
|
+
* plane against the proposed rows in the same statement, so "only on a
|
|
57
|
+
* parent the caller can see" holds for inserts and FK-changing updates;
|
|
56
58
|
* - `col = claim(k)` AND-conjuncts of the write policy become pinned columns
|
|
57
59
|
* merged into every inserted row (and excluded from insertable/settable).
|
|
58
60
|
*/
|
package/dist/compiler.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { CanonicalEnum, CanonicalDefinition } from './canonical.js';
|
|
|
2
2
|
import { ClaimKey, PredIr, RootIr, InputRefKind, TableMetaIr, CompiledOperation, CompiledArtifact, VariableIr, OrderIr, SelectionIr } from './ir.js';
|
|
3
3
|
import { DocumentNode, OperationDefinitionNode, FragmentDefinitionNode, GraphQLSchema, ValueNode, SelectionSetNode } from 'graphql';
|
|
4
4
|
export { DynamicInputIssue, DynamicInputResult, NormalizedBoolExp, NormalizedOnConflict, NormalizedOrderBy, NormalizedRow, ORDER_BY_DIRECTIONS, ScalarKind, allowedBoolExpOperators, allowedOps, validateAppendInput, validateBoolExpInput, validateInsertInput, validateOnConflictInput, validateOrderByInput, validateSelectColumns, validateSetInput } from './dynamic-input.js';
|
|
5
|
-
export { CompilePolicyInput, CompilePredicateInput, POLICY_COMPARE_OPS, POLICY_MAX_LINK_DEPTH, ParsedPolicy, PolicyColumnInfo, PolicyCompareOp, PolicyCompileError, PolicyCompileErrorCode, PolicyLinkInfo, PolicyNode, PolicyOperand, PolicyParseError, PolicyResolver, PolicyTableInfo, assertClaimsOnlyWhen, compilePolicy, compilePredicateV2, parsePolicy, walkPolicy } from './predicate-v2.js';
|
|
5
|
+
export { CompilePolicyInput, CompilePredicateInput, POLICY_COMPARE_OPS, POLICY_MAX_LINK_DEPTH, ParsedPolicy, PolicyAccess, PolicyColumnInfo, PolicyCompareOp, PolicyCompileError, PolicyCompileErrorCode, PolicyLinkInfo, PolicyNode, PolicyOperand, PolicyParseError, PolicyResolver, PolicyTableInfo, assertClaimsOnlyWhen, compilePolicy, compilePredicateV2, parsePolicy, walkPolicy } from './predicate-v2.js';
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
export { P as PLATFORM_USER_TYPENAME, c as camelCase, g as enumTypeName, p as pascalCase } from './naming-CPfx7EfF.js';
|
|
8
8
|
export { S as SqlOperationDefinition, d as defineOperation, s as sqlOperationDefinitionSchema } from './definition-DjfC7Lll.js';
|
|
@@ -50,9 +50,11 @@ declare class NamespaceCompileError extends Error {
|
|
|
50
50
|
* - document-authored relationship predicates (exists/aggPredicate) get the
|
|
51
51
|
* TARGET table's read policy injected too, so filtering through a link
|
|
52
52
|
* can't become an existence oracle on rows the caller can't read;
|
|
53
|
-
* - write policy AND-ed into update/delete row filters,
|
|
54
|
-
*
|
|
55
|
-
* exists
|
|
53
|
+
* - write policy AND-ed into update/delete row filters, set as the insert
|
|
54
|
+
* check for inserts, and re-checked against the NEW rows of every update.
|
|
55
|
+
* Link-traversing (exists/visible) write policies are evaluated by the data
|
|
56
|
+
* plane against the proposed rows in the same statement, so "only on a
|
|
57
|
+
* parent the caller can see" holds for inserts and FK-changing updates;
|
|
56
58
|
* - `col = claim(k)` AND-conjuncts of the write policy become pinned columns
|
|
57
59
|
* merged into every inserted row (and excluded from insertable/settable).
|
|
58
60
|
*/
|
package/dist/compiler.js
CHANGED
|
@@ -1854,6 +1854,7 @@ var Parser2 = class {
|
|
|
1854
1854
|
return node;
|
|
1855
1855
|
}
|
|
1856
1856
|
if (this.peekKeyword("exists")) return this.parseExists();
|
|
1857
|
+
if (this.peekKeyword("visible") && this.tokens[this.index + 1]?.kind === "lparen") return this.parseVisible();
|
|
1857
1858
|
return this.parseComparison();
|
|
1858
1859
|
}
|
|
1859
1860
|
parseBooleanCall(fn) {
|
|
@@ -1873,6 +1874,13 @@ var Parser2 = class {
|
|
|
1873
1874
|
this.expect("rparen", "')' closing exists(...)");
|
|
1874
1875
|
return { kind: "exists", path, where };
|
|
1875
1876
|
}
|
|
1877
|
+
parseVisible() {
|
|
1878
|
+
this.advance();
|
|
1879
|
+
this.expect("lparen", "'(' after visible");
|
|
1880
|
+
const path = this.parsePath("a link path in visible(...)");
|
|
1881
|
+
this.expect("rparen", "')' closing visible(...)");
|
|
1882
|
+
return { kind: "visible", path };
|
|
1883
|
+
}
|
|
1876
1884
|
parseComparison() {
|
|
1877
1885
|
const left = this.parseOperand();
|
|
1878
1886
|
const operator = this.expect("operator", "a comparison operator");
|
|
@@ -1988,6 +1996,24 @@ function parsePolicy(source) {
|
|
|
1988
1996
|
|
|
1989
1997
|
// src/predicate-v2/compile.ts
|
|
1990
1998
|
var POLICY_MAX_LINK_DEPTH = 3;
|
|
1999
|
+
function scopeToNamespace(pred, namespace) {
|
|
2000
|
+
switch (pred.kind) {
|
|
2001
|
+
case "capability":
|
|
2002
|
+
case "role":
|
|
2003
|
+
return pred.namespace ? pred : { ...pred, namespace };
|
|
2004
|
+
case "and":
|
|
2005
|
+
case "or":
|
|
2006
|
+
return { ...pred, operands: pred.operands.map((operand) => scopeToNamespace(operand, namespace)) };
|
|
2007
|
+
case "not":
|
|
2008
|
+
return { ...pred, operand: scopeToNamespace(pred.operand, namespace) };
|
|
2009
|
+
case "exists":
|
|
2010
|
+
return { ...pred, where: scopeToNamespace(pred.where, namespace) };
|
|
2011
|
+
case "aggPredicate":
|
|
2012
|
+
return pred.where ? { ...pred, where: scopeToNamespace(pred.where, namespace) } : pred;
|
|
2013
|
+
default:
|
|
2014
|
+
return pred;
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
1991
2017
|
var CMP_BY_OP = {
|
|
1992
2018
|
"=": "eq",
|
|
1993
2019
|
"!=": "neq",
|
|
@@ -2021,7 +2047,7 @@ function resolveLink(info, ref) {
|
|
|
2021
2047
|
function columnCandidates(info) {
|
|
2022
2048
|
return [...info.columns.map((c) => c.name), ...info.links.map((l) => l.name)];
|
|
2023
2049
|
}
|
|
2024
|
-
var PolicyCompiler = class {
|
|
2050
|
+
var PolicyCompiler = class _PolicyCompiler {
|
|
2025
2051
|
constructor(ctx) {
|
|
2026
2052
|
this.ctx = ctx;
|
|
2027
2053
|
}
|
|
@@ -2034,13 +2060,15 @@ var PolicyCompiler = class {
|
|
|
2034
2060
|
return { kind: node.kind, operands: node.operands.map((operand) => this.compile(operand, table, depth)) };
|
|
2035
2061
|
case "not":
|
|
2036
2062
|
assertNoNegatedExternalClaim(node.operand);
|
|
2037
|
-
return { kind: "not", operand: this.compile(node.operand, table, depth) };
|
|
2063
|
+
return { kind: "not", operand: new _PolicyCompiler({ ...this.ctx, negated: true }).compile(node.operand, table, depth) };
|
|
2038
2064
|
case "capability":
|
|
2039
2065
|
return { kind: "capability", key: node.key };
|
|
2040
2066
|
case "role":
|
|
2041
2067
|
return { kind: "role", key: node.key };
|
|
2042
2068
|
case "exists":
|
|
2043
2069
|
return this.compileExists(node.path, node.where, table, depth);
|
|
2070
|
+
case "visible":
|
|
2071
|
+
return this.compileVisible(node.path, table, depth);
|
|
2044
2072
|
case "compare":
|
|
2045
2073
|
return this.compileCompare(node, table, depth);
|
|
2046
2074
|
}
|
|
@@ -2054,6 +2082,36 @@ var PolicyCompiler = class {
|
|
|
2054
2082
|
}
|
|
2055
2083
|
return pred;
|
|
2056
2084
|
}
|
|
2085
|
+
/** `visible(path)` → `exists(path, <final target's read policy>)`. */
|
|
2086
|
+
compileVisible(path, table, depth) {
|
|
2087
|
+
const { links, finalTable } = this.resolveLinkPath(path, table, depth, { toOneOnly: false });
|
|
2088
|
+
const readPolicy = this.ctx.resolver.readPolicy;
|
|
2089
|
+
if (!readPolicy) {
|
|
2090
|
+
throw new PolicyCompileError(
|
|
2091
|
+
`visible(${path.join(".")}) needs the target's read policy, which this compile context does not provide`,
|
|
2092
|
+
"visible-unresolvable"
|
|
2093
|
+
);
|
|
2094
|
+
}
|
|
2095
|
+
if (this.ctx.visiting.includes(finalTable)) {
|
|
2096
|
+
throw new PolicyCompileError(
|
|
2097
|
+
`visible(${path.join(".")}) on '${table}' reaches '${finalTable}' whose read policy is already being expanded (${[...this.ctx.visiting, finalTable].join(" \u2192 ")})`,
|
|
2098
|
+
"visible-cycle"
|
|
2099
|
+
);
|
|
2100
|
+
}
|
|
2101
|
+
const expression = readPolicy(finalTable);
|
|
2102
|
+
let pred = expression === void 0 ? { kind: "const", value: true } : compilePolicyAt({
|
|
2103
|
+
expression,
|
|
2104
|
+
table: finalTable,
|
|
2105
|
+
ctx: { ...this.ctx, visiting: [...this.ctx.visiting, finalTable] },
|
|
2106
|
+
depth: depth + links.length
|
|
2107
|
+
});
|
|
2108
|
+
const owner = this.ctx.resolver.policyNamespace?.(finalTable);
|
|
2109
|
+
if (owner) pred = scopeToNamespace(pred, owner);
|
|
2110
|
+
for (let i = links.length - 1; i >= 0; i -= 1) {
|
|
2111
|
+
pred = { kind: "exists", link: links[i].name, where: pred };
|
|
2112
|
+
}
|
|
2113
|
+
return pred;
|
|
2114
|
+
}
|
|
2057
2115
|
resolveLinkPath(path, table, depth, { toOneOnly }) {
|
|
2058
2116
|
const links = [];
|
|
2059
2117
|
let current = table;
|
|
@@ -2114,6 +2172,7 @@ var PolicyCompiler = class {
|
|
|
2114
2172
|
);
|
|
2115
2173
|
}
|
|
2116
2174
|
if (valueSide.kind === "claim" && isExternalPolicyClaimKey(valueSide.key)) {
|
|
2175
|
+
if (this.ctx.negated) throw negatedExternalClaim(valueSide.key);
|
|
2117
2176
|
assertExternalClaimComparison({ op, key: valueSide.key, column: info.columns.find((c) => c.name === column) });
|
|
2118
2177
|
}
|
|
2119
2178
|
let cmp = this.buildCmp(op, column, valueSide);
|
|
@@ -2151,22 +2210,30 @@ function assertExternalClaimComparison({ op, key, column }) {
|
|
|
2151
2210
|
);
|
|
2152
2211
|
}
|
|
2153
2212
|
}
|
|
2213
|
+
function negatedExternalClaim(key) {
|
|
2214
|
+
return new PolicyCompileError(
|
|
2215
|
+
`claim('${key}') cannot appear under not(): a negated borrower comparison admits other borrowers' rows`,
|
|
2216
|
+
"unsupported-comparison"
|
|
2217
|
+
);
|
|
2218
|
+
}
|
|
2154
2219
|
function assertNoNegatedExternalClaim(operand) {
|
|
2155
2220
|
walkPolicy(operand, (node) => {
|
|
2156
2221
|
if (node.kind !== "compare") return;
|
|
2157
2222
|
const claim = [node.left, node.right].find((side) => side.kind === "claim" && isExternalPolicyClaimKey(side.key));
|
|
2158
|
-
if (claim?.kind === "claim")
|
|
2159
|
-
throw new PolicyCompileError(
|
|
2160
|
-
`claim('${claim.key}') cannot appear under not(): a negated borrower comparison admits other borrowers' rows`,
|
|
2161
|
-
"unsupported-comparison"
|
|
2162
|
-
);
|
|
2163
|
-
}
|
|
2223
|
+
if (claim?.kind === "claim") throw negatedExternalClaim(claim.key);
|
|
2164
2224
|
});
|
|
2165
2225
|
}
|
|
2166
2226
|
function compilePredicateV2({ expression, table, resolver, maxLinkDepth }) {
|
|
2227
|
+
return compilePredicateAt({
|
|
2228
|
+
expression,
|
|
2229
|
+
table,
|
|
2230
|
+
depth: 0,
|
|
2231
|
+
ctx: { resolver, maxLinkDepth: maxLinkDepth ?? POLICY_MAX_LINK_DEPTH, visiting: [table] }
|
|
2232
|
+
});
|
|
2233
|
+
}
|
|
2234
|
+
function compilePredicateAt({ expression, table, ctx, depth }) {
|
|
2167
2235
|
const parsed = typeof expression === "string" ? parsePolicy(expression) : expression;
|
|
2168
|
-
|
|
2169
|
-
return compiler.compile(parsed.ast, table, 0);
|
|
2236
|
+
return new PolicyCompiler(ctx).compile(parsed.ast, table, depth);
|
|
2170
2237
|
}
|
|
2171
2238
|
function assertClaimsOnlyWhen(parsed) {
|
|
2172
2239
|
walkPolicy(parsed.ast, (node) => {
|
|
@@ -2183,25 +2250,34 @@ function assertClaimsOnlyWhen(parsed) {
|
|
|
2183
2250
|
"when-not-claims-only"
|
|
2184
2251
|
);
|
|
2185
2252
|
}
|
|
2186
|
-
if (node.kind === "exists") {
|
|
2253
|
+
if (node.kind === "exists" || node.kind === "visible") {
|
|
2187
2254
|
throw new PolicyCompileError(
|
|
2188
|
-
|
|
2255
|
+
`variant 'when' guards are claims-only \u2014 ${node.kind}() is not allowed`,
|
|
2189
2256
|
"when-not-claims-only"
|
|
2190
2257
|
);
|
|
2191
2258
|
}
|
|
2192
2259
|
});
|
|
2193
2260
|
}
|
|
2194
|
-
function
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2261
|
+
function initialVisiting({ table, access }) {
|
|
2262
|
+
return (access ?? "read") === "read" ? [table] : [];
|
|
2263
|
+
}
|
|
2264
|
+
function compilePolicy({ expression, table, resolver, maxLinkDepth, access }) {
|
|
2265
|
+
return compilePolicyAt({
|
|
2266
|
+
expression,
|
|
2267
|
+
table,
|
|
2268
|
+
depth: 0,
|
|
2269
|
+
ctx: { resolver, maxLinkDepth: maxLinkDepth ?? POLICY_MAX_LINK_DEPTH, visiting: initialVisiting({ table, access }) }
|
|
2270
|
+
});
|
|
2271
|
+
}
|
|
2272
|
+
function compilePolicyAt({ expression, table, ctx, depth }) {
|
|
2273
|
+
if (typeof expression === "string") return compilePredicateAt({ expression, table, ctx, depth });
|
|
2274
|
+
const defaultPred = compilePredicateAt({ expression: expression.default, table, ctx, depth });
|
|
2199
2275
|
if (expression.variants.length === 0) return defaultPred;
|
|
2200
2276
|
const branches = expression.variants.map((variant) => {
|
|
2201
2277
|
const parsedWhen = parsePolicy(variant.when);
|
|
2202
2278
|
assertClaimsOnlyWhen(parsedWhen);
|
|
2203
|
-
const when =
|
|
2204
|
-
const grant = variant.allow === true ? { kind: "const", value: true } :
|
|
2279
|
+
const when = compilePredicateAt({ expression: parsedWhen, table, ctx, depth });
|
|
2280
|
+
const grant = variant.allow === true ? { kind: "const", value: true } : compilePredicateAt({ expression: variant.policy, table, ctx, depth });
|
|
2205
2281
|
return { kind: "and", operands: [when, grant] };
|
|
2206
2282
|
});
|
|
2207
2283
|
return { kind: "or", operands: [defaultPred, ...branches] };
|
|
@@ -2417,12 +2493,6 @@ var PolicyInjector = class {
|
|
|
2417
2493
|
if (root.op === "resolvedWrite") return this.injectResolvedWrite(root, returning);
|
|
2418
2494
|
if (root.op === "insert" || root.op === "insertOne") {
|
|
2419
2495
|
const insertPolicy = this.insert(table);
|
|
2420
|
-
if (predContainsExists(insertPolicy)) {
|
|
2421
|
-
throw new DocumentCompileError(
|
|
2422
|
-
`table '${table}' cannot be inserted into: v2.0 insert checks are claims + inserted-values only, but its insert policy traverses a link (exists)`,
|
|
2423
|
-
"insert-check-unrepresentable"
|
|
2424
|
-
);
|
|
2425
|
-
}
|
|
2426
2496
|
const pins = (this.ctx.pins.get(table) ?? []).map(
|
|
2427
2497
|
(pin) => ({ column: pin.column, value: { kind: "claim", key: pin.claim } })
|
|
2428
2498
|
);
|
|
@@ -2437,22 +2507,14 @@ var PolicyInjector = class {
|
|
|
2437
2507
|
const updatePolicy = this.update(table);
|
|
2438
2508
|
const where = andPred(updatePolicy, root.where ? this.injectDocPred(root.where, table) : void 0);
|
|
2439
2509
|
if (root.op === "update" || root.op === "updateByPk") {
|
|
2440
|
-
|
|
2441
|
-
return { ...root, where, ...check, returning };
|
|
2510
|
+
return { ...root, where, insertCheck: updatePolicy, returning };
|
|
2442
2511
|
}
|
|
2443
2512
|
if (root.op === "cowOverride") {
|
|
2444
2513
|
const insertPolicy = this.insert(table);
|
|
2445
|
-
if (predContainsExists(insertPolicy)) {
|
|
2446
|
-
throw new DocumentCompileError(
|
|
2447
|
-
`table '${table}' cannot be copy-on-write overridden: v2.0 insert checks are claims + inserted-values only, but its insert policy traverses a link (exists)`,
|
|
2448
|
-
"insert-check-unrepresentable"
|
|
2449
|
-
);
|
|
2450
|
-
}
|
|
2451
2514
|
const pins = (this.ctx.pins.get(table) ?? []).map(
|
|
2452
2515
|
(pin) => ({ column: pin.column, value: { kind: "claim", key: pin.claim } })
|
|
2453
2516
|
);
|
|
2454
|
-
|
|
2455
|
-
return { ...root, pinnedColumns: pins, cowCopyCheck: insertPolicy, where, ...check, returning };
|
|
2517
|
+
return { ...root, pinnedColumns: pins, cowCopyCheck: insertPolicy, where, insertCheck: updatePolicy, returning };
|
|
2456
2518
|
}
|
|
2457
2519
|
return { ...root, where, returning };
|
|
2458
2520
|
}
|
|
@@ -2674,7 +2736,7 @@ function scopePolicy(pred, namespace) {
|
|
|
2674
2736
|
switch (pred.kind) {
|
|
2675
2737
|
case "capability":
|
|
2676
2738
|
case "role":
|
|
2677
|
-
return { ...pred, namespace };
|
|
2739
|
+
return pred.namespace ? pred : { ...pred, namespace };
|
|
2678
2740
|
case "and":
|
|
2679
2741
|
case "or":
|
|
2680
2742
|
return { ...pred, operands: pred.operands.map((p) => scopePolicy(p, namespace)) };
|
|
@@ -2883,7 +2945,14 @@ function buildCompileContext(rawCanonical) {
|
|
|
2883
2945
|
const updatePolicies = /* @__PURE__ */ new Map();
|
|
2884
2946
|
const pins = /* @__PURE__ */ new Map();
|
|
2885
2947
|
const splitWritePolicyTables = /* @__PURE__ */ new Set();
|
|
2886
|
-
const
|
|
2948
|
+
const readPolicyExpressions = new Map(relations.map((relation) => [relation.table, relation.policies.read]));
|
|
2949
|
+
const resolver = {
|
|
2950
|
+
tables,
|
|
2951
|
+
readPolicy: (table) => readPolicyExpressions.get(table),
|
|
2952
|
+
// In a composed namespace, an imported table's read policy (inlined by
|
|
2953
|
+
// visible()) is checked against the namespace that owns it.
|
|
2954
|
+
...normalized.imports?.length ? { policyNamespace: (table) => owners.get(table)?.namespace } : {}
|
|
2955
|
+
};
|
|
2887
2956
|
for (const table of relations) {
|
|
2888
2957
|
const isView = viewNames.has(table.table);
|
|
2889
2958
|
const compilePolicyFor = (access, store) => {
|
|
@@ -2892,7 +2961,7 @@ function buildCompileContext(rawCanonical) {
|
|
|
2892
2961
|
return;
|
|
2893
2962
|
}
|
|
2894
2963
|
try {
|
|
2895
|
-
const pred = compilePolicy({ expression, table: table.table, resolver });
|
|
2964
|
+
const pred = compilePolicy({ expression, table: table.table, resolver, access });
|
|
2896
2965
|
store.set(table.table, normalized.imports?.length ? scopePolicy(pred, owners.get(table.table).namespace) : pred);
|
|
2897
2966
|
} catch (error) {
|
|
2898
2967
|
if (error instanceof PolicyCompileError || error instanceof PolicyParseError) {
|