@lunora/do 1.0.0-alpha.17 → 1.0.0-alpha.19
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/index.d.mts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.mjs +7 -7
- package/dist/packem_shared/{ADMIN_FUNCTIONS-fMl1vyt1.mjs → ADMIN_FUNCTIONS-BvGiv2u6.mjs} +2 -1
- package/dist/packem_shared/{NotUniqueError-BXn2j5vu.mjs → NotUniqueError-Do5h_jiW.mjs} +2 -2
- package/dist/packem_shared/{ROOT_DO_SIZE_WARN_BYTES-DDp_NomS.mjs → ROOT_DO_SIZE_WARN_BYTES-DlFX7CLL.mjs} +78 -20
- package/dist/packem_shared/{compileWhereSql-CXrhFA3G.mjs → compileWhereSql-MW_Lk8nJ.mjs} +3 -2
- package/dist/packem_shared/{ctx-db-shapes-BQapRFjB.mjs → ctx-db-shapes-0RaIOy7J.mjs} +1 -1
- package/dist/packem_shared/{isSourceDue-BMTJv65e.mjs → isSourceDue-9mJRJ9Ld.mjs} +1 -1
- package/dist/packem_shared/{materializeExternalRows-uKBx9H0s.mjs → materializeExternalRows-Bj6EXy50.mjs} +1 -1
- package/dist/packem_shared/{serveRelationFanout-EZLD9-O3.mjs → serveRelationFanout-BuSmWawx.mjs} +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -2800,8 +2800,14 @@ interface StorageRulesResult {
|
|
|
2800
2800
|
* package's tests and the studio's fails the build if the two key sets diverge.
|
|
2801
2801
|
*/
|
|
2802
2802
|
interface StudioFeaturesResult {
|
|
2803
|
+
/** `@lunora/bindings/analytics` / `ctx.analytics` is used, or it is a declared dependency. */
|
|
2804
|
+
analytics: boolean;
|
|
2805
|
+
/** `@lunora/auth` is a declared dependency (backs the Users / Sessions / Organizations / Configuration pages). */
|
|
2806
|
+
auth: boolean;
|
|
2803
2807
|
/** `@lunora/flags` / `ctx.flags` is used, or it is a declared dependency. */
|
|
2804
2808
|
flags: boolean;
|
|
2809
|
+
/** `@lunora/bindings/kv` / `ctx.kv` is used, or it is a declared dependency. */
|
|
2810
|
+
kv: boolean;
|
|
2805
2811
|
/** `@lunora/mail` is imported by a `lunora/` source or a declared dependency. */
|
|
2806
2812
|
mail: boolean;
|
|
2807
2813
|
/** `@lunora/payment` is used (import or `ctx.payments`) or a declared dependency. */
|
|
@@ -6597,8 +6603,11 @@ interface WhereSqlStrategy {
|
|
|
6597
6603
|
fieldRef: FieldRefSql;
|
|
6598
6604
|
/**
|
|
6599
6605
|
* Dialect `contains` rendering given the field reference and the (already
|
|
6600
|
-
* bound) search term. Absent ⇒ the portable
|
|
6601
|
-
* concat form (SQLite/Postgres); MySQL
|
|
6606
|
+
* bound, already wildcard-escaped) search term. Absent ⇒ the portable
|
|
6607
|
+
* `… LIKE '%' || term || '%' ESCAPE '\'` concat form (SQLite/Postgres); MySQL
|
|
6608
|
+
* supplies a `CONCAT(...)` variant. The term is escaped by
|
|
6609
|
+
* {@link compileContains}, so an implementation MUST pair it with
|
|
6610
|
+
* `ESCAPE '\'` for the literal-match to hold.
|
|
6602
6611
|
*/
|
|
6603
6612
|
likeContains?: (reference: SQL, term: SQL) => SQL;
|
|
6604
6613
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -2800,8 +2800,14 @@ interface StorageRulesResult {
|
|
|
2800
2800
|
* package's tests and the studio's fails the build if the two key sets diverge.
|
|
2801
2801
|
*/
|
|
2802
2802
|
interface StudioFeaturesResult {
|
|
2803
|
+
/** `@lunora/bindings/analytics` / `ctx.analytics` is used, or it is a declared dependency. */
|
|
2804
|
+
analytics: boolean;
|
|
2805
|
+
/** `@lunora/auth` is a declared dependency (backs the Users / Sessions / Organizations / Configuration pages). */
|
|
2806
|
+
auth: boolean;
|
|
2803
2807
|
/** `@lunora/flags` / `ctx.flags` is used, or it is a declared dependency. */
|
|
2804
2808
|
flags: boolean;
|
|
2809
|
+
/** `@lunora/bindings/kv` / `ctx.kv` is used, or it is a declared dependency. */
|
|
2810
|
+
kv: boolean;
|
|
2805
2811
|
/** `@lunora/mail` is imported by a `lunora/` source or a declared dependency. */
|
|
2806
2812
|
mail: boolean;
|
|
2807
2813
|
/** `@lunora/payment` is used (import or `ctx.payments`) or a declared dependency. */
|
|
@@ -6597,8 +6603,11 @@ interface WhereSqlStrategy {
|
|
|
6597
6603
|
fieldRef: FieldRefSql;
|
|
6598
6604
|
/**
|
|
6599
6605
|
* Dialect `contains` rendering given the field reference and the (already
|
|
6600
|
-
* bound) search term. Absent ⇒ the portable
|
|
6601
|
-
* concat form (SQLite/Postgres); MySQL
|
|
6606
|
+
* bound, already wildcard-escaped) search term. Absent ⇒ the portable
|
|
6607
|
+
* `… LIKE '%' || term || '%' ESCAPE '\'` concat form (SQLite/Postgres); MySQL
|
|
6608
|
+
* supplies a `CONCAT(...)` variant. The term is escaped by
|
|
6609
|
+
* {@link compileContains}, so an implementation MUST pair it with
|
|
6610
|
+
* `ESCAPE '\'` for the literal-match to hold.
|
|
6602
6611
|
*/
|
|
6603
6612
|
likeContains?: (reference: SQL, term: SQL) => SQL;
|
|
6604
6613
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -3,15 +3,15 @@ export { AGGREGATE_SQL_FUNCTION, aggregateSqlFunction, matchesStaticWhere, norma
|
|
|
3
3
|
export { aggregateTableName, coerceAggregateNumber, encodeAggregateKey, foldAggregateTally, readAggregateValue } from './packem_shared/aggregateTableName-CxNqY1Sl.mjs';
|
|
4
4
|
export { CountRlsUnsupportedError, mergeWhere, planAggregateLookup, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy } from './packem_shared/CountRlsUnsupportedError-28ZvvwKS.mjs';
|
|
5
5
|
export { AUTH_METRICS_BUCKETS_TABLE, AUTH_METRICS_BUCKET_MS, AUTH_METRICS_BUCKET_RETENTION, AUTH_METRICS_TABLE, ensureAuthMetricsTables, readAuthMetrics, recordAuthEvent } from './packem_shared/AUTH_METRICS_BUCKETS_TABLE-CiHHYeJi.mjs';
|
|
6
|
-
export { NotUniqueError, assertValidClientId, createShardCtxDb, normalizeIdStructurally } from './packem_shared/NotUniqueError-
|
|
6
|
+
export { NotUniqueError, assertValidClientId, createShardCtxDb, normalizeIdStructurally } from './packem_shared/NotUniqueError-Do5h_jiW.mjs';
|
|
7
7
|
export { DATA_MIGRATION_STATE_TABLE, readMigrationStatus, runDataMigration } from './packem_shared/DATA_MIGRATION_STATE_TABLE-DfPxn8I0.mjs';
|
|
8
8
|
export { SCAN_DEP, createDependencyTracker, depKey } from './packem_shared/SCAN_DEP-DLJF8dsj.mjs';
|
|
9
9
|
export { renderSql } from './packem_shared/renderSql-D6eUcn2N.mjs';
|
|
10
10
|
export { diffExternalSource } from './packem_shared/diffExternalSource-Cx9HUPJj.mjs';
|
|
11
|
-
export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-
|
|
12
|
-
export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-
|
|
11
|
+
export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-Bj6EXy50.mjs';
|
|
12
|
+
export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-9mJRJ9Ld.mjs';
|
|
13
13
|
export { FUNCTION_METRICS_BUCKETS_TABLE, FUNCTION_METRICS_BUCKET_MS, FUNCTION_METRICS_BUCKET_RETENTION, FUNCTION_METRICS_INDEX_TABLE, FUNCTION_METRICS_TABLE, ensureFunctionMetricsTables, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, recordFunctionMetric } from './packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
|
|
14
|
-
export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, FLAGS_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, facetColumn, listTables, readTablePage, selectMatchingIds } from './packem_shared/ADMIN_FUNCTIONS-
|
|
14
|
+
export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, FLAGS_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, facetColumn, listTables, readTablePage, selectMatchingIds } from './packem_shared/ADMIN_FUNCTIONS-BvGiv2u6.mjs';
|
|
15
15
|
export { LogBuffer } from './packem_shared/LogBuffer-B_Ezju_N.mjs';
|
|
16
16
|
export { MAIL_RETENTION, MAIL_TABLE, clearCapturedMail, ensureMailTable, readCapturedMail, recordCapturedMail } from './packem_shared/MAIL_RETENTION-CPpgl-dX.mjs';
|
|
17
17
|
export { default as NotFoundError } from './packem_shared/NotFoundError-CMuMZt81.mjs';
|
|
@@ -19,20 +19,20 @@ export { armRestore, readBookmark } from './packem_shared/armRestore-BJk53Ro8.mj
|
|
|
19
19
|
export { applySelect, buildSeekWhere, decodeCursor, encodeCursor, normalizeOrderKeys, softDeleteScope } from './packem_shared/applySelect-BvZdFUBT.mjs';
|
|
20
20
|
export { RANK_TIEBREAK, encodePartitionKey, matchesRankStaticWhere, rankTableName, resolveRankPartition, sortColumnName } from './packem_shared/RANK_TIEBREAK-CXhdcA1o.mjs';
|
|
21
21
|
export { ReactiveCache, reactiveCacheKey } from './packem_shared/ReactiveCache-BYlSGY0N.mjs';
|
|
22
|
-
export { serveRelationFanout } from './packem_shared/serveRelationFanout-
|
|
22
|
+
export { serveRelationFanout } from './packem_shared/serveRelationFanout-BuSmWawx.mjs';
|
|
23
23
|
export { DEFAULT_MAX_RELATION_KEYS, assertFlatPredicate, assertShapeShardable, containsRelationPredicate, isRelationPredicate, resolveRelationPredicates } from './packem_shared/DEFAULT_MAX_RELATION_KEYS-DU-Y4-LJ.mjs';
|
|
24
24
|
export { applyOnDelete, fanOutScalarCounts, resolveWith, runRowValidators } from './packem_shared/applyOnDelete-BQ-8ZlZ1.mjs';
|
|
25
25
|
export { RLS_UNWRAP_SYMBOL, RlsRequiredError, guardWriter } from './packem_shared/RLS_UNWRAP_SYMBOL-EtGQdC9d.mjs';
|
|
26
26
|
export { buildFtsMatch, ftsTableName, scoreDocument, stringifySearchText, tokenizeSearch } from './packem_shared/buildFtsMatch-BLEMawrp.mjs';
|
|
27
27
|
export { M as MIN_ADMIN_TOKEN_LENGTH, a as MIN_AUTH_SECRET_LENGTH, b as buildSecurityAudit } from './packem_shared/security-audit-CucgBice.mjs';
|
|
28
28
|
export { SESSION_DO_TTL_DEFAULT, SessionDO } from './packem_shared/SESSION_DO_TTL_DEFAULT-ilPZsVwu.mjs';
|
|
29
|
-
export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-
|
|
29
|
+
export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-DlFX7CLL.mjs';
|
|
30
30
|
export { SHARD_REGISTRY_DO_NAME, ShardRegistryDO } from './packem_shared/SHARD_REGISTRY_DO_NAME-BsAbi5Mn.mjs';
|
|
31
31
|
export { MAX_SQL_ROWS, assertReadonly, runReadonlySql } from './packem_shared/MAX_SQL_ROWS-dDcFE1YZ.mjs';
|
|
32
32
|
export { createSystemReader } from './packem_shared/createSystemReader-8CzSZP9V.mjs';
|
|
33
33
|
export { ConflictError } from './packem_shared/ConflictError-C0STs6bU.mjs';
|
|
34
34
|
export { hasTrigger, runTriggers } from './packem_shared/hasTrigger-5N6_Fx0A.mjs';
|
|
35
|
-
export { compileWhereSql } from './packem_shared/compileWhereSql-
|
|
35
|
+
export { compileWhereSql } from './packem_shared/compileWhereSql-MW_Lk8nJ.mjs';
|
|
36
36
|
export { CDC_LOG_TABLE, applyCdcChanges, readCdcChanges, trimCdcChanges } from './packem_shared/CDC_LOG_TABLE-DSycmnDf.mjs';
|
|
37
37
|
export { backfillAggregateIndexes, backfillRankIndexes } from './packem_shared/backfillAggregateIndexes-BZsOqDXP.mjs';
|
|
38
38
|
export { runShardMigrations } from './packem_shared/runShardMigrations-nIwoQeOK.mjs';
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
const quoteIdentifier = (name) => `"${name.replaceAll('"', '""')}"`;
|
|
2
|
+
|
|
1
3
|
const ADMIN_FUNCTION_PREFIX = "__lunora_admin__:";
|
|
2
4
|
const RELATION_FUNCTION_PREFIX = "__lunora_relation__:";
|
|
3
5
|
const FLAGS_FUNCTION_PREFIX = "__lunora_flags__:";
|
|
@@ -95,7 +97,6 @@ const expandDocumentRows = (columns, rows) => {
|
|
|
95
97
|
};
|
|
96
98
|
const escapeLike = (value) => value.replaceAll(/[\\%_]/g, (character) => `\\${character}`);
|
|
97
99
|
const isInternalTable = (name) => name.startsWith("sqlite_") || name.startsWith("_cf_") || name.startsWith("__miniflare") || name.startsWith("__lunora") || name.includes("__fts_");
|
|
98
|
-
const quoteIdentifier = (name) => `"${name.replaceAll('"', '""')}"`;
|
|
99
100
|
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
|
|
100
101
|
const countRows = (sql, quotedTable) => {
|
|
101
102
|
const row = sql.exec(`SELECT COUNT(*) AS c FROM ${quotedTable}`).one();
|
|
@@ -19,11 +19,11 @@ import { guardWriter } from './RLS_UNWRAP_SYMBOL-EtGQdC9d.mjs';
|
|
|
19
19
|
import { createSystemReader } from './createSystemReader-8CzSZP9V.mjs';
|
|
20
20
|
import { ConflictError } from './ConflictError-C0STs6bU.mjs';
|
|
21
21
|
import { runTriggers } from './hasTrigger-5N6_Fx0A.mjs';
|
|
22
|
-
import { compileWhereSql } from './compileWhereSql-
|
|
22
|
+
import { compileWhereSql } from './compileWhereSql-MW_Lk8nJ.mjs';
|
|
23
23
|
export { backfillAggregateIndexes, backfillRankIndexes } from './backfillAggregateIndexes-BZsOqDXP.mjs';
|
|
24
24
|
export { C as CLIENT_WATERMARK_TABLE, G as GLOBAL_SHAPE_SNAPSHOT_TABLE, I as IDEMPOTENCY_TABLE, c as advanceClientWatermark, d as deleteGlobalShapeSnapshot, e as deleteGlobalShapeSnapshotsForConnection, m as migrateClientWatermark, b as migrateGlobalShapeSnapshot, r as readClientWatermark, f as readGlobalShapeSnapshot, g as readIdempotent, t as trimIdempotent, w as writeGlobalShapeSnapshot, h as writeIdempotent } from './ctx-db-idempotency-BdcNpvY4.mjs';
|
|
25
25
|
export { runShardMigrations } from './runShardMigrations-nIwoQeOK.mjs';
|
|
26
|
-
export { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-
|
|
26
|
+
export { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-0RaIOy7J.mjs';
|
|
27
27
|
|
|
28
28
|
const rankIndexFieldsUnchanged = (index, previous, next) => {
|
|
29
29
|
const fields = [...index.partitionBy ?? [], ...index.sortBy.map((key) => key.field), ...index.where ? Object.keys(index.where) : []];
|
|
@@ -5,7 +5,7 @@ import { recordAuthEvent, readAuthMetrics } from './AUTH_METRICS_BUCKETS_TABLE-C
|
|
|
5
5
|
import { DATA_MIGRATION_STATE_TABLE, readMigrationStatus } from './DATA_MIGRATION_STATE_TABLE-DfPxn8I0.mjs';
|
|
6
6
|
import { SCAN_DEP, createDependencyTracker, tableFromDepKey } from './SCAN_DEP-DLJF8dsj.mjs';
|
|
7
7
|
import { readFunctionMetricsTotals, readFunctionMetricIndexHits, recordFunctionMetric, mergeScanAttribution, readFunctionMetrics, readFunctionMetricBuckets } from './FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
|
|
8
|
-
import { createFanoutCounters, ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, summarizeFanoutTopics, readTablePage, facetColumn, FLAGS_FUNCTION_PREFIX, recordFanoutPass, MAX_PAGE_SIZE } from './ADMIN_FUNCTIONS-
|
|
8
|
+
import { createFanoutCounters, ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, summarizeFanoutTopics, readTablePage, facetColumn, FLAGS_FUNCTION_PREFIX, recordFanoutPass, MAX_PAGE_SIZE } from './ADMIN_FUNCTIONS-BvGiv2u6.mjs';
|
|
9
9
|
import { LogBuffer } from './LogBuffer-B_Ezju_N.mjs';
|
|
10
10
|
import { recordCapturedMail, clearCapturedMail, readCapturedMail, MAIL_TABLE } from './MAIL_RETENTION-CPpgl-dX.mjs';
|
|
11
11
|
import { readBookmark, armRestore } from './armRestore-BJk53Ro8.mjs';
|
|
@@ -17,7 +17,7 @@ import { runReadonlySql } from './MAX_SQL_ROWS-dDcFE1YZ.mjs';
|
|
|
17
17
|
import { ConflictError } from './ConflictError-C0STs6bU.mjs';
|
|
18
18
|
import { e as deleteGlobalShapeSnapshotsForConnection, g as readIdempotent, h as writeIdempotent, t as trimIdempotent, r as readClientWatermark, m as migrateClientWatermark, c as advanceClientWatermark, d as deleteGlobalShapeSnapshot, f as readGlobalShapeSnapshot, w as writeGlobalShapeSnapshot } from './ctx-db-idempotency-BdcNpvY4.mjs';
|
|
19
19
|
import { CDC_LOG_TABLE, readCdcChanges, readCdcCursor, readCdcEpoch, minCdcSeq, bumpCdcEpoch } from './CDC_LOG_TABLE-DSycmnDf.mjs';
|
|
20
|
-
import { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-
|
|
20
|
+
import { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-0RaIOy7J.mjs';
|
|
21
21
|
|
|
22
22
|
const MAX_BATCH_ENTRIES = 500;
|
|
23
23
|
|
|
@@ -269,6 +269,30 @@ const buildPokeFrames = (parts, meta, options = {}) => {
|
|
|
269
269
|
|
|
270
270
|
const DEFAULT_RELAY_FAN = 2;
|
|
271
271
|
const DEFAULT_MAX_RELAYS = 8;
|
|
272
|
+
const RELAY_SECRET_KEY = "LUNORA_RELAY_SECRET";
|
|
273
|
+
const RELAY_SIGNATURE_HEADER = "x-lunora-relay-sig";
|
|
274
|
+
const relaySecretOf = (env) => {
|
|
275
|
+
const value = env?.[RELAY_SECRET_KEY];
|
|
276
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
277
|
+
};
|
|
278
|
+
const constantTimeEqual$1 = (a, b) => {
|
|
279
|
+
if (a.length !== b.length) {
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
let mismatch = 0;
|
|
283
|
+
for (let index = 0; index < a.length; index += 1) {
|
|
284
|
+
const charA = a.charCodeAt(index);
|
|
285
|
+
const charB = b.charCodeAt(index);
|
|
286
|
+
mismatch |= charA ^ charB;
|
|
287
|
+
}
|
|
288
|
+
return mismatch === 0;
|
|
289
|
+
};
|
|
290
|
+
const signRelayBody = async (secret, body) => {
|
|
291
|
+
const encoder = new TextEncoder();
|
|
292
|
+
const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { hash: "SHA-256", name: "HMAC" }, false, ["sign"]);
|
|
293
|
+
const signature = await crypto.subtle.sign("HMAC", key, encoder.encode(body));
|
|
294
|
+
return [...new Uint8Array(signature)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
295
|
+
};
|
|
272
296
|
const envPositiveInt = (env, key, fallback) => {
|
|
273
297
|
const raw = env?.[key];
|
|
274
298
|
let parsed = Number.NaN;
|
|
@@ -305,9 +329,23 @@ class RelayLink {
|
|
|
305
329
|
* to `relay.ts` without a case here is a COMPILE error, not a runtime mis-route.
|
|
306
330
|
*/
|
|
307
331
|
async handleControl(request) {
|
|
332
|
+
let raw;
|
|
333
|
+
try {
|
|
334
|
+
raw = await request.text();
|
|
335
|
+
} catch {
|
|
336
|
+
return new Response("bad request", { status: 400 });
|
|
337
|
+
}
|
|
338
|
+
const secret = relaySecretOf(this.host.env());
|
|
339
|
+
if (secret !== void 0) {
|
|
340
|
+
const supplied = request.headers.get(RELAY_SIGNATURE_HEADER);
|
|
341
|
+
const expected = await signRelayBody(secret, raw);
|
|
342
|
+
if (supplied === null || !constantTimeEqual$1(supplied, expected)) {
|
|
343
|
+
return new Response("forbidden", { status: 403 });
|
|
344
|
+
}
|
|
345
|
+
}
|
|
308
346
|
let message;
|
|
309
347
|
try {
|
|
310
|
-
message =
|
|
348
|
+
message = JSON.parse(raw);
|
|
311
349
|
} catch {
|
|
312
350
|
return new Response("bad request", { status: 400 });
|
|
313
351
|
}
|
|
@@ -372,10 +410,16 @@ class RelayLink {
|
|
|
372
410
|
return void 0;
|
|
373
411
|
}
|
|
374
412
|
const stub = typeof namespace.getByName === "function" ? namespace.getByName(targetName) : namespace.get(namespace.idFromName(targetName));
|
|
413
|
+
const body = JSON.stringify(message);
|
|
414
|
+
const headers = { "content-type": "application/json", "x-lunora-shard-binding": this.host.shardBinding() ?? "" };
|
|
415
|
+
const secret = relaySecretOf(this.host.env());
|
|
416
|
+
if (secret !== void 0) {
|
|
417
|
+
headers[RELAY_SIGNATURE_HEADER] = await signRelayBody(secret, body);
|
|
418
|
+
}
|
|
375
419
|
try {
|
|
376
420
|
return await stub.fetch("https://relay.internal/_lunora/relay", {
|
|
377
|
-
body
|
|
378
|
-
headers
|
|
421
|
+
body,
|
|
422
|
+
headers,
|
|
379
423
|
method: "POST"
|
|
380
424
|
});
|
|
381
425
|
} catch {
|
|
@@ -679,8 +723,9 @@ class OwnerRelay extends RelayLink {
|
|
|
679
723
|
* sound against the cross-identity row-leak (review). Resolves under the anonymous
|
|
680
724
|
* multicast identity (the base) plus two `Proxy`-backed identities that return a
|
|
681
725
|
* distinct value for ANY accessed claim, requires all to agree on table + where +
|
|
682
|
-
* columns, rejects any table with an RLS read policy or
|
|
683
|
-
*
|
|
726
|
+
* columns, rejects any table with an RLS read policy or ANY masked column
|
|
727
|
+
* defined (even if unprojected — see {@link OwnerRelay.tableHasAnyMask}), and
|
|
728
|
+
* fails closed if the claims are enumerated (a wholesale copy the proxy can't
|
|
684
729
|
* differentiate).
|
|
685
730
|
*/
|
|
686
731
|
probeShapeRelayUniform(name, args) {
|
|
@@ -696,7 +741,7 @@ class OwnerRelay extends RelayLink {
|
|
|
696
741
|
if (this.host.rlsMetadata().policies.some((policy) => policy.on === "read" && policy.table === base.table)) {
|
|
697
742
|
return false;
|
|
698
743
|
}
|
|
699
|
-
if (this.
|
|
744
|
+
if (this.tableHasAnyMask(base.table)) {
|
|
700
745
|
return false;
|
|
701
746
|
}
|
|
702
747
|
const baseWhere = stableStringify(base.effectiveWhere);
|
|
@@ -734,17 +779,18 @@ class OwnerRelay extends RelayLink {
|
|
|
734
779
|
});
|
|
735
780
|
return matches && !enumerated;
|
|
736
781
|
}
|
|
737
|
-
/**
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
782
|
+
/**
|
|
783
|
+
* Whether `table` has ANY masked column defined (L7). Deliberately conservative:
|
|
784
|
+
* we disqualify a shape from relay-multicast if its table declares any mask at
|
|
785
|
+
* all, even when the current query doesn't project the masked column. A masked
|
|
786
|
+
* value is identity-dependent, and keying uniformity off the *projected* set
|
|
787
|
+
* meant a later column addition (or a `select` change) could silently widen a
|
|
788
|
+
* cohort to include an identity-dependent value. Refusing on any table-level
|
|
789
|
+
* mask removes that footgun; the cost is a few extra shapes falling back to the
|
|
790
|
+
* per-identity path, which is always correct.
|
|
791
|
+
*/
|
|
792
|
+
tableHasAnyMask(table) {
|
|
793
|
+
return this.host.maskMetadata().columns.some((entry) => entry.table === table);
|
|
748
794
|
}
|
|
749
795
|
}
|
|
750
796
|
class RelayMember extends RelayLink {
|
|
@@ -2785,7 +2831,19 @@ class ShardDO {
|
|
|
2785
2831
|
*/
|
|
2786
2832
|
// eslint-disable-next-line class-methods-use-this -- base-class override hook: the codegen subclass overrides this with the statically-discovered feature flags
|
|
2787
2833
|
studioFeatures() {
|
|
2788
|
-
return {
|
|
2834
|
+
return {
|
|
2835
|
+
analytics: false,
|
|
2836
|
+
auth: false,
|
|
2837
|
+
flags: false,
|
|
2838
|
+
kv: false,
|
|
2839
|
+
mail: false,
|
|
2840
|
+
payments: false,
|
|
2841
|
+
queues: false,
|
|
2842
|
+
scheduler: false,
|
|
2843
|
+
storage: false,
|
|
2844
|
+
vectors: false,
|
|
2845
|
+
workflows: false
|
|
2846
|
+
};
|
|
2789
2847
|
}
|
|
2790
2848
|
/**
|
|
2791
2849
|
* Evaluate every statically-discovered feature flag under `context` for the
|
|
@@ -11,9 +11,10 @@ const isOperatorObject = (value) => {
|
|
|
11
11
|
const keys = Object.keys(value);
|
|
12
12
|
return keys.length > 0 && keys.every((key) => OPERATOR_KEY_SET.has(key));
|
|
13
13
|
};
|
|
14
|
+
const escapeLikeTerm = (value) => typeof value === "string" ? value.replaceAll(/[\\%_]/g, (character) => `\\${character}`) : value;
|
|
14
15
|
const compileContains = (reference, value, strategy) => {
|
|
15
|
-
const term = sql`${strategy.serialize(value)}`;
|
|
16
|
-
return strategy.likeContains ? strategy.likeContains(reference, term) : sql`${reference} LIKE '%' || ${term} || '%'`;
|
|
16
|
+
const term = sql`${strategy.serialize(escapeLikeTerm(value))}`;
|
|
17
|
+
return strategy.likeContains ? strategy.likeContains(reference, term) : sql`${reference} LIKE '%' || ${term} || '%' ESCAPE '\\'`;
|
|
17
18
|
};
|
|
18
19
|
const compileComparator = (reference, operator, comparator, value, strategy) => {
|
|
19
20
|
if (value === null) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { sql } from 'drizzle-orm';
|
|
2
2
|
import { r as runDrizzle } from './do-exec-5eQy5cEi.mjs';
|
|
3
3
|
import { D as DOC_COLUMN, r as rowToDocument, j as jsonPathSql } from './do-sql-BCHCWtrD.mjs';
|
|
4
|
-
import { compileWhereSql } from './compileWhereSql-
|
|
4
|
+
import { compileWhereSql } from './compileWhereSql-MW_Lk8nJ.mjs';
|
|
5
5
|
import { s as serializeSqlValue } from './serialize-sql-BlRUoiQe.mjs';
|
|
6
6
|
|
|
7
7
|
const shapeWhereStrategy = { fieldRef: jsonPathSql, serialize: serializeSqlValue };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { applyCdcChanges } from './CDC_LOG_TABLE-DSycmnDf.mjs';
|
|
2
|
-
import { s as selectShapeRows } from './ctx-db-shapes-
|
|
2
|
+
import { s as selectShapeRows } from './ctx-db-shapes-0RaIOy7J.mjs';
|
|
3
3
|
import { diffExternalSource, projectExternalSourceRow } from './diffExternalSource-Cx9HUPJj.mjs';
|
|
4
4
|
import { stableStringify } from './stableStringify-MydiuScU.mjs';
|
|
5
5
|
|
package/dist/packem_shared/{serveRelationFanout-EZLD9-O3.mjs → serveRelationFanout-BuSmWawx.mjs}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RELATION_FUNCTION_PREFIX } from './ADMIN_FUNCTIONS-
|
|
1
|
+
import { RELATION_FUNCTION_PREFIX } from './ADMIN_FUNCTIONS-BvGiv2u6.mjs';
|
|
2
2
|
|
|
3
3
|
const serveRelationFanout = async (schema, database, functionPath, args) => {
|
|
4
4
|
const table = typeof args["table"] === "string" ? args["table"] : "";
|