@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.
- package/README.md +23 -10
- package/README.zh-CN.md +23 -10
- package/dist/cli/edge-worker-script.d.ts +4 -0
- package/dist/cli/edge-worker-script.d.ts.map +1 -0
- package/dist/cli.js +16882 -8691
- package/dist/cli.js.map +109 -59
- package/dist/core/access-policy.d.ts +82 -0
- package/dist/core/access-policy.d.ts.map +1 -0
- package/dist/core/blobs-core.d.ts +19 -0
- package/dist/core/blobs-core.d.ts.map +1 -1
- package/dist/core/blobs.d.ts.map +1 -1
- package/dist/core/compact.d.ts.map +1 -1
- package/dist/core/config.d.ts +13 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/crdt.d.ts +29 -2
- package/dist/core/crdt.d.ts.map +1 -1
- package/dist/core/data-map.d.ts +105 -0
- package/dist/core/data-map.d.ts.map +1 -0
- package/dist/core/db.d.ts +1 -1
- package/dist/core/db.d.ts.map +1 -1
- package/dist/core/documents.d.ts.map +1 -1
- package/dist/core/errors.d.ts +2 -0
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/grants-core.d.ts +132 -0
- package/dist/core/grants-core.d.ts.map +1 -0
- package/dist/core/guest-intent.d.ts +33 -0
- package/dist/core/guest-intent.d.ts.map +1 -0
- package/dist/core/hash.d.ts +4 -0
- package/dist/core/hash.d.ts.map +1 -0
- package/dist/core/history.d.ts.map +1 -1
- package/dist/core/hlc.d.ts +5 -0
- package/dist/core/hlc.d.ts.map +1 -1
- package/dist/core/ids.d.ts +1 -1
- package/dist/core/ids.d.ts.map +1 -1
- package/dist/core/inject-runtime.d.ts +8 -0
- package/dist/core/inject-runtime.d.ts.map +1 -0
- package/dist/core/intent-retention.d.ts +23 -0
- package/dist/core/intent-retention.d.ts.map +1 -0
- package/dist/core/md/inline.d.ts +6 -2
- package/dist/core/md/inline.d.ts.map +1 -1
- package/dist/core/node.d.ts +13 -0
- package/dist/core/node.d.ts.map +1 -1
- package/dist/core/records.d.ts +31 -0
- package/dist/core/records.d.ts.map +1 -1
- package/dist/core/schema-init.d.ts +19 -2
- package/dist/core/schema-init.d.ts.map +1 -1
- package/dist/core/schema.d.ts +1 -1
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/shares.d.ts +15 -0
- package/dist/core/shares.d.ts.map +1 -1
- package/dist/core/site-channel-lifecycle.d.ts +10 -0
- package/dist/core/site-channel-lifecycle.d.ts.map +1 -0
- package/dist/core/site-channel-store.d.ts +120 -0
- package/dist/core/site-channel-store.d.ts.map +1 -0
- package/dist/core/site-channels.d.ts +65 -0
- package/dist/core/site-channels.d.ts.map +1 -0
- package/dist/core/sites-core.d.ts +100 -7
- package/dist/core/sites-core.d.ts.map +1 -1
- package/dist/core/sites.d.ts +65 -2
- package/dist/core/sites.d.ts.map +1 -1
- package/dist/core/sync/anti-abuse.d.ts +26 -0
- package/dist/core/sync/anti-abuse.d.ts.map +1 -0
- package/dist/core/sync/auth.d.ts +30 -2
- package/dist/core/sync/auth.d.ts.map +1 -1
- package/dist/core/sync/blob-routes.d.ts.map +1 -1
- package/dist/core/sync/cf-api.d.ts +54 -0
- package/dist/core/sync/cf-api.d.ts.map +1 -0
- package/dist/core/sync/cf-oauth.d.ts +91 -0
- package/dist/core/sync/cf-oauth.d.ts.map +1 -0
- package/dist/core/sync/client.d.ts +12 -0
- package/dist/core/sync/client.d.ts.map +1 -1
- package/dist/core/sync/data-map-db.d.ts +8 -0
- package/dist/core/sync/data-map-db.d.ts.map +1 -0
- package/dist/core/sync/devices.d.ts +65 -0
- package/dist/core/sync/devices.d.ts.map +1 -0
- package/dist/core/sync/drop-host.d.ts +40 -0
- package/dist/core/sync/drop-host.d.ts.map +1 -0
- package/dist/core/sync/drop-keys.d.ts +64 -0
- package/dist/core/sync/drop-keys.d.ts.map +1 -0
- package/dist/core/sync/drop-protocol.d.ts +94 -0
- package/dist/core/sync/drop-protocol.d.ts.map +1 -0
- package/dist/core/sync/drop-pull.d.ts +67 -0
- package/dist/core/sync/drop-pull.d.ts.map +1 -0
- package/dist/core/sync/drop-wire.d.ts +39 -0
- package/dist/core/sync/drop-wire.d.ts.map +1 -0
- package/dist/core/sync/e2ee.d.ts +3 -0
- package/dist/core/sync/e2ee.d.ts.map +1 -1
- package/dist/core/sync/edge-config.d.ts +77 -0
- package/dist/core/sync/edge-config.d.ts.map +1 -0
- package/dist/core/sync/edge-connect.d.ts +13 -0
- package/dist/core/sync/edge-connect.d.ts.map +1 -0
- package/dist/core/sync/edge-service.d.ts +100 -0
- package/dist/core/sync/edge-service.d.ts.map +1 -0
- package/dist/core/sync/grants-routes.d.ts +46 -0
- package/dist/core/sync/grants-routes.d.ts.map +1 -0
- package/dist/core/sync/guest-session.d.ts +29 -0
- package/dist/core/sync/guest-session.d.ts.map +1 -0
- package/dist/core/sync/html-escape.d.ts +2 -0
- package/dist/core/sync/html-escape.d.ts.map +1 -0
- package/dist/core/sync/http-status.d.ts +14 -0
- package/dist/core/sync/http-status.d.ts.map +1 -0
- package/dist/core/sync/http-util.d.ts +6 -0
- package/dist/core/sync/http-util.d.ts.map +1 -0
- package/dist/core/sync/pairing.d.ts +9 -9
- package/dist/core/sync/pairing.d.ts.map +1 -1
- package/dist/core/sync/partition.d.ts +77 -0
- package/dist/core/sync/partition.d.ts.map +1 -0
- package/dist/core/sync/peers-routes.d.ts.map +1 -1
- package/dist/core/sync/peers.d.ts +77 -0
- package/dist/core/sync/peers.d.ts.map +1 -1
- package/dist/core/sync/protocol.d.ts +2 -0
- package/dist/core/sync/protocol.d.ts.map +1 -1
- package/dist/core/sync/rate-limit.d.ts +20 -0
- package/dist/core/sync/rate-limit.d.ts.map +1 -0
- package/dist/core/sync/recovery.d.ts +9 -0
- package/dist/core/sync/recovery.d.ts.map +1 -0
- package/dist/core/sync/room-client.d.ts +50 -0
- package/dist/core/sync/room-client.d.ts.map +1 -0
- package/dist/core/sync/room-peer.d.ts +62 -0
- package/dist/core/sync/room-peer.d.ts.map +1 -0
- package/dist/core/sync/room-protocol.d.ts +130 -0
- package/dist/core/sync/room-protocol.d.ts.map +1 -0
- package/dist/core/sync/room-serve.d.ts +38 -0
- package/dist/core/sync/room-serve.d.ts.map +1 -0
- package/dist/core/sync/room-url.d.ts +4 -0
- package/dist/core/sync/room-url.d.ts.map +1 -0
- package/dist/core/sync/routes.d.ts +4 -1
- package/dist/core/sync/routes.d.ts.map +1 -1
- package/dist/core/sync/seal.d.ts +22 -0
- package/dist/core/sync/seal.d.ts.map +1 -0
- package/dist/core/sync/server.d.ts +7 -0
- package/dist/core/sync/server.d.ts.map +1 -1
- package/dist/core/sync/share-actions.d.ts +55 -6
- package/dist/core/sync/share-actions.d.ts.map +1 -1
- package/dist/core/sync/share-export.d.ts +14 -0
- package/dist/core/sync/share-export.d.ts.map +1 -1
- package/dist/core/sync/share-render.d.ts +9 -1
- package/dist/core/sync/share-render.d.ts.map +1 -1
- package/dist/core/sync/share-serve.d.ts +5 -1
- package/dist/core/sync/share-serve.d.ts.map +1 -1
- package/dist/core/sync/site-channel-reconcile.d.ts +26 -0
- package/dist/core/sync/site-channel-reconcile.d.ts.map +1 -0
- package/dist/core/sync/site-publish-recovery.d.ts +32 -0
- package/dist/core/sync/site-publish-recovery.d.ts.map +1 -0
- package/dist/core/sync/site-reachability.d.ts +13 -0
- package/dist/core/sync/site-reachability.d.ts.map +1 -0
- package/dist/core/sync/sites-routes.d.ts.map +1 -1
- package/dist/core/sync/sites-serve.d.ts +24 -1
- package/dist/core/sync/sites-serve.d.ts.map +1 -1
- package/dist/core/sync/storage-s3-bun.d.ts +1 -24
- package/dist/core/sync/storage-s3-bun.d.ts.map +1 -1
- package/dist/core/sync/storage-s3-sign.d.ts +43 -0
- package/dist/core/sync/storage-s3-sign.d.ts.map +1 -0
- package/dist/core/sync/storage.d.ts +59 -0
- package/dist/core/sync/storage.d.ts.map +1 -1
- package/dist/db-worker.js +206 -76
- package/dist/edge-worker.js +3960 -0
- package/dist/index.js +13175 -6670
- package/dist/index.js.map +87 -41
- package/dist/metahub-sdk.js +10 -1
- package/dist/mh-runtime.js +1 -1
- package/dist/room/do-driver.d.ts +30 -0
- package/dist/room/do-driver.d.ts.map +1 -0
- package/dist/sw.js +10 -1
- package/dist/webui/server/edge-routes.d.ts +3 -0
- package/dist/webui/server/edge-routes.d.ts.map +1 -0
- package/dist/webui/server/json-handler.d.ts +4 -0
- package/dist/webui/server/json-handler.d.ts.map +1 -0
- package/dist/webui/server/routes.d.ts.map +1 -1
- package/dist/webui/server/share-routes.d.ts.map +1 -1
- package/dist/webui/server/site-hosting-routes.d.ts +7 -0
- package/dist/webui/server/site-hosting-routes.d.ts.map +1 -0
- package/dist/webui.js +192 -137
- package/dist/workers/edge-worker.d.ts +66 -0
- package/dist/workers/edge-worker.d.ts.map +1 -0
- package/dist/workers/room.d.ts +34 -0
- package/dist/workers/room.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { DbDriver } from "../driver.ts";
|
|
2
|
+
import { type Change } from "../crdt.ts";
|
|
3
|
+
import type { RecordRow } from "../records.ts";
|
|
4
|
+
import { type RowKey } from "./partition.ts";
|
|
5
|
+
export declare const ROOM_PROTOCOL_VERSION = 1;
|
|
6
|
+
export type ShareState = "active" | "expired";
|
|
7
|
+
/** Owner → room, one sync round. `changes` is the partition increment plus
|
|
8
|
+
* full-row winner baselines for rows that just entered (overlap is fine —
|
|
9
|
+
* the room oplog's UNIQUE dedups). `since` is the room-side seq cursor for
|
|
10
|
+
* the guest-op pull AND the ack that lets the room GC deferred guest oplog
|
|
11
|
+
* rows of evicted rows. `members`, when present, is the authoritative member
|
|
12
|
+
* key set (digest-mismatch reconciliation): the room locally deletes every
|
|
13
|
+
* partition row not listed. */
|
|
14
|
+
export interface OwnerSyncRequest {
|
|
15
|
+
protocol: number;
|
|
16
|
+
mh_version?: string;
|
|
17
|
+
node_id: string;
|
|
18
|
+
since: number;
|
|
19
|
+
changes: Change[];
|
|
20
|
+
evict: RowKey[];
|
|
21
|
+
members?: RowKey[];
|
|
22
|
+
digest?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Room → owner. `changes` are guest-authored ops after `since` (never any
|
|
25
|
+
* other author), paged — `more` says the page was truncated and the owner
|
|
26
|
+
* should sync again promptly. `need_baseline` lists rows the room holds
|
|
27
|
+
* incompletely (orphaned by a shadow split) for the owner to re-judge.
|
|
28
|
+
* `need_blobs` lists site-file blob hashes the room lacks (chunked upload
|
|
29
|
+
* channel, /owner/blob). */
|
|
30
|
+
export interface OwnerSyncResponse {
|
|
31
|
+
protocol: number;
|
|
32
|
+
node_id: string;
|
|
33
|
+
changes: Change[];
|
|
34
|
+
cursor: number;
|
|
35
|
+
/** The guest pull was truncated at the page limit — more rows are queued. */
|
|
36
|
+
more?: boolean;
|
|
37
|
+
need_baseline: RowKey[];
|
|
38
|
+
need_blobs: string[];
|
|
39
|
+
digest?: string;
|
|
40
|
+
share_state: ShareState;
|
|
41
|
+
}
|
|
42
|
+
export interface RoomConfig {
|
|
43
|
+
slug: string;
|
|
44
|
+
/** The room's own node identity (meta.node_id) — clock owner, never an author. */
|
|
45
|
+
roomNode: string;
|
|
46
|
+
/** The share's base guest node id; per-visitor sub ids are `<base>-<rand6>`. */
|
|
47
|
+
guestBase: string;
|
|
48
|
+
/** Serialized GrantSet snapshot (read through parseGrantSet, default-deny). */
|
|
49
|
+
grants: string;
|
|
50
|
+
pwHash?: string | null;
|
|
51
|
+
pwSalt?: string | null;
|
|
52
|
+
expiresAt?: number | null;
|
|
53
|
+
state: ShareState;
|
|
54
|
+
}
|
|
55
|
+
export interface RoomProvision {
|
|
56
|
+
slug: string;
|
|
57
|
+
guestBase: string;
|
|
58
|
+
grants: string;
|
|
59
|
+
pwHash?: string | null;
|
|
60
|
+
pwSalt?: string | null;
|
|
61
|
+
expiresAt?: number | null;
|
|
62
|
+
/** Defaults to `room-<slug>`. */
|
|
63
|
+
roomNode?: string;
|
|
64
|
+
}
|
|
65
|
+
/** Bring a fresh (or reopened) room database to shape and store its config.
|
|
66
|
+
* Idempotent; re-provisioning updates the config but keeps the node identity
|
|
67
|
+
* and clock (HLCs already issued must stay monotonic). */
|
|
68
|
+
export declare function initRoomDb(db: DbDriver, prov: RoomProvision): RoomConfig;
|
|
69
|
+
export declare function readRoomConfig(db: DbDriver): RoomConfig;
|
|
70
|
+
/** Flip the share state (revocation propagates as "expired"; the physical
|
|
71
|
+
* destroy — DO deleteAll — is the C2 host's job). */
|
|
72
|
+
export declare function setRoomState(db: DbDriver, state: ShareState): void;
|
|
73
|
+
/** Refresh the grants snapshot (owner re-granted; takes effect immediately
|
|
74
|
+
* for guest writes — pulls/pushes are unaffected, the owner re-scopes those). */
|
|
75
|
+
export declare function setRoomGrants(db: DbDriver, grants: string): void;
|
|
76
|
+
export declare function roomExpired(cfg: RoomConfig, now?: number): boolean;
|
|
77
|
+
/** Chunk size cap enforced at the upload endpoint (DO row limit is ~2MB). */
|
|
78
|
+
export declare const ROOM_BLOB_CHUNK_LIMIT: number;
|
|
79
|
+
/** Blob hashes referenced by live site_files rows with no complete chunk set. */
|
|
80
|
+
export declare function roomMissingBlobs(db: DbDriver, limit?: number): string[];
|
|
81
|
+
/** Store one uploaded chunk. Chunk 0 resets the hash (a re-upload with a
|
|
82
|
+
* different chunking never leaves a stale mixed set behind). */
|
|
83
|
+
export declare function roomPutBlobChunk(db: DbDriver, hash: string, idx: number, total: number, bytes: Uint8Array): void;
|
|
84
|
+
/** Reassemble a blob's bytes, or null while the chunk set is incomplete. */
|
|
85
|
+
export declare function roomBlobBytes(db: DbDriver, hash: string): Uint8Array | null;
|
|
86
|
+
/**
|
|
87
|
+
* One owner sync round, room side. Order matters:
|
|
88
|
+
* 1. ingest the owner's changes (idempotent — baseline/increment overlap and
|
|
89
|
+
* retried requests dedup on the oplog UNIQUE);
|
|
90
|
+
* 2. compute the guest-op pull BEFORE any eviction GC, so an evict racing an
|
|
91
|
+
* undelivered guest op still delivers it this round;
|
|
92
|
+
* 3. membership reset (when `members` rides along) then explicit evicts —
|
|
93
|
+
* local physical deletion, deferred for unacked guest ops;
|
|
94
|
+
* 4. sweep deferred evictions now covered by `since`;
|
|
95
|
+
* 5. orphan detection → need_baseline;
|
|
96
|
+
* 6. digest, echoed only when the owner attached one (anti-entropy rounds).
|
|
97
|
+
*/
|
|
98
|
+
export declare function handleOwnerSync(roomDb: DbDriver, req: OwnerSyncRequest, cfg?: RoomConfig): OwnerSyncResponse;
|
|
99
|
+
/** A guest write intent (final decision 1: intents, not pre-signed ops — the
|
|
100
|
+
* room's clock is the time authority; the write shape mirrors share-serve).
|
|
101
|
+
* The wire form the room WS accepts; mapped to the shared GuestIntent in
|
|
102
|
+
* handleGuestWrite. `intentId`/`submittedAt` are optional (new SDK sends them
|
|
103
|
+
* for retry-idempotency; older clients omit and the server synthesizes). */
|
|
104
|
+
export interface GuestWriteIntent {
|
|
105
|
+
op: "createRecord" | "updateRecord";
|
|
106
|
+
/** Database ref (id or granted name) — createRecord. */
|
|
107
|
+
db?: string;
|
|
108
|
+
/** Record id — updateRecord (or client-minted id on createRecord). */
|
|
109
|
+
record?: string;
|
|
110
|
+
values: Record<string, unknown>;
|
|
111
|
+
intentId?: string;
|
|
112
|
+
submittedAt?: number;
|
|
113
|
+
}
|
|
114
|
+
export interface RoomGuestSession {
|
|
115
|
+
/** Per-visitor guest sub id, minted at unlock (mintRoomGuestSub). */
|
|
116
|
+
sub: string;
|
|
117
|
+
}
|
|
118
|
+
/** Mint a per-visitor guest sub id (`<base>-<rand6>`) — same shape as
|
|
119
|
+
* share-serve's session subs, so per-visitor rollback and the base-prefix
|
|
120
|
+
* bulk predicate work identically for room-authored writes. */
|
|
121
|
+
export declare function mintRoomGuestSub(cfg: RoomConfig): string;
|
|
122
|
+
/**
|
|
123
|
+
* Apply one guest intent inside the room. Access gating (expiry + guest-node
|
|
124
|
+
* validity) is enforced here; authorization, guardrails and the write itself go
|
|
125
|
+
* through the shared applyGuestIntent executor (the same one the server share
|
|
126
|
+
* endpoints and — from Stage 4 — drop replay use). Authority clock: the room's
|
|
127
|
+
* persisted clock stamps the HLC, with the session's sub id as the author node.
|
|
128
|
+
*/
|
|
129
|
+
export declare function handleGuestWrite(roomDb: DbDriver, cfg: RoomConfig, session: RoomGuestSession, intent: GuestWriteIntent): RecordRow;
|
|
130
|
+
//# sourceMappingURL=room-protocol.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-protocol.d.ts","sourceRoot":"","sources":["../../../src/core/sync/room-protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { DbDriver } from "../driver.ts";
|
|
2
|
+
import { type RoomConfig } from "./room-protocol.ts";
|
|
3
|
+
export interface RoomHostDeps {
|
|
4
|
+
db: DbDriver;
|
|
5
|
+
/** The edge owner secret ("drt_…"); empty/undefined denies every owner route. */
|
|
6
|
+
ownerToken: string | undefined;
|
|
7
|
+
/** Broadcast a data-changed poke to connected guests (WS fan-out). */
|
|
8
|
+
poke?: (seq: number) => void;
|
|
9
|
+
/** Physical destruction — DO: deleteAll + close sockets; tests: drop the db. */
|
|
10
|
+
destroy: () => void | Promise<void>;
|
|
11
|
+
/** Schedule (epoch ms) / clear (null) the expiry self-destruct alarm. */
|
|
12
|
+
setAlarm?: (at: number | null) => void | Promise<void>;
|
|
13
|
+
/** Cede CPU so a frozen workerd clock can advance (HLC counter headroom —
|
|
14
|
+
* DO shell passes scheduler.wait(1)). Optional belt-and-braces: hlc.ts's
|
|
15
|
+
* carry-into-millis already keeps overflow correct without it. */
|
|
16
|
+
yieldClock?: () => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
/** Session context for a WebSocket upgrade: null = refuse (unprovisioned /
|
|
19
|
+
* expired / password-locked without a session). A cookieless connection to an
|
|
20
|
+
* unlocked room gets a fresh per-connection sub (P2 WS writes attribute to it). */
|
|
21
|
+
export declare function roomWsSession(db: DbDriver, req: Request): Promise<{
|
|
22
|
+
cfg: RoomConfig;
|
|
23
|
+
sub: string;
|
|
24
|
+
} | null>;
|
|
25
|
+
export interface RoomWsOutcome {
|
|
26
|
+
/** JSON reply for THIS socket, or null (nothing to say). */
|
|
27
|
+
reply: string | null;
|
|
28
|
+
/** Broadcast a poke to every connected guest. */
|
|
29
|
+
poke: boolean;
|
|
30
|
+
seq: number;
|
|
31
|
+
}
|
|
32
|
+
/** Handle one guest WS message: `{type:"write", intent, id?}` applies a write
|
|
33
|
+
* intent through handleGuestWrite (grants + guardrails + room-stamped HLC)
|
|
34
|
+
* and answers `{type:"result"|"error", id, …}`. Ping/pong is the host's
|
|
35
|
+
* auto-response pair and never reaches here. */
|
|
36
|
+
export declare function roomWsMessage(db: DbDriver, sub: string, raw: string): Promise<RoomWsOutcome>;
|
|
37
|
+
export declare function createRoomFetch(deps: RoomHostDeps): (req: Request) => Promise<Response>;
|
|
38
|
+
//# sourceMappingURL=room-serve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-serve.d.ts","sourceRoot":"","sources":["../../../src/core/sync/room-serve.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAiB7C,OAAO,EAWL,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAM5B,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,QAAQ,CAAC;IACb,iFAAiF;IACjF,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,sEAAsE;IACtE,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,gFAAgF;IAChF,OAAO,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD;;uEAEmE;IACnE,UAAU,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAkHD;;oFAEoF;AACpF,wBAAsB,aAAa,CACjC,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,OAAO,GACX,OAAO,CAAC;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAMlD;AAID,MAAM,WAAW,aAAa;IAC5B,4DAA4D;IAC5D,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,iDAAiD;IACjD,IAAI,EAAE,OAAO,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;iDAGiD;AACjD,wBAAsB,aAAa,CACjC,EAAE,EAAE,QAAQ,EACZ,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,aAAa,CAAC,CA4CxB;AAID,wBAAgB,eAAe,CAAC,IAAI,EAAE,YAAY,GAAG,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAyIvF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-url.d.ts","sourceRoot":"","sources":["../../../src/core/sync/room-url.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,MAAM,CAE/E"}
|
|
@@ -4,6 +4,9 @@ import type { Database } from "bun:sqlite";
|
|
|
4
4
|
export interface RouteCtx {
|
|
5
5
|
db: Database;
|
|
6
6
|
node: string;
|
|
7
|
+
/** Desktop's unauthenticated loopback sidecar may preview locally but must
|
|
8
|
+
* never be accepted as a LAN/public hosting origin. */
|
|
9
|
+
allowRemoteSiteHosting?: boolean;
|
|
7
10
|
}
|
|
8
11
|
/** Turn a thrown handler error into a JSON response: `{error, code?}` with a
|
|
9
12
|
* semantic status, so HTTP clients can dispatch on `code` like CLI users
|
|
@@ -15,7 +18,7 @@ export declare function errorResponse(e: unknown): Response;
|
|
|
15
18
|
* in /docs automatically — no generate step, no separate spec file.
|
|
16
19
|
*/
|
|
17
20
|
export interface Route {
|
|
18
|
-
method: "GET" | "POST" | "PATCH" | "DELETE";
|
|
21
|
+
method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
19
22
|
path: string;
|
|
20
23
|
summary: string;
|
|
21
24
|
request?: ZodType;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/core/sync/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/core/sync/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgB3C,yEAAyE;AACzE,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,QAAQ,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb;4DACwD;IACxD,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAClC;AAgBD;;8BAE8B;AAC9B,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,QAAQ,CAMlD;AAED;;;;GAIG;AACH,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,OAAO,GAAG,QAAQ,CAAC;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;CACxE;AAsCD,eAAO,MAAM,MAAM,EAAE,KAAK,EAAmE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export declare const SEAL_ENC = "sealed-p256";
|
|
2
|
+
export interface SealKeypair {
|
|
3
|
+
/** Raw uncompressed public point (65 bytes) — what mh-drop.json publishes. */
|
|
4
|
+
publicKey: Uint8Array;
|
|
5
|
+
/** PKCS#8 private key — wrapped with the master key before it leaves the device. */
|
|
6
|
+
privateKey: Uint8Array;
|
|
7
|
+
}
|
|
8
|
+
/** A fresh P-256 keypair for a drop recipient. Independent generation is a
|
|
9
|
+
* design decision, not a shortcut: WebCrypto cannot derive a P-256 keypair
|
|
10
|
+
* from a seed, so "derive from the master key" is technically impossible. */
|
|
11
|
+
export declare function generateSealKeypair(): Promise<SealKeypair>;
|
|
12
|
+
/** Seal plaintext to a recipient's raw P-256 public key (anonymous sender). */
|
|
13
|
+
export declare function seal(recipientPkRaw: Uint8Array, plaintext: Uint8Array): Promise<Uint8Array>;
|
|
14
|
+
/**
|
|
15
|
+
* Open a sealed box with the recipient's PKCS#8 private key (+ its raw public
|
|
16
|
+
* key, which the keyring stores alongside — needed to rebuild the KDF info).
|
|
17
|
+
* EVERY failure mode — truncated input, bad ephemeral point, wrong key,
|
|
18
|
+
* tampered ciphertext — answers with the same MhError("auth"), so a caller
|
|
19
|
+
* can't distinguish "wrong key" from "corrupted": both mean "not for you".
|
|
20
|
+
*/
|
|
21
|
+
export declare function openSealed(privateKeyPkcs8: Uint8Array, recipientPkRaw: Uint8Array, sealed: Uint8Array): Promise<Uint8Array>;
|
|
22
|
+
//# sourceMappingURL=seal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seal.d.ts","sourceRoot":"","sources":["../../../src/core/sync/seal.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,QAAQ,gBAAgB,CAAC;AAyBtC,MAAM,WAAW,WAAW;IAC1B,8EAA8E;IAC9E,SAAS,EAAE,UAAU,CAAC;IACtB,oFAAoF;IACpF,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;8EAE8E;AAC9E,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,WAAW,CAAC,CAMhE;AAqBD,+EAA+E;AAC/E,wBAAsB,IAAI,CAAC,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CASjG;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,eAAe,EAAE,UAAU,EAC3B,cAAc,EAAE,UAAU,EAC1B,MAAM,EAAE,UAAU,GACjB,OAAO,CAAC,UAAU,CAAC,CAerB"}
|
|
@@ -40,6 +40,12 @@ export interface ServerOptions {
|
|
|
40
40
|
syncIntervalMs?: number;
|
|
41
41
|
/** Master switch for the auto-sync timer. Falls back to stored config. */
|
|
42
42
|
autoSync?: boolean;
|
|
43
|
+
/** Disable LAN/public site-base verification for an unauthenticated
|
|
44
|
+
* loopback-only shell such as the Desktop sidecar. */
|
|
45
|
+
allowRemoteSiteHosting?: boolean;
|
|
46
|
+
/** Desktop's debug sidecar: reject DNS-rebinding hosts and cross-site
|
|
47
|
+
* mutations even though the token gate is intentionally disabled. */
|
|
48
|
+
loopbackUiOnly?: boolean;
|
|
43
49
|
/** Browser UI plug-in point. Core ships no UI; callers (CLI, desktop
|
|
44
50
|
* sidecar) inject the WebUI's asset handler + data API routes here.
|
|
45
51
|
* Omitted = a headless sync/sites server. */
|
|
@@ -60,6 +66,7 @@ export interface UiHandler {
|
|
|
60
66
|
/** The UI's data API routes, merged into the route registry (and /docs). */
|
|
61
67
|
routes: Route[];
|
|
62
68
|
}
|
|
69
|
+
export declare function loopbackUiRejection(req: Request, port: number): Response | null;
|
|
63
70
|
/** Start the CRDT sync server. It is just another node backed by ~/.metahub. */
|
|
64
71
|
export declare function startServer(opts?: ServerOptions): RunningServer;
|
|
65
72
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/core/sync/server.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAIvC,OAAO,EAAU,KAAK,KAAK,EAAiB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/core/sync/server.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAIvC,OAAO,EAAU,KAAK,KAAK,EAAiB,MAAM,aAAa,CAAC;AAuBhE,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,iEAAiE;IACjE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,qFAAqF;IACrF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,wFAAwF;IACxF,QAAQ,EAAE,SAAS,GAAG,QAAQ,GAAG,UAAU,CAAC;IAC5C,oEAAoE;IACpE,GAAG,EAAE,OAAO,CAAC;IACb,8CAA8C;IAC9C,QAAQ,EAAE,OAAO,CAAC;IAClB,qEAAqE;IACrE,cAAc,EAAE,MAAM,CAAC;IACvB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,6EAA6E;AAC7E,qBAAa,cAAe,SAAQ,OAAO;IAEvC,QAAQ,CAAC,IAAI,EAAE,MAAM;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM;gBADZ,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM;CASxB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,oEAAoE;IACpE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,oFAAoF;IACpF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;2DACuD;IACvD,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;yEACqE;IACrE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;kDAE8C;IAC9C,EAAE,CAAC,EAAE,SAAS,CAAC;IACf;;;mEAG+D;IAC/D,GAAG,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7C;AAED,oEAAoE;AACpE,MAAM,WAAW,SAAS;IACxB,8EAA8E;IAC9E,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IACpD,4EAA4E;IAC5E,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAe/E;AAYD,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,IAAI,GAAE,aAAkB,GAAG,aAAa,CAsUnE"}
|
|
@@ -5,6 +5,8 @@ export interface CreateShareRequest {
|
|
|
5
5
|
ref: string;
|
|
6
6
|
permission?: SharePermission;
|
|
7
7
|
transport?: "server" | "s3";
|
|
8
|
+
/** Hosting surface for server shares. room provisions an always-on Edge room. */
|
|
9
|
+
hosting?: "server" | "room";
|
|
8
10
|
password?: string | null;
|
|
9
11
|
/** Server: any duration (ms); null = never. s3: clamped to ≤7d; default 7d. */
|
|
10
12
|
expiresMs?: number | null;
|
|
@@ -16,12 +18,18 @@ export interface CreateShareRequest {
|
|
|
16
18
|
bucketUrl?: string | null;
|
|
17
19
|
/** s3 only: the static viewer base for the link. */
|
|
18
20
|
viewerBase?: string;
|
|
21
|
+
/** Serialized GrantSet enabling /share/<slug>/api/* (server transport only —
|
|
22
|
+
* a presigned static export has no API surface). */
|
|
23
|
+
grants?: string | null;
|
|
24
|
+
/** Idempotency key used when a paired node creates the share remotely. */
|
|
25
|
+
requestId?: string | null;
|
|
19
26
|
}
|
|
20
27
|
export interface CreatedShare {
|
|
21
28
|
slug: string;
|
|
22
29
|
kind: ShareKind;
|
|
23
30
|
permission: SharePermission;
|
|
24
31
|
transport: "server" | "s3";
|
|
32
|
+
hosting: "server" | "room" | "s3";
|
|
25
33
|
/** Full link to copy (server: served_base/share/slug; s3: viewer link). */
|
|
26
34
|
url: string;
|
|
27
35
|
expiresAt: number | null;
|
|
@@ -38,32 +46,73 @@ export interface ShareListItem {
|
|
|
38
46
|
permission: string;
|
|
39
47
|
transport: "server" | "s3";
|
|
40
48
|
source: string;
|
|
41
|
-
sourceKind: "server" | "peer" | "bucket";
|
|
49
|
+
sourceKind: "server" | "peer" | "room" | "bucket";
|
|
50
|
+
/** Paired node that owns this share; present only in aggregated listings so
|
|
51
|
+
* management actions can be routed back to the correct device. */
|
|
52
|
+
sourceUrl?: string;
|
|
53
|
+
/** Where the share is actually served from: this/a server, an always-on DO
|
|
54
|
+
* room (server share + kind='room' peer), or a bucket export. */
|
|
55
|
+
hosting?: "server" | "room" | "s3";
|
|
42
56
|
expiresAt: number | null;
|
|
43
57
|
hasPassword: boolean;
|
|
44
58
|
/** server: ready-to-copy link; s3: omitted (use renew to mint a fresh one). */
|
|
45
59
|
url?: string;
|
|
60
|
+
lifecycle?: "active" | "provisioning" | "cleanup_pending";
|
|
61
|
+
/** s3 only: when the snapshot content was last exported (≠ link expiry). */
|
|
62
|
+
contentUpdatedAt?: number;
|
|
46
63
|
}
|
|
47
64
|
/** s3 bucket peers (no secrets) for a transport picker. */
|
|
48
65
|
export declare function listShareBuckets(db: DbDriver): {
|
|
49
66
|
url: string;
|
|
50
67
|
label: string;
|
|
51
68
|
}[];
|
|
52
|
-
/** Paired HTTP peer servers (a share can be created on / served by them).
|
|
69
|
+
/** Paired HTTP peer servers (a share can be created on / served by them).
|
|
70
|
+
* Room peers are deliberately excluded: they are Edge destinations, not
|
|
71
|
+
* devices a user can select as a hosting node. */
|
|
53
72
|
export declare function listShareServers(db: DbDriver): {
|
|
54
73
|
url: string;
|
|
55
74
|
label: string;
|
|
75
|
+
enabled: boolean;
|
|
76
|
+
lastStatus: string | null;
|
|
77
|
+
lastSuccessAt: number | null;
|
|
56
78
|
}[];
|
|
79
|
+
/** The legal-combination matrix in ONE place. Every rule names the conflict and
|
|
80
|
+
* the way out, so surfaces (CLI flags, WebUI selects, remote peers) fail the
|
|
81
|
+
* same way instead of each scattering its own throws. */
|
|
82
|
+
export declare function assertShareCombo(req: {
|
|
83
|
+
kind: ShareKind;
|
|
84
|
+
transport: "server" | "s3";
|
|
85
|
+
hosting: "server" | "room";
|
|
86
|
+
permission: SharePermission;
|
|
87
|
+
hasGrants: boolean;
|
|
88
|
+
}): void;
|
|
57
89
|
/** Resolve, validate, and create (server local / server remote / s3 bucket) a share. */
|
|
58
90
|
export declare function createShareAction(db: DbDriver, req: CreateShareRequest): Promise<CreatedShare>;
|
|
91
|
+
/** This node's server-share rows only (sync, no network) — the bucket-free
|
|
92
|
+
* subset of listSharesLocal. Site reachability and CLI listings use it so a
|
|
93
|
+
* local derivation never waits on an S3 scan. */
|
|
94
|
+
export declare function listServerSharesLocal(db: DbDriver, targetId?: string): ShareListItem[];
|
|
59
95
|
/** Local listing (server rows + each attached bucket) — NO peer fan-out (so the
|
|
60
96
|
* /api/shares endpoint a peer calls can't recurse). Optional target filter. */
|
|
61
97
|
export declare function listSharesLocal(db: DbDriver, targetId?: string): Promise<ShareListItem[]>;
|
|
98
|
+
export declare function createdShareByRequestId(db: DbDriver, requestId: string): CreatedShare | null;
|
|
99
|
+
export declare function revokeShareByRequestId(db: DbDriver, requestId: string): Promise<RevokeShareResult>;
|
|
62
100
|
/** Aggregated listing for CLI/WebUI: local ∪ each paired peer's /api/shares
|
|
63
101
|
* (best-effort, bounded), deduped by slug. Optional target filter. */
|
|
64
102
|
export declare function listSharesAggregated(db: DbDriver, targetId?: string): Promise<ShareListItem[]>;
|
|
65
|
-
/** Revoke: local server row → delete it
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
export
|
|
103
|
+
/** Revoke: local server row → delete it (cascading the share's room, if one is
|
|
104
|
+
* provisioned — final decision 3: the room's lifecycle is the share's); else a
|
|
105
|
+
* bucket holds it → delete objects. */
|
|
106
|
+
export interface RevokeShareResult {
|
|
107
|
+
ok: boolean;
|
|
108
|
+
status: "revoked" | "cleanup_pending" | "not_found";
|
|
109
|
+
}
|
|
110
|
+
export declare function revokeShareAction(db: DbDriver, slug: string): Promise<RevokeShareResult>;
|
|
111
|
+
/** Renew an s3 share's LINK. Default is re-presign only — the snapshot content
|
|
112
|
+
* is untouched, so "renew" means exactly what it says. Pass
|
|
113
|
+
* `refreshContent: true` for the explicit "update the snapshot from current
|
|
114
|
+
* data AND renew" action (the old implicit behavior). */
|
|
115
|
+
export declare function renewShareAction(db: DbDriver, slug: string, viewerBaseOverride?: string, opts?: {
|
|
116
|
+
refreshContent?: boolean;
|
|
117
|
+
}): Promise<CreatedShare>;
|
|
69
118
|
//# sourceMappingURL=share-actions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share-actions.d.ts","sourceRoot":"","sources":["../../../src/core/sync/share-actions.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"share-actions.d.ts","sourceRoot":"","sources":["../../../src/core/sync/share-actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,6 +38,10 @@ export interface BucketShareMeta {
|
|
|
38
38
|
key: string;
|
|
39
39
|
/** base64 salt (password shares); the link carries this, viewer derives the key. */
|
|
40
40
|
salt?: string;
|
|
41
|
+
/** epoch ms the snapshot CONTENT was last (re-)exported. Distinct from
|
|
42
|
+
* presign_exp: re-signing the link does not touch this. Older metas lack the
|
|
43
|
+
* field — readers fall back to created_at. */
|
|
44
|
+
content_updated_at?: number;
|
|
41
45
|
}
|
|
42
46
|
export interface BucketShareLink {
|
|
43
47
|
manifestUrl: string;
|
|
@@ -64,6 +68,16 @@ export declare function createBucketShare(db: DbDriver, opts: {
|
|
|
64
68
|
* stored per-share key, re-upload + re-presign, refresh meta.json. Works for
|
|
65
69
|
* password shares too (the key is stored master-encrypted). */
|
|
66
70
|
export declare function renewBucketShare(db: DbDriver, config: S3Config, slug: string, expiresSec?: number): Promise<BucketShareLink>;
|
|
71
|
+
/** Rewrite ONLY the presigned blob URLs inside a decrypted manifest — content
|
|
72
|
+
* untouched. Pure over the presign callback (unit-testable). */
|
|
73
|
+
export declare function refreshManifestUrls(manifest: ShareManifest, presign: (hash: string) => Promise<string>): Promise<ShareManifest>;
|
|
74
|
+
/** Re-presign an object-storage share WITHOUT touching its content: decrypt
|
|
75
|
+
* the stored manifest, refresh the embedded blob URLs, re-encrypt in place.
|
|
76
|
+
* No live data is read and no blob bytes are re-uploaded — recipients keep
|
|
77
|
+
* seeing the same snapshot (content_updated_at stays put). This is what
|
|
78
|
+
* "renew the link" means; re-exporting current data is a separate, explicit
|
|
79
|
+
* action (renewBucketShare). */
|
|
80
|
+
export declare function represignBucketShare(config: S3Config, slug: string, expiresSec?: number): Promise<BucketShareLink>;
|
|
67
81
|
/** List all object-storage shares in a bucket (decrypts each meta.json). */
|
|
68
82
|
export declare function listBucketShares(config: S3Config): Promise<BucketShareMeta[]>;
|
|
69
83
|
/** Delete a bucket share's objects. meta.json is deleted FIRST so the share
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share-export.d.ts","sourceRoot":"","sources":["../../../src/core/sync/share-export.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"share-export.d.ts","sourceRoot":"","sources":["../../../src/core/sync/share-export.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
import { escapeHtml } from "./html-escape.ts";
|
|
2
|
+
export { escapeHtml };
|
|
2
3
|
export interface RenderOpts {
|
|
3
4
|
/** Rewrite a `/blob/<hash>` URL to a reachable one (scoped endpoint or data URL). */
|
|
4
5
|
rewriteBlob?: (url: string) => string;
|
|
6
|
+
/** Resolve a `[[doc_x]]` internal reference to its current title. Absent (or
|
|
7
|
+
* returning null) the reference renders as its alias/id. Share pages render
|
|
8
|
+
* doclinks as inert text either way: auto-linking to the target's own share
|
|
9
|
+
* would extend one share's capability with another's. */
|
|
10
|
+
resolveDocLink?: (id: string) => {
|
|
11
|
+
title: string;
|
|
12
|
+
} | null;
|
|
5
13
|
}
|
|
6
14
|
/** Inline Markdown → HTML: a pure function of the shared tokenizer. Gaps are
|
|
7
15
|
* escaped text; each token maps to one tag shape (the parity test's oracle
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share-render.d.ts","sourceRoot":"","sources":["../../../src/core/sync/share-render.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"share-render.d.ts","sourceRoot":"","sources":["../../../src/core/sync/share-render.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,UAAU,EAAE,CAAC;AAEtB,MAAM,WAAW,UAAU;IACzB,qFAAqF;IACrF,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACtC;;;8DAG0D;IAC1D,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CAC3D;AAED;;mCAEmC;AACnC,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,CA8CvE;AAyBD,8DAA8D;AAC9D,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,UAAe,GAAG,MAAM,CA+JxE"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import type { RouteCtx } from "./routes.ts";
|
|
2
|
-
export
|
|
2
|
+
export interface ServeShareOpts {
|
|
3
|
+
/** Client IP — rate-limit fallback key for cookieless callers. */
|
|
4
|
+
ip?: string | null;
|
|
5
|
+
}
|
|
6
|
+
export declare function serveShare(req: Request, ctx: RouteCtx, opts?: ServeShareOpts): Promise<Response | null>;
|
|
3
7
|
//# sourceMappingURL=share-serve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"share-serve.d.ts","sourceRoot":"","sources":["../../../src/core/sync/share-serve.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"share-serve.d.ts","sourceRoot":"","sources":["../../../src/core/sync/share-serve.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAwC5C,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACpB;AAED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAmC1B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { DbDriver } from "../driver.ts";
|
|
2
|
+
/** Prefix marking an observation written because the controller's node-local
|
|
3
|
+
* share row (the capability secret) is missing. The reconciler clears it once
|
|
4
|
+
* the row reappears; surfaces show the channel as errored, never as revoked. */
|
|
5
|
+
export declare const CONTROLLER_STATE_MISSING = "controller_state_missing";
|
|
6
|
+
/** Apply synced desired-state changes whose node-local secret is owned here.
|
|
7
|
+
* Other devices may revoke an Edge link without receiving the account token:
|
|
8
|
+
* they sync desired_state=revoked; the controller performs teardown when it
|
|
9
|
+
* next comes online and records a local observation.
|
|
10
|
+
*
|
|
11
|
+
* Revocations are emitted on POSITIVE evidence only:
|
|
12
|
+
* - a replicated site tombstone (older clients delete sites without knowing
|
|
13
|
+
* about channels) revokes the orphaned channels;
|
|
14
|
+
* - an ABSENT site row means "not replicated here yet" and is left untouched;
|
|
15
|
+
* - a missing node-local share row is an error observation, not a revocation;
|
|
16
|
+
* - share expiry never revokes or deletes — serving refuses expired links,
|
|
17
|
+
* but the share stays manageable (renewable) per the status contract.
|
|
18
|
+
* The "revoked" observation likewise requires teardown evidence: an absent
|
|
19
|
+
* Room record is cleanup_pending, never a fabricated destroy confirmation. */
|
|
20
|
+
/** Reconcile without ever throwing: channel maintenance is LOCAL housekeeping
|
|
21
|
+
* and must not turn an otherwise-successful data sync (or an already-committed
|
|
22
|
+
* delete) into a reported failure. Returns the error message for callers that
|
|
23
|
+
* surface warnings, null on success. */
|
|
24
|
+
export declare function reconcileSiteChannelsQuietly(db: DbDriver): Promise<string | null>;
|
|
25
|
+
export declare function reconcileSiteChannels(db: DbDriver): Promise<void>;
|
|
26
|
+
//# sourceMappingURL=site-channel-reconcile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site-channel-reconcile.d.ts","sourceRoot":"","sources":["../../../src/core/sync/site-channel-reconcile.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAa7C;;gFAEgF;AAChF,eAAO,MAAM,wBAAwB,6BAA6B,CAAC;AAEnE;;;;;;;;;;;;;8EAa8E;AAC9E;;;wCAGwC;AACxC,wBAAsB,4BAA4B,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CASvF;AAED,wBAAsB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA2FvE"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { DbDriver } from "../driver.ts";
|
|
2
|
+
export interface SitePublishState {
|
|
3
|
+
siteId: string;
|
|
4
|
+
targetBase: string;
|
|
5
|
+
url: string;
|
|
6
|
+
status: "ready" | "syncing";
|
|
7
|
+
updatedAt: number;
|
|
8
|
+
}
|
|
9
|
+
/** Node-local safety record: a private rollback has been emitted locally but
|
|
10
|
+
* the target peer has not yet acknowledged a cursor that includes it. */
|
|
11
|
+
export interface PendingSiteRollback {
|
|
12
|
+
siteId: string;
|
|
13
|
+
peerUrl: string;
|
|
14
|
+
targetUrl: string;
|
|
15
|
+
requiredSeq: number;
|
|
16
|
+
createdAt: number;
|
|
17
|
+
lastError: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function listPendingSiteRollbacks(db: DbDriver): PendingSiteRollback[];
|
|
20
|
+
export declare function getPendingSiteRollback(db: DbDriver, siteId: string, peerUrl: string): PendingSiteRollback | null;
|
|
21
|
+
export declare function putPendingSiteRollback(db: DbDriver, pending: PendingSiteRollback): PendingSiteRollback;
|
|
22
|
+
export declare function updatePendingSiteRollbackError(db: DbDriver, siteId: string, peerUrl: string, error: string): PendingSiteRollback | null;
|
|
23
|
+
export declare function removePendingSiteRollback(db: DbDriver, siteId: string, peerUrl: string): boolean;
|
|
24
|
+
/** A successful HTTP-peer sync advances push_cursor to the highest local CRDT
|
|
25
|
+
* sequence included in the request. That cursor is the durable proof that the
|
|
26
|
+
* compensating private write reached the target. */
|
|
27
|
+
export declare function clearCoveredSiteRollbacks(db: DbDriver, peerUrl: string): number;
|
|
28
|
+
export declare function latestLocalSeq(db: DbDriver): number;
|
|
29
|
+
export declare function listSitePublishStates(db: DbDriver): SitePublishState[];
|
|
30
|
+
export declare function putSitePublishState(db: DbDriver, state: SitePublishState): SitePublishState;
|
|
31
|
+
export declare function removeSitePublishStates(db: DbDriver, siteId: string): number;
|
|
32
|
+
//# sourceMappingURL=site-publish-recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site-publish-recovery.d.ts","sourceRoot":"","sources":["../../../src/core/sync/site-publish-recovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAK7C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;yEACyE;AACzE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAmCD,wBAAgB,wBAAwB,CAAC,EAAE,EAAE,QAAQ,GAAG,mBAAmB,EAAE,CAE5E;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,mBAAmB,GAAG,IAAI,CAE5B;AAED,wBAAgB,sBAAsB,CACpC,EAAE,EAAE,QAAQ,EACZ,OAAO,EAAE,mBAAmB,GAC3B,mBAAmB,CAOrB;AAED,wBAAgB,8BAA8B,CAC5C,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,GACZ,mBAAmB,GAAG,IAAI,CAO5B;AAED,wBAAgB,yBAAyB,CACvC,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAMT;AAED;;oDAEoD;AACpD,wBAAgB,yBAAyB,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAW/E;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,CAKnD;AAkCD,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,QAAQ,GAAG,gBAAgB,EAAE,CAEtE;AAED,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,QAAQ,EACZ,KAAK,EAAE,gBAAgB,GACtB,gBAAgB,CAOlB;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAK5E"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { DbDriver } from "../driver.ts";
|
|
2
|
+
import { type SiteChannel, type SiteState } from "../site-channels.ts";
|
|
3
|
+
import { type SitePublicAccessState } from "../site-channel-store.ts";
|
|
4
|
+
export interface SiteReachability {
|
|
5
|
+
siteId: string;
|
|
6
|
+
visibility: "public" | "private";
|
|
7
|
+
state: SiteState;
|
|
8
|
+
channels: SiteChannel[];
|
|
9
|
+
/** Unified public-access decision (serve/config/anomaly) for this node. */
|
|
10
|
+
publicAccess: SitePublicAccessState;
|
|
11
|
+
}
|
|
12
|
+
export declare function siteReachability(db: DbDriver, siteId: string): SiteReachability;
|
|
13
|
+
//# sourceMappingURL=site-reachability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site-reachability.d.ts","sourceRoot":"","sources":["../../../src/core/sync/site-reachability.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7C,OAAO,EAGL,KAAK,WAAW,EAEhB,KAAK,SAAS,EACf,MAAM,qBAAqB,CAAC;AAM7B,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAC;IACjC,KAAK,EAAE,SAAS,CAAC;IACjB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,2EAA2E;IAC3E,YAAY,EAAE,qBAAqB,CAAC;CACrC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAkB/E"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sites-routes.d.ts","sourceRoot":"","sources":["../../../src/core/sync/sites-routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,KAAK,EAAiB,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"sites-routes.d.ts","sourceRoot":"","sources":["../../../src/core/sync/sites-routes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,KAAK,EAAiB,MAAM,aAAa,CAAC;AAoHvE,eAAO,MAAM,WAAW,EAAE,KAAK,EAmH9B,CAAC"}
|
|
@@ -1,3 +1,26 @@
|
|
|
1
|
+
import type { DbDriver } from "../driver.ts";
|
|
1
2
|
import type { RouteCtx } from "./routes.ts";
|
|
2
|
-
|
|
3
|
+
import { type AuthConfig } from "./auth.ts";
|
|
4
|
+
/** Host wiring serveSite can't do itself: the request's client IP (rate-limit
|
|
5
|
+
* key material) and an in-process forwarder into the main /api route table
|
|
6
|
+
* (token-holders under /sites/<name>/api/* get the FULL API). */
|
|
7
|
+
export interface ServeSiteOpts {
|
|
8
|
+
ip?: string | null;
|
|
9
|
+
forwardApi?: (req: Request) => Promise<Response>;
|
|
10
|
+
}
|
|
11
|
+
export declare function serveSite(req: Request, ctx: RouteCtx, auth: AuthConfig, opts?: ServeSiteOpts): Promise<Response | null>;
|
|
12
|
+
/**
|
|
13
|
+
* Serve one file of a resolved site: ETag/304 negotiation → decode → response
|
|
14
|
+
* with content-type + cache headers. Shared by /sites/<name>/ (above) and the
|
|
15
|
+
* token-exempt /share/<slug>/ site path (share-serve.ts) so both surfaces agree
|
|
16
|
+
* on caching and 404 behavior. This function never injects the runtime — the
|
|
17
|
+
* /sites/ caller adds it (withShim) only on the authenticated private branch.
|
|
18
|
+
* `isPublic` selects the Cache-Control scope: only a visibility:public site may
|
|
19
|
+
* pass true (share responses stay `private` always — the slug IS the
|
|
20
|
+
* capability and must never enter a shared cache).
|
|
21
|
+
*/
|
|
22
|
+
export declare function serveSiteFile(req: Request, db: DbDriver, siteId: string, path: string, opts?: {
|
|
23
|
+
spa?: boolean;
|
|
24
|
+
isPublic?: boolean;
|
|
25
|
+
}): Promise<Response>;
|
|
3
26
|
//# sourceMappingURL=sites-serve.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sites-serve.d.ts","sourceRoot":"","sources":["../../../src/core/sync/sites-serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"sites-serve.d.ts","sourceRoot":"","sources":["../../../src/core/sync/sites-serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAmB5C,OAAO,EACL,KAAK,UAAU,EAShB,MAAM,WAAW,CAAC;AAwBnB;;kEAEkE;AAClE,MAAM,WAAW,aAAa;IAC5B,EAAE,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CAClD;AAED,wBAAsB,SAAS,CAC7B,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,UAAU,EAChB,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA0G1B;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,OAAO,EACZ,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/C,OAAO,CAAC,QAAQ,CAAC,CA8BnB"}
|