@tinycloud/sdk-services 3.2.6-beta.4 → 3.3.0-beta.7
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-1Ug6y7DC.d.cts → BaseService-Cc6Ueicm.d.cts} +1 -1
- package/dist/{BaseService-Bn07Vudy.d.ts → BaseService-DOdXd7sr.d.ts} +1 -1
- package/dist/encryption/index.cjs +8 -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 +8 -0
- package/dist/encryption/index.js.map +1 -1
- package/dist/index.cjs +94 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -6
- package/dist/index.d.ts +29 -6
- package/dist/index.js +93 -57
- 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 +66 -21
- package/dist/kv/index.cjs.map +1 -1
- package/dist/kv/index.d.cts +4 -4
- package/dist/kv/index.d.ts +4 -4
- package/dist/kv/index.js +66 -21
- package/dist/kv/index.js.map +1 -1
- package/dist/kv/replication/grantPolicy.cjs +82 -0
- package/dist/kv/replication/grantPolicy.cjs.map +1 -0
- package/dist/kv/replication/grantPolicy.d.cts +19 -0
- package/dist/kv/replication/grantPolicy.d.ts +19 -0
- package/dist/kv/replication/grantPolicy.js +50 -0
- package/dist/kv/replication/grantPolicy.js.map +1 -0
- package/dist/kv/replication/index.cjs +571 -128
- package/dist/kv/replication/index.cjs.map +1 -1
- package/dist/kv/replication/index.d.cts +3 -3
- package/dist/kv/replication/index.d.ts +3 -3
- package/dist/kv/replication/index.js +571 -128
- package/dist/kv/replication/index.js.map +1 -1
- package/dist/{scope-BnyVPZ5E.d.ts → scope-B-m6cKH-.d.ts} +310 -7
- package/dist/{scope-CQ5kmHlt.d.cts → scope-B7oeKdLM.d.cts} +310 -7
- package/dist/sql/index.cjs +70 -36
- 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 +70 -36
- package/dist/sql/index.js.map +1 -1
- package/dist/{types-gmdUiorz.d.cts → types-BjH0ZtGy.d.cts} +6 -0
- package/dist/{types-gmdUiorz.d.ts → types-BjH0ZtGy.d.ts} +6 -0
- package/package.json +16 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { R as Result, F as FetchFunction } from './types-
|
|
1
|
+
import { R as Result, F as FetchFunction } from './types-BjH0ZtGy.js';
|
|
2
2
|
import { REPLICA_KV_STORES } from './kv/replication/contractConstants.js';
|
|
3
3
|
import { ReplicaConsentAnchor, ReplicaGrantPolicy } from './kv/replication/grantPolicyTypes.js';
|
|
4
4
|
|
|
@@ -526,7 +526,7 @@ interface ReplicaAccountGate {
|
|
|
526
526
|
/** Active account's principal hash; null after sign-out. */
|
|
527
527
|
principalHash: string | null;
|
|
528
528
|
lifecycleEpoch: number;
|
|
529
|
-
/** ms since epoch of the last deny (browser: preserved across database recreation). */
|
|
529
|
+
/** ms since epoch of the last committed deny (browser: preserved across database recreation). */
|
|
530
530
|
deniedAt: number | null;
|
|
531
531
|
/** Browser: finite ms, fixed from verified fresh consent at establish; mandatory while active. */
|
|
532
532
|
consentDeadline?: number | null;
|
|
@@ -665,8 +665,9 @@ type ReplicaDenyOutcome =
|
|
|
665
665
|
/**
|
|
666
666
|
* Gate moved, intents recorded, first-install anchors cleared and pending generations advanced
|
|
667
667
|
* in one commit. Browser: owner device deleted in that same IDB transaction. Node: the gate
|
|
668
|
-
* file cannot commit atomically with the device file, so
|
|
669
|
-
* identity's pending-intent erase before
|
|
668
|
+
* file cannot commit atomically with the device file, so an ordinary denial deletes it
|
|
669
|
+
* through the identity's pending-intent erase before intent clear. Deferred node sign-out
|
|
670
|
+
* holds that intent and the device file until validated resume (CONTRACT.md §2).
|
|
670
671
|
*/
|
|
671
672
|
{
|
|
672
673
|
status: "denied";
|
|
@@ -691,6 +692,15 @@ type ReplicaDenyOutcome =
|
|
|
691
692
|
status: "unguarded";
|
|
692
693
|
code: string;
|
|
693
694
|
};
|
|
695
|
+
/** A deferred sign-out denial: a committed `denied` always carries its resume token. */
|
|
696
|
+
type ProfileReplicaDeferredDenyOutcome = {
|
|
697
|
+
status: "denied";
|
|
698
|
+
lifecycleEpoch: number;
|
|
699
|
+
intents: number;
|
|
700
|
+
resumeToken: ProfileReplicaDeferredToken;
|
|
701
|
+
} | Exclude<ReplicaDenyOutcome, {
|
|
702
|
+
status: "denied";
|
|
703
|
+
}>;
|
|
694
704
|
interface ReplicaEraseReport {
|
|
695
705
|
erased: string[];
|
|
696
706
|
failed: Array<{
|
|
@@ -699,6 +709,11 @@ interface ReplicaEraseReport {
|
|
|
699
709
|
}>;
|
|
700
710
|
/** Intents still outstanding after this pass. */
|
|
701
711
|
remaining: number;
|
|
712
|
+
/**
|
|
713
|
+
* Node/CLI: a durable deferred denial held this pass, so nothing was erased and
|
|
714
|
+
* `remaining` (possibly 0) is not completion; check `deferredErase()`.
|
|
715
|
+
*/
|
|
716
|
+
deferred?: true;
|
|
702
717
|
/** Browser startup discovered elapsed consent and durably crypto-shredded the account/gate keys. */
|
|
703
718
|
consentExpired?: boolean;
|
|
704
719
|
}
|
|
@@ -781,6 +796,8 @@ interface ReplicaLifecycleGate {
|
|
|
781
796
|
* if expired, denies and crypto-shreds keys before any replica access; it also retries a
|
|
782
797
|
* pending `deleteDatabase` marker and erases intents. Failures remain gated and visible via
|
|
783
798
|
* `pendingPurge()` / `purgePending`; a browser closed at expiry catches it on its next load.
|
|
799
|
+
* Node/CLI recovery leaves durably deferred revoke intents and physical files untouched,
|
|
800
|
+
* reporting them as remaining until `ProfileReplicaPurge.resumeDeferredErase`.
|
|
784
801
|
*/
|
|
785
802
|
recover(o: {
|
|
786
803
|
signal: AbortSignal;
|
|
@@ -830,6 +847,12 @@ interface ReplicaLifecycleGate {
|
|
|
830
847
|
* return null when its gate has no persisted consent deadline.
|
|
831
848
|
*/
|
|
832
849
|
consentDeadline(stamp: ReplicaSessionStamp): number | null;
|
|
850
|
+
/**
|
|
851
|
+
* Browser-only post-commit consent expiry observer. Fires only after deny/delete
|
|
852
|
+
* destroys the origin account keys; a subscriber failure cannot undo denial.
|
|
853
|
+
* Controllers register after binding so events use their opened opaque replica IDs.
|
|
854
|
+
*/
|
|
855
|
+
subscribeConsentExpired?(listener: (stamp: ReplicaSessionStamp) => void): () => void;
|
|
833
856
|
/**
|
|
834
857
|
* Synchronous main-thread delivery check before replica-served values/list keys/event fields,
|
|
835
858
|
* and before open, installGrant and sync. Browser checks marker, origin deny tombstone,
|
|
@@ -853,6 +876,275 @@ interface ReplicaLifecycleGate {
|
|
|
853
876
|
/** Outstanding intents; non-empty means status `purgePending: true`. */
|
|
854
877
|
pendingPurge(): Promise<ReplicaPurgeIntent[]>;
|
|
855
878
|
}
|
|
879
|
+
/** Node/CLI profile-local fencing token, not a secret capability; the profile lock remains authoritative. */
|
|
880
|
+
interface ProfileReplicaDeferredToken {
|
|
881
|
+
deniedEpoch: number;
|
|
882
|
+
principalHash: string;
|
|
883
|
+
}
|
|
884
|
+
/** Profile-relative, JSON-safe identity of a path listed before destructive logout. */
|
|
885
|
+
interface ProfileReplicaUnknownEntry {
|
|
886
|
+
path: string;
|
|
887
|
+
kind: "file" | "directory" | "symlink";
|
|
888
|
+
dev: string;
|
|
889
|
+
ino: string;
|
|
890
|
+
}
|
|
891
|
+
/** Profile-relative directory identity; dev/ino are decimal strings for durable JSON. */
|
|
892
|
+
interface ProfileReplicaRootIdentity {
|
|
893
|
+
path: string;
|
|
894
|
+
dev: string;
|
|
895
|
+
ino: string;
|
|
896
|
+
}
|
|
897
|
+
/** Exact nonsecret path identity displayed with an inventory confirmation token. */
|
|
898
|
+
interface ProfileReplicaApprovalEntry extends ProfileReplicaRootIdentity {
|
|
899
|
+
kind: ProfileReplicaUnknownEntry["kind"] | "missing";
|
|
900
|
+
}
|
|
901
|
+
/** Read-only profile-locked inventory, including legacy mirrors and flag-owned roots. */
|
|
902
|
+
interface ProfileReplicaPreflight {
|
|
903
|
+
knownLegacyReplicas: number;
|
|
904
|
+
unknownLegacyPaths: string[];
|
|
905
|
+
unknownPaths: string[];
|
|
906
|
+
unknownEntries: ProfileReplicaUnknownEntry[];
|
|
907
|
+
knownRoots: ProfileReplicaRootIdentity[];
|
|
908
|
+
knownEntries: ProfileReplicaUnknownEntry[];
|
|
909
|
+
missingDatabases: string[];
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* CLI-only durable crash fence. `principalDigest` is a domain-separated
|
|
913
|
+
* SHA-256 owner binding, not a secret or a substitute for the profile lock;
|
|
914
|
+
* v2/v3 never fabricate a scoped gate principal hash. A v1 `lifecycleEpoch`
|
|
915
|
+
* is the pre-denial epoch; `deniedEpoch` is the epoch the v1 denial actually
|
|
916
|
+
* committed, bound once after that denial and compared for equality from then
|
|
917
|
+
* on (CONTRACT.md §2). Remote-pending and remote-abandoned are mutually
|
|
918
|
+
* exclusive durable states.
|
|
919
|
+
*/
|
|
920
|
+
type ProfileReplicaLogoutPending = ({
|
|
921
|
+
v: 1;
|
|
922
|
+
incarnation: string;
|
|
923
|
+
lifecycleEpoch: number;
|
|
924
|
+
principalHash: string;
|
|
925
|
+
deniedEpoch?: number;
|
|
926
|
+
} | {
|
|
927
|
+
v: 2;
|
|
928
|
+
scope: "orphan_profile";
|
|
929
|
+
nonce: string;
|
|
930
|
+
} | {
|
|
931
|
+
v: 3;
|
|
932
|
+
scope: "inactive_gate";
|
|
933
|
+
incarnation: string;
|
|
934
|
+
lifecycleEpoch: number;
|
|
935
|
+
}) & ProfileReplicaRemoteLogoutState & {
|
|
936
|
+
principalDigest: string;
|
|
937
|
+
/** Random durable 16-byte challenge salt as 32 lowercase hex characters. */
|
|
938
|
+
approvalSalt: string;
|
|
939
|
+
discardLocalChanges?: true;
|
|
940
|
+
approvedUnknown: ProfileReplicaUnknownEntry[];
|
|
941
|
+
knownRoots: ProfileReplicaRootIdentity[];
|
|
942
|
+
knownEntries: ProfileReplicaUnknownEntry[];
|
|
943
|
+
missingDatabases: string[];
|
|
944
|
+
};
|
|
945
|
+
/** A logout marker is remote-pending, remote-abandoned or neither; never both. */
|
|
946
|
+
type ProfileReplicaRemoteLogoutState = {
|
|
947
|
+
remotePending: true;
|
|
948
|
+
remoteAbandoned?: never;
|
|
949
|
+
} | {
|
|
950
|
+
remoteAbandoned: true;
|
|
951
|
+
remotePending?: never;
|
|
952
|
+
} | {
|
|
953
|
+
remotePending?: never;
|
|
954
|
+
remoteAbandoned?: never;
|
|
955
|
+
};
|
|
956
|
+
/**
|
|
957
|
+
* Node/CLI-only lifecycle facade for a profile's replica root. The node-sdk exports
|
|
958
|
+
* `createProfileReplicaPurge({ profileDir, guard })`; `guard` is the caller's
|
|
959
|
+
* mandatory profile lock and MUST be reentrant within one async call chain: the
|
|
960
|
+
* CLI calls the facade while already holding its (reentrant) profile lock. This
|
|
961
|
+
* does not widen the browser `ReplicaLifecycleGate`.
|
|
962
|
+
*
|
|
963
|
+
* While a durable deferred denial is active, `recover` and `erasePending`
|
|
964
|
+
* leave intents and physical files untouched; `pendingPurge` lists the intents.
|
|
965
|
+
* A complete enumeration may have zero intents, so `remaining: 0` does not
|
|
966
|
+
* prove completion: `deferredErase()` is the authoritative marker check, and
|
|
967
|
+
* `LocalReplicaStatus.purgePending` / `ReplicaInspectedStatus.purgePending`
|
|
968
|
+
* are true while the deferred marker or any intent remains. All guarded reads
|
|
969
|
+
* and new establishment remain refused. Deferred intents leave that state only
|
|
970
|
+
* through a validated resume (CONTRACT.md §2); there is no account-switch or
|
|
971
|
+
* consent-expiry override. The facade never denies or erases a gate,
|
|
972
|
+
* partition, pending state or device record whose active principal is not
|
|
973
|
+
* the caller's ("Logout by another account", CONTRACT.md §2).
|
|
974
|
+
*/
|
|
975
|
+
interface ProfileReplicaPurge extends Pick<ReplicaLifecycleGate, "recover" | "erasePending" | "pendingPurge"> {
|
|
976
|
+
/**
|
|
977
|
+
* `deferErase: true` is valid only for `reason: "sign_out"`; other reasons throw
|
|
978
|
+
* TypeError before any mutation. A successful deferred `denied` outcome MUST carry
|
|
979
|
+
* `resumeToken`; stale or unguarded outcomes do not authorize a retryable revoke.
|
|
980
|
+
* Step 1 atomically denies, records every opaque partition/pending intent and
|
|
981
|
+
* pending generation, and persists the deferred marker. Physical files remain
|
|
982
|
+
* until `resumeDeferredErase`, even across process restart.
|
|
983
|
+
*/
|
|
984
|
+
deny(input: ReplicaDenyInput & {
|
|
985
|
+
reason: "sign_out";
|
|
986
|
+
}, options: {
|
|
987
|
+
deferErase: true;
|
|
988
|
+
}): Promise<ProfileReplicaDeferredDenyOutcome>;
|
|
989
|
+
deny(input: ReplicaDenyInput, options?: {
|
|
990
|
+
deferErase?: false;
|
|
991
|
+
}): Promise<ReplicaDenyOutcome>;
|
|
992
|
+
/** Returns the persisted active token across restart, even with zero intents; null only after the marker clears. */
|
|
993
|
+
deferredErase(): Promise<ProfileReplicaDeferredToken | null>;
|
|
994
|
+
/**
|
|
995
|
+
* Under the profile lock, require the exact denied epoch and principal hash and a
|
|
996
|
+
* null gate principal; otherwise throw `REPLICA_GATED`/`stamp_stale` without erasure.
|
|
997
|
+
* Clear the deferred marker durably before idempotent erase. A crash after clearing
|
|
998
|
+
* is completed by ordinary recovery. Repeating the same token is safe only while
|
|
999
|
+
* the same denied epoch/hash persists; a successor establishment fences it.
|
|
1000
|
+
*/
|
|
1001
|
+
resumeDeferredErase(token: ProfileReplicaDeferredToken, options: {
|
|
1002
|
+
signal: AbortSignal;
|
|
1003
|
+
}): Promise<ReplicaEraseReport>;
|
|
1004
|
+
/**
|
|
1005
|
+
* Read-only profile-locked inventory BEFORE marker, denial or remote call.
|
|
1006
|
+
* Report exact profile-relative unknown paths, kinds and dev/ino plus all
|
|
1007
|
+
* known roots/entries. Unknown/indeterminate data refuses unless explicit
|
|
1008
|
+
* discard consent was supplied; the CLI displays the inventory before acting.
|
|
1009
|
+
* A prior inventory is not a wildcard authorization for later new paths.
|
|
1010
|
+
*/
|
|
1011
|
+
preflightLogout(input: {
|
|
1012
|
+
principal: string;
|
|
1013
|
+
discardLocalChanges?: boolean;
|
|
1014
|
+
}): Promise<ProfileReplicaPreflight>;
|
|
1015
|
+
/**
|
|
1016
|
+
* Re-inspect and compare the complete approved inventory under the profile
|
|
1017
|
+
* lock, then atomically fsync a scoped v1, orphan v2 or inactive v3 marker.
|
|
1018
|
+
* `approval` is required: the CLI passes its just-displayed preflight even
|
|
1019
|
+
* when it contains no unknown paths. With `remotePending`, the marker fences
|
|
1020
|
+
* replica reads but forbids credential cleanup or erasure until
|
|
1021
|
+
* `completeRemoteLogout` after all exact-CID revokes. Only approved
|
|
1022
|
+
* path/type/dev/ino identities and the explicit discard bit survive; changed
|
|
1023
|
+
* paths refuse pre-action. V1 active remote logout additionally requires a
|
|
1024
|
+
* committed deferred denial/token before online revoke; v2 orphan and v3
|
|
1025
|
+
* inactive markers instead use their version-specific gate-absence/epoch
|
|
1026
|
+
* fences.
|
|
1027
|
+
*
|
|
1028
|
+
* An existing marker is never rewritten here: the same owner, fence,
|
|
1029
|
+
* `remotePending` state and approved inventory return it unchanged; anything
|
|
1030
|
+
* else refuses without mutation. When the gate's active principal is the
|
|
1031
|
+
* caller's, it always yields a v1 marker, even with no replica roots or
|
|
1032
|
+
* intents; another account's active gate yields null and is never denied.
|
|
1033
|
+
* Null otherwise means there is no active principal and no replica-owned
|
|
1034
|
+
* work, not completed logout.
|
|
1035
|
+
*
|
|
1036
|
+
* A missing flag pending index, unrecognized child, nonempty pending state
|
|
1037
|
+
* or corrupt gate requires explicit discard. The CLI still fsyncs
|
|
1038
|
+
* authSignedOut then unlinks and fsyncs both credentials. CLI-bound reads
|
|
1039
|
+
* and ordinary network restore refuse any marker; an explicit remote-revoke
|
|
1040
|
+
* retry may use the retained key/session while `remotePending` without
|
|
1041
|
+
* delivering replica data.
|
|
1042
|
+
*/
|
|
1043
|
+
prepareLogoutPending(input: {
|
|
1044
|
+
principal: string;
|
|
1045
|
+
approval: ProfileReplicaPreflight;
|
|
1046
|
+
discardLocalChanges?: boolean;
|
|
1047
|
+
remotePending?: true;
|
|
1048
|
+
}): Promise<ProfileReplicaLogoutPending | null>;
|
|
1049
|
+
/**
|
|
1050
|
+
* After every authoritative exact-CID revoke succeeds, revalidate the
|
|
1051
|
+
* marker's principal and version-specific fence under the profile lock:
|
|
1052
|
+
* v1 `deniedEpoch`/hash, v2 no replacement gate, or v3 exact inactive
|
|
1053
|
+
* epoch/null principal. Then durably remove `remotePending`. A marker that is
|
|
1054
|
+
* not remote-pending (remote-abandoned or already cleanup-ready) refuses
|
|
1055
|
+
* without mutation. A failed/partial remote sequence never calls this.
|
|
1056
|
+
*/
|
|
1057
|
+
completeRemoteLogout(input: {
|
|
1058
|
+
principal: string;
|
|
1059
|
+
}): Promise<ProfileReplicaLogoutPending>;
|
|
1060
|
+
/**
|
|
1061
|
+
* Under the profile lock, report whether this principal's marker is still
|
|
1062
|
+
* remote-pending and its v1 deferred gate, v2 orphan or v3 inactive gate
|
|
1063
|
+
* fence still matches. False only when the marker is absent/completed;
|
|
1064
|
+
* a mismatched principal or stale gate refuses. This permits an explicit
|
|
1065
|
+
* network-only revoke retry, never replica delivery.
|
|
1066
|
+
*/
|
|
1067
|
+
remotePendingLogout(input: {
|
|
1068
|
+
principal: string;
|
|
1069
|
+
}): Promise<boolean>;
|
|
1070
|
+
/**
|
|
1071
|
+
* First explicit PLAIN logout attempt after unfinished remote revoke:
|
|
1072
|
+
* compare the original durable approved inventory with the current
|
|
1073
|
+
* path/type/dev/ino set under the profile lock. Any change refuses with
|
|
1074
|
+
* `REPLICA_GATED`/`gate_unavailable`, prints every token-bound
|
|
1075
|
+
* `ProfileReplicaApprovalEntry`, exposes the same complete set as
|
|
1076
|
+
* `error.inventoryApprovalEntries` plus a nonsecret 32-hex-character
|
|
1077
|
+
* `error.inventoryApprovalToken`, and mutates nothing even when `approval`
|
|
1078
|
+
* contains the new paths or `discardLocalChanges` is true. With the
|
|
1079
|
+
* original inventory intact, validate the fresh approval and the marker's
|
|
1080
|
+
* version-specific owner/gate fence (a v1 marker is classified by its gate
|
|
1081
|
+
* and checked exactly one way, CONTRACT.md §2), then atomically replace
|
|
1082
|
+
* `remotePending` with `remoteAbandoned: true`.
|
|
1083
|
+
* This is not an online-success receipt and makes no further node call.
|
|
1084
|
+
*/
|
|
1085
|
+
abandonRemoteLogout(input: {
|
|
1086
|
+
principal: string;
|
|
1087
|
+
approval: ProfileReplicaPreflight;
|
|
1088
|
+
discardLocalChanges?: boolean;
|
|
1089
|
+
}): Promise<ProfileReplicaLogoutPending>;
|
|
1090
|
+
/**
|
|
1091
|
+
* Only a separate explicit CLI command with
|
|
1092
|
+
* `--discard-local-changes --approve-inventory <token>` may approve a
|
|
1093
|
+
* changed remote-pending inventory. Under the profile lock, require the
|
|
1094
|
+
* same owner and version-specific gate fence, original-to-current inventory
|
|
1095
|
+
* mismatch, exact fresh preflight and matching displayed 32-hex-character
|
|
1096
|
+
* token. Commit the newly approved identities with `remoteAbandoned: true`,
|
|
1097
|
+
* never a remote receipt. Missing, stale or reused tokens fail without
|
|
1098
|
+
* mutation; there is no same-command fallback from `abandonRemoteLogout`.
|
|
1099
|
+
*/
|
|
1100
|
+
approveChangedPlainLogout(input: {
|
|
1101
|
+
principal: string;
|
|
1102
|
+
approval: ProfileReplicaPreflight;
|
|
1103
|
+
discardLocalChanges: true;
|
|
1104
|
+
inventoryApprovalToken: string;
|
|
1105
|
+
}): Promise<ProfileReplicaLogoutPending>;
|
|
1106
|
+
/**
|
|
1107
|
+
* After a completed remote sequence, an inventory mismatch leaves the
|
|
1108
|
+
* marker and signed-out state in place. A fresh explicit listing/ack under
|
|
1109
|
+
* the profile lock replaces only the approved inventory; remote revokes
|
|
1110
|
+
* are not repeated, and a still-pending remote sequence cannot reapprove.
|
|
1111
|
+
*/
|
|
1112
|
+
reapproveLogoutPending(input: {
|
|
1113
|
+
principal: string;
|
|
1114
|
+
approval: ProfileReplicaPreflight;
|
|
1115
|
+
}): Promise<ProfileReplicaLogoutPending>;
|
|
1116
|
+
/**
|
|
1117
|
+
* CLI startup/logout recovery under the same profile lock. A `remotePending`
|
|
1118
|
+
* marker returns failure with no credential or file deletion. For a
|
|
1119
|
+
* cleanup-ready active-v1 marker, validate the gate and durably commit
|
|
1120
|
+
* generation-fenced denial with complete partition/pending intents
|
|
1121
|
+
* BEFORE calling `clearCredentials`; denial failure leaves the marker,
|
|
1122
|
+
* both credentials and replica files intact and reports nonzero failure.
|
|
1123
|
+
* An already-deferred v1 validates its exact denial; v3 validates its
|
|
1124
|
+
* inactive epoch and v2 its orphan/no-replacement-gate fence without
|
|
1125
|
+
* inventing scoped intents. Only then does `clearCredentials` atomically
|
|
1126
|
+
* fsync CLI authSignedOut before unlinking and fsyncing both session.json
|
|
1127
|
+
* and key.json. Recheck durable approved identities before each unlink;
|
|
1128
|
+
* mismatch stops with marker, remaining files and nonzero failure.
|
|
1129
|
+
* Post-success credentials remain shredded. The callback erases only its
|
|
1130
|
+
* approved inventory under the profile lock (never recursive legacy
|
|
1131
|
+
* deletion). In-repo CLI code owns the signed-out postcondition; the
|
|
1132
|
+
* facade verifies credential absence before erasure. A missing marker
|
|
1133
|
+
* with corrupt/unreadable gate reports failure and nonzero remaining,
|
|
1134
|
+
* without invoking callbacks or fabricating successful completion.
|
|
1135
|
+
*/
|
|
1136
|
+
recoverLogoutPending(options: {
|
|
1137
|
+
signal: AbortSignal;
|
|
1138
|
+
clearCredentials: () => Promise<void>;
|
|
1139
|
+
eraseLegacyReplicas: (options: {
|
|
1140
|
+
discardLocalChanges: boolean;
|
|
1141
|
+
approvedUnknown: readonly ProfileReplicaUnknownEntry[];
|
|
1142
|
+
knownRoots: readonly ProfileReplicaRootIdentity[];
|
|
1143
|
+
knownEntries: readonly ProfileReplicaUnknownEntry[];
|
|
1144
|
+
missingDatabases: readonly string[];
|
|
1145
|
+
}) => Promise<void>;
|
|
1146
|
+
}): Promise<ReplicaEraseReport>;
|
|
1147
|
+
}
|
|
856
1148
|
/** Worker replies that carry replica-served data are stamped; a reply without a stamp is dropped. */
|
|
857
1149
|
interface ReplicaStampedReply {
|
|
858
1150
|
stamp: ReplicaSessionStamp;
|
|
@@ -1315,10 +1607,13 @@ interface ReplicationAuthority {
|
|
|
1315
1607
|
mint(deviceDid: string, prefix: string, signal: AbortSignal,
|
|
1316
1608
|
/**
|
|
1317
1609
|
* `expiryMs` is a DURATION from now (forwarded as `delegateTo(…, { expiry: expiryMs })`), from
|
|
1318
|
-
* `mintRemainingMs`. Absent means Phase 1 behaviour (session-tier default).
|
|
1610
|
+
* `mintRemainingMs`. Absent means Phase 1 behaviour (session-tier default). `renewalOnly`
|
|
1611
|
+
* requires the authority to recheck a session-key parent at mint time; an initial runtime
|
|
1612
|
+
* parent mint leaves it unset.
|
|
1319
1613
|
*/
|
|
1320
1614
|
options?: {
|
|
1321
1615
|
expiryMs?: number;
|
|
1616
|
+
renewalOnly?: boolean;
|
|
1322
1617
|
}): Promise<{
|
|
1323
1618
|
ucan: string;
|
|
1324
1619
|
parentCid: string;
|
|
@@ -1425,6 +1720,12 @@ interface KVReadThrough {
|
|
|
1425
1720
|
}): void;
|
|
1426
1721
|
}
|
|
1427
1722
|
interface KVReplicationController extends KVReadThrough {
|
|
1723
|
+
/**
|
|
1724
|
+
* Internal browser gate observer: invoked only after the stamped durable consent-expiry
|
|
1725
|
+
* denial/deletion commits. Records opened opaque grant transitions even if the gate's own
|
|
1726
|
+
* timer wins before this controller's timer; does not issue a second deny.
|
|
1727
|
+
*/
|
|
1728
|
+
observeConsentExpired(stamp: ReplicaSessionStamp): void;
|
|
1428
1729
|
status(): Promise<ReplicaStatusEntry[]>;
|
|
1429
1730
|
sync(o?: {
|
|
1430
1731
|
prefix?: string;
|
|
@@ -1525,7 +1826,9 @@ interface ReplicaStatusEntry extends Partial<LocalReplicaStatus> {
|
|
|
1525
1826
|
type ReplicaState = "idle" | "ready" | "grant_missing" | "runtime_unsupported" | "unavailable" | "revoked"
|
|
1526
1827
|
/** The lifecycle gate refuses this session (REPLICA_GATED); reads use the network. */
|
|
1527
1828
|
| "gated" | "closed";
|
|
1528
|
-
type ReplicationReason = "hit" | "absent" | "deleted" | "content_missing" | "coverage_incomplete" | "not_covered" | "pending_write" | "grant_missing" | "grant_expired"
|
|
1829
|
+
type ReplicationReason = "hit" | "absent" | "deleted" | "content_missing" | "coverage_incomplete" | "not_covered" | "pending_write" | "grant_missing" | "grant_expired"
|
|
1830
|
+
/** A revoked grant, including a stale-read sync refusal; read-through uses network with code GRANT_REVOKED. */
|
|
1831
|
+
| "grant_revoked" | "grant_not_yet_valid" | "stale" | "replica_error" | "runtime_unsupported" | "replica_unavailable" | "unsupported_option" | "network_cursor" | "cursor_restart" | "aborted" | "REPLICA_BEHIND_OWN_WRITES" | "REPLICA_UNPROVEN_SINCE_START" | "NETWORK_REQUESTED"
|
|
1529
1832
|
/** The lifecycle gate refused (REPLICA_GATED); the read went to the network. */
|
|
1530
1833
|
| "replica_gated";
|
|
1531
1834
|
type ReplicationEvent = {
|
|
@@ -1656,4 +1959,4 @@ declare function replicationIdentityKey(id: ReplicationIdentity): string;
|
|
|
1656
1959
|
/** Whether replicating this space/prefix can copy encrypted secret material to disk. */
|
|
1657
1960
|
declare function requiresSecretsOptIn(space: string, prefix: string): boolean;
|
|
1658
1961
|
|
|
1659
|
-
export { type
|
|
1962
|
+
export { type ReplicaGuardedStore as $, type AuthorityRefusal as A, type ReplicaBrowserGateAccess as B, CLEAR_PENDING_WARNING as C, type ReplicaBrowserGateSnapshot as D, type ReplicaBrowserGateTx as E, type ReplicaBrowserPageAdmission as F, type ReplicaClock as G, type ReplicaCoverage as H, type ReplicaDeliveryDecision as I, type ReplicaDenyInput as J, type KVReplicationDeps as K, type LocalGetResult as L, type ReplicaDenyOutcome as M, type ReplicaDevice as N, type ReplicaEraseReport as O, type PendingWriteStore as P, type ReplicaGateAccess as Q, type ReplicationIdentity as R, type ReplicaGateReason as S, type ReplicaGateScope as T, type ReplicaGateSnapshot as U, type ReplicaGateTx as V, type ReplicaGatedError as W, type ReplicaGatedHandle as X, type ReplicaGatedSpec as Y, type ReplicaGatedStorage as Z, type ReplicaGrantInfo as _, type KVReplicationController as a, type ReplicaInspectedStatus as a0, type ReplicaLifecycleGate as a1, type ReplicaPageAdmission as a2, type ReplicaPartitionEraser as a3, type ReplicaPartitionIndexEntry as a4, type ReplicaPeerCommit as a5, type ReplicaPrivateGateHash as a6, type ReplicaPurgeIntent as a7, type ReplicaQuotaLedger as a8, type ReplicaQuotaSpec as a9, type KVChangesResponse as aA, type KVCreateSignedReadUrlOptions as aB, type KVDeleteOptions as aC, type KVGetOptions as aD, type KVHeadOptions as aE, type KVListOptions as aF, type KVListResponse as aG, type KVPutOptions as aH, type KVResponse as aI, type KVResponseHeaders as aJ, type KVServiceConfig as aK, type KVSignedReadUrlResponse as aL, type ReplicaSessionStamp as aa, type ReplicaStampedReply as ab, type ReplicaState as ac, type ReplicaStatusEntry as ad, type ReplicationAuthority as ae, type ReplicationControl as af, type ReplicationEvent as ag, type ReplicationOptions as ah, type ReplicationPurgeReport as ai, type ReplicationReason as aj, type ReplicationScheduler as ak, type ResolvedReplicationOptions as al, type SaltedHash as am, canonicalReplicationIdentity as an, replicationIdentityKey as ao, requiresSecretsOptIn as ap, DEFAULT_SIGNED_READ_URL_EXPIRY_MS as aq, KVAction as ar, type KVActionType as as, type KVBatchPutItem as at, type KVBatchPutOptions as au, type KVBatchPutResponse as av, type KVBatchReadResponse as aw, type KVChange as ax, type KVChangesAuthority as ay, type KVChangesOptions as az, type KVListPage as b, type KVReadThrough as c, type KVReplicaHandle as d, type KVReplicaSpec as e, type KVReplicaStorage as f, type LocalListResult as g, type LocalReadMeta as h, type LocalReplicaStatus as i, type LocalSyncResult as j, type PendingWriteRecord as k, type PendingWriteState as l, type PinnedKey as m, type ProfileReplicaApprovalEntry as n, type ProfileReplicaDeferredDenyOutcome as o, type ProfileReplicaDeferredToken as p, type ProfileReplicaLogoutPending as q, type ProfileReplicaPreflight as r, type ProfileReplicaPurge as s, type ProfileReplicaRemoteLogoutState as t, type ProfileReplicaRootIdentity as u, type ProfileReplicaUnknownEntry as v, type PurgeTarget as w, type ReplicaAccountGate as x, type ReplicaAdmitHook as y, type ReplicaAuthorityState as z };
|