@ifc-lite/collab-server 0.2.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth.d.ts +2 -0
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +3 -1
- package/dist/auth.js.map +1 -1
- package/dist/bin.js +102 -2
- package/dist/bin.js.map +1 -1
- package/dist/blob-route.d.ts +24 -0
- package/dist/blob-route.d.ts.map +1 -1
- package/dist/blob-route.js +82 -0
- package/dist/blob-route.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/layer-registry-route.d.ts +46 -0
- package/dist/layer-registry-route.d.ts.map +1 -0
- package/dist/layer-registry-route.js +503 -0
- package/dist/layer-registry-route.js.map +1 -0
- package/dist/layer-registry.d.ts +69 -0
- package/dist/layer-registry.d.ts.map +1 -0
- package/dist/layer-registry.js +119 -0
- package/dist/layer-registry.js.map +1 -0
- package/dist/room-manager.d.ts +16 -0
- package/dist/room-manager.d.ts.map +1 -1
- package/dist/room-manager.js +29 -0
- package/dist/room-manager.js.map +1 -1
- package/dist/room-token.d.ts +160 -0
- package/dist/room-token.d.ts.map +1 -0
- package/dist/room-token.js +387 -0
- package/dist/room-token.js.map +1 -0
- package/dist/server.d.ts +60 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +130 -0
- package/dist/server.js.map +1 -1
- package/package.json +4 -2
package/dist/auth.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface Principal {
|
|
|
15
15
|
meta?: Record<string, unknown>;
|
|
16
16
|
}
|
|
17
17
|
export type AuthenticateFn = (token: string | undefined, roomId: string) => Promise<Principal | null> | Principal | null;
|
|
18
|
+
/** The sentinel identity minted by `allowAnonymousEditor` — not a real credential. */
|
|
19
|
+
export declare const ANONYMOUS_USER_ID = "anonymous";
|
|
18
20
|
/** Default: anonymous editor, useful for local dev. */
|
|
19
21
|
export declare const allowAnonymousEditor: AuthenticateFn;
|
|
20
22
|
/** Default: hard-deny. Apps that don't supply an auth hook get this. */
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,MAAM,MAAM,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/D,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,MAAM,cAAc,GAAG,CAC3B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;AAElD,uDAAuD;AACvD,eAAO,MAAM,oBAAoB,EAAE,cAGjC,CAAC;AAEH,wEAAwE;AACxE,eAAO,MAAM,OAAO,EAAE,cAA2B,CAAC;AAElD,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAEtD"}
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AAEH,MAAM,MAAM,IAAI,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE/D,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,gFAAgF;IAChF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED,MAAM,MAAM,cAAc,GAAG,CAC3B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;AAElD,sFAAsF;AACtF,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAE7C,uDAAuD;AACvD,eAAO,MAAM,oBAAoB,EAAE,cAGjC,CAAC;AAEH,wEAAwE;AACxE,eAAO,MAAM,OAAO,EAAE,cAA2B,CAAC;AAElD,iEAAiE;AACjE,wBAAgB,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAEtD"}
|
package/dist/auth.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/** The sentinel identity minted by `allowAnonymousEditor` — not a real credential. */
|
|
5
|
+
export const ANONYMOUS_USER_ID = 'anonymous';
|
|
4
6
|
/** Default: anonymous editor, useful for local dev. */
|
|
5
7
|
export const allowAnonymousEditor = (_token, _room) => ({
|
|
6
|
-
userId:
|
|
8
|
+
userId: ANONYMOUS_USER_ID,
|
|
7
9
|
role: 'editor',
|
|
8
10
|
});
|
|
9
11
|
/** Default: hard-deny. Apps that don't supply an auth hook get this. */
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AA0B/D,uDAAuD;AACvD,MAAM,CAAC,MAAM,oBAAoB,GAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IACtE,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AA0B/D,sFAAsF;AACtF,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAE7C,uDAAuD;AACvD,MAAM,CAAC,MAAM,oBAAoB,GAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IACtE,MAAM,EAAE,iBAAiB;IACzB,IAAI,EAAE,QAAQ;CACf,CAAC,CAAC;AAEH,wEAAwE;AACxE,MAAM,CAAC,MAAM,OAAO,GAAmB,GAAG,EAAE,CAAC,IAAI,CAAC;AAElD,iEAAiE;AACjE,MAAM,UAAU,QAAQ,CAAC,SAAoB;IAC3C,OAAO,SAAS,CAAC,IAAI,KAAK,QAAQ,IAAI,SAAS,CAAC,IAAI,KAAK,OAAO,CAAC;AACnE,CAAC"}
|
package/dist/bin.js
CHANGED
|
@@ -3,20 +3,120 @@
|
|
|
3
3
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
4
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
5
5
|
/** CLI entry point: `ifc-lite-collab-server`. */
|
|
6
|
+
import * as fs from 'node:fs';
|
|
7
|
+
import * as path from 'node:path';
|
|
6
8
|
import { FilePersistence, startCollabServer } from './server.js';
|
|
7
|
-
|
|
9
|
+
import { FsBlobStorage } from './blob-route.js';
|
|
10
|
+
import { createRoomTokenAuthenticator, verifyRoomToken } from './room-token.js';
|
|
11
|
+
// `PORT` is the convention most hosts inject (Railway, Render, Fly, …).
|
|
12
|
+
const port = Number(process.env.COLLAB_PORT ?? process.env.PORT ?? 1234);
|
|
8
13
|
const host = process.env.COLLAB_HOST ?? '0.0.0.0';
|
|
9
14
|
const dataDir = process.env.COLLAB_DATA_DIR ?? './.collab-data';
|
|
10
15
|
const maxRooms = Number(process.env.COLLAB_MAX_ROOMS ?? 1024);
|
|
16
|
+
// Link-based access control is enabled by setting a signing secret. Without it
|
|
17
|
+
// the server stays open (anonymous editor) — fine for local/dev, see auth.ts.
|
|
18
|
+
const tokenSecret = process.env.COLLAB_TOKEN_SECRET;
|
|
19
|
+
/**
|
|
20
|
+
* Accountless room access control:
|
|
21
|
+
* - Joins require a valid signed room token (role is tamper-proof + revocable).
|
|
22
|
+
* - The *first* token minted for a brand-new room makes its requester admin
|
|
23
|
+
* (room creation / first-touch). Afterwards only an admin token for that
|
|
24
|
+
* room may mint further links — so a link's holder can't escalate.
|
|
25
|
+
* - Admins can revoke a link by `jti` (deny-list).
|
|
26
|
+
*/
|
|
27
|
+
function tokenOptions(secret, dir) {
|
|
28
|
+
// Persist the revocation deny-list + claimed-room set to disk so they survive
|
|
29
|
+
// restarts. Without this, a restart (a) forgets revocations and (b) lets the
|
|
30
|
+
// first POST /collab/token for an already-claimed persisted room take it over
|
|
31
|
+
// with a fresh admin token. (Needs a durable volume to actually persist.)
|
|
32
|
+
const statePath = path.join(dir, 'access-control.json');
|
|
33
|
+
const revoked = new Set();
|
|
34
|
+
const claimedRooms = new Set();
|
|
35
|
+
try {
|
|
36
|
+
const parsed = JSON.parse(fs.readFileSync(statePath, 'utf8'));
|
|
37
|
+
for (const j of parsed.revoked ?? [])
|
|
38
|
+
revoked.add(j);
|
|
39
|
+
for (const r of parsed.claimedRooms ?? [])
|
|
40
|
+
claimedRooms.add(r);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
if (err.code !== 'ENOENT') {
|
|
44
|
+
// eslint-disable-next-line no-console
|
|
45
|
+
console.warn('[collab-server] could not read access-control state:', err);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const persist = () => {
|
|
49
|
+
try {
|
|
50
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
51
|
+
fs.writeFileSync(statePath, JSON.stringify({ revoked: [...revoked], claimedRooms: [...claimedRooms] }));
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
// eslint-disable-next-line no-console
|
|
55
|
+
console.warn('[collab-server] could not persist access-control state:', err);
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
return {
|
|
59
|
+
authenticate: createRoomTokenAuthenticator({ secret, isRevoked: (jti) => revoked.has(jti) }),
|
|
60
|
+
// Blobs are content-addressed and NOT room-scoped, but the default blob
|
|
61
|
+
// authorizer reuses the WS `authenticate` with a pseudo-room scope — which
|
|
62
|
+
// a room-bound token can never match. Verify signature/expiry/revocation
|
|
63
|
+
// without the room binding instead; writes additionally need editor/admin.
|
|
64
|
+
authorizeBlob: (token, method) => {
|
|
65
|
+
const claims = verifyRoomToken(token ?? '', { secret });
|
|
66
|
+
if (!claims || revoked.has(claims.jti))
|
|
67
|
+
return false;
|
|
68
|
+
if (method === 'PUT' || method === 'DELETE') {
|
|
69
|
+
return claims.role === 'editor' || claims.role === 'admin';
|
|
70
|
+
}
|
|
71
|
+
return true;
|
|
72
|
+
},
|
|
73
|
+
tokenEndpoint: {
|
|
74
|
+
secret,
|
|
75
|
+
// A revoked bearer (e.g. a kicked admin) is treated as absent before the
|
|
76
|
+
// authorize policy even runs; the policy's own check below is defense in
|
|
77
|
+
// depth for custom deployments that omit `isRevoked`.
|
|
78
|
+
isRevoked: (jti) => revoked.has(jti),
|
|
79
|
+
authorize: (request, { bearerClaims }) => {
|
|
80
|
+
const room = request.roomId;
|
|
81
|
+
// A revoked bearer must not be able to keep minting links, even though
|
|
82
|
+
// its signature + expiry still verify.
|
|
83
|
+
if (bearerClaims?.jti && revoked.has(bearerClaims.jti))
|
|
84
|
+
return null;
|
|
85
|
+
if (bearerClaims?.room === room && bearerClaims.role === 'admin')
|
|
86
|
+
return request.role;
|
|
87
|
+
if (!claimedRooms.has(room)) {
|
|
88
|
+
claimedRooms.add(room);
|
|
89
|
+
persist();
|
|
90
|
+
return 'admin'; // creator of a fresh room
|
|
91
|
+
}
|
|
92
|
+
return null; // claimed room + non-admin caller → denied
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
revokeEndpoint: {
|
|
96
|
+
secret,
|
|
97
|
+
isRevoked: (jti) => revoked.has(jti),
|
|
98
|
+
recordRevocation: (jti) => {
|
|
99
|
+
revoked.add(jti);
|
|
100
|
+
persist();
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
kickEndpoint: { secret, isRevoked: (jti) => revoked.has(jti) },
|
|
104
|
+
};
|
|
105
|
+
}
|
|
11
106
|
async function main() {
|
|
12
107
|
const handle = await startCollabServer({
|
|
13
108
|
port,
|
|
14
109
|
host,
|
|
15
110
|
persistence: new FilePersistence({ dataDir }),
|
|
111
|
+
// Disk-backed blobs (not the in-RAM default): mesh blobs dominate a room's
|
|
112
|
+
// size, so keeping them in memory made memory the top hosting cost and lost
|
|
113
|
+
// them on restart. On a mounted volume this is durable and far cheaper.
|
|
114
|
+
blobStorage: new FsBlobStorage(dataDir),
|
|
16
115
|
maxRooms,
|
|
116
|
+
...(tokenSecret ? tokenOptions(tokenSecret, dataDir) : {}),
|
|
17
117
|
});
|
|
18
118
|
// eslint-disable-next-line no-console
|
|
19
|
-
console.log(`[collab-server] listening at ${handle.url} (data: ${dataDir})`);
|
|
119
|
+
console.log(`[collab-server] listening at ${handle.url} (data: ${dataDir}, auth: ${tokenSecret ? 'room-token' : 'anonymous'})`);
|
|
20
120
|
const shutdown = async () => {
|
|
21
121
|
// eslint-disable-next-line no-console
|
|
22
122
|
console.log('[collab-server] shutting down…');
|
package/dist/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":";AACA;;+DAE+D;AAE/D,iDAAiD;AAEjD,OAAO,EAAE,eAAe,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"bin.js","sourceRoot":"","sources":["../src/bin.ts"],"names":[],"mappings":"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"}
|
package/dist/blob-route.d.ts
CHANGED
|
@@ -42,6 +42,30 @@ export declare class InMemoryBlobStorage implements ServerBlobStorage {
|
|
|
42
42
|
delete(hash: string): Promise<boolean>;
|
|
43
43
|
list(): Promise<string[]>;
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Disk-backed storage — one file per blob under `<dataDir>/blobs/<hash>`.
|
|
47
|
+
*
|
|
48
|
+
* Mesh blobs are the bulk of a room's data; keeping them in RAM
|
|
49
|
+
* (`InMemoryBlobStorage`) made memory the dominant hosting cost AND lost every
|
|
50
|
+
* blob on restart (orphaning the doc's geometry refs). Disk is far cheaper per
|
|
51
|
+
* GB than memory on a mounted volume, and durable. Content-addressed, so writes
|
|
52
|
+
* are idempotent. `hash` is validated as 32 hex chars by the route before it
|
|
53
|
+
* reaches here, so it's safe as a filename (no traversal).
|
|
54
|
+
*/
|
|
55
|
+
export declare class FsBlobStorage implements ServerBlobStorage {
|
|
56
|
+
private readonly dir;
|
|
57
|
+
private readonly ready;
|
|
58
|
+
constructor(dataDir: string);
|
|
59
|
+
private file;
|
|
60
|
+
put(hash: string, bytes: Uint8Array, contentType?: string): Promise<ServerBlobMeta>;
|
|
61
|
+
get(hash: string): Promise<{
|
|
62
|
+
bytes: Uint8Array;
|
|
63
|
+
meta: ServerBlobMeta;
|
|
64
|
+
} | null>;
|
|
65
|
+
has(hash: string): Promise<boolean>;
|
|
66
|
+
delete(hash: string): Promise<boolean>;
|
|
67
|
+
list(): Promise<string[]>;
|
|
68
|
+
}
|
|
45
69
|
/**
|
|
46
70
|
* Authorizer for blob requests. Returns `true` to allow the operation,
|
|
47
71
|
* `false` to reject with 401. `method` is the HTTP verb, `hash` is the
|
package/dist/blob-route.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blob-route.d.ts","sourceRoot":"","sources":["../src/blob-route.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"blob-route.d.ts","sourceRoot":"","sources":["../src/blob-route.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAKlC,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACpF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IAC/E,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAC3B;AAED,kDAAkD;AAClD,qBAAa,mBAAoB,YAAW,iBAAiB;IAC3D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAkE;IAElF,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAUnF,GAAG,CAAC,IAAI,EAAE,MAAM;;;;IAIhB,GAAG,CAAC,IAAI,EAAE,MAAM;IAGhB,MAAM,CAAC,IAAI,EAAE,MAAM;IAGnB,IAAI;CAGX;AAKD;;;;;;;;;GASG;AACH,qBAAa,aAAc,YAAW,iBAAiB;IACrD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgB;gBAE1B,OAAO,EAAE,MAAM;IAK3B,OAAO,CAAC,IAAI;IAIN,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAgBnF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,IAAI,EAAE,cAAc,CAAA;KAAE,GAAG,IAAI,CAAC;IAe9E,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUnC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWtC,IAAI,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAMhC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG,CAC5B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,GAAG,SAAS,KACrB,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAEhC,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAgBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAM5B"}
|
package/dist/blob-route.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
4
|
import * as crypto from 'node:crypto';
|
|
5
|
+
import * as fs from 'node:fs';
|
|
6
|
+
import * as path from 'node:path';
|
|
5
7
|
/** In-memory storage. Default for tests + dev. */
|
|
6
8
|
export class InMemoryBlobStorage {
|
|
7
9
|
blobs = new Map();
|
|
@@ -31,6 +33,86 @@ export class InMemoryBlobStorage {
|
|
|
31
33
|
}
|
|
32
34
|
/** Match exactly 32 lowercase hex chars (the client's `fnv128` output). */
|
|
33
35
|
const HASH_REGEX = /^[a-f0-9]{32}$/;
|
|
36
|
+
/**
|
|
37
|
+
* Disk-backed storage — one file per blob under `<dataDir>/blobs/<hash>`.
|
|
38
|
+
*
|
|
39
|
+
* Mesh blobs are the bulk of a room's data; keeping them in RAM
|
|
40
|
+
* (`InMemoryBlobStorage`) made memory the dominant hosting cost AND lost every
|
|
41
|
+
* blob on restart (orphaning the doc's geometry refs). Disk is far cheaper per
|
|
42
|
+
* GB than memory on a mounted volume, and durable. Content-addressed, so writes
|
|
43
|
+
* are idempotent. `hash` is validated as 32 hex chars by the route before it
|
|
44
|
+
* reaches here, so it's safe as a filename (no traversal).
|
|
45
|
+
*/
|
|
46
|
+
export class FsBlobStorage {
|
|
47
|
+
dir;
|
|
48
|
+
ready;
|
|
49
|
+
constructor(dataDir) {
|
|
50
|
+
this.dir = path.join(dataDir, 'blobs');
|
|
51
|
+
this.ready = fs.promises.mkdir(this.dir, { recursive: true }).then(() => undefined);
|
|
52
|
+
}
|
|
53
|
+
file(hash) {
|
|
54
|
+
return path.join(this.dir, hash);
|
|
55
|
+
}
|
|
56
|
+
async put(hash, bytes, contentType) {
|
|
57
|
+
await this.ready;
|
|
58
|
+
const file = this.file(hash);
|
|
59
|
+
// Atomic write (temp + rename) so a concurrent/interrupted PUT of the same
|
|
60
|
+
// content-addressed blob can't leave a torn file.
|
|
61
|
+
const tmp = `${file}.tmp-${crypto.randomUUID()}`;
|
|
62
|
+
await fs.promises.writeFile(tmp, bytes);
|
|
63
|
+
await fs.promises.rename(tmp, file);
|
|
64
|
+
return {
|
|
65
|
+
hash,
|
|
66
|
+
byteLength: bytes.byteLength,
|
|
67
|
+
contentType,
|
|
68
|
+
uploadedAt: new Date().toISOString(),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async get(hash) {
|
|
72
|
+
await this.ready;
|
|
73
|
+
try {
|
|
74
|
+
const file = this.file(hash);
|
|
75
|
+
const [bytes, stat] = await Promise.all([fs.promises.readFile(file), fs.promises.stat(file)]);
|
|
76
|
+
return {
|
|
77
|
+
bytes: new Uint8Array(bytes),
|
|
78
|
+
meta: { hash, byteLength: stat.size, uploadedAt: stat.mtime.toISOString() },
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
if (err.code === 'ENOENT')
|
|
83
|
+
return null;
|
|
84
|
+
throw err;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async has(hash) {
|
|
88
|
+
await this.ready;
|
|
89
|
+
try {
|
|
90
|
+
await fs.promises.access(this.file(hash));
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async delete(hash) {
|
|
98
|
+
await this.ready;
|
|
99
|
+
try {
|
|
100
|
+
await fs.promises.unlink(this.file(hash));
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
if (err.code === 'ENOENT')
|
|
105
|
+
return false;
|
|
106
|
+
throw err;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async list() {
|
|
110
|
+
await this.ready;
|
|
111
|
+
const names = await fs.promises.readdir(this.dir);
|
|
112
|
+
// Exclude in-flight temp files; only return real content-addressed blobs.
|
|
113
|
+
return names.filter((n) => HASH_REGEX.test(n));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
34
116
|
/**
|
|
35
117
|
* Lift the auth credential from a request: prefer the `Authorization:
|
|
36
118
|
* Bearer <token>` header, fall back to a `?token=` query param (matching
|
package/dist/blob-route.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blob-route.js","sourceRoot":"","sources":["../src/blob-route.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAmB/D,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"blob-route.js","sourceRoot":"","sources":["../src/blob-route.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { startCollabServer, FilePersistence, MemoryPersistence, type StartCollabServerOptions, type CollabServerHandle, } from './server.js';
|
|
1
|
+
export { startCollabServer, FilePersistence, MemoryPersistence, type StartCollabServerOptions, type CollabServerHandle, type CorsOptions, } from './server.js';
|
|
2
2
|
export { type Persistence, type FilePersistenceOptions, } from './persistence.js';
|
|
3
3
|
export { S3Persistence, type S3PersistenceOptions, type S3LikeClient, type S3Commands, } from './persistence-s3.js';
|
|
4
4
|
export { RedisPersistence, type RedisPersistenceOptions, type RedisLikeClient, } from './persistence-redis.js';
|
|
@@ -14,5 +14,8 @@ export { applySecurityHeaders, createSecureHttpServer, secureHttpHandler, type S
|
|
|
14
14
|
export { startSecureCollabServer, type StartSecureCollabServerOptions, } from './secure-bundle.js';
|
|
15
15
|
export { createPathLockRegistry, harvestUpdatePaths, verifyAgainstPathLocks, type PathLock, type PathLockRegistry, } from './path-locks.js';
|
|
16
16
|
export { createRateLimiter, type RateLimitOptions, type RateLimiter, } from './rate-limit.js';
|
|
17
|
-
export { InMemoryBlobStorage, handleBlobRequest, type ServerBlobStorage, type ServerBlobMeta, type BlobRouteOptions, type BlobAuthorizeFn, } from './blob-route.js';
|
|
17
|
+
export { InMemoryBlobStorage, FsBlobStorage, handleBlobRequest, type ServerBlobStorage, type ServerBlobMeta, type BlobRouteOptions, type BlobAuthorizeFn, } from './blob-route.js';
|
|
18
|
+
export { signRoomToken, verifyRoomToken, createRoomTokenAuthenticator, handleTokenMintRequest, handleRevokeRequest, handleKickRequest, type RoomTokenClaims, type SecretResolver, type SignRoomTokenOptions, type VerifyRoomTokenOptions, type RoomTokenAuthenticatorOptions, type TokenEndpointOptions, type RevokeEndpointOptions, type KickEndpointOptions, type MintRequestBody, } from './room-token.js';
|
|
19
|
+
export { LayerPushError, MemoryLayerRegistry, type LayerRegistryStore, type RegistryReview, type RegistryReviewDecision, type RegistryReviewStatus, } from './layer-registry.js';
|
|
20
|
+
export { handleLayerRegistryRequest, type LayerRegistryRouteOptions, type RegistryAuthorizeFn, } from './layer-registry-route.js';
|
|
18
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -15,5 +15,8 @@ export { applySecurityHeaders, createSecureHttpServer, secureHttpHandler, } from
|
|
|
15
15
|
export { startSecureCollabServer, } from './secure-bundle.js';
|
|
16
16
|
export { createPathLockRegistry, harvestUpdatePaths, verifyAgainstPathLocks, } from './path-locks.js';
|
|
17
17
|
export { createRateLimiter, } from './rate-limit.js';
|
|
18
|
-
export { InMemoryBlobStorage, handleBlobRequest, } from './blob-route.js';
|
|
18
|
+
export { InMemoryBlobStorage, FsBlobStorage, handleBlobRequest, } from './blob-route.js';
|
|
19
|
+
export { signRoomToken, verifyRoomToken, createRoomTokenAuthenticator, handleTokenMintRequest, handleRevokeRequest, handleKickRequest, } from './room-token.js';
|
|
20
|
+
export { LayerPushError, MemoryLayerRegistry, } from './layer-registry.js';
|
|
21
|
+
export { handleLayerRegistryRequest, } from './layer-registry-route.js';
|
|
19
22
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,GAIlB,MAAM,aAAa,CAAC;AAKrB,OAAO,EACL,aAAa,GAId,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,gBAAgB,GAGjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAIL,oBAAoB,EACpB,OAAO,EACP,QAAQ,GACT,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,IAAI,EACJ,WAAW,GAIZ,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,SAAS,GAKV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,iBAAiB,EACjB,cAAc,EACd,aAAa,GAGd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,GAGf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,eAAe,EACf,cAAc,GAEf,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,GAK1B,MAAM,qBAAqB,CAAC;AAK7B,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,GAElB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,uBAAuB,GAExB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,sBAAsB,GAGvB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,iBAAiB,GAGlB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,iBAAiB,GAKlB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,aAAa,EACb,eAAe,EACf,4BAA4B,EAC5B,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,GAUlB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,cAAc,EACd,mBAAmB,GAKpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,0BAA0B,GAG3B,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP layer-registry route (10-registry.md): push/pull content-addressed
|
|
3
|
+
* layers by id, a ref database with server-side policy enforcement, and
|
|
4
|
+
* review (PR) objects.
|
|
5
|
+
*
|
|
6
|
+
* POST /api/v1/layers push (id verified server-side)
|
|
7
|
+
* GET /api/v1/layers list ids
|
|
8
|
+
* GET /api/v1/layers/:id pull
|
|
9
|
+
* GET /api/v1/refs list refs + policies
|
|
10
|
+
* PUT /api/v1/refs/:name create / move / protect
|
|
11
|
+
* POST /api/v1/refs/:name/merge shared merge flow, policies enforced
|
|
12
|
+
* POST /api/v1/reviews open a review (PR object)
|
|
13
|
+
* GET /api/v1/reviews[/:id] read review(s)
|
|
14
|
+
* POST /api/v1/reviews/:id/feedback per-entity decisions + status
|
|
15
|
+
*
|
|
16
|
+
* Policy-bearing refs cannot be moved by PUT — only the merge endpoint
|
|
17
|
+
* moves them, which is where required checks and approval rules run.
|
|
18
|
+
* Authentication mirrors the blob route: the websocket `authenticate`
|
|
19
|
+
* hook is adapted into an authorizer, so one token scheme covers sync,
|
|
20
|
+
* blobs, and the registry.
|
|
21
|
+
*
|
|
22
|
+
* v1 visibility: any authenticated principal reads ALL layers and refs
|
|
23
|
+
* (team-scoped registry); per-ref/per-layer visibility is the
|
|
24
|
+
* public/internal/private roadmap work (10 §10.5). Approval is a
|
|
25
|
+
* point-in-time check — the lookup and the merge run synchronously in
|
|
26
|
+
* one request, but an approval withdrawn after a merge completed does
|
|
27
|
+
* not un-merge it.
|
|
28
|
+
*/
|
|
29
|
+
import * as http from 'node:http';
|
|
30
|
+
import { type Principal } from './auth.js';
|
|
31
|
+
import { type LayerRegistryStore } from './layer-registry.js';
|
|
32
|
+
/** Resolve the acting principal, or null to reject with 401. */
|
|
33
|
+
export type RegistryAuthorizeFn = (token: string | undefined, method: string) => Promise<Principal | null> | Principal | null;
|
|
34
|
+
export interface LayerRegistryRouteOptions {
|
|
35
|
+
registry: LayerRegistryStore;
|
|
36
|
+
/** Reject layer pushes over this size (default 50 MB). */
|
|
37
|
+
maxBytes?: number;
|
|
38
|
+
/** When omitted, traffic is anonymous (dev/tests) — matches the blob route. */
|
|
39
|
+
authorize?: RegistryAuthorizeFn;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Handle a registry request. Returns false (untouched response) when the
|
|
43
|
+
* path is not a registry path, true when a response was written.
|
|
44
|
+
*/
|
|
45
|
+
export declare function handleLayerRegistryRequest(req: http.IncomingMessage, res: http.ServerResponse, opts: LayerRegistryRouteOptions): Promise<boolean>;
|
|
46
|
+
//# sourceMappingURL=layer-registry-route.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layer-registry-route.d.ts","sourceRoot":"","sources":["../src/layer-registry-route.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAMlC,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAEL,KAAK,kBAAkB,EAGxB,MAAM,qBAAqB,CAAC;AAE7B,gEAAgE;AAChE,MAAM,MAAM,mBAAmB,GAAG,CAChC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,KACX,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC;AAElD,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+EAA+E;IAC/E,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC;AAkGD;;;GAGG;AACH,wBAAsB,0BAA0B,CAC9C,GAAG,EAAE,IAAI,CAAC,eAAe,EACzB,GAAG,EAAE,IAAI,CAAC,cAAc,EACxB,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,OAAO,CAAC,CA4XlB"}
|