@tinycloud/sdk-services 3.2.6-beta.2 → 3.2.6-beta.4
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/{BaseService-4wwJq1Gn.d.cts → BaseService-1Ug6y7DC.d.cts} +1 -1
- package/dist/{BaseService-BGr2slUz.d.ts → BaseService-Bn07Vudy.d.ts} +1 -1
- package/dist/encryption/index.cjs +2 -0
- package/dist/encryption/index.cjs.map +1 -1
- package/dist/encryption/index.d.cts +2 -2
- package/dist/encryption/index.d.ts +2 -2
- package/dist/encryption/index.js +2 -0
- package/dist/encryption/index.js.map +1 -1
- package/dist/index.cjs +15 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -11
- package/dist/index.d.ts +14 -11
- package/dist/index.js +15 -7
- package/dist/index.js.map +1 -1
- package/dist/internal/decrypt-transport-response-error.d.cts +1 -1
- package/dist/internal/decrypt-transport-response-error.d.ts +1 -1
- package/dist/kv/index.cjs +2 -0
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +7 -4
- package/dist/kv/index.d.ts +7 -4
- package/dist/kv/index.js +2 -0
- package/dist/kv/index.js.map +1 -1
- package/dist/kv/replication/contractConstants.cjs +115 -0
- package/dist/kv/replication/contractConstants.cjs.map +1 -0
- package/dist/kv/replication/contractConstants.d.cts +77 -0
- package/dist/kv/replication/contractConstants.d.ts +77 -0
- package/dist/kv/replication/contractConstants.js +75 -0
- package/dist/kv/replication/contractConstants.js.map +1 -0
- package/dist/kv/replication/grantPolicyConstants.cjs +42 -0
- package/dist/kv/replication/grantPolicyConstants.cjs.map +1 -0
- package/dist/kv/replication/grantPolicyConstants.d.cts +10 -0
- package/dist/kv/replication/grantPolicyConstants.d.ts +10 -0
- package/dist/kv/replication/grantPolicyConstants.js +14 -0
- package/dist/kv/replication/grantPolicyConstants.js.map +1 -0
- package/dist/kv/replication/grantPolicyTypes.cjs +19 -0
- package/dist/kv/replication/grantPolicyTypes.cjs.map +1 -0
- package/dist/kv/replication/grantPolicyTypes.d.cts +87 -0
- package/dist/kv/replication/grantPolicyTypes.d.ts +87 -0
- package/dist/kv/replication/grantPolicyTypes.js +1 -0
- package/dist/kv/replication/grantPolicyTypes.js.map +1 -0
- package/dist/kv/replication/index.cjs +5 -4
- package/dist/kv/replication/index.cjs.map +1 -1
- package/dist/kv/replication/index.d.cts +6 -3
- package/dist/kv/replication/index.d.ts +6 -3
- package/dist/kv/replication/index.js +5 -4
- package/dist/kv/replication/index.js.map +1 -1
- package/dist/scope-BnyVPZ5E.d.ts +1659 -0
- package/dist/scope-CQ5kmHlt.d.cts +1659 -0
- package/dist/sql/index.cjs +2 -0
- package/dist/sql/index.cjs.map +1 -1
- package/dist/sql/index.d.cts +2 -2
- package/dist/sql/index.d.ts +2 -2
- package/dist/sql/index.js +2 -0
- package/dist/sql/index.js.map +1 -1
- package/dist/{types-D-9A3Sut.d.cts → types-gmdUiorz.d.cts} +2 -0
- package/dist/{types-D-9A3Sut.d.ts → types-gmdUiorz.d.ts} +2 -0
- package/package.json +40 -1
- package/dist/scope-CoKKmMiI.d.ts +0 -957
- package/dist/scope-D7wmjbMH.d.cts +0 -957
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/kv/replication/contractConstants.ts
|
|
21
|
+
var contractConstants_exports = {};
|
|
22
|
+
__export(contractConstants_exports, {
|
|
23
|
+
CONSENT_WINDOW_MS: () => CONSENT_WINDOW_MS,
|
|
24
|
+
DEFAULT_GRANT_TTL_MS: () => DEFAULT_GRANT_TTL_MS,
|
|
25
|
+
DEFAULT_MIN_FREE_BYTES: () => DEFAULT_MIN_FREE_BYTES,
|
|
26
|
+
MAX_GRANT_TTL_MS: () => MAX_GRANT_TTL_MS,
|
|
27
|
+
RENEW_BELOW_FRACTION: () => RENEW_BELOW_FRACTION,
|
|
28
|
+
REPLICA_DENY_TOMBSTONE: () => REPLICA_DENY_TOMBSTONE,
|
|
29
|
+
REPLICA_GATE_FILE: () => REPLICA_GATE_FILE,
|
|
30
|
+
REPLICA_KV_CHANNEL: () => REPLICA_KV_CHANNEL,
|
|
31
|
+
REPLICA_KV_DATABASE: () => REPLICA_KV_DATABASE,
|
|
32
|
+
REPLICA_KV_SCHEMA_VERSION: () => REPLICA_KV_SCHEMA_VERSION,
|
|
33
|
+
REPLICA_KV_STORES: () => REPLICA_KV_STORES,
|
|
34
|
+
REPLICA_LOGOUT_MARKER: () => REPLICA_LOGOUT_MARKER,
|
|
35
|
+
REPLICA_PENDING_LOCK_PREFIX: () => REPLICA_PENDING_LOCK_PREFIX,
|
|
36
|
+
ReplicaContractCode: () => ReplicaContractCode
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(contractConstants_exports);
|
|
39
|
+
|
|
40
|
+
// src/kv/replication/grantPolicyConstants.ts
|
|
41
|
+
var HOUR_MS = 60 * 60 * 1e3;
|
|
42
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
43
|
+
var DEFAULT_GRANT_TTL_MS = DAY_MS;
|
|
44
|
+
var MAX_GRANT_TTL_MS = 7 * DAY_MS;
|
|
45
|
+
var CONSENT_WINDOW_MS = 7 * DAY_MS;
|
|
46
|
+
var RENEW_BELOW_FRACTION = 0.25;
|
|
47
|
+
|
|
48
|
+
// src/kv/replication/contractConstants.ts
|
|
49
|
+
var ReplicaContractCode = {
|
|
50
|
+
/**
|
|
51
|
+
* The lifecycle gate refused the operation: the handle's session stamp or principal no longer
|
|
52
|
+
* matches the gate, a purge intent covers the partition, or the logout marker is set. The error
|
|
53
|
+
* carries `gate: ReplicaGateReason`. Read-through answers from the network; nothing is erased.
|
|
54
|
+
*/
|
|
55
|
+
REPLICA_GATED: "REPLICA_GATED",
|
|
56
|
+
/**
|
|
57
|
+
* Reserved for handles whose partition was erased (purge or revocation) after they opened. The
|
|
58
|
+
* gate check runs first, so a handle that is both gated and erased reports REPLICA_GATED.
|
|
59
|
+
*/
|
|
60
|
+
RESET_REQUIRED: "RESET_REQUIRED",
|
|
61
|
+
/** A page was refused by quota admission (`maxBytes` or the free-space floor). Nothing committed. */
|
|
62
|
+
STORAGE_BUDGET: "STORAGE_BUDGET",
|
|
63
|
+
/** The platform store refused the write (IndexedDB `QuotaExceededError`, ENOSPC). Nothing committed. */
|
|
64
|
+
STORAGE_FULL: "STORAGE_FULL",
|
|
65
|
+
/** The consent deadline has passed: no grant may be minted, renewed or served until re-consent. */
|
|
66
|
+
CONSENT_EXPIRED: "CONSENT_EXPIRED",
|
|
67
|
+
/** The installed grant's effective expiry (not necessarily its signed `exp`) has passed. */
|
|
68
|
+
GRANT_EXPIRED: "GRANT_EXPIRED"
|
|
69
|
+
};
|
|
70
|
+
var DEFAULT_MIN_FREE_BYTES = 64 * 1024 * 1024;
|
|
71
|
+
var REPLICA_KV_DATABASE = "tinycloud-replica-kv";
|
|
72
|
+
var REPLICA_KV_SCHEMA_VERSION = 2;
|
|
73
|
+
var REPLICA_KV_STORES = {
|
|
74
|
+
/** Data: partition meta (opaque fences, sealed config/grants), private gate-HMAC partition id. */
|
|
75
|
+
meta: "meta",
|
|
76
|
+
/** Data: sealed KV entries, key `[privatePartitionId, accountHmac(path)]`. */
|
|
77
|
+
entries: "entries",
|
|
78
|
+
/** Data: AES-GCM content blobs, key `[privatePartitionId, accountHmac(hash)]`. */
|
|
79
|
+
blobs: "blobs",
|
|
80
|
+
/** Data: AES-sealed pending state, key private gate-HMAC `identityKeyHash`. */
|
|
81
|
+
pending: "pending",
|
|
82
|
+
/** Data: sealed owner device, private nonextractable key records and opaque install anchors. */
|
|
83
|
+
device: "device",
|
|
84
|
+
/** Control: the account gate, singleton key `"account"`, value `ReplicaAccountGate`. */
|
|
85
|
+
gate: "gate",
|
|
86
|
+
/** Control: partition index keyed by private `partitionId`; nonunique `byLookupId` index. */
|
|
87
|
+
partitions: "partitions",
|
|
88
|
+
/** Control: purge intents, key `ReplicaPurgeIntent.id`, value `ReplicaPurgeIntent`. */
|
|
89
|
+
purgeIntents: "purgeIntents",
|
|
90
|
+
/** Control: quota ledger, keys owned by the ledger (S5). */
|
|
91
|
+
quota: "quota"
|
|
92
|
+
};
|
|
93
|
+
var REPLICA_LOGOUT_MARKER = "tinycloud-replica:logout-pending";
|
|
94
|
+
var REPLICA_DENY_TOMBSTONE = "tinycloud-replica:deny-tombstone";
|
|
95
|
+
var REPLICA_KV_CHANNEL = "tinycloud-replica-kv";
|
|
96
|
+
var REPLICA_PENDING_LOCK_PREFIX = "tinycloud-replica-kv:pending:";
|
|
97
|
+
var REPLICA_GATE_FILE = "replica-gate.json";
|
|
98
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
99
|
+
0 && (module.exports = {
|
|
100
|
+
CONSENT_WINDOW_MS,
|
|
101
|
+
DEFAULT_GRANT_TTL_MS,
|
|
102
|
+
DEFAULT_MIN_FREE_BYTES,
|
|
103
|
+
MAX_GRANT_TTL_MS,
|
|
104
|
+
RENEW_BELOW_FRACTION,
|
|
105
|
+
REPLICA_DENY_TOMBSTONE,
|
|
106
|
+
REPLICA_GATE_FILE,
|
|
107
|
+
REPLICA_KV_CHANNEL,
|
|
108
|
+
REPLICA_KV_DATABASE,
|
|
109
|
+
REPLICA_KV_SCHEMA_VERSION,
|
|
110
|
+
REPLICA_KV_STORES,
|
|
111
|
+
REPLICA_LOGOUT_MARKER,
|
|
112
|
+
REPLICA_PENDING_LOCK_PREFIX,
|
|
113
|
+
ReplicaContractCode
|
|
114
|
+
});
|
|
115
|
+
//# sourceMappingURL=contractConstants.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/kv/replication/contractConstants.ts","../../../src/kv/replication/grantPolicyConstants.ts"],"sourcesContent":["/**\n * Frozen constants of the shared replica contract (TC-858 Phase 2, see CONTRACT.md).\n *\n * Exported via `@tinycloud/sdk-services/kv/replication/contractConstants`, never from the\n * package root. Runtime grant policy imports the numeric-only `grantPolicyConstants` subpath\n * instead, so the default web bundle does not carry browser storage identifiers.\n */\nexport {\n DEFAULT_GRANT_TTL_MS,\n MAX_GRANT_TTL_MS,\n CONSENT_WINDOW_MS,\n RENEW_BELOW_FRACTION,\n} from \"./grantPolicyConstants\";\n\n/** Error codes the contract adds or gives new meaning. Values equal keys. */\nexport const ReplicaContractCode = {\n /**\n * The lifecycle gate refused the operation: the handle's session stamp or principal no longer\n * matches the gate, a purge intent covers the partition, or the logout marker is set. The error\n * carries `gate: ReplicaGateReason`. Read-through answers from the network; nothing is erased.\n */\n REPLICA_GATED: \"REPLICA_GATED\",\n /**\n * Reserved for handles whose partition was erased (purge or revocation) after they opened. The\n * gate check runs first, so a handle that is both gated and erased reports REPLICA_GATED.\n */\n RESET_REQUIRED: \"RESET_REQUIRED\",\n /** A page was refused by quota admission (`maxBytes` or the free-space floor). Nothing committed. */\n STORAGE_BUDGET: \"STORAGE_BUDGET\",\n /** The platform store refused the write (IndexedDB `QuotaExceededError`, ENOSPC). Nothing committed. */\n STORAGE_FULL: \"STORAGE_FULL\",\n /** The consent deadline has passed: no grant may be minted, renewed or served until re-consent. */\n CONSENT_EXPIRED: \"CONSENT_EXPIRED\",\n /** The installed grant's effective expiry (not necessarily its signed `exp`) has passed. */\n GRANT_EXPIRED: \"GRANT_EXPIRED\",\n} as const;\nexport type ReplicaContractCode = (typeof ReplicaContractCode)[keyof typeof ReplicaContractCode];\n\n/** Browser free-space floor in bytes (64 MiB, `navigator.storage.estimate()`); not applied on node/CLI. */\nexport const DEFAULT_MIN_FREE_BYTES = 64 * 1024 * 1024;\n\n/** The single per-origin IndexedDB database of the browser `KVReplicaStorage` adapter. */\nexport const REPLICA_KV_DATABASE = \"tinycloud-replica-kv\";\n/** Origin database schema: v2 destructively replaces v1 plaintext replica-owned stores. */\nexport const REPLICA_KV_SCHEMA_VERSION = 2;\n\n/**\n * Object-store names in {@link REPLICA_KV_DATABASE}. Every store uses out-of-line keys (no\n * `keyPath`, no autoIncrement) so the schema upgrade can create control stores without knowing\n * their record shapes. Data stores are owned by the adapter (S1); control stores by the lifecycle\n * gate (S3) and quota ledger (S5).\n */\nexport const REPLICA_KV_STORES = {\n /** Data: partition meta (opaque fences, sealed config/grants), private gate-HMAC partition id. */\n meta: \"meta\",\n /** Data: sealed KV entries, key `[privatePartitionId, accountHmac(path)]`. */\n entries: \"entries\",\n /** Data: AES-GCM content blobs, key `[privatePartitionId, accountHmac(hash)]`. */\n blobs: \"blobs\",\n /** Data: AES-sealed pending state, key private gate-HMAC `identityKeyHash`. */\n pending: \"pending\",\n /** Data: sealed owner device, private nonextractable key records and opaque install anchors. */\n device: \"device\",\n /** Control: the account gate, singleton key `\"account\"`, value `ReplicaAccountGate`. */\n gate: \"gate\",\n /** Control: partition index keyed by private `partitionId`; nonunique `byLookupId` index. */\n partitions: \"partitions\",\n /** Control: purge intents, key `ReplicaPurgeIntent.id`, value `ReplicaPurgeIntent`. */\n purgeIntents: \"purgeIntents\",\n /** Control: quota ledger, keys owned by the ledger (S5). */\n quota: \"quota\",\n} as const;\n\n/** Synchronous, cross-tab `localStorage` marker set when the deny transaction and fallback delete both failed. */\nexport const REPLICA_LOGOUT_MARKER = \"tinycloud-replica:logout-pending\";\n\n/** Origin-wide deny floor outside the deletable replica database; JSON `{ epoch, deniedAt }`. */\nexport const REPLICA_DENY_TOMBSTONE = \"tinycloud-replica:deny-tombstone\";\n\n/** BroadcastChannel name used for lifecycle nudges and peer-commit notifications. */\nexport const REPLICA_KV_CHANNEL = \"tinycloud-replica-kv\";\n\n/** Web Lock name prefix for pending-write read-modify-write; suffix is the private gate-HMAC identity id. */\nexport const REPLICA_PENDING_LOCK_PREFIX = \"tinycloud-replica-kv:pending:\";\n\n/** Node/CLI gate file name. CLI places it at `<profile>/replica-gate.json`. */\nexport const REPLICA_GATE_FILE = \"replica-gate.json\";\n","/** Grant lifetime constants without browser storage identifiers. */\nconst HOUR_MS = 60 * 60 * 1000;\nconst DAY_MS = 24 * HOUR_MS;\n\n/** Default device-grant lifetime from install (24 h). All durations are milliseconds. */\nexport const DEFAULT_GRANT_TTL_MS = DAY_MS;\n/** `grantTtlMs` above this (7 d) is a config error: TypeError at construction. */\nexport const MAX_GRANT_TTL_MS = 7 * DAY_MS;\n/** Consent deadline = consent anchor + this window (7 d). */\nexport const CONSENT_WINDOW_MS = 7 * DAY_MS;\n/** Silent renewal starts when remaining effective lifetime < this fraction of the effective lifetime. */\nexport const RENEW_BELOW_FRACTION = 0.25;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,IAAM,UAAU,KAAK,KAAK;AAC1B,IAAM,SAAS,KAAK;AAGb,IAAM,uBAAuB;AAE7B,IAAM,mBAAmB,IAAI;AAE7B,IAAM,oBAAoB,IAAI;AAE9B,IAAM,uBAAuB;;;ADI7B,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjC,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAKf,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAAA;AAAA,EAEhB,cAAc;AAAA;AAAA,EAEd,iBAAiB;AAAA;AAAA,EAEjB,eAAe;AACjB;AAIO,IAAM,yBAAyB,KAAK,OAAO;AAG3C,IAAM,sBAAsB;AAE5B,IAAM,4BAA4B;AAQlC,IAAM,oBAAoB;AAAA;AAAA,EAE/B,MAAM;AAAA;AAAA,EAEN,SAAS;AAAA;AAAA,EAET,OAAO;AAAA;AAAA,EAEP,SAAS;AAAA;AAAA,EAET,QAAQ;AAAA;AAAA,EAER,MAAM;AAAA;AAAA,EAEN,YAAY;AAAA;AAAA,EAEZ,cAAc;AAAA;AAAA,EAEd,OAAO;AACT;AAGO,IAAM,wBAAwB;AAG9B,IAAM,yBAAyB;AAG/B,IAAM,qBAAqB;AAG3B,IAAM,8BAA8B;AAGpC,IAAM,oBAAoB;","names":[]}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export { CONSENT_WINDOW_MS, DEFAULT_GRANT_TTL_MS, MAX_GRANT_TTL_MS, RENEW_BELOW_FRACTION } from './grantPolicyConstants.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Frozen constants of the shared replica contract (TC-858 Phase 2, see CONTRACT.md).
|
|
5
|
+
*
|
|
6
|
+
* Exported via `@tinycloud/sdk-services/kv/replication/contractConstants`, never from the
|
|
7
|
+
* package root. Runtime grant policy imports the numeric-only `grantPolicyConstants` subpath
|
|
8
|
+
* instead, so the default web bundle does not carry browser storage identifiers.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Error codes the contract adds or gives new meaning. Values equal keys. */
|
|
12
|
+
declare const ReplicaContractCode: {
|
|
13
|
+
/**
|
|
14
|
+
* The lifecycle gate refused the operation: the handle's session stamp or principal no longer
|
|
15
|
+
* matches the gate, a purge intent covers the partition, or the logout marker is set. The error
|
|
16
|
+
* carries `gate: ReplicaGateReason`. Read-through answers from the network; nothing is erased.
|
|
17
|
+
*/
|
|
18
|
+
readonly REPLICA_GATED: "REPLICA_GATED";
|
|
19
|
+
/**
|
|
20
|
+
* Reserved for handles whose partition was erased (purge or revocation) after they opened. The
|
|
21
|
+
* gate check runs first, so a handle that is both gated and erased reports REPLICA_GATED.
|
|
22
|
+
*/
|
|
23
|
+
readonly RESET_REQUIRED: "RESET_REQUIRED";
|
|
24
|
+
/** A page was refused by quota admission (`maxBytes` or the free-space floor). Nothing committed. */
|
|
25
|
+
readonly STORAGE_BUDGET: "STORAGE_BUDGET";
|
|
26
|
+
/** The platform store refused the write (IndexedDB `QuotaExceededError`, ENOSPC). Nothing committed. */
|
|
27
|
+
readonly STORAGE_FULL: "STORAGE_FULL";
|
|
28
|
+
/** The consent deadline has passed: no grant may be minted, renewed or served until re-consent. */
|
|
29
|
+
readonly CONSENT_EXPIRED: "CONSENT_EXPIRED";
|
|
30
|
+
/** The installed grant's effective expiry (not necessarily its signed `exp`) has passed. */
|
|
31
|
+
readonly GRANT_EXPIRED: "GRANT_EXPIRED";
|
|
32
|
+
};
|
|
33
|
+
type ReplicaContractCode = (typeof ReplicaContractCode)[keyof typeof ReplicaContractCode];
|
|
34
|
+
/** Browser free-space floor in bytes (64 MiB, `navigator.storage.estimate()`); not applied on node/CLI. */
|
|
35
|
+
declare const DEFAULT_MIN_FREE_BYTES: number;
|
|
36
|
+
/** The single per-origin IndexedDB database of the browser `KVReplicaStorage` adapter. */
|
|
37
|
+
declare const REPLICA_KV_DATABASE = "tinycloud-replica-kv";
|
|
38
|
+
/** Origin database schema: v2 destructively replaces v1 plaintext replica-owned stores. */
|
|
39
|
+
declare const REPLICA_KV_SCHEMA_VERSION = 2;
|
|
40
|
+
/**
|
|
41
|
+
* Object-store names in {@link REPLICA_KV_DATABASE}. Every store uses out-of-line keys (no
|
|
42
|
+
* `keyPath`, no autoIncrement) so the schema upgrade can create control stores without knowing
|
|
43
|
+
* their record shapes. Data stores are owned by the adapter (S1); control stores by the lifecycle
|
|
44
|
+
* gate (S3) and quota ledger (S5).
|
|
45
|
+
*/
|
|
46
|
+
declare const REPLICA_KV_STORES: {
|
|
47
|
+
/** Data: partition meta (opaque fences, sealed config/grants), private gate-HMAC partition id. */
|
|
48
|
+
readonly meta: "meta";
|
|
49
|
+
/** Data: sealed KV entries, key `[privatePartitionId, accountHmac(path)]`. */
|
|
50
|
+
readonly entries: "entries";
|
|
51
|
+
/** Data: AES-GCM content blobs, key `[privatePartitionId, accountHmac(hash)]`. */
|
|
52
|
+
readonly blobs: "blobs";
|
|
53
|
+
/** Data: AES-sealed pending state, key private gate-HMAC `identityKeyHash`. */
|
|
54
|
+
readonly pending: "pending";
|
|
55
|
+
/** Data: sealed owner device, private nonextractable key records and opaque install anchors. */
|
|
56
|
+
readonly device: "device";
|
|
57
|
+
/** Control: the account gate, singleton key `"account"`, value `ReplicaAccountGate`. */
|
|
58
|
+
readonly gate: "gate";
|
|
59
|
+
/** Control: partition index keyed by private `partitionId`; nonunique `byLookupId` index. */
|
|
60
|
+
readonly partitions: "partitions";
|
|
61
|
+
/** Control: purge intents, key `ReplicaPurgeIntent.id`, value `ReplicaPurgeIntent`. */
|
|
62
|
+
readonly purgeIntents: "purgeIntents";
|
|
63
|
+
/** Control: quota ledger, keys owned by the ledger (S5). */
|
|
64
|
+
readonly quota: "quota";
|
|
65
|
+
};
|
|
66
|
+
/** Synchronous, cross-tab `localStorage` marker set when the deny transaction and fallback delete both failed. */
|
|
67
|
+
declare const REPLICA_LOGOUT_MARKER = "tinycloud-replica:logout-pending";
|
|
68
|
+
/** Origin-wide deny floor outside the deletable replica database; JSON `{ epoch, deniedAt }`. */
|
|
69
|
+
declare const REPLICA_DENY_TOMBSTONE = "tinycloud-replica:deny-tombstone";
|
|
70
|
+
/** BroadcastChannel name used for lifecycle nudges and peer-commit notifications. */
|
|
71
|
+
declare const REPLICA_KV_CHANNEL = "tinycloud-replica-kv";
|
|
72
|
+
/** Web Lock name prefix for pending-write read-modify-write; suffix is the private gate-HMAC identity id. */
|
|
73
|
+
declare const REPLICA_PENDING_LOCK_PREFIX = "tinycloud-replica-kv:pending:";
|
|
74
|
+
/** Node/CLI gate file name. CLI places it at `<profile>/replica-gate.json`. */
|
|
75
|
+
declare const REPLICA_GATE_FILE = "replica-gate.json";
|
|
76
|
+
|
|
77
|
+
export { DEFAULT_MIN_FREE_BYTES, REPLICA_DENY_TOMBSTONE, REPLICA_GATE_FILE, REPLICA_KV_CHANNEL, REPLICA_KV_DATABASE, REPLICA_KV_SCHEMA_VERSION, REPLICA_KV_STORES, REPLICA_LOGOUT_MARKER, REPLICA_PENDING_LOCK_PREFIX, ReplicaContractCode };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export { CONSENT_WINDOW_MS, DEFAULT_GRANT_TTL_MS, MAX_GRANT_TTL_MS, RENEW_BELOW_FRACTION } from './grantPolicyConstants.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Frozen constants of the shared replica contract (TC-858 Phase 2, see CONTRACT.md).
|
|
5
|
+
*
|
|
6
|
+
* Exported via `@tinycloud/sdk-services/kv/replication/contractConstants`, never from the
|
|
7
|
+
* package root. Runtime grant policy imports the numeric-only `grantPolicyConstants` subpath
|
|
8
|
+
* instead, so the default web bundle does not carry browser storage identifiers.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/** Error codes the contract adds or gives new meaning. Values equal keys. */
|
|
12
|
+
declare const ReplicaContractCode: {
|
|
13
|
+
/**
|
|
14
|
+
* The lifecycle gate refused the operation: the handle's session stamp or principal no longer
|
|
15
|
+
* matches the gate, a purge intent covers the partition, or the logout marker is set. The error
|
|
16
|
+
* carries `gate: ReplicaGateReason`. Read-through answers from the network; nothing is erased.
|
|
17
|
+
*/
|
|
18
|
+
readonly REPLICA_GATED: "REPLICA_GATED";
|
|
19
|
+
/**
|
|
20
|
+
* Reserved for handles whose partition was erased (purge or revocation) after they opened. The
|
|
21
|
+
* gate check runs first, so a handle that is both gated and erased reports REPLICA_GATED.
|
|
22
|
+
*/
|
|
23
|
+
readonly RESET_REQUIRED: "RESET_REQUIRED";
|
|
24
|
+
/** A page was refused by quota admission (`maxBytes` or the free-space floor). Nothing committed. */
|
|
25
|
+
readonly STORAGE_BUDGET: "STORAGE_BUDGET";
|
|
26
|
+
/** The platform store refused the write (IndexedDB `QuotaExceededError`, ENOSPC). Nothing committed. */
|
|
27
|
+
readonly STORAGE_FULL: "STORAGE_FULL";
|
|
28
|
+
/** The consent deadline has passed: no grant may be minted, renewed or served until re-consent. */
|
|
29
|
+
readonly CONSENT_EXPIRED: "CONSENT_EXPIRED";
|
|
30
|
+
/** The installed grant's effective expiry (not necessarily its signed `exp`) has passed. */
|
|
31
|
+
readonly GRANT_EXPIRED: "GRANT_EXPIRED";
|
|
32
|
+
};
|
|
33
|
+
type ReplicaContractCode = (typeof ReplicaContractCode)[keyof typeof ReplicaContractCode];
|
|
34
|
+
/** Browser free-space floor in bytes (64 MiB, `navigator.storage.estimate()`); not applied on node/CLI. */
|
|
35
|
+
declare const DEFAULT_MIN_FREE_BYTES: number;
|
|
36
|
+
/** The single per-origin IndexedDB database of the browser `KVReplicaStorage` adapter. */
|
|
37
|
+
declare const REPLICA_KV_DATABASE = "tinycloud-replica-kv";
|
|
38
|
+
/** Origin database schema: v2 destructively replaces v1 plaintext replica-owned stores. */
|
|
39
|
+
declare const REPLICA_KV_SCHEMA_VERSION = 2;
|
|
40
|
+
/**
|
|
41
|
+
* Object-store names in {@link REPLICA_KV_DATABASE}. Every store uses out-of-line keys (no
|
|
42
|
+
* `keyPath`, no autoIncrement) so the schema upgrade can create control stores without knowing
|
|
43
|
+
* their record shapes. Data stores are owned by the adapter (S1); control stores by the lifecycle
|
|
44
|
+
* gate (S3) and quota ledger (S5).
|
|
45
|
+
*/
|
|
46
|
+
declare const REPLICA_KV_STORES: {
|
|
47
|
+
/** Data: partition meta (opaque fences, sealed config/grants), private gate-HMAC partition id. */
|
|
48
|
+
readonly meta: "meta";
|
|
49
|
+
/** Data: sealed KV entries, key `[privatePartitionId, accountHmac(path)]`. */
|
|
50
|
+
readonly entries: "entries";
|
|
51
|
+
/** Data: AES-GCM content blobs, key `[privatePartitionId, accountHmac(hash)]`. */
|
|
52
|
+
readonly blobs: "blobs";
|
|
53
|
+
/** Data: AES-sealed pending state, key private gate-HMAC `identityKeyHash`. */
|
|
54
|
+
readonly pending: "pending";
|
|
55
|
+
/** Data: sealed owner device, private nonextractable key records and opaque install anchors. */
|
|
56
|
+
readonly device: "device";
|
|
57
|
+
/** Control: the account gate, singleton key `"account"`, value `ReplicaAccountGate`. */
|
|
58
|
+
readonly gate: "gate";
|
|
59
|
+
/** Control: partition index keyed by private `partitionId`; nonunique `byLookupId` index. */
|
|
60
|
+
readonly partitions: "partitions";
|
|
61
|
+
/** Control: purge intents, key `ReplicaPurgeIntent.id`, value `ReplicaPurgeIntent`. */
|
|
62
|
+
readonly purgeIntents: "purgeIntents";
|
|
63
|
+
/** Control: quota ledger, keys owned by the ledger (S5). */
|
|
64
|
+
readonly quota: "quota";
|
|
65
|
+
};
|
|
66
|
+
/** Synchronous, cross-tab `localStorage` marker set when the deny transaction and fallback delete both failed. */
|
|
67
|
+
declare const REPLICA_LOGOUT_MARKER = "tinycloud-replica:logout-pending";
|
|
68
|
+
/** Origin-wide deny floor outside the deletable replica database; JSON `{ epoch, deniedAt }`. */
|
|
69
|
+
declare const REPLICA_DENY_TOMBSTONE = "tinycloud-replica:deny-tombstone";
|
|
70
|
+
/** BroadcastChannel name used for lifecycle nudges and peer-commit notifications. */
|
|
71
|
+
declare const REPLICA_KV_CHANNEL = "tinycloud-replica-kv";
|
|
72
|
+
/** Web Lock name prefix for pending-write read-modify-write; suffix is the private gate-HMAC identity id. */
|
|
73
|
+
declare const REPLICA_PENDING_LOCK_PREFIX = "tinycloud-replica-kv:pending:";
|
|
74
|
+
/** Node/CLI gate file name. CLI places it at `<profile>/replica-gate.json`. */
|
|
75
|
+
declare const REPLICA_GATE_FILE = "replica-gate.json";
|
|
76
|
+
|
|
77
|
+
export { DEFAULT_MIN_FREE_BYTES, REPLICA_DENY_TOMBSTONE, REPLICA_GATE_FILE, REPLICA_KV_CHANNEL, REPLICA_KV_DATABASE, REPLICA_KV_SCHEMA_VERSION, REPLICA_KV_STORES, REPLICA_LOGOUT_MARKER, REPLICA_PENDING_LOCK_PREFIX, ReplicaContractCode };
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// src/kv/replication/grantPolicyConstants.ts
|
|
2
|
+
var HOUR_MS = 60 * 60 * 1e3;
|
|
3
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
4
|
+
var DEFAULT_GRANT_TTL_MS = DAY_MS;
|
|
5
|
+
var MAX_GRANT_TTL_MS = 7 * DAY_MS;
|
|
6
|
+
var CONSENT_WINDOW_MS = 7 * DAY_MS;
|
|
7
|
+
var RENEW_BELOW_FRACTION = 0.25;
|
|
8
|
+
|
|
9
|
+
// src/kv/replication/contractConstants.ts
|
|
10
|
+
var ReplicaContractCode = {
|
|
11
|
+
/**
|
|
12
|
+
* The lifecycle gate refused the operation: the handle's session stamp or principal no longer
|
|
13
|
+
* matches the gate, a purge intent covers the partition, or the logout marker is set. The error
|
|
14
|
+
* carries `gate: ReplicaGateReason`. Read-through answers from the network; nothing is erased.
|
|
15
|
+
*/
|
|
16
|
+
REPLICA_GATED: "REPLICA_GATED",
|
|
17
|
+
/**
|
|
18
|
+
* Reserved for handles whose partition was erased (purge or revocation) after they opened. The
|
|
19
|
+
* gate check runs first, so a handle that is both gated and erased reports REPLICA_GATED.
|
|
20
|
+
*/
|
|
21
|
+
RESET_REQUIRED: "RESET_REQUIRED",
|
|
22
|
+
/** A page was refused by quota admission (`maxBytes` or the free-space floor). Nothing committed. */
|
|
23
|
+
STORAGE_BUDGET: "STORAGE_BUDGET",
|
|
24
|
+
/** The platform store refused the write (IndexedDB `QuotaExceededError`, ENOSPC). Nothing committed. */
|
|
25
|
+
STORAGE_FULL: "STORAGE_FULL",
|
|
26
|
+
/** The consent deadline has passed: no grant may be minted, renewed or served until re-consent. */
|
|
27
|
+
CONSENT_EXPIRED: "CONSENT_EXPIRED",
|
|
28
|
+
/** The installed grant's effective expiry (not necessarily its signed `exp`) has passed. */
|
|
29
|
+
GRANT_EXPIRED: "GRANT_EXPIRED"
|
|
30
|
+
};
|
|
31
|
+
var DEFAULT_MIN_FREE_BYTES = 64 * 1024 * 1024;
|
|
32
|
+
var REPLICA_KV_DATABASE = "tinycloud-replica-kv";
|
|
33
|
+
var REPLICA_KV_SCHEMA_VERSION = 2;
|
|
34
|
+
var REPLICA_KV_STORES = {
|
|
35
|
+
/** Data: partition meta (opaque fences, sealed config/grants), private gate-HMAC partition id. */
|
|
36
|
+
meta: "meta",
|
|
37
|
+
/** Data: sealed KV entries, key `[privatePartitionId, accountHmac(path)]`. */
|
|
38
|
+
entries: "entries",
|
|
39
|
+
/** Data: AES-GCM content blobs, key `[privatePartitionId, accountHmac(hash)]`. */
|
|
40
|
+
blobs: "blobs",
|
|
41
|
+
/** Data: AES-sealed pending state, key private gate-HMAC `identityKeyHash`. */
|
|
42
|
+
pending: "pending",
|
|
43
|
+
/** Data: sealed owner device, private nonextractable key records and opaque install anchors. */
|
|
44
|
+
device: "device",
|
|
45
|
+
/** Control: the account gate, singleton key `"account"`, value `ReplicaAccountGate`. */
|
|
46
|
+
gate: "gate",
|
|
47
|
+
/** Control: partition index keyed by private `partitionId`; nonunique `byLookupId` index. */
|
|
48
|
+
partitions: "partitions",
|
|
49
|
+
/** Control: purge intents, key `ReplicaPurgeIntent.id`, value `ReplicaPurgeIntent`. */
|
|
50
|
+
purgeIntents: "purgeIntents",
|
|
51
|
+
/** Control: quota ledger, keys owned by the ledger (S5). */
|
|
52
|
+
quota: "quota"
|
|
53
|
+
};
|
|
54
|
+
var REPLICA_LOGOUT_MARKER = "tinycloud-replica:logout-pending";
|
|
55
|
+
var REPLICA_DENY_TOMBSTONE = "tinycloud-replica:deny-tombstone";
|
|
56
|
+
var REPLICA_KV_CHANNEL = "tinycloud-replica-kv";
|
|
57
|
+
var REPLICA_PENDING_LOCK_PREFIX = "tinycloud-replica-kv:pending:";
|
|
58
|
+
var REPLICA_GATE_FILE = "replica-gate.json";
|
|
59
|
+
export {
|
|
60
|
+
CONSENT_WINDOW_MS,
|
|
61
|
+
DEFAULT_GRANT_TTL_MS,
|
|
62
|
+
DEFAULT_MIN_FREE_BYTES,
|
|
63
|
+
MAX_GRANT_TTL_MS,
|
|
64
|
+
RENEW_BELOW_FRACTION,
|
|
65
|
+
REPLICA_DENY_TOMBSTONE,
|
|
66
|
+
REPLICA_GATE_FILE,
|
|
67
|
+
REPLICA_KV_CHANNEL,
|
|
68
|
+
REPLICA_KV_DATABASE,
|
|
69
|
+
REPLICA_KV_SCHEMA_VERSION,
|
|
70
|
+
REPLICA_KV_STORES,
|
|
71
|
+
REPLICA_LOGOUT_MARKER,
|
|
72
|
+
REPLICA_PENDING_LOCK_PREFIX,
|
|
73
|
+
ReplicaContractCode
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=contractConstants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/kv/replication/grantPolicyConstants.ts","../../../src/kv/replication/contractConstants.ts"],"sourcesContent":["/** Grant lifetime constants without browser storage identifiers. */\nconst HOUR_MS = 60 * 60 * 1000;\nconst DAY_MS = 24 * HOUR_MS;\n\n/** Default device-grant lifetime from install (24 h). All durations are milliseconds. */\nexport const DEFAULT_GRANT_TTL_MS = DAY_MS;\n/** `grantTtlMs` above this (7 d) is a config error: TypeError at construction. */\nexport const MAX_GRANT_TTL_MS = 7 * DAY_MS;\n/** Consent deadline = consent anchor + this window (7 d). */\nexport const CONSENT_WINDOW_MS = 7 * DAY_MS;\n/** Silent renewal starts when remaining effective lifetime < this fraction of the effective lifetime. */\nexport const RENEW_BELOW_FRACTION = 0.25;\n","/**\n * Frozen constants of the shared replica contract (TC-858 Phase 2, see CONTRACT.md).\n *\n * Exported via `@tinycloud/sdk-services/kv/replication/contractConstants`, never from the\n * package root. Runtime grant policy imports the numeric-only `grantPolicyConstants` subpath\n * instead, so the default web bundle does not carry browser storage identifiers.\n */\nexport {\n DEFAULT_GRANT_TTL_MS,\n MAX_GRANT_TTL_MS,\n CONSENT_WINDOW_MS,\n RENEW_BELOW_FRACTION,\n} from \"./grantPolicyConstants\";\n\n/** Error codes the contract adds or gives new meaning. Values equal keys. */\nexport const ReplicaContractCode = {\n /**\n * The lifecycle gate refused the operation: the handle's session stamp or principal no longer\n * matches the gate, a purge intent covers the partition, or the logout marker is set. The error\n * carries `gate: ReplicaGateReason`. Read-through answers from the network; nothing is erased.\n */\n REPLICA_GATED: \"REPLICA_GATED\",\n /**\n * Reserved for handles whose partition was erased (purge or revocation) after they opened. The\n * gate check runs first, so a handle that is both gated and erased reports REPLICA_GATED.\n */\n RESET_REQUIRED: \"RESET_REQUIRED\",\n /** A page was refused by quota admission (`maxBytes` or the free-space floor). Nothing committed. */\n STORAGE_BUDGET: \"STORAGE_BUDGET\",\n /** The platform store refused the write (IndexedDB `QuotaExceededError`, ENOSPC). Nothing committed. */\n STORAGE_FULL: \"STORAGE_FULL\",\n /** The consent deadline has passed: no grant may be minted, renewed or served until re-consent. */\n CONSENT_EXPIRED: \"CONSENT_EXPIRED\",\n /** The installed grant's effective expiry (not necessarily its signed `exp`) has passed. */\n GRANT_EXPIRED: \"GRANT_EXPIRED\",\n} as const;\nexport type ReplicaContractCode = (typeof ReplicaContractCode)[keyof typeof ReplicaContractCode];\n\n/** Browser free-space floor in bytes (64 MiB, `navigator.storage.estimate()`); not applied on node/CLI. */\nexport const DEFAULT_MIN_FREE_BYTES = 64 * 1024 * 1024;\n\n/** The single per-origin IndexedDB database of the browser `KVReplicaStorage` adapter. */\nexport const REPLICA_KV_DATABASE = \"tinycloud-replica-kv\";\n/** Origin database schema: v2 destructively replaces v1 plaintext replica-owned stores. */\nexport const REPLICA_KV_SCHEMA_VERSION = 2;\n\n/**\n * Object-store names in {@link REPLICA_KV_DATABASE}. Every store uses out-of-line keys (no\n * `keyPath`, no autoIncrement) so the schema upgrade can create control stores without knowing\n * their record shapes. Data stores are owned by the adapter (S1); control stores by the lifecycle\n * gate (S3) and quota ledger (S5).\n */\nexport const REPLICA_KV_STORES = {\n /** Data: partition meta (opaque fences, sealed config/grants), private gate-HMAC partition id. */\n meta: \"meta\",\n /** Data: sealed KV entries, key `[privatePartitionId, accountHmac(path)]`. */\n entries: \"entries\",\n /** Data: AES-GCM content blobs, key `[privatePartitionId, accountHmac(hash)]`. */\n blobs: \"blobs\",\n /** Data: AES-sealed pending state, key private gate-HMAC `identityKeyHash`. */\n pending: \"pending\",\n /** Data: sealed owner device, private nonextractable key records and opaque install anchors. */\n device: \"device\",\n /** Control: the account gate, singleton key `\"account\"`, value `ReplicaAccountGate`. */\n gate: \"gate\",\n /** Control: partition index keyed by private `partitionId`; nonunique `byLookupId` index. */\n partitions: \"partitions\",\n /** Control: purge intents, key `ReplicaPurgeIntent.id`, value `ReplicaPurgeIntent`. */\n purgeIntents: \"purgeIntents\",\n /** Control: quota ledger, keys owned by the ledger (S5). */\n quota: \"quota\",\n} as const;\n\n/** Synchronous, cross-tab `localStorage` marker set when the deny transaction and fallback delete both failed. */\nexport const REPLICA_LOGOUT_MARKER = \"tinycloud-replica:logout-pending\";\n\n/** Origin-wide deny floor outside the deletable replica database; JSON `{ epoch, deniedAt }`. */\nexport const REPLICA_DENY_TOMBSTONE = \"tinycloud-replica:deny-tombstone\";\n\n/** BroadcastChannel name used for lifecycle nudges and peer-commit notifications. */\nexport const REPLICA_KV_CHANNEL = \"tinycloud-replica-kv\";\n\n/** Web Lock name prefix for pending-write read-modify-write; suffix is the private gate-HMAC identity id. */\nexport const REPLICA_PENDING_LOCK_PREFIX = \"tinycloud-replica-kv:pending:\";\n\n/** Node/CLI gate file name. CLI places it at `<profile>/replica-gate.json`. */\nexport const REPLICA_GATE_FILE = \"replica-gate.json\";\n"],"mappings":";AACA,IAAM,UAAU,KAAK,KAAK;AAC1B,IAAM,SAAS,KAAK;AAGb,IAAM,uBAAuB;AAE7B,IAAM,mBAAmB,IAAI;AAE7B,IAAM,oBAAoB,IAAI;AAE9B,IAAM,uBAAuB;;;ACI7B,IAAM,sBAAsB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjC,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA,EAKf,gBAAgB;AAAA;AAAA,EAEhB,gBAAgB;AAAA;AAAA,EAEhB,cAAc;AAAA;AAAA,EAEd,iBAAiB;AAAA;AAAA,EAEjB,eAAe;AACjB;AAIO,IAAM,yBAAyB,KAAK,OAAO;AAG3C,IAAM,sBAAsB;AAE5B,IAAM,4BAA4B;AAQlC,IAAM,oBAAoB;AAAA;AAAA,EAE/B,MAAM;AAAA;AAAA,EAEN,SAAS;AAAA;AAAA,EAET,OAAO;AAAA;AAAA,EAEP,SAAS;AAAA;AAAA,EAET,QAAQ;AAAA;AAAA,EAER,MAAM;AAAA;AAAA,EAEN,YAAY;AAAA;AAAA,EAEZ,cAAc;AAAA;AAAA,EAEd,OAAO;AACT;AAGO,IAAM,wBAAwB;AAG9B,IAAM,yBAAyB;AAG/B,IAAM,qBAAqB;AAG3B,IAAM,8BAA8B;AAGpC,IAAM,oBAAoB;","names":[]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/kv/replication/grantPolicyConstants.ts
|
|
21
|
+
var grantPolicyConstants_exports = {};
|
|
22
|
+
__export(grantPolicyConstants_exports, {
|
|
23
|
+
CONSENT_WINDOW_MS: () => CONSENT_WINDOW_MS,
|
|
24
|
+
DEFAULT_GRANT_TTL_MS: () => DEFAULT_GRANT_TTL_MS,
|
|
25
|
+
MAX_GRANT_TTL_MS: () => MAX_GRANT_TTL_MS,
|
|
26
|
+
RENEW_BELOW_FRACTION: () => RENEW_BELOW_FRACTION
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(grantPolicyConstants_exports);
|
|
29
|
+
var HOUR_MS = 60 * 60 * 1e3;
|
|
30
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
31
|
+
var DEFAULT_GRANT_TTL_MS = DAY_MS;
|
|
32
|
+
var MAX_GRANT_TTL_MS = 7 * DAY_MS;
|
|
33
|
+
var CONSENT_WINDOW_MS = 7 * DAY_MS;
|
|
34
|
+
var RENEW_BELOW_FRACTION = 0.25;
|
|
35
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
36
|
+
0 && (module.exports = {
|
|
37
|
+
CONSENT_WINDOW_MS,
|
|
38
|
+
DEFAULT_GRANT_TTL_MS,
|
|
39
|
+
MAX_GRANT_TTL_MS,
|
|
40
|
+
RENEW_BELOW_FRACTION
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=grantPolicyConstants.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/kv/replication/grantPolicyConstants.ts"],"sourcesContent":["/** Grant lifetime constants without browser storage identifiers. */\nconst HOUR_MS = 60 * 60 * 1000;\nconst DAY_MS = 24 * HOUR_MS;\n\n/** Default device-grant lifetime from install (24 h). All durations are milliseconds. */\nexport const DEFAULT_GRANT_TTL_MS = DAY_MS;\n/** `grantTtlMs` above this (7 d) is a config error: TypeError at construction. */\nexport const MAX_GRANT_TTL_MS = 7 * DAY_MS;\n/** Consent deadline = consent anchor + this window (7 d). */\nexport const CONSENT_WINDOW_MS = 7 * DAY_MS;\n/** Silent renewal starts when remaining effective lifetime < this fraction of the effective lifetime. */\nexport const RENEW_BELOW_FRACTION = 0.25;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,IAAM,UAAU,KAAK,KAAK;AAC1B,IAAM,SAAS,KAAK;AAGb,IAAM,uBAAuB;AAE7B,IAAM,mBAAmB,IAAI;AAE7B,IAAM,oBAAoB,IAAI;AAE9B,IAAM,uBAAuB;","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Default device-grant lifetime from install (24 h). All durations are milliseconds. */
|
|
2
|
+
declare const DEFAULT_GRANT_TTL_MS: number;
|
|
3
|
+
/** `grantTtlMs` above this (7 d) is a config error: TypeError at construction. */
|
|
4
|
+
declare const MAX_GRANT_TTL_MS: number;
|
|
5
|
+
/** Consent deadline = consent anchor + this window (7 d). */
|
|
6
|
+
declare const CONSENT_WINDOW_MS: number;
|
|
7
|
+
/** Silent renewal starts when remaining effective lifetime < this fraction of the effective lifetime. */
|
|
8
|
+
declare const RENEW_BELOW_FRACTION = 0.25;
|
|
9
|
+
|
|
10
|
+
export { CONSENT_WINDOW_MS, DEFAULT_GRANT_TTL_MS, MAX_GRANT_TTL_MS, RENEW_BELOW_FRACTION };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Default device-grant lifetime from install (24 h). All durations are milliseconds. */
|
|
2
|
+
declare const DEFAULT_GRANT_TTL_MS: number;
|
|
3
|
+
/** `grantTtlMs` above this (7 d) is a config error: TypeError at construction. */
|
|
4
|
+
declare const MAX_GRANT_TTL_MS: number;
|
|
5
|
+
/** Consent deadline = consent anchor + this window (7 d). */
|
|
6
|
+
declare const CONSENT_WINDOW_MS: number;
|
|
7
|
+
/** Silent renewal starts when remaining effective lifetime < this fraction of the effective lifetime. */
|
|
8
|
+
declare const RENEW_BELOW_FRACTION = 0.25;
|
|
9
|
+
|
|
10
|
+
export { CONSENT_WINDOW_MS, DEFAULT_GRANT_TTL_MS, MAX_GRANT_TTL_MS, RENEW_BELOW_FRACTION };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/kv/replication/grantPolicyConstants.ts
|
|
2
|
+
var HOUR_MS = 60 * 60 * 1e3;
|
|
3
|
+
var DAY_MS = 24 * HOUR_MS;
|
|
4
|
+
var DEFAULT_GRANT_TTL_MS = DAY_MS;
|
|
5
|
+
var MAX_GRANT_TTL_MS = 7 * DAY_MS;
|
|
6
|
+
var CONSENT_WINDOW_MS = 7 * DAY_MS;
|
|
7
|
+
var RENEW_BELOW_FRACTION = 0.25;
|
|
8
|
+
export {
|
|
9
|
+
CONSENT_WINDOW_MS,
|
|
10
|
+
DEFAULT_GRANT_TTL_MS,
|
|
11
|
+
MAX_GRANT_TTL_MS,
|
|
12
|
+
RENEW_BELOW_FRACTION
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=grantPolicyConstants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/kv/replication/grantPolicyConstants.ts"],"sourcesContent":["/** Grant lifetime constants without browser storage identifiers. */\nconst HOUR_MS = 60 * 60 * 1000;\nconst DAY_MS = 24 * HOUR_MS;\n\n/** Default device-grant lifetime from install (24 h). All durations are milliseconds. */\nexport const DEFAULT_GRANT_TTL_MS = DAY_MS;\n/** `grantTtlMs` above this (7 d) is a config error: TypeError at construction. */\nexport const MAX_GRANT_TTL_MS = 7 * DAY_MS;\n/** Consent deadline = consent anchor + this window (7 d). */\nexport const CONSENT_WINDOW_MS = 7 * DAY_MS;\n/** Silent renewal starts when remaining effective lifetime < this fraction of the effective lifetime. */\nexport const RENEW_BELOW_FRACTION = 0.25;\n"],"mappings":";AACA,IAAM,UAAU,KAAK,KAAK;AAC1B,IAAM,SAAS,KAAK;AAGb,IAAM,uBAAuB;AAE7B,IAAM,mBAAmB,IAAI;AAE7B,IAAM,oBAAoB,IAAI;AAE9B,IAAM,uBAAuB;","names":[]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
|
|
16
|
+
// src/kv/replication/grantPolicyTypes.ts
|
|
17
|
+
var grantPolicyTypes_exports = {};
|
|
18
|
+
module.exports = __toCommonJS(grantPolicyTypes_exports);
|
|
19
|
+
//# sourceMappingURL=grantPolicyTypes.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/kv/replication/grantPolicyTypes.ts"],"sourcesContent":["/**\n * Grant lifetime and renewal contract (TC-858 Phase 2, CONTRACT.md §3). Types only; S4 implements\n * these signatures in `grantPolicy.ts` using the constants in `contractConstants.ts`.\n * All instants are milliseconds since epoch; all durations are milliseconds.\n */\n\n/** Verified source selected by session form; `first_install` is expiry-only. */\nexport type ReplicaConsentSource =\n /** Verified owner SIWE `issuedAt` with finite signed expiration and exact-space KV witness. */\n | \"siwe\"\n /** `iat` of the oldest independently verified owner-authorizing proof, never a child leaf. */\n | \"delegation_iat\"\n /** `nbf` of that same oldest owner proof; a leaf signature alone is insufficient. */\n | \"delegation_nbf\"\n /** Neither: persisted first grant install time, for expiry only; never session establishment. */\n | \"first_install\";\n\n/**\n * Invariants: `at` is finite milliseconds and clamped to ≤ now by `clampConsentAnchor`. Second-based\n * sources (UCAN `iat`/`nbf`) are converted ×1000 exactly once, at the authority; SIWE `issuedAt`\n * is parsed as an ISO date. Renewals never re-anchor: only a fresh sign-in yields a new anchor.\n */\nexport interface ReplicaConsentAnchor {\n at: number;\n source: ReplicaConsentSource;\n}\n\n/**\n * Returns the eligible anchor with `at` clamped to ≤ now, or null when it is not finite.\n * A full SIWE session with missing/invalid signed expiration or issuedAt remains unanchored;\n * never fall through to a compact leaf or first-install timestamp. Compact-only sessions\n * may try the same independently verified oldest owner proof's `nbf` after invalid `iat`.\n * S4 implements this as `clampConsentAnchor` in `grantPolicy.ts`.\n */\nexport type ClampConsentAnchor = (anchor: ReplicaConsentAnchor, now: number) => ReplicaConsentAnchor | null;\n\n/**\n * Policy the controller passes to storage in `KVReplicaSpec.grantPolicy`. Storage stores the\n * resulting effective expiry with the installed grant and recomputes it at open.\n */\nexport interface ReplicaGrantPolicy {\n /** Validated: 0 < grantTtlMs ≤ MAX_GRANT_TTL_MS. */\n grantTtlMs: number;\n /**\n * From `ReplicationAuthority.consentAnchor()`: a full SIWE session requires an\n * independently verified signed owner `issuedAt`, finite signed expiration and\n * exact-space KV get+sync witness. A compact-only session instead needs the oldest\n * independently verified owner-authorizing proof's `iat`, then its `nbf` (never a\n * fresh child leaf minted under an old owner grant). Invalid SIWE does not fall\n * through to compact/first-install sources.\n * Null means no verified source; storage uses its persisted first-install time only\n * to bound grant expiry, never as freshness proof for a session stamp. That anchor\n * survives partition reset, purge and reinstall, and is cleared only by `deny`.\n */\n consentAnchor: ReplicaConsentAnchor | null;\n}\n\nexport interface EffectiveGrantExpiryInput {\n /** The grant's signed `exp` in ms; null when it has none. */\n signedExpiresAt: number | null;\n installedAt: number;\n grantTtlMs: number;\n /** `min(consentDeadlineMs(policyAnchor), durableGateDeadline)` when browser gate is active. */\n consentDeadline: number;\n}\n\n/** effective expiry = min(signed exp, installedAt + grantTtlMs, consentDeadline). */\nexport type EffectiveGrantExpiry = (input: EffectiveGrantExpiryInput) => number;\n\n/** anchor.at + CONSENT_WINDOW_MS. */\nexport type ConsentDeadlineMs = (anchor: ReplicaConsentAnchor) => number;\n\n/**\n * Duration passed to `ReplicationAuthority.mint` as `expiryMs`:\n * min(grantTtlMs, consentDeadline − now). The caller MUST NOT mint when the result is ≤ 0.\n */\nexport type MintRemainingMs = (input: { now: number; grantTtlMs: number; consentDeadline: number }) => number;\n\n/**\n * True when online-renewal should run: remaining = effectiveExpiresAt − now is STRICTLY below\n * RENEW_BELOW_FRACTION × (effectiveExpiresAt − installedAt) (exactly 25% remaining does not\n * renew), and now < consentDeadline. All inputs finite; otherwise false.\n * Checked on a timer, before each sync, and at open.\n */\nexport type NeedsSilentRenewal = (input: {\n now: number;\n installedAt: number;\n effectiveExpiresAt: number;\n consentDeadline: number;\n}) => boolean;\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Grant lifetime and renewal contract (TC-858 Phase 2, CONTRACT.md §3). Types only; S4 implements
|
|
3
|
+
* these signatures in `grantPolicy.ts` using the constants in `contractConstants.ts`.
|
|
4
|
+
* All instants are milliseconds since epoch; all durations are milliseconds.
|
|
5
|
+
*/
|
|
6
|
+
/** Verified source selected by session form; `first_install` is expiry-only. */
|
|
7
|
+
type ReplicaConsentSource =
|
|
8
|
+
/** Verified owner SIWE `issuedAt` with finite signed expiration and exact-space KV witness. */
|
|
9
|
+
"siwe"
|
|
10
|
+
/** `iat` of the oldest independently verified owner-authorizing proof, never a child leaf. */
|
|
11
|
+
| "delegation_iat"
|
|
12
|
+
/** `nbf` of that same oldest owner proof; a leaf signature alone is insufficient. */
|
|
13
|
+
| "delegation_nbf"
|
|
14
|
+
/** Neither: persisted first grant install time, for expiry only; never session establishment. */
|
|
15
|
+
| "first_install";
|
|
16
|
+
/**
|
|
17
|
+
* Invariants: `at` is finite milliseconds and clamped to ≤ now by `clampConsentAnchor`. Second-based
|
|
18
|
+
* sources (UCAN `iat`/`nbf`) are converted ×1000 exactly once, at the authority; SIWE `issuedAt`
|
|
19
|
+
* is parsed as an ISO date. Renewals never re-anchor: only a fresh sign-in yields a new anchor.
|
|
20
|
+
*/
|
|
21
|
+
interface ReplicaConsentAnchor {
|
|
22
|
+
at: number;
|
|
23
|
+
source: ReplicaConsentSource;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns the eligible anchor with `at` clamped to ≤ now, or null when it is not finite.
|
|
27
|
+
* A full SIWE session with missing/invalid signed expiration or issuedAt remains unanchored;
|
|
28
|
+
* never fall through to a compact leaf or first-install timestamp. Compact-only sessions
|
|
29
|
+
* may try the same independently verified oldest owner proof's `nbf` after invalid `iat`.
|
|
30
|
+
* S4 implements this as `clampConsentAnchor` in `grantPolicy.ts`.
|
|
31
|
+
*/
|
|
32
|
+
type ClampConsentAnchor = (anchor: ReplicaConsentAnchor, now: number) => ReplicaConsentAnchor | null;
|
|
33
|
+
/**
|
|
34
|
+
* Policy the controller passes to storage in `KVReplicaSpec.grantPolicy`. Storage stores the
|
|
35
|
+
* resulting effective expiry with the installed grant and recomputes it at open.
|
|
36
|
+
*/
|
|
37
|
+
interface ReplicaGrantPolicy {
|
|
38
|
+
/** Validated: 0 < grantTtlMs ≤ MAX_GRANT_TTL_MS. */
|
|
39
|
+
grantTtlMs: number;
|
|
40
|
+
/**
|
|
41
|
+
* From `ReplicationAuthority.consentAnchor()`: a full SIWE session requires an
|
|
42
|
+
* independently verified signed owner `issuedAt`, finite signed expiration and
|
|
43
|
+
* exact-space KV get+sync witness. A compact-only session instead needs the oldest
|
|
44
|
+
* independently verified owner-authorizing proof's `iat`, then its `nbf` (never a
|
|
45
|
+
* fresh child leaf minted under an old owner grant). Invalid SIWE does not fall
|
|
46
|
+
* through to compact/first-install sources.
|
|
47
|
+
* Null means no verified source; storage uses its persisted first-install time only
|
|
48
|
+
* to bound grant expiry, never as freshness proof for a session stamp. That anchor
|
|
49
|
+
* survives partition reset, purge and reinstall, and is cleared only by `deny`.
|
|
50
|
+
*/
|
|
51
|
+
consentAnchor: ReplicaConsentAnchor | null;
|
|
52
|
+
}
|
|
53
|
+
interface EffectiveGrantExpiryInput {
|
|
54
|
+
/** The grant's signed `exp` in ms; null when it has none. */
|
|
55
|
+
signedExpiresAt: number | null;
|
|
56
|
+
installedAt: number;
|
|
57
|
+
grantTtlMs: number;
|
|
58
|
+
/** `min(consentDeadlineMs(policyAnchor), durableGateDeadline)` when browser gate is active. */
|
|
59
|
+
consentDeadline: number;
|
|
60
|
+
}
|
|
61
|
+
/** effective expiry = min(signed exp, installedAt + grantTtlMs, consentDeadline). */
|
|
62
|
+
type EffectiveGrantExpiry = (input: EffectiveGrantExpiryInput) => number;
|
|
63
|
+
/** anchor.at + CONSENT_WINDOW_MS. */
|
|
64
|
+
type ConsentDeadlineMs = (anchor: ReplicaConsentAnchor) => number;
|
|
65
|
+
/**
|
|
66
|
+
* Duration passed to `ReplicationAuthority.mint` as `expiryMs`:
|
|
67
|
+
* min(grantTtlMs, consentDeadline − now). The caller MUST NOT mint when the result is ≤ 0.
|
|
68
|
+
*/
|
|
69
|
+
type MintRemainingMs = (input: {
|
|
70
|
+
now: number;
|
|
71
|
+
grantTtlMs: number;
|
|
72
|
+
consentDeadline: number;
|
|
73
|
+
}) => number;
|
|
74
|
+
/**
|
|
75
|
+
* True when online-renewal should run: remaining = effectiveExpiresAt − now is STRICTLY below
|
|
76
|
+
* RENEW_BELOW_FRACTION × (effectiveExpiresAt − installedAt) (exactly 25% remaining does not
|
|
77
|
+
* renew), and now < consentDeadline. All inputs finite; otherwise false.
|
|
78
|
+
* Checked on a timer, before each sync, and at open.
|
|
79
|
+
*/
|
|
80
|
+
type NeedsSilentRenewal = (input: {
|
|
81
|
+
now: number;
|
|
82
|
+
installedAt: number;
|
|
83
|
+
effectiveExpiresAt: number;
|
|
84
|
+
consentDeadline: number;
|
|
85
|
+
}) => boolean;
|
|
86
|
+
|
|
87
|
+
export type { ClampConsentAnchor, ConsentDeadlineMs, EffectiveGrantExpiry, EffectiveGrantExpiryInput, MintRemainingMs, NeedsSilentRenewal, ReplicaConsentAnchor, ReplicaConsentSource, ReplicaGrantPolicy };
|