@xnetjs/core 0.12.0 → 2.0.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/index.d.ts +77 -24
- package/dist/index.js +72 -7
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -385,9 +385,13 @@ interface Role {
|
|
|
385
385
|
capabilities: Capability[];
|
|
386
386
|
}
|
|
387
387
|
/**
|
|
388
|
-
* Available capabilities
|
|
388
|
+
* Available capabilities.
|
|
389
|
+
*
|
|
390
|
+
* `create`/`update` are refinements of `write` (exploration 0304): a role
|
|
391
|
+
* holding `write` implicitly covers both; the granular capabilities cover
|
|
392
|
+
* only themselves.
|
|
389
393
|
*/
|
|
390
|
-
type Capability = 'read' | 'write' | 'delete' | 'share' | 'admin';
|
|
394
|
+
type Capability = 'read' | 'create' | 'update' | 'write' | 'delete' | 'share' | 'admin';
|
|
391
395
|
/**
|
|
392
396
|
* All capabilities in order of privilege
|
|
393
397
|
*/
|
|
@@ -451,7 +455,8 @@ interface PermissionEvaluator {
|
|
|
451
455
|
*/
|
|
452
456
|
declare const STANDARD_ROLES: Record<string, Role>;
|
|
453
457
|
/**
|
|
454
|
-
* Check if a capability is included in a role
|
|
458
|
+
* Check if a capability is included in a role.
|
|
459
|
+
* A role holding `write` covers the `create`/`update` refinements.
|
|
455
460
|
*/
|
|
456
461
|
declare function roleHasCapability(role: Role, capability: Capability): boolean;
|
|
457
462
|
/**
|
|
@@ -483,12 +488,46 @@ type SchemaIRI = `xnet://${string}/${string}`;
|
|
|
483
488
|
/**
|
|
484
489
|
* Canonical authorization actions.
|
|
485
490
|
* All action checks map to one of these values.
|
|
491
|
+
*
|
|
492
|
+
* `create` and `update` are refinements of the coarse `write` action
|
|
493
|
+
* (exploration 0304): `create` governs bringing a node into existence,
|
|
494
|
+
* `update` governs mutating a node that already exists. A schema MAY declare
|
|
495
|
+
* either refinement; when one is absent its expression falls back to the
|
|
496
|
+
* schema's `write` expression (see {@link actionExpressionOrder}), so schemas
|
|
497
|
+
* that only declare `write` behave exactly as before. Checking `write` on an
|
|
498
|
+
* existing node is equivalent to checking `update`.
|
|
499
|
+
*
|
|
500
|
+
* `create` checks evaluate roles against the *draft* node built from the
|
|
501
|
+
* create payload (`createdBy` = the caller). Because `role.creator()` then
|
|
502
|
+
* always matches, a schema that wants real admission control must exclude the
|
|
503
|
+
* creator role from `create` and require a container role instead — the
|
|
504
|
+
* draft's relation properties (e.g. `space`, `channel`) resolve normally.
|
|
486
505
|
*/
|
|
487
|
-
declare const AUTH_ACTIONS: readonly ["read", "write", "delete", "share", "admin"];
|
|
506
|
+
declare const AUTH_ACTIONS: readonly ["read", "create", "update", "write", "delete", "share", "admin"];
|
|
488
507
|
/**
|
|
489
508
|
* An authorization action that can be checked or granted.
|
|
490
509
|
*/
|
|
491
510
|
type AuthAction = (typeof AUTH_ACTIONS)[number];
|
|
511
|
+
/**
|
|
512
|
+
* Expression lookup order for a checked action — the first action name whose
|
|
513
|
+
* expression a schema defines wins (exploration 0304 fallback table):
|
|
514
|
+
*
|
|
515
|
+
* | checked | expression used |
|
|
516
|
+
* |--------------------|-------------------------------------|
|
|
517
|
+
* | `create` | `actions.create` ?? `actions.write` |
|
|
518
|
+
* | `update` / `write` | `actions.update` ?? `actions.write` |
|
|
519
|
+
* | anything else | `actions[action]` |
|
|
520
|
+
*/
|
|
521
|
+
declare function actionExpressionOrder(action: AuthAction): readonly AuthAction[];
|
|
522
|
+
/**
|
|
523
|
+
* Whether a granted action satisfies a checked action.
|
|
524
|
+
*
|
|
525
|
+
* A `write` grant covers its refinements (`create`, `update`); a granular
|
|
526
|
+
* grant covers only itself. A granular grant does NOT satisfy a legacy
|
|
527
|
+
* `write` check (fail closed — old callers checking `write` on an existing
|
|
528
|
+
* node mean update, which `update` covers).
|
|
529
|
+
*/
|
|
530
|
+
declare function grantActionSatisfies(granted: AuthAction, checked: AuthAction): boolean;
|
|
492
531
|
/**
|
|
493
532
|
* The result of an authorization check.
|
|
494
533
|
* Contains whether access is allowed plus diagnostic info for debugging.
|
|
@@ -554,7 +593,11 @@ interface AuthTraceStep {
|
|
|
554
593
|
* },
|
|
555
594
|
* actions: {
|
|
556
595
|
* read: allow('editor', 'admin', 'owner'),
|
|
596
|
+
* // coarse mutation policy; also the fallback for create/update
|
|
557
597
|
* write: allow('editor', 'admin', 'owner'),
|
|
598
|
+
* // optional refinements (0304): who may add vs. who may modify
|
|
599
|
+
* create: allow('editor', 'admin'),
|
|
600
|
+
* update: allow('owner', 'admin'),
|
|
558
601
|
* delete: allow('admin', 'owner'),
|
|
559
602
|
* share: allow('admin', 'owner')
|
|
560
603
|
* },
|
|
@@ -865,14 +908,14 @@ declare function validateExternalUrl(rawUrl: string): {
|
|
|
865
908
|
};
|
|
866
909
|
|
|
867
910
|
/**
|
|
868
|
-
* Retry/backoff policies (exploration
|
|
911
|
+
* Retry/backoff policies (exploration 0303).
|
|
869
912
|
*
|
|
870
913
|
* One dependency-free vocabulary for every reconnect/retry loop in the repo,
|
|
871
914
|
* replacing the hand-rolled backoff math that had drifted into three parallel
|
|
872
915
|
* implementations (sync connection-manager, WebSocketSyncProvider, webhook
|
|
873
916
|
* emitter). Deliberately shaped like Effect's `Schedule` combinators so a
|
|
874
917
|
* later migration would be mechanical — but scope-guarded: if this module
|
|
875
|
-
* needs union/intersect/cron/hedging, stop and re-read exploration
|
|
918
|
+
* needs union/intersect/cron/hedging, stop and re-read exploration 0303.
|
|
876
919
|
*/
|
|
877
920
|
/**
|
|
878
921
|
* A retry policy maps a 1-based attempt number to the delay (in ms) to wait
|
|
@@ -902,7 +945,7 @@ declare function jittered(policy: RetryPolicy, ratio?: number, random?: () => nu
|
|
|
902
945
|
declare function limitAttempts(policy: RetryPolicy, maxAttempts: number): RetryPolicy;
|
|
903
946
|
|
|
904
947
|
/**
|
|
905
|
-
* Tagged errors (exploration
|
|
948
|
+
* Tagged errors (exploration 0303).
|
|
906
949
|
*
|
|
907
950
|
* The repo-wide convention for structured errors, formalizing what
|
|
908
951
|
* `NodeRelayError.code` and friends already did by hand: every structured
|
|
@@ -925,7 +968,7 @@ declare abstract class TaggedError<Tag extends string = string> extends Error {
|
|
|
925
968
|
declare function isTagged<Tag extends string>(error: unknown, tag: Tag): error is TaggedError<Tag>;
|
|
926
969
|
|
|
927
970
|
/**
|
|
928
|
-
* Single-flight promise memoization (exploration
|
|
971
|
+
* Single-flight promise memoization (exploration 0303).
|
|
929
972
|
*
|
|
930
973
|
* The one implementation of the "share the in-flight promise so concurrent
|
|
931
974
|
* callers don't convoy the backend" pattern that had been independently
|
|
@@ -954,27 +997,28 @@ interface SingleFlightOptions {
|
|
|
954
997
|
*/
|
|
955
998
|
declare function singleFlight<K, V>(map: Map<K, Promise<V>>, key: K, fn: () => Promise<V>, options?: SingleFlightOptions): Promise<V>;
|
|
956
999
|
|
|
1000
|
+
/** Protocol version at which the grinding-resistant tiebreak key activates. */
|
|
1001
|
+
declare const LWW_TIEBREAK_KEY_VERSION = 4;
|
|
957
1002
|
/**
|
|
958
|
-
* The
|
|
959
|
-
*
|
|
960
|
-
*
|
|
961
|
-
* Per-property conflict resolution and change-log application ordering were
|
|
962
|
-
* previously re-implemented in three places (`NodeStore.applyChange`, the
|
|
963
|
-
* SQLite adapter's ON CONFLICT guards, and the hub storages' change
|
|
964
|
-
* ordering) — a drift class on the protocol's core convergence invariant.
|
|
965
|
-
* Every implementation now derives from this module, and the golden-vector
|
|
966
|
-
* conformance suite (exploration 0200) pins them equal.
|
|
1003
|
+
* The grinding-resistant LWW final tiebreak key (exploration 0305):
|
|
1004
|
+
* `blake3_hex( author ‖ US ‖ propertyKey ‖ US ‖ canonicalJSON(value) )`.
|
|
967
1005
|
*
|
|
968
|
-
*
|
|
969
|
-
*
|
|
970
|
-
*
|
|
971
|
-
* `0004-tie-author-case-codeunit` golden vector).
|
|
1006
|
+
* Portable by construction — a kernel in any language reproduces it from
|
|
1007
|
+
* canonical JSON of the value (which every kernel already computes for the
|
|
1008
|
+
* change hash). A deletion (`value === undefined`) canonicalises as `null`.
|
|
972
1009
|
*/
|
|
973
|
-
|
|
1010
|
+
declare function computeLwwTiebreakKey(author: string, propertyKey: string, value: unknown): string;
|
|
1011
|
+
/** The timestamp every LWW comparison runs on. */
|
|
974
1012
|
interface LwwStamp {
|
|
975
1013
|
lamport: number;
|
|
976
1014
|
wallTime: number;
|
|
977
1015
|
author: string;
|
|
1016
|
+
/**
|
|
1017
|
+
* Grinding-resistant tiebreak key ({@link computeLwwTiebreakKey}), present
|
|
1018
|
+
* only for changes at protocol version ≥ {@link LWW_TIEBREAK_KEY_VERSION}.
|
|
1019
|
+
* Absent (legacy) stamps fall back to the author-DID tiebreak.
|
|
1020
|
+
*/
|
|
1021
|
+
tiebreakKey?: string;
|
|
978
1022
|
}
|
|
979
1023
|
/**
|
|
980
1024
|
* Spec comparator (§L1.7): negative when `a` loses to `b`, positive when `a`
|
|
@@ -1000,13 +1044,22 @@ declare function compareChangeApplicationOrder(a: {
|
|
|
1000
1044
|
* SQL `ON CONFLICT … DO UPDATE … WHERE` guard implementing {@link lwwWins}
|
|
1001
1045
|
* inside SQLite (the `excluded.` pseudo-table is the incoming row). Column
|
|
1002
1046
|
* text comparison (`>`) is byte order under SQLite's default BINARY
|
|
1003
|
-
* collation, which matches the code-unit rule for our ASCII DID strings.
|
|
1047
|
+
* collation, which matches the code-unit rule for our ASCII DID/hex strings.
|
|
1048
|
+
*
|
|
1049
|
+
* When `tiebreakKeyColumn` is supplied, the final rung mirrors
|
|
1050
|
+
* {@link compareLwwStamps}: on a `lamport`+`wallTime` tie, if BOTH rows carry a
|
|
1051
|
+
* non-null tiebreak key the larger key wins outright (author irrelevant);
|
|
1052
|
+
* otherwise (either key null, or keys equal) the author DID decides. The stored
|
|
1053
|
+
* key is precomputed in application code ({@link computeLwwTiebreakKey}), so SQL
|
|
1054
|
+
* only ever compares the opaque hex — never recomputes it — keeping the JS and
|
|
1055
|
+
* SQL paths byte-identical without a user-defined function.
|
|
1004
1056
|
*/
|
|
1005
1057
|
declare function lwwUpdateGuardSql(input: {
|
|
1006
1058
|
table: string;
|
|
1007
1059
|
lamportColumn: string;
|
|
1008
1060
|
wallTimeColumn: string;
|
|
1009
1061
|
authorColumn: string;
|
|
1062
|
+
tiebreakKeyColumn?: string;
|
|
1010
1063
|
}): string;
|
|
1011
1064
|
|
|
1012
1065
|
/**
|
|
@@ -1016,4 +1069,4 @@ declare function lwwUpdateGuardSql(input: {
|
|
|
1016
1069
|
type DID = `did:key:${string}`;
|
|
1017
1070
|
type DocumentPath = `xnet://${DID}/workspace/${string}/doc/${string}`;
|
|
1018
1071
|
|
|
1019
|
-
export { ALL_CAPABILITIES, AUTH_ACTIONS, type ActionKey, type AllowExpr, type AndExpr, type AuthAction, type AuthCheckInput, type AuthDecision, type AuthDenyReason, type AuthExpression, type AuthTrace, type AuthTraceStep, type AuthenticatedExpr, type AuthorizationDefinition, BOOTSTRAP_PEERS, type Capability, type ChainStatus, type Condition, type ContentChunk, type ContentId, type ContentResolver, type ContentTree, type CreatorRoleResolver, DEFAULT_SNAPSHOT_TRIGGERS, DEFAULT_STREAMING_OPTIONS, DHT_CONFIG, type DID, type DIDResolution, type DIDResolver, type DataSource, type DenyExpr, type DocumentLoad, type DocumentPath, type Fork, type Group, type IPCondition, type LwwStamp, type MembershipRoleResolver, type MerkleNode, type NotExpr, type OrExpr, type PeerLocation, type PermissionEvaluator, type PermissionGrant, type PolicyEvaluator, type PropertyRoleResolver, type PublicExpr, type Query, type QueryPlan, type QueryRequest, type QueryResponse, type QueryRouter, RESOLUTION_CACHE_CONFIG, type RelationRoleResolver, type ResolutionStrategy, type ResourceScope, type RetryPolicy, type Role, type RoleKey, type RoleRefExpr, type RoleResolver, STANDARD_ROLES, type SchemaAction, type SerializedAuthExpression, type SerializedAuthorization, type SerializedRoleResolver, type SignedUpdate, type SingleFlightOptions, type Snapshot, type SnapshotTriggers, SsrfError, type StreamingQueryOptions, type SubQuery, TaggedError, type TimeCondition, type UpdateVerifier, type VectorClock, assertPublicUrl, buildMerkleTree, capped, clamp, clamp01, compareChangeApplicationOrder, compareLwwStamps, compareVectorClocks, createChunk, createContentId, deduplicatedUnion, detectFork, estimateQueryCost, evaluateCondition, exponential, fixed, formatBytes, getMostPermissiveCapability, hashContent, incrementVectorClock, isLocationFresh, isTagged, isValidDID, isValidProgression, jittered, limitAttempts, lwwUpdateGuardSql, lwwWins, mergeStateVectors, mergeVectorClocks, parseContentId, parseDID, roleHasCapability, shouldCreateSnapshot, singleFlight, unionAggregate, validateExternalUrl, verifyContent, verifyUpdateChain };
|
|
1072
|
+
export { ALL_CAPABILITIES, AUTH_ACTIONS, type ActionKey, type AllowExpr, type AndExpr, type AuthAction, type AuthCheckInput, type AuthDecision, type AuthDenyReason, type AuthExpression, type AuthTrace, type AuthTraceStep, type AuthenticatedExpr, type AuthorizationDefinition, BOOTSTRAP_PEERS, type Capability, type ChainStatus, type Condition, type ContentChunk, type ContentId, type ContentResolver, type ContentTree, type CreatorRoleResolver, DEFAULT_SNAPSHOT_TRIGGERS, DEFAULT_STREAMING_OPTIONS, DHT_CONFIG, type DID, type DIDResolution, type DIDResolver, type DataSource, type DenyExpr, type DocumentLoad, type DocumentPath, type Fork, type Group, type IPCondition, LWW_TIEBREAK_KEY_VERSION, type LwwStamp, type MembershipRoleResolver, type MerkleNode, type NotExpr, type OrExpr, type PeerLocation, type PermissionEvaluator, type PermissionGrant, type PolicyEvaluator, type PropertyRoleResolver, type PublicExpr, type Query, type QueryPlan, type QueryRequest, type QueryResponse, type QueryRouter, RESOLUTION_CACHE_CONFIG, type RelationRoleResolver, type ResolutionStrategy, type ResourceScope, type RetryPolicy, type Role, type RoleKey, type RoleRefExpr, type RoleResolver, STANDARD_ROLES, type SchemaAction, type SerializedAuthExpression, type SerializedAuthorization, type SerializedRoleResolver, type SignedUpdate, type SingleFlightOptions, type Snapshot, type SnapshotTriggers, SsrfError, type StreamingQueryOptions, type SubQuery, TaggedError, type TimeCondition, type UpdateVerifier, type VectorClock, actionExpressionOrder, assertPublicUrl, buildMerkleTree, capped, clamp, clamp01, compareChangeApplicationOrder, compareLwwStamps, compareVectorClocks, computeLwwTiebreakKey, createChunk, createContentId, deduplicatedUnion, detectFork, estimateQueryCost, evaluateCondition, exponential, fixed, formatBytes, getMostPermissiveCapability, grantActionSatisfies, hashContent, incrementVectorClock, isLocationFresh, isTagged, isValidDID, isValidProgression, jittered, limitAttempts, lwwUpdateGuardSql, lwwWins, mergeStateVectors, mergeVectorClocks, parseContentId, parseDID, roleHasCapability, shouldCreateSnapshot, singleFlight, unionAggregate, validateExternalUrl, verifyContent, verifyUpdateChain };
|
package/dist/index.js
CHANGED
|
@@ -267,8 +267,38 @@ function deduplicatedUnion(results) {
|
|
|
267
267
|
return output;
|
|
268
268
|
}
|
|
269
269
|
|
|
270
|
+
// src/auth-types.ts
|
|
271
|
+
var AUTH_ACTIONS = [
|
|
272
|
+
"read",
|
|
273
|
+
"create",
|
|
274
|
+
"update",
|
|
275
|
+
"write",
|
|
276
|
+
"delete",
|
|
277
|
+
"share",
|
|
278
|
+
"admin"
|
|
279
|
+
];
|
|
280
|
+
function actionExpressionOrder(action) {
|
|
281
|
+
if (action === "create") return ["create", "write"];
|
|
282
|
+
if (action === "update" || action === "write") return ["update", "write"];
|
|
283
|
+
return [action];
|
|
284
|
+
}
|
|
285
|
+
function grantActionSatisfies(granted, checked) {
|
|
286
|
+
if (granted === checked) return true;
|
|
287
|
+
if (granted === "write") return checked === "create" || checked === "update";
|
|
288
|
+
if (granted === "update") return checked === "write";
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
|
|
270
292
|
// src/permissions.ts
|
|
271
|
-
var ALL_CAPABILITIES = [
|
|
293
|
+
var ALL_CAPABILITIES = [
|
|
294
|
+
"read",
|
|
295
|
+
"create",
|
|
296
|
+
"update",
|
|
297
|
+
"write",
|
|
298
|
+
"delete",
|
|
299
|
+
"share",
|
|
300
|
+
"admin"
|
|
301
|
+
];
|
|
272
302
|
var STANDARD_ROLES = {
|
|
273
303
|
viewer: {
|
|
274
304
|
id: "viewer",
|
|
@@ -284,7 +314,7 @@ var STANDARD_ROLES = {
|
|
|
284
314
|
}
|
|
285
315
|
};
|
|
286
316
|
function roleHasCapability(role, capability) {
|
|
287
|
-
return role.capabilities.
|
|
317
|
+
return role.capabilities.some((held) => grantActionSatisfies(held, capability));
|
|
288
318
|
}
|
|
289
319
|
function evaluateCondition(condition, context) {
|
|
290
320
|
switch (condition.type) {
|
|
@@ -306,9 +336,6 @@ function getMostPermissiveCapability(capabilities) {
|
|
|
306
336
|
return null;
|
|
307
337
|
}
|
|
308
338
|
|
|
309
|
-
// src/auth-types.ts
|
|
310
|
-
var AUTH_ACTIONS = ["read", "write", "delete", "share", "admin"];
|
|
311
|
-
|
|
312
339
|
// src/utils/math.ts
|
|
313
340
|
function clamp(value, min, max) {
|
|
314
341
|
if (value < min) return min;
|
|
@@ -470,9 +497,36 @@ function singleFlight(map, key, fn, options = {}) {
|
|
|
470
497
|
}
|
|
471
498
|
|
|
472
499
|
// src/lww.ts
|
|
500
|
+
import { blake3 as blake32 } from "@noble/hashes/blake3.js";
|
|
501
|
+
var LWW_TIEBREAK_KEY_VERSION = 4;
|
|
502
|
+
var US = "";
|
|
503
|
+
function canonicalize(value) {
|
|
504
|
+
if (value === null || typeof value !== "object") return value;
|
|
505
|
+
if (Array.isArray(value)) return value.map(canonicalize);
|
|
506
|
+
const out = {};
|
|
507
|
+
for (const key of Object.keys(value).sort()) {
|
|
508
|
+
out[key] = canonicalize(value[key]);
|
|
509
|
+
}
|
|
510
|
+
return out;
|
|
511
|
+
}
|
|
512
|
+
function toHex(bytes) {
|
|
513
|
+
let s = "";
|
|
514
|
+
for (const b of bytes) s += b.toString(16).padStart(2, "0");
|
|
515
|
+
return s;
|
|
516
|
+
}
|
|
517
|
+
function computeLwwTiebreakKey(author, propertyKey, value) {
|
|
518
|
+
const canonical = JSON.stringify(canonicalize(value === void 0 ? null : value));
|
|
519
|
+
const bytes = new TextEncoder().encode(`${author}${US}${propertyKey}${US}${canonical}`);
|
|
520
|
+
return toHex(blake32(bytes));
|
|
521
|
+
}
|
|
473
522
|
function compareLwwStamps(a, b) {
|
|
474
523
|
if (a.lamport !== b.lamport) return a.lamport - b.lamport;
|
|
475
524
|
if (a.wallTime !== b.wallTime) return a.wallTime - b.wallTime;
|
|
525
|
+
const aK = a.tiebreakKey;
|
|
526
|
+
const bK = b.tiebreakKey;
|
|
527
|
+
if (aK !== void 0 && bK !== void 0 && aK !== bK) {
|
|
528
|
+
return aK < bK ? -1 : 1;
|
|
529
|
+
}
|
|
476
530
|
return a.author < b.author ? -1 : a.author > b.author ? 1 : 0;
|
|
477
531
|
}
|
|
478
532
|
function lwwWins(incoming, existing) {
|
|
@@ -483,12 +537,19 @@ function compareChangeApplicationOrder(a, b) {
|
|
|
483
537
|
return a.author < b.author ? -1 : a.author > b.author ? 1 : 0;
|
|
484
538
|
}
|
|
485
539
|
function lwwUpdateGuardSql(input) {
|
|
486
|
-
const { table, lamportColumn, wallTimeColumn, authorColumn } = input;
|
|
540
|
+
const { table, lamportColumn, wallTimeColumn, authorColumn, tiebreakKeyColumn } = input;
|
|
541
|
+
const finalRung = tiebreakKeyColumn ? `(excluded.${tiebreakKeyColumn} IS NOT NULL
|
|
542
|
+
AND ${table}.${tiebreakKeyColumn} IS NOT NULL
|
|
543
|
+
AND excluded.${tiebreakKeyColumn} > ${table}.${tiebreakKeyColumn})
|
|
544
|
+
OR (NOT (excluded.${tiebreakKeyColumn} IS NOT NULL
|
|
545
|
+
AND ${table}.${tiebreakKeyColumn} IS NOT NULL
|
|
546
|
+
AND excluded.${tiebreakKeyColumn} <> ${table}.${tiebreakKeyColumn})
|
|
547
|
+
AND excluded.${authorColumn} > ${table}.${authorColumn})` : `excluded.${authorColumn} > ${table}.${authorColumn}`;
|
|
487
548
|
return `excluded.${lamportColumn} > ${table}.${lamportColumn}
|
|
488
549
|
OR (excluded.${lamportColumn} = ${table}.${lamportColumn}
|
|
489
550
|
AND (excluded.${wallTimeColumn} > ${table}.${wallTimeColumn}
|
|
490
551
|
OR (excluded.${wallTimeColumn} = ${table}.${wallTimeColumn}
|
|
491
|
-
AND
|
|
552
|
+
AND (${finalRung}))))`;
|
|
492
553
|
}
|
|
493
554
|
export {
|
|
494
555
|
ALL_CAPABILITIES,
|
|
@@ -497,10 +558,12 @@ export {
|
|
|
497
558
|
DEFAULT_SNAPSHOT_TRIGGERS,
|
|
498
559
|
DEFAULT_STREAMING_OPTIONS,
|
|
499
560
|
DHT_CONFIG,
|
|
561
|
+
LWW_TIEBREAK_KEY_VERSION,
|
|
500
562
|
RESOLUTION_CACHE_CONFIG,
|
|
501
563
|
STANDARD_ROLES,
|
|
502
564
|
SsrfError,
|
|
503
565
|
TaggedError,
|
|
566
|
+
actionExpressionOrder,
|
|
504
567
|
assertPublicUrl,
|
|
505
568
|
buildMerkleTree,
|
|
506
569
|
capped,
|
|
@@ -509,6 +572,7 @@ export {
|
|
|
509
572
|
compareChangeApplicationOrder,
|
|
510
573
|
compareLwwStamps,
|
|
511
574
|
compareVectorClocks,
|
|
575
|
+
computeLwwTiebreakKey,
|
|
512
576
|
createChunk,
|
|
513
577
|
createContentId,
|
|
514
578
|
deduplicatedUnion,
|
|
@@ -519,6 +583,7 @@ export {
|
|
|
519
583
|
fixed,
|
|
520
584
|
formatBytes,
|
|
521
585
|
getMostPermissiveCapability,
|
|
586
|
+
grantActionSatisfies,
|
|
522
587
|
hashContent,
|
|
523
588
|
incrementVectorClock,
|
|
524
589
|
isLocationFresh,
|