@tensorix/metahub 0.3.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. package/README.md +23 -10
  2. package/README.zh-CN.md +23 -10
  3. package/dist/cli/edge-worker-script.d.ts +4 -0
  4. package/dist/cli/edge-worker-script.d.ts.map +1 -0
  5. package/dist/cli.js +16882 -8691
  6. package/dist/cli.js.map +109 -59
  7. package/dist/core/access-policy.d.ts +82 -0
  8. package/dist/core/access-policy.d.ts.map +1 -0
  9. package/dist/core/blobs-core.d.ts +19 -0
  10. package/dist/core/blobs-core.d.ts.map +1 -1
  11. package/dist/core/blobs.d.ts.map +1 -1
  12. package/dist/core/compact.d.ts.map +1 -1
  13. package/dist/core/config.d.ts +13 -0
  14. package/dist/core/config.d.ts.map +1 -1
  15. package/dist/core/crdt.d.ts +29 -2
  16. package/dist/core/crdt.d.ts.map +1 -1
  17. package/dist/core/data-map.d.ts +105 -0
  18. package/dist/core/data-map.d.ts.map +1 -0
  19. package/dist/core/db.d.ts +1 -1
  20. package/dist/core/db.d.ts.map +1 -1
  21. package/dist/core/documents.d.ts.map +1 -1
  22. package/dist/core/errors.d.ts +2 -0
  23. package/dist/core/errors.d.ts.map +1 -1
  24. package/dist/core/grants-core.d.ts +132 -0
  25. package/dist/core/grants-core.d.ts.map +1 -0
  26. package/dist/core/guest-intent.d.ts +33 -0
  27. package/dist/core/guest-intent.d.ts.map +1 -0
  28. package/dist/core/hash.d.ts +4 -0
  29. package/dist/core/hash.d.ts.map +1 -0
  30. package/dist/core/history.d.ts.map +1 -1
  31. package/dist/core/hlc.d.ts +5 -0
  32. package/dist/core/hlc.d.ts.map +1 -1
  33. package/dist/core/ids.d.ts +1 -1
  34. package/dist/core/ids.d.ts.map +1 -1
  35. package/dist/core/inject-runtime.d.ts +8 -0
  36. package/dist/core/inject-runtime.d.ts.map +1 -0
  37. package/dist/core/intent-retention.d.ts +23 -0
  38. package/dist/core/intent-retention.d.ts.map +1 -0
  39. package/dist/core/md/inline.d.ts +6 -2
  40. package/dist/core/md/inline.d.ts.map +1 -1
  41. package/dist/core/node.d.ts +13 -0
  42. package/dist/core/node.d.ts.map +1 -1
  43. package/dist/core/records.d.ts +31 -0
  44. package/dist/core/records.d.ts.map +1 -1
  45. package/dist/core/schema-init.d.ts +19 -2
  46. package/dist/core/schema-init.d.ts.map +1 -1
  47. package/dist/core/schema.d.ts +1 -1
  48. package/dist/core/schema.d.ts.map +1 -1
  49. package/dist/core/shares.d.ts +15 -0
  50. package/dist/core/shares.d.ts.map +1 -1
  51. package/dist/core/site-channel-lifecycle.d.ts +10 -0
  52. package/dist/core/site-channel-lifecycle.d.ts.map +1 -0
  53. package/dist/core/site-channel-store.d.ts +120 -0
  54. package/dist/core/site-channel-store.d.ts.map +1 -0
  55. package/dist/core/site-channels.d.ts +65 -0
  56. package/dist/core/site-channels.d.ts.map +1 -0
  57. package/dist/core/sites-core.d.ts +100 -7
  58. package/dist/core/sites-core.d.ts.map +1 -1
  59. package/dist/core/sites.d.ts +65 -2
  60. package/dist/core/sites.d.ts.map +1 -1
  61. package/dist/core/sync/anti-abuse.d.ts +26 -0
  62. package/dist/core/sync/anti-abuse.d.ts.map +1 -0
  63. package/dist/core/sync/auth.d.ts +30 -2
  64. package/dist/core/sync/auth.d.ts.map +1 -1
  65. package/dist/core/sync/blob-routes.d.ts.map +1 -1
  66. package/dist/core/sync/cf-api.d.ts +54 -0
  67. package/dist/core/sync/cf-api.d.ts.map +1 -0
  68. package/dist/core/sync/cf-oauth.d.ts +91 -0
  69. package/dist/core/sync/cf-oauth.d.ts.map +1 -0
  70. package/dist/core/sync/client.d.ts +12 -0
  71. package/dist/core/sync/client.d.ts.map +1 -1
  72. package/dist/core/sync/data-map-db.d.ts +8 -0
  73. package/dist/core/sync/data-map-db.d.ts.map +1 -0
  74. package/dist/core/sync/devices.d.ts +65 -0
  75. package/dist/core/sync/devices.d.ts.map +1 -0
  76. package/dist/core/sync/drop-host.d.ts +40 -0
  77. package/dist/core/sync/drop-host.d.ts.map +1 -0
  78. package/dist/core/sync/drop-keys.d.ts +64 -0
  79. package/dist/core/sync/drop-keys.d.ts.map +1 -0
  80. package/dist/core/sync/drop-protocol.d.ts +94 -0
  81. package/dist/core/sync/drop-protocol.d.ts.map +1 -0
  82. package/dist/core/sync/drop-pull.d.ts +67 -0
  83. package/dist/core/sync/drop-pull.d.ts.map +1 -0
  84. package/dist/core/sync/drop-wire.d.ts +39 -0
  85. package/dist/core/sync/drop-wire.d.ts.map +1 -0
  86. package/dist/core/sync/e2ee.d.ts +3 -0
  87. package/dist/core/sync/e2ee.d.ts.map +1 -1
  88. package/dist/core/sync/edge-config.d.ts +77 -0
  89. package/dist/core/sync/edge-config.d.ts.map +1 -0
  90. package/dist/core/sync/edge-connect.d.ts +13 -0
  91. package/dist/core/sync/edge-connect.d.ts.map +1 -0
  92. package/dist/core/sync/edge-service.d.ts +100 -0
  93. package/dist/core/sync/edge-service.d.ts.map +1 -0
  94. package/dist/core/sync/grants-routes.d.ts +46 -0
  95. package/dist/core/sync/grants-routes.d.ts.map +1 -0
  96. package/dist/core/sync/guest-session.d.ts +29 -0
  97. package/dist/core/sync/guest-session.d.ts.map +1 -0
  98. package/dist/core/sync/html-escape.d.ts +2 -0
  99. package/dist/core/sync/html-escape.d.ts.map +1 -0
  100. package/dist/core/sync/http-status.d.ts +14 -0
  101. package/dist/core/sync/http-status.d.ts.map +1 -0
  102. package/dist/core/sync/http-util.d.ts +6 -0
  103. package/dist/core/sync/http-util.d.ts.map +1 -0
  104. package/dist/core/sync/pairing.d.ts +9 -9
  105. package/dist/core/sync/pairing.d.ts.map +1 -1
  106. package/dist/core/sync/partition.d.ts +77 -0
  107. package/dist/core/sync/partition.d.ts.map +1 -0
  108. package/dist/core/sync/peers-routes.d.ts.map +1 -1
  109. package/dist/core/sync/peers.d.ts +77 -0
  110. package/dist/core/sync/peers.d.ts.map +1 -1
  111. package/dist/core/sync/protocol.d.ts +2 -0
  112. package/dist/core/sync/protocol.d.ts.map +1 -1
  113. package/dist/core/sync/rate-limit.d.ts +20 -0
  114. package/dist/core/sync/rate-limit.d.ts.map +1 -0
  115. package/dist/core/sync/recovery.d.ts +9 -0
  116. package/dist/core/sync/recovery.d.ts.map +1 -0
  117. package/dist/core/sync/room-client.d.ts +50 -0
  118. package/dist/core/sync/room-client.d.ts.map +1 -0
  119. package/dist/core/sync/room-peer.d.ts +62 -0
  120. package/dist/core/sync/room-peer.d.ts.map +1 -0
  121. package/dist/core/sync/room-protocol.d.ts +130 -0
  122. package/dist/core/sync/room-protocol.d.ts.map +1 -0
  123. package/dist/core/sync/room-serve.d.ts +38 -0
  124. package/dist/core/sync/room-serve.d.ts.map +1 -0
  125. package/dist/core/sync/room-url.d.ts +4 -0
  126. package/dist/core/sync/room-url.d.ts.map +1 -0
  127. package/dist/core/sync/routes.d.ts +4 -1
  128. package/dist/core/sync/routes.d.ts.map +1 -1
  129. package/dist/core/sync/seal.d.ts +22 -0
  130. package/dist/core/sync/seal.d.ts.map +1 -0
  131. package/dist/core/sync/server.d.ts +7 -0
  132. package/dist/core/sync/server.d.ts.map +1 -1
  133. package/dist/core/sync/share-actions.d.ts +55 -6
  134. package/dist/core/sync/share-actions.d.ts.map +1 -1
  135. package/dist/core/sync/share-export.d.ts +14 -0
  136. package/dist/core/sync/share-export.d.ts.map +1 -1
  137. package/dist/core/sync/share-render.d.ts +9 -1
  138. package/dist/core/sync/share-render.d.ts.map +1 -1
  139. package/dist/core/sync/share-serve.d.ts +5 -1
  140. package/dist/core/sync/share-serve.d.ts.map +1 -1
  141. package/dist/core/sync/site-channel-reconcile.d.ts +26 -0
  142. package/dist/core/sync/site-channel-reconcile.d.ts.map +1 -0
  143. package/dist/core/sync/site-publish-recovery.d.ts +32 -0
  144. package/dist/core/sync/site-publish-recovery.d.ts.map +1 -0
  145. package/dist/core/sync/site-reachability.d.ts +13 -0
  146. package/dist/core/sync/site-reachability.d.ts.map +1 -0
  147. package/dist/core/sync/sites-routes.d.ts.map +1 -1
  148. package/dist/core/sync/sites-serve.d.ts +24 -1
  149. package/dist/core/sync/sites-serve.d.ts.map +1 -1
  150. package/dist/core/sync/storage-s3-bun.d.ts +1 -24
  151. package/dist/core/sync/storage-s3-bun.d.ts.map +1 -1
  152. package/dist/core/sync/storage-s3-sign.d.ts +43 -0
  153. package/dist/core/sync/storage-s3-sign.d.ts.map +1 -0
  154. package/dist/core/sync/storage.d.ts +59 -0
  155. package/dist/core/sync/storage.d.ts.map +1 -1
  156. package/dist/db-worker.js +206 -76
  157. package/dist/edge-worker.js +3960 -0
  158. package/dist/index.js +13175 -6670
  159. package/dist/index.js.map +87 -41
  160. package/dist/metahub-sdk.js +10 -1
  161. package/dist/mh-runtime.js +1 -1
  162. package/dist/room/do-driver.d.ts +30 -0
  163. package/dist/room/do-driver.d.ts.map +1 -0
  164. package/dist/sw.js +10 -1
  165. package/dist/webui/server/edge-routes.d.ts +3 -0
  166. package/dist/webui/server/edge-routes.d.ts.map +1 -0
  167. package/dist/webui/server/json-handler.d.ts +4 -0
  168. package/dist/webui/server/json-handler.d.ts.map +1 -0
  169. package/dist/webui/server/routes.d.ts.map +1 -1
  170. package/dist/webui/server/share-routes.d.ts.map +1 -1
  171. package/dist/webui/server/site-hosting-routes.d.ts +7 -0
  172. package/dist/webui/server/site-hosting-routes.d.ts.map +1 -0
  173. package/dist/webui.js +192 -137
  174. package/dist/workers/edge-worker.d.ts +66 -0
  175. package/dist/workers/edge-worker.d.ts.map +1 -0
  176. package/dist/workers/room.d.ts +34 -0
  177. package/dist/workers/room.d.ts.map +1 -0
  178. package/package.json +1 -1
@@ -0,0 +1,65 @@
1
+ import type { DbDriver } from "../driver.ts";
2
+ /** One way a device is connected to this node. */
3
+ export interface DeviceChannel {
4
+ /** paired_out = an outbound peer row here; grant_in = a credential we issued
5
+ * to it; oplog = its changes reached us (bucket or historic sync). */
6
+ kind: "paired_out" | "grant_in" | "oplog" | "bucket_presence";
7
+ /** peer url (paired_out) / full grant token (grant_in; surfaces mask it) /
8
+ * "" (oplog). */
9
+ ref: string;
10
+ lastSeenAt: number | null;
11
+ /** Future expiry of a currently-live publisher lease. It is not a
12
+ * last-activity timestamp and must not be rendered as one. */
13
+ leaseLiveUntil?: number | null;
14
+ transport?: "http" | "s3" | "room";
15
+ }
16
+ /**
17
+ * yes — one-click: revoke the grant and/or remove the peer row.
18
+ * bucket_rotate — only reachable through the shared bucket key: cutting it off
19
+ * means rotating the bucket credentials (rotateStoragePeer).
20
+ * unknown — only historical authorship is known; no destructive action
21
+ * can yet be tied to the right credential.
22
+ * none — this device itself, or nothing to revoke.
23
+ */
24
+ export type Revocable = "yes" | "bucket_rotate" | "unknown" | "none";
25
+ export interface DeviceView {
26
+ /** null: a grant that never learned its peer's node id (one-directional). */
27
+ nodeId: string | null;
28
+ label: string | null;
29
+ self: boolean;
30
+ channels: DeviceChannel[];
31
+ lastActivityAt: number | null;
32
+ revocable: Revocable;
33
+ /** Why the revocation verdict is safe to show. Unknown deliberately prevents
34
+ * an unrelated configured bucket from being blamed for a historical oplog
35
+ * author. */
36
+ revocationConfidence: "confirmed" | "unknown" | "none";
37
+ /** What a revoke would act on: peer url, bucket url, or a grant-token PREFIX
38
+ * (8 chars — never the full credential; masked at the source). */
39
+ revocationSources: string[];
40
+ }
41
+ /** Fold the three stores into one per-device list: self first, then by most
42
+ * recent activity. Purely local reads — same answer offline. */
43
+ export declare function listDevices(db: DbDriver): DeviceView[];
44
+ export interface BucketPresence {
45
+ nodeId: string;
46
+ /** The node's own segment stream exists under oplog/ in this bucket. */
47
+ inBucket: boolean;
48
+ /** Publisher heartbeat expiry when live (≈ "recently online"), else null. */
49
+ leaseLiveUntil: number | null;
50
+ }
51
+ export interface BucketPresenceResult {
52
+ url: string;
53
+ nodes?: BucketPresence[];
54
+ error?: string;
55
+ }
56
+ /** Refine an offline roster with online bucket evidence. Only an explicit
57
+ * stream/lease match may produce bucket_rotate; absence or refresh failure
58
+ * remains unknown because the oplog author might have arrived via old HTTP
59
+ * pairing or a bucket no longer attached here. */
60
+ export declare function resolveDevicePresence(devices: DeviceView[], buckets: BucketPresenceResult[]): DeviceView[];
61
+ /** Online refresh for one bucket: which nodes' streams live in it and whose
62
+ * publisher heartbeat is fresh. Resolves the honest classification for devices
63
+ * the offline listing could only call "通过存储桶或历史同步". */
64
+ export declare function refreshBucketPresence(db: DbDriver, url: string): Promise<BucketPresence[]>;
65
+ //# sourceMappingURL=devices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devices.d.ts","sourceRoot":"","sources":["../../../src/core/sync/devices.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAa7C,kDAAkD;AAClD,MAAM,WAAW,aAAa;IAC5B;2EACuE;IACvE,IAAI,EAAE,YAAY,GAAG,UAAU,GAAG,OAAO,GAAG,iBAAiB,CAAC;IAC9D;sBACkB;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B;kEAC8D;IAC9D,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAAC;CACpC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG,KAAK,GAAG,eAAe,GAAG,SAAS,GAAG,MAAM,CAAC;AAErE,MAAM,WAAW,UAAU;IACzB,6EAA6E;IAC7E,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,SAAS,CAAC;IACrB;;kBAEc;IACd,oBAAoB,EAAE,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;IACvD;uEACmE;IACnE,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B;AAED;iEACiE;AACjE,wBAAgB,WAAW,CAAC,EAAE,EAAE,QAAQ,GAAG,UAAU,EAAE,CAqFtD;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,QAAQ,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;kDAGkD;AAClD,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,UAAU,EAAE,EACrB,OAAO,EAAE,oBAAoB,EAAE,GAC9B,UAAU,EAAE,CAsCd;AAED;;wDAEwD;AACxD,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CA4BhG"}
@@ -0,0 +1,40 @@
1
+ export interface DropRegistration {
2
+ turnstile_sitekey?: string | null;
3
+ turnstile_secret?: string | null;
4
+ password_salt?: string | null;
5
+ password_verifier?: string | null;
6
+ max_envelopes?: number;
7
+ max_bytes?: number;
8
+ }
9
+ export interface DropEnvelopeRow {
10
+ /** Host-side monotonically increasing row id — the pull/ack cursor. */
11
+ id: number;
12
+ /** The stored envelope JSON (validated by drop-protocol on the owner side). */
13
+ envelope: unknown;
14
+ }
15
+ export interface DropStats {
16
+ drop_id: string;
17
+ envelopes: number;
18
+ bytes: number;
19
+ max_envelopes: number;
20
+ max_bytes: number;
21
+ }
22
+ export interface DropHostApi {
23
+ register(dropId: string, reg: DropRegistration): Promise<void>;
24
+ unregister(dropId: string): Promise<boolean>;
25
+ listEnvelopes(dropId: string, afterId: number, limit: number): Promise<DropEnvelopeRow[]>;
26
+ ackEnvelopes(dropId: string, ids: number[]): Promise<number>;
27
+ stats(dropId: string): Promise<DropStats>;
28
+ health(): Promise<{
29
+ ok: boolean;
30
+ version?: string;
31
+ }>;
32
+ ownerHealth(): Promise<{
33
+ ok: boolean;
34
+ version?: string;
35
+ }>;
36
+ }
37
+ /** HTTP implementation against an inbox host base URL + drt_ owner secret.
38
+ * `fetcher` is injectable so tests drive the edge worker handler in-process. */
39
+ export declare function httpDropHost(endpoint: string, token: string, fetcher?: typeof fetch): DropHostApi;
40
+ //# sourceMappingURL=drop-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drop-host.d.ts","sourceRoot":"","sources":["../../../src/core/sync/drop-host.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,gBAAgB;IAC/B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,+EAA+E;IAC/E,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7C,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IAC1F,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7D,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,WAAW,IAAI,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC3D;AASD;iFACiF;AACjF,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,OAAO,KAAa,GAC5B,WAAW,CA0Db"}
@@ -0,0 +1,64 @@
1
+ import type { DbDriver } from "../driver.ts";
2
+ import { type S3Config, type StorageClient } from "./storage.ts";
3
+ export interface DropKeyRecord {
4
+ key_id: string;
5
+ /** base64 raw uncompressed P-256 public point — published in mh-drop.json. */
6
+ pk: string;
7
+ /** base64 private key: encryptBytes(masterKey, pkcs8) when `wrapped`, else raw pkcs8. */
8
+ sk: string;
9
+ wrapped: boolean;
10
+ created_at: number;
11
+ retired: boolean;
12
+ }
13
+ export interface DropKeyring {
14
+ v: 1;
15
+ keys: DropKeyRecord[];
16
+ }
17
+ export declare function getLocalDropKeyring(db: DbDriver): DropKeyring | null;
18
+ export declare function saveLocalDropKeyring(db: DbDriver, kr: DropKeyring): void;
19
+ /** The bucket a drop keyring anchors to: the first enabled ENCRYPTED s3 peer.
20
+ * A plaintext bucket is deliberately not used — a raw private key must never
21
+ * sit on third-party storage, so no-encrypted-bucket behaves like no bucket
22
+ * (keyring stays local-only). `client` is lazy so callers that only need the
23
+ * peer identity (push-cursor ack gate) never construct an S3 client. */
24
+ export interface DropBucket {
25
+ peerUrl: string;
26
+ config: S3Config;
27
+ base: string;
28
+ keyPath: string;
29
+ masterKey: Uint8Array;
30
+ client: () => StorageClient;
31
+ }
32
+ export declare function dropBucketFor(db: DbDriver): DropBucket | null;
33
+ export declare function activeDropKey(kr: DropKeyring): DropKeyRecord;
34
+ export declare function findDropKey(kr: DropKeyring, keyId: string): DropKeyRecord | undefined;
35
+ /** Decrypt a key record's private half to raw PKCS#8 bytes. A wrapped key needs
36
+ * the bucket's master key; a mismatched master key fails the GCM tag → auth. */
37
+ export declare function dropKeySecret(db: DbDriver, key: DropKeyRecord, opts?: {
38
+ bucket?: DropBucket | null;
39
+ }): Promise<Uint8Array>;
40
+ /**
41
+ * Load (or first-provision) the drop keyring. Bucket attached → the bucket
42
+ * object is authoritative: adopt it when present; otherwise upload ours with
43
+ * If-None-Match and adopt the winner on a lost first-create race (the exact
44
+ * provisionMasterKey pattern). No bucket → local meta only.
45
+ */
46
+ export declare function ensureDropKeys(db: DbDriver, opts?: {
47
+ bucket?: DropBucket | null;
48
+ }): Promise<DropKeyring>;
49
+ /**
50
+ * Rotate: append a fresh active key; every currently-active key becomes
51
+ * retired (kept, so in-flight envelopes still open). With `purgeRetired`, keys
52
+ * that were ALREADY retired before this call are dropped — the just-retired
53
+ * generation always survives one rotation, so a rotate can never orphan mail
54
+ * sealed a second earlier.
55
+ */
56
+ export declare function rotateDropKeys(db: DbDriver, opts?: {
57
+ purgeRetired?: boolean;
58
+ bucket?: DropBucket | null;
59
+ }): Promise<{
60
+ keyring: DropKeyring;
61
+ active: DropKeyRecord;
62
+ purged: string[];
63
+ }>;
64
+ //# sourceMappingURL=drop-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drop-keys.d.ts","sourceRoot":"","sources":["../../../src/core/sync/drop-keys.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI7C,OAAO,EAKL,KAAK,QAAQ,EACb,KAAK,aAAa,EACnB,MAAM,cAAc,CAAC;AAItB,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,yFAAyF;IACzF,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,CAAC,CAAC;IACL,IAAI,EAAE,aAAa,EAAE,CAAC;CACvB;AAcD,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,WAAW,GAAG,IAAI,CAWpE;AAED,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAIxE;AAID;;;;yEAIyE;AACzE,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,UAAU,CAAC;IACtB,MAAM,EAAE,MAAM,aAAa,CAAC;CAC7B;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,GAAG,UAAU,GAAG,IAAI,CAoB7D;AAqFD,wBAAgB,aAAa,CAAC,EAAE,EAAE,WAAW,GAAG,aAAa,CAK5D;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAErF;AAED;iFACiF;AACjF,wBAAsB,aAAa,CACjC,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,aAAa,EAClB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;CAAO,GACxC,OAAO,CAAC,UAAU,CAAC,CAMrB;AAID;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,QAAQ,EACZ,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;CAAO,GACxC,OAAO,CAAC,WAAW,CAAC,CA4DtB;AAED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,QAAQ,EACZ,IAAI,GAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI,CAAA;CAAO,GAChE,OAAO,CAAC;IAAE,OAAO,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAiB5E"}
@@ -0,0 +1,94 @@
1
+ import type { DbDriver } from "../driver.ts";
2
+ import type { Change } from "../crdt.ts";
3
+ import { type GrantSet } from "../grants-core.ts";
4
+ import type { GuestIntent } from "../guest-intent.ts";
5
+ import { SEAL_ENC } from "./seal.ts";
6
+ /** Hard ceiling a serialized envelope may weigh (edge enforces 413 above it). */
7
+ export declare const DROP_ENVELOPE_MAX_BYTES: number;
8
+ /** Reject any change whose HLC claims to be further in the future than this —
9
+ * ingest() observeHlc's every change unconditionally, so an unclamped remote
10
+ * timestamp would permanently poison the local clock (design.md §7 red line 6). */
11
+ export declare const DROP_HLC_SKEW_MS: number;
12
+ /** Inbox guest identity: "g" + 8 base36, minted per visitor, localStorage-persisted.
13
+ * 9 chars total — structurally distinct from real 8-char node ids. */
14
+ export declare const GUEST_NODE_RE: RegExp;
15
+ export interface DropEnvelope {
16
+ v: 1;
17
+ /** "e" + 16 base36 — replay-stable identity; also keys the txn rewrite. */
18
+ envelope_id: string;
19
+ /** The drop this was addressed to (site id today; "sh_"+slug reserved). */
20
+ drop_id: string;
21
+ enc: typeof SEAL_ENC;
22
+ /** Which recipient key sealed it (drop-keys keyring key_id). */
23
+ key_id: string;
24
+ /** base64(MH-SEAL-P256 sealed DropPayload JSON). */
25
+ sealed: string;
26
+ /** Sender wall clock, epoch ms (informational only — never trusted). */
27
+ created_at: number;
28
+ }
29
+ export interface DropPayload {
30
+ v: 1;
31
+ /** The visitor's guest node id ("g"+8) — every change must be signed by it. */
32
+ guest_node: string;
33
+ /** Pre-signed ops in oplog row format, authored under guest_node's mini-HLC. */
34
+ changes: Change[];
35
+ meta?: Record<string, unknown>;
36
+ }
37
+ /** Payload v2: high-level GuestIntents instead of pre-signed Change[]. The
38
+ * browser no longer mints HLC/oplog rows — the owner's applyGuestIntent does,
39
+ * on the guest's own timeline at each intent's (clamped) submittedAt. Idempotent
40
+ * on intentId (a replay under a new envelope_id is a no-op). This is where the
41
+ * guest-clock-minting attack surface (NaN-HLC, seed offsets) stops existing. */
42
+ export interface DropPayloadV2 {
43
+ v: 2;
44
+ guest_node: string;
45
+ intents: GuestIntent[];
46
+ meta?: Record<string, unknown>;
47
+ }
48
+ /** Either wire version — decodeDropPayload returns this; callers discriminate on `v`. */
49
+ export type AnyDropPayload = DropPayload | DropPayloadV2;
50
+ export declare function newEnvelopeId(): string;
51
+ export declare function newGuestNode(): string;
52
+ export declare function encodeDropPayload(payload: AnyDropPayload): Uint8Array;
53
+ export declare function decodeDropPayload(bytes: Uint8Array): AnyDropPayload;
54
+ /** Structural check on an envelope as it comes off the edge host. */
55
+ export declare function parseDropEnvelope(raw: unknown): DropEnvelope;
56
+ /** Seal a payload into a complete envelope (sender side — the SDK). */
57
+ export declare function sealDropEnvelope(opts: {
58
+ dropId: string;
59
+ keyId: string;
60
+ /** Recipient public key, raw uncompressed P-256 point. */
61
+ pk: Uint8Array;
62
+ payload: AnyDropPayload;
63
+ now?: number;
64
+ }): Promise<DropEnvelope>;
65
+ /** Decrypt + decode an envelope with one keyring key (owner side). Wrong key /
66
+ * tampered ciphertext → MhError("auth") from openSealed. */
67
+ export declare function openDropEnvelope(env: DropEnvelope, key: {
68
+ pk: Uint8Array;
69
+ sk: Uint8Array;
70
+ }): Promise<AnyDropPayload>;
71
+ /** Validate a v2 payload's guest identity before its intents are applied
72
+ * (mirrors checkDropPayload's guest_node guard; per-intent authorization +
73
+ * minting is applyGuestIntent's job in drop-pull). */
74
+ export declare function checkDropIntents(ownNode: string, payload: DropPayloadV2): DropPayloadV2;
75
+ /**
76
+ * The write-inbox isolation layer: validate a decrypted payload BEFORE any of
77
+ * it touches the oplog. Any violation throws (MhError) and the WHOLE envelope
78
+ * is rejected — a form submission is atomic, partial ingest would strand half
79
+ * a row. Checks, in order:
80
+ * 1. guest_node has the inbox shape ("g"+8) and is not this node's own id —
81
+ * an envelope can never impersonate a real device;
82
+ * 2. changes is non-empty;
83
+ * 3. HLC clamp: every change's millis ≤ now + 5min (clock-poisoning guard —
84
+ * this is the one check that lives HERE rather than in grants-core,
85
+ * because it is clock hygiene, not authorization);
86
+ * 4. grant semantics via grants-core.checkGuestChanges (records-only, node
87
+ * segment match, granted tables/ops, coercible property types — blob-
88
+ * carrying types refused, value coercion, size/row ceilings).
89
+ * Returns the changes with txn force-rewritten to "drop:"+envelope_id, so
90
+ * replays are stable (oplog UNIQUE dedups) and history can group + roll back
91
+ * by envelope.
92
+ */
93
+ export declare function checkDropPayload(db: DbDriver, set: GrantSet, ownNode: string, envelopeId: string, payload: DropPayload, now?: number): Change[];
94
+ //# sourceMappingURL=drop-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drop-protocol.d.ts","sourceRoot":"","sources":["../../../src/core/sync/drop-protocol.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAqB,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAoB,QAAQ,EAAE,MAAM,WAAW,CAAC;AAIvD,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,QAAY,CAAC;AACjD;;oFAEoF;AACpF,eAAO,MAAM,gBAAgB,QAAa,CAAC;AAC3C;uEACuE;AACvE,eAAO,MAAM,aAAa,QAAmB,CAAC;AAI9C,MAAM,WAAW,YAAY;IAC3B,CAAC,EAAE,CAAC,CAAC;IACL,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,OAAO,QAAQ,CAAC;IACrB,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,CAAC,CAAC;IACL,+EAA+E;IAC/E,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;;;iFAIiF;AACjF,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,CAAC,CAAC;IACL,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,yFAAyF;AACzF,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,aAAa,CAAC;AAEzD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAID,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,UAAU,CAErE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,UAAU,GAAG,cAAc,CAanE;AAuCD,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAgB5D;AAED,uEAAuE;AACvE,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,EAAE,EAAE,UAAU,CAAC;IACf,OAAO,EAAE,cAAc,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,YAAY,CAAC,CAWxB;AAED;6DAC6D;AAC7D,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,YAAY,EACjB,GAAG,EAAE;IAAE,EAAE,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,UAAU,CAAA;CAAE,GACtC,OAAO,CAAC,cAAc,CAAC,CAGzB;AAED;;uDAEuD;AACvD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,aAAa,CAKvF;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,QAAQ,EACb,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,WAAW,EACpB,GAAG,SAAa,GACf,MAAM,EAAE,CAkBV"}
@@ -0,0 +1,67 @@
1
+ import type { DbDriver } from "../driver.ts";
2
+ import type { Change } from "../crdt.ts";
3
+ import { type SiteRow } from "../sites-core.ts";
4
+ import { type DropHostApi } from "./drop-host.ts";
5
+ /** Live sites that expose a `create` grant — exactly the sites the auto-wiring
6
+ * registers as drops, so this derivation IS the drop inventory (no extra
7
+ * registry to keep in sync). */
8
+ export declare function dropWiredSites(db: DbDriver): SiteRow[];
9
+ export interface DropPullDropSummary {
10
+ drop_id: string;
11
+ site: string;
12
+ /** Envelopes fetched this round. */
13
+ fetched: number;
14
+ /** New oplog rows gained (ingest's honest "received" count). */
15
+ ingested: number;
16
+ acked: number;
17
+ rejected: number;
18
+ /** Valid + ingested but ack deferred to a later round (bucket gate). */
19
+ deferred: number;
20
+ /** Held (NOT acked, NOT deleted) because opening failed on OUR side — a local
21
+ * key/bucket fault, not bad mail. Retried on a later, fixed pull; never lost. */
22
+ held: number;
23
+ /** Payload-version breakdown of the envelopes ingested this round — drives the
24
+ * drain metric for the v1→v2 migration (mh edge status). */
25
+ v1: number;
26
+ v2: number;
27
+ }
28
+ export interface DropPullSummary {
29
+ skipped?: "no_edge" | "no_sites" | "no_keys" | "not_publisher";
30
+ drops: DropPullDropSummary[];
31
+ fetched: number;
32
+ ingested: number;
33
+ acked: number;
34
+ rejected: number;
35
+ deferred: number;
36
+ held: number;
37
+ v1: number;
38
+ v2: number;
39
+ }
40
+ /** Ack watermark of a payload's ops, keyed by their register coordinates —
41
+ * (dataset,row_id,col) plus `hlc >= theirs`, i.e. each op counts as accounted
42
+ * for when it either LANDED (exact row present; the oplog UNIQUE tuple, so a
43
+ * new-id replay resolves to the ORIGINAL seq and acks instead of deferring
44
+ * forever) or was SUPERSEDED (a newer register write exists — LWW-moot, incl.
45
+ * a long-deferred envelope whose op was compacted away, or one applyChange
46
+ * rejected because a newer winner already made it un-materializable).
47
+ * Returns null unless EVERY op is accounted for: a partial ingest (one change
48
+ * skipped as poison) must NOT ack the envelope — the caller holds it and
49
+ * retries, because ack+delete would permanently lose that guest write.
50
+ * (Known limit: a held-partial envelope re-pulled after its landed sibling
51
+ * passed the push cursor takes the envelopeMaxSeq fast path and acks — the txn
52
+ * probe can't know the sealed payload's op count. Partial ingest is
53
+ * constructively unreachable via checkDropPayload today; this gate is the
54
+ * same-round backstop. Exported for the gate's unit tests.) */
55
+ export declare function changesMaxSeq(db: DbDriver, changes: Change[]): number | null;
56
+ /**
57
+ * One pull round over every wired drop. With a bucket attached the round rides
58
+ * the publisher lease (only the elected device pays the poll — correctness
59
+ * never depends on it, double pulls converge); `ignoreLease` (manual
60
+ * `mh edge pull`) skips that economy.
61
+ */
62
+ export declare function pullDropsOnce(db: DbDriver, opts?: {
63
+ host?: DropHostApi;
64
+ ignoreLease?: boolean;
65
+ now?: () => number;
66
+ }): Promise<DropPullSummary>;
67
+ //# sourceMappingURL=drop-pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drop-pull.d.ts","sourceRoot":"","sources":["../../../src/core/sync/drop-pull.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAOzC,OAAO,EAAa,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAqBhE;;iCAEiC;AACjC,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,EAAE,CAItD;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,QAAQ,EAAE,MAAM,CAAC;IACjB;sFACkF;IAClF,IAAI,EAAE,MAAM,CAAC;IACb;iEAC6D;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,SAAS,GAAG,eAAe,CAAC;IAC/D,KAAK,EAAE,mBAAmB,EAAE,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;CACZ;AA2BD;;;;;;;;;;;;;;gEAcgE;AAChE,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAU5E;AA2DD;;;;;GAKG;AACH,wBAAsB,aAAa,CACjC,EAAE,EAAE,QAAQ,EACZ,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,WAAW,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAA;CAAO,GAC3E,OAAO,CAAC,eAAe,CAAC,CAqL1B"}
@@ -0,0 +1,39 @@
1
+ import type { DbDriver } from "../driver.ts";
2
+ import { type SiteRow } from "../sites-core.ts";
3
+ import { type DropHostApi } from "./drop-host.ts";
4
+ /** Reserved site file the SDK auto-discovers. publishDirectory's --prune
5
+ * deliberately skips it (sites.ts) so a mirror re-publish can't sever the
6
+ * wiring between two grant commands. */
7
+ export declare const DROP_CONFIG_PATH = "mh-drop.json";
8
+ /** Reserved deployment manifest the SDK reads for EXPLICIT channel selection
9
+ * (mode + endpoints + policy revision) instead of guessing from 401/network.
10
+ * Published alongside mh-drop.json; --prune skips it too. */
11
+ export declare const MANIFEST_PATH = "mh-manifest.json";
12
+ /** The reserved files the grant/edge wiring owns — never pruned by a mirror
13
+ * publish (they'd be re-created immediately: pure delete/recreate oplog churn). */
14
+ export declare const RESERVED_SITE_FILES: ReadonlySet<string>;
15
+ export interface DropWireResult {
16
+ site: string;
17
+ name: string;
18
+ /** create grant present AND edge configured — the drop transport is live. */
19
+ wired: boolean;
20
+ /** What happened to mh-drop.json. */
21
+ file: "written" | "unchanged" | "removed" | "none";
22
+ /** Host registration outcome; null when none was attempted. */
23
+ registered: boolean | null;
24
+ registerError?: string;
25
+ /** Which transport create-grant submissions ride (null: no create grant). */
26
+ transport: "edge" | "server" | null;
27
+ }
28
+ export declare function siteHasCreateGrant(site: Pick<SiteRow, "public_grants">): boolean;
29
+ /**
30
+ * Reconcile one site's drop wiring with its grants + the edge config. File
31
+ * writes are idempotent (writeFileRow skip-unchanged: zero oplog rows when
32
+ * nothing changed); host registration is re-PUT every time (idempotent upsert)
33
+ * and failures are reported, not thrown — a temporarily unreachable edge must
34
+ * not fail the grant/publish command that triggered the wiring.
35
+ */
36
+ export declare function syncDropWiring(db: DbDriver, site: SiteRow, opts?: {
37
+ host?: DropHostApi;
38
+ }): Promise<DropWireResult>;
39
+ //# sourceMappingURL=drop-wire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drop-wire.d.ts","sourceRoot":"","sources":["../../../src/core/sync/drop-wire.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAK7C,OAAO,EAA6B,KAAK,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE3E,OAAO,EAAgB,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGhE;;yCAEyC;AACzC,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAE/C;;8DAE8D;AAC9D,eAAO,MAAM,aAAa,qBAAqB,CAAC;AAEhD;oFACoF;AACpF,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAA8C,CAAC;AAEnG,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,6EAA6E;IAC7E,KAAK,EAAE,OAAO,CAAC;IACf,qCAAqC;IACrC,IAAI,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,MAAM,CAAC;IACnD,+DAA+D;IAC/D,UAAU,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAAC;CACrC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,GAAG,OAAO,CAEhF;AAgED;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,EAAE,EAAE,QAAQ,EACZ,IAAI,EAAE,OAAO,EACb,IAAI,GAAE;IAAE,IAAI,CAAC,EAAE,WAAW,CAAA;CAAO,GAChC,OAAO,CAAC,cAAc,CAAC,CAqEzB"}
@@ -10,6 +10,9 @@ export interface KeyEnvelope {
10
10
  }
11
11
  export declare function toB64(bytes: Uint8Array): string;
12
12
  export declare function fromB64(b64: string): Uint8Array;
13
+ /** base64url (RFC 4648 §5, unpadded) of raw bytes — for OAuth PKCE verifiers and
14
+ * SHA-256 challenges, where the value travels in a URL query. */
15
+ export declare function toB64url(bytes: Uint8Array): string;
13
16
  /** A fresh random 256-bit master key (raw bytes). */
14
17
  export declare function generateMasterKey(): Uint8Array;
15
18
  /** Wrap the master key under a passphrase-derived KEK → bucket keys/main.json. */
@@ -1 +1 @@
1
- {"version":3,"file":"e2ee.d.ts","sourceRoot":"","sources":["../../../src/core/sync/e2ee.ts"],"names":[],"mappings":"AAkCA,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,CAAC,CAAC;IACL,GAAG,EAAE,eAAe,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAI/C;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAK/C;AAID,qDAAqD;AACrD,wBAAgB,iBAAiB,IAAI,UAAU,CAE9C;AAmBD,kFAAkF;AAClF,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBhG;AAED;2EAC2E;AAC3E,wBAAsB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAc/F;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAc5F;AAWD,iFAAiF;AACjF,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAUjG;AAED,mFAAmF;AACnF,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAU/F"}
1
+ {"version":3,"file":"e2ee.d.ts","sourceRoot":"","sources":["../../../src/core/sync/e2ee.ts"],"names":[],"mappings":"AAkCA,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,CAAC,CAAC;IACL,GAAG,EAAE,eAAe,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,6DAA6D;IAC7D,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAI/C;AAED,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAK/C;AAED;kEACkE;AAClE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAElD;AAID,qDAAqD;AACrD,wBAAgB,iBAAiB,IAAI,UAAU,CAE9C;AAmBD,kFAAkF;AAClF,wBAAsB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAkBhG;AAED;2EAC2E;AAC3E,wBAAsB,eAAe,CAAC,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAc/F;AAED;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAc5F;AAWD,iFAAiF;AACjF,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAUjG;AAED,mFAAmF;AACnF,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAU/F"}
@@ -0,0 +1,77 @@
1
+ import type { DbDriver } from "../driver.ts";
2
+ /** Shared without importing the Worker bundle into browser/Node clients. */
3
+ export declare const EXPECTED_EDGE_WORKER_VERSION = "3";
4
+ export type EdgeCapability = "inbox" | "room";
5
+ /** Persisted Cloudflare resource identity. Deliberately excludes the account
6
+ * API token: deploy/upgrade callers must supply that ephemeral credential. */
7
+ export interface CfEdgeTarget {
8
+ accountId: string;
9
+ workerName: string;
10
+ d1Id: string;
11
+ d1Name?: string;
12
+ workersSubdomain?: string;
13
+ /** Non-secret marker also uploaded with the Worker, used to distinguish a
14
+ * resumable deployment from an unrelated same-name script. */
15
+ deploymentId?: string;
16
+ }
17
+ export interface CfApiTarget extends CfEdgeTarget {
18
+ apiToken: string;
19
+ }
20
+ export interface EdgeConfig {
21
+ /** Base URL of the inbox host (workers.dev URL, or any compatible host). */
22
+ endpoint: string;
23
+ /** Owner secret ("drt_…") — independent of the master token so a leaked
24
+ * inbox credential can only read/ack ciphertext mail, nothing else. */
25
+ token: string;
26
+ /** Third-party inbox hosts need not implement MetaHub Room APIs. */
27
+ capabilities?: EdgeCapability[];
28
+ /** Present when the host is a CF worker managed by `mh edge deploy`. */
29
+ cf?: CfEdgeTarget;
30
+ /** EDGE_WORKER_VERSION at last deploy — `mh edge status` alignment check. */
31
+ deployedVersion?: string;
32
+ }
33
+ export declare function getEdgeConfig(db: DbDriver): EdgeConfig | null;
34
+ export declare function setEdgeConfig(db: DbDriver, cfg: EdgeConfig | null): void;
35
+ export declare function edgeCapabilities(cfg: EdgeConfig): EdgeCapability[];
36
+ export type EdgeDeployStep = "creating_d1" | "creating_subdomain" | "uploading_worker" | "migrating_d1" | "setting_secret" | "enabling_subdomain";
37
+ export interface EdgeDeployProgress {
38
+ accountId: string;
39
+ workerName: string;
40
+ d1Name: string;
41
+ d1Id?: string;
42
+ workersSubdomain?: string;
43
+ deploymentId: string;
44
+ startedAt: number;
45
+ step: EdgeDeployStep;
46
+ updatedAt: number;
47
+ }
48
+ export declare function getEdgeDeployProgress(db: DbDriver): EdgeDeployProgress | null;
49
+ export declare function setEdgeDeployProgress(db: DbDriver, progress: EdgeDeployProgress | null): void;
50
+ /** In-flight R2 bucket provisioning (edge-service provisionR2Bucket). Persisted
51
+ * BEFORE the remote create so a crash mid-flight can prove on re-run that the
52
+ * half-created bucket is OURS to adopt (the R2 API has no ownership marker). */
53
+ export interface R2ProvisionProgress {
54
+ accountId: string;
55
+ bucketName: string;
56
+ startedAt: number;
57
+ }
58
+ export declare function getR2ProvisionProgress(db: DbDriver): R2ProvisionProgress | null;
59
+ export declare function setR2ProvisionProgress(db: DbDriver, progress: R2ProvisionProgress | null): void;
60
+ /**
61
+ * Per-site anti-abuse knobs, set on `mh site grant … --turnstile/--password`.
62
+ * They gate BOTH guest-write transports of the same grant: the write-inbox
63
+ * (enforced at the edge worker) and the server's realtime granted endpoint.
64
+ * The password itself is never stored — only a PBKDF2 salt (published in
65
+ * mh-drop.json so the page can derive the verifier) and the verifier (sent to
66
+ * the edge registration for constant-time comparison).
67
+ */
68
+ export interface DropKnobs {
69
+ turnstileSitekey?: string;
70
+ /** Turnstile SECRET key — needed by the edge for siteverify; never published. */
71
+ turnstileSecret?: string;
72
+ passwordSalt?: string;
73
+ passwordVerifier?: string;
74
+ }
75
+ export declare function getDropKnobs(db: DbDriver, siteId: string): DropKnobs | null;
76
+ export declare function setDropKnobs(db: DbDriver, siteId: string, knobs: DropKnobs | null): void;
77
+ //# sourceMappingURL=edge-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-config.d.ts","sourceRoot":"","sources":["../../../src/core/sync/edge-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { type EdgeCapability } from "./edge-config.ts";
2
+ export type EdgeConnectionMode = "edge" | "inbox";
3
+ export interface VerifiedEdgeConnection {
4
+ endpoint: string;
5
+ token: string;
6
+ version: string | undefined;
7
+ capabilities: EdgeCapability[];
8
+ }
9
+ /** Portable connection validation shared by Bun server/CLI and the OPFS
10
+ * browser worker. `edge` means our versioned Worker with Rooms; `inbox` keeps
11
+ * the historical third-party protocol-host contract. */
12
+ export declare function verifyEdgeConnection(endpointInput: string, tokenInput: string, mode: EdgeConnectionMode): Promise<VerifiedEdgeConnection>;
13
+ //# sourceMappingURL=edge-connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-connect.d.ts","sourceRoot":"","sources":["../../../src/core/sync/edge-connect.ts"],"names":[],"mappings":"AACA,OAAO,EAAgC,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGrF,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,OAAO,CAAC;AAElD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,YAAY,EAAE,cAAc,EAAE,CAAC;CAChC;AAED;;wDAEwD;AACxD,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,sBAAsB,CAAC,CA8BjC"}
@@ -0,0 +1,100 @@
1
+ import type { DbDriver } from "../driver.ts";
2
+ import { getEdgeDeployProgress } from "./edge-config.ts";
3
+ export interface EdgeDeployInput {
4
+ accountId: string;
5
+ apiToken: string;
6
+ workerName?: string;
7
+ d1Name?: string;
8
+ workersSubdomain?: string;
9
+ /** Required acknowledgment for the account-scoped remote mutations. */
10
+ confirmed: boolean;
11
+ }
12
+ export interface EdgeDeployResult {
13
+ status: "deployed";
14
+ endpoint: string;
15
+ workerName: string;
16
+ d1Id: string;
17
+ d1Name: string;
18
+ version: string;
19
+ keyId: string;
20
+ wired: {
21
+ site: string;
22
+ registered: boolean;
23
+ error?: string;
24
+ }[];
25
+ warnings: string[];
26
+ }
27
+ export declare function defaultEdgeNames(db: DbDriver): {
28
+ workerName: string;
29
+ d1Name: string;
30
+ workersSubdomain: string;
31
+ r2BucketName: string;
32
+ };
33
+ export interface R2ProvisionInput {
34
+ accountId: string;
35
+ apiToken: string;
36
+ bucketName?: string;
37
+ /** Required acknowledgment for the account-scoped remote creation. */
38
+ confirmed: boolean;
39
+ }
40
+ export interface R2ProvisionResult {
41
+ status: "created" | "adopted";
42
+ bucketName: string;
43
+ /** S3 endpoint to attach with (path-style, region "auto"). */
44
+ endpoint: string;
45
+ /** Dashboard page where the user mints the S3 credentials. */
46
+ credentialsUrl: string;
47
+ }
48
+ export declare function defaultR2BucketName(db: DbDriver): string;
49
+ export declare function provisionR2Bucket(db: DbDriver, input: R2ProvisionInput): Promise<R2ProvisionResult>;
50
+ /** Create/upgrade a dedicated Worker+D1. Progress is persisted before every
51
+ * remote effect, while the API token exists only in this stack frame. */
52
+ export declare function deployEdge(db: DbDriver, input: EdgeDeployInput, workerScript: string): Promise<EdgeDeployResult>;
53
+ export interface EdgeConnectResult extends EdgeStatus {
54
+ status: "connected";
55
+ wired: {
56
+ site: string;
57
+ registered: boolean;
58
+ error?: string;
59
+ }[];
60
+ warnings: string[];
61
+ }
62
+ export declare function connectEdge(db: DbDriver, endpointInput: string, token: string): Promise<EdgeConnectResult>;
63
+ /** CLI-only compatibility path for any host implementing the inbox protocol.
64
+ * It deliberately does not claim Room capability or require our Worker version. */
65
+ export declare function connectInboxHost(db: DbDriver, endpointInput: string, token: string): Promise<EdgeConnectResult>;
66
+ export interface EdgeRoomStatus {
67
+ slug: string;
68
+ url: string;
69
+ status: string | null;
70
+ lastSuccessAt: number | null;
71
+ error: string | null;
72
+ }
73
+ export interface EdgeStatus {
74
+ configured: boolean;
75
+ endpoint?: string;
76
+ version?: string | null;
77
+ expectedVersion: string;
78
+ aligned: boolean;
79
+ reachable: boolean;
80
+ error?: string;
81
+ managed: boolean;
82
+ deployment?: {
83
+ accountId: string;
84
+ workerName: string;
85
+ d1Name: string;
86
+ workersSubdomain: string;
87
+ };
88
+ rooms: EdgeRoomStatus[];
89
+ defaults: ReturnType<typeof defaultEdgeNames>;
90
+ pending: ReturnType<typeof getEdgeDeployProgress>;
91
+ capabilities?: ("inbox" | "room")[];
92
+ wired?: {
93
+ site: string;
94
+ registered: boolean;
95
+ error?: string;
96
+ }[];
97
+ }
98
+ export declare function edgeStatus(db: DbDriver): Promise<EdgeStatus>;
99
+ export declare function disconnectEdge(db: DbDriver): void;
100
+ //# sourceMappingURL=edge-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-service.d.ts","sourceRoot":"","sources":["../../../src/core/sync/edge-service.ts"],"names":[],"mappings":"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"}