was-teaching-server 0.9.1
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/CHANGELOG.md +1432 -0
- package/LICENSE +661 -0
- package/README.md +305 -0
- package/common/css/materialize.1.0.0.min.css +13 -0
- package/dist/auth-header-hooks.d.ts +84 -0
- package/dist/auth-header-hooks.d.ts.map +1 -0
- package/dist/auth-header-hooks.js +136 -0
- package/dist/auth-header-hooks.js.map +1 -0
- package/dist/authorize.d.ts +45 -0
- package/dist/authorize.d.ts.map +1 -0
- package/dist/authorize.js +76 -0
- package/dist/authorize.js.map +1 -0
- package/dist/backends/filesystem.d.ts +1179 -0
- package/dist/backends/filesystem.d.ts.map +1 -0
- package/dist/backends/filesystem.js +2727 -0
- package/dist/backends/filesystem.js.map +1 -0
- package/dist/backends/postgres.d.ts +833 -0
- package/dist/backends/postgres.d.ts.map +1 -0
- package/dist/backends/postgres.js +2164 -0
- package/dist/backends/postgres.js.map +1 -0
- package/dist/backends/postgresSchema.d.ts +36 -0
- package/dist/backends/postgresSchema.d.ts.map +1 -0
- package/dist/backends/postgresSchema.js +203 -0
- package/dist/backends/postgresSchema.js.map +1 -0
- package/dist/config.default.d.ts +360 -0
- package/dist/config.default.d.ts.map +1 -0
- package/dist/config.default.js +493 -0
- package/dist/config.default.js.map +1 -0
- package/dist/corsProxy.d.ts +45 -0
- package/dist/corsProxy.d.ts.map +1 -0
- package/dist/corsProxy.js +278 -0
- package/dist/corsProxy.js.map +1 -0
- package/dist/digest.d.ts +45 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +174 -0
- package/dist/digest.js.map +1 -0
- package/dist/errors.d.ts +654 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +960 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/atomicFile.d.ts +61 -0
- package/dist/lib/atomicFile.d.ts.map +1 -0
- package/dist/lib/atomicFile.js +150 -0
- package/dist/lib/atomicFile.js.map +1 -0
- package/dist/lib/backendRegistry.d.ts +59 -0
- package/dist/lib/backendRegistry.d.ts.map +1 -0
- package/dist/lib/backendRegistry.js +92 -0
- package/dist/lib/backendRegistry.js.map +1 -0
- package/dist/lib/backendUsage.d.ts +28 -0
- package/dist/lib/backendUsage.d.ts.map +1 -0
- package/dist/lib/backendUsage.js +55 -0
- package/dist/lib/backendUsage.js.map +1 -0
- package/dist/lib/backends.d.ts +142 -0
- package/dist/lib/backends.d.ts.map +1 -0
- package/dist/lib/backends.js +272 -0
- package/dist/lib/backends.js.map +1 -0
- package/dist/lib/blindedIndex.d.ts +156 -0
- package/dist/lib/blindedIndex.d.ts.map +1 -0
- package/dist/lib/blindedIndex.js +338 -0
- package/dist/lib/blindedIndex.js.map +1 -0
- package/dist/lib/collectionDescription.d.ts +33 -0
- package/dist/lib/collectionDescription.d.ts.map +1 -0
- package/dist/lib/collectionDescription.js +21 -0
- package/dist/lib/collectionDescription.js.map +1 -0
- package/dist/lib/cursor.d.ts +18 -0
- package/dist/lib/cursor.d.ts.map +1 -0
- package/dist/lib/cursor.js +50 -0
- package/dist/lib/cursor.js.map +1 -0
- package/dist/lib/edvEnvelope.d.ts +50 -0
- package/dist/lib/edvEnvelope.d.ts.map +1 -0
- package/dist/lib/edvEnvelope.js +106 -0
- package/dist/lib/edvEnvelope.js.map +1 -0
- package/dist/lib/encryption.d.ts +192 -0
- package/dist/lib/encryption.d.ts.map +1 -0
- package/dist/lib/encryption.js +383 -0
- package/dist/lib/encryption.js.map +1 -0
- package/dist/lib/etag.d.ts +33 -0
- package/dist/lib/etag.d.ts.map +1 -0
- package/dist/lib/etag.js +36 -0
- package/dist/lib/etag.js.map +1 -0
- package/dist/lib/exportManifest.d.ts +29 -0
- package/dist/lib/exportManifest.d.ts.map +1 -0
- package/dist/lib/exportManifest.js +77 -0
- package/dist/lib/exportManifest.js.map +1 -0
- package/dist/lib/importTar.d.ts +81 -0
- package/dist/lib/importTar.d.ts.map +1 -0
- package/dist/lib/importTar.js +301 -0
- package/dist/lib/importTar.js.map +1 -0
- package/dist/lib/isJson.d.ts +16 -0
- package/dist/lib/isJson.d.ts.map +1 -0
- package/dist/lib/isJson.js +17 -0
- package/dist/lib/isJson.js.map +1 -0
- package/dist/lib/keyEpoch.d.ts +38 -0
- package/dist/lib/keyEpoch.d.ts.map +1 -0
- package/dist/lib/keyEpoch.js +75 -0
- package/dist/lib/keyEpoch.js.map +1 -0
- package/dist/lib/keyedMutex.d.ts +28 -0
- package/dist/lib/keyedMutex.d.ts.map +1 -0
- package/dist/lib/keyedMutex.js +45 -0
- package/dist/lib/keyedMutex.js.map +1 -0
- package/dist/lib/kmsModule.d.ts +62 -0
- package/dist/lib/kmsModule.d.ts.map +1 -0
- package/dist/lib/kmsModule.js +327 -0
- package/dist/lib/kmsModule.js.map +1 -0
- package/dist/lib/kmsRecordCipher.d.ts +82 -0
- package/dist/lib/kmsRecordCipher.d.ts.map +1 -0
- package/dist/lib/kmsRecordCipher.js +226 -0
- package/dist/lib/kmsRecordCipher.js.map +1 -0
- package/dist/lib/pagination.d.ts +19 -0
- package/dist/lib/pagination.d.ts.map +1 -0
- package/dist/lib/pagination.js +21 -0
- package/dist/lib/pagination.js.map +1 -0
- package/dist/lib/paths.d.ts +273 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +270 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/preconditions.d.ts +65 -0
- package/dist/lib/preconditions.d.ts.map +1 -0
- package/dist/lib/preconditions.js +112 -0
- package/dist/lib/preconditions.js.map +1 -0
- package/dist/lib/resourceFileName.d.ts +41 -0
- package/dist/lib/resourceFileName.d.ts.map +1 -0
- package/dist/lib/resourceFileName.js +58 -0
- package/dist/lib/resourceFileName.js.map +1 -0
- package/dist/lib/revocations.d.ts +49 -0
- package/dist/lib/revocations.d.ts.map +1 -0
- package/dist/lib/revocations.js +86 -0
- package/dist/lib/revocations.js.map +1 -0
- package/dist/lib/validateDid.d.ts +19 -0
- package/dist/lib/validateDid.d.ts.map +1 -0
- package/dist/lib/validateDid.js +35 -0
- package/dist/lib/validateDid.js.map +1 -0
- package/dist/lib/validateId.d.ts +66 -0
- package/dist/lib/validateId.d.ts.map +1 -0
- package/dist/lib/validateId.js +126 -0
- package/dist/lib/validateId.js.map +1 -0
- package/dist/plugin.d.ts +115 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +134 -0
- package/dist/plugin.js.map +1 -0
- package/dist/policy.d.ts +78 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +115 -0
- package/dist/policy.js.map +1 -0
- package/dist/provisioning.d.ts +38 -0
- package/dist/provisioning.d.ts.map +1 -0
- package/dist/provisioning.js +72 -0
- package/dist/provisioning.js.map +1 -0
- package/dist/requests/BackendRequest.d.ts +61 -0
- package/dist/requests/BackendRequest.d.ts.map +1 -0
- package/dist/requests/BackendRequest.js +152 -0
- package/dist/requests/BackendRequest.js.map +1 -0
- package/dist/requests/CollectionRequest.d.ts +234 -0
- package/dist/requests/CollectionRequest.d.ts.map +1 -0
- package/dist/requests/CollectionRequest.js +705 -0
- package/dist/requests/CollectionRequest.js.map +1 -0
- package/dist/requests/KeyRequest.d.ts +115 -0
- package/dist/requests/KeyRequest.d.ts.map +1 -0
- package/dist/requests/KeyRequest.js +468 -0
- package/dist/requests/KeyRequest.js.map +1 -0
- package/dist/requests/KeystoreRequest.d.ts +99 -0
- package/dist/requests/KeystoreRequest.d.ts.map +1 -0
- package/dist/requests/KeystoreRequest.js +247 -0
- package/dist/requests/KeystoreRequest.js.map +1 -0
- package/dist/requests/PolicyRequest.d.ts +53 -0
- package/dist/requests/PolicyRequest.d.ts.map +1 -0
- package/dist/requests/PolicyRequest.js +124 -0
- package/dist/requests/PolicyRequest.js.map +1 -0
- package/dist/requests/ResourceRequest.d.ts +134 -0
- package/dist/requests/ResourceRequest.d.ts.map +1 -0
- package/dist/requests/ResourceRequest.js +548 -0
- package/dist/requests/ResourceRequest.js.map +1 -0
- package/dist/requests/RevocationRequest.d.ts +67 -0
- package/dist/requests/RevocationRequest.d.ts.map +1 -0
- package/dist/requests/RevocationRequest.js +187 -0
- package/dist/requests/RevocationRequest.js.map +1 -0
- package/dist/requests/SpaceRequest.d.ts +204 -0
- package/dist/requests/SpaceRequest.d.ts.map +1 -0
- package/dist/requests/SpaceRequest.js +520 -0
- package/dist/requests/SpaceRequest.js.map +1 -0
- package/dist/requests/SpacesRepositoryRequest.d.ts +50 -0
- package/dist/requests/SpacesRepositoryRequest.d.ts.map +1 -0
- package/dist/requests/SpacesRepositoryRequest.js +159 -0
- package/dist/requests/SpacesRepositoryRequest.js.map +1 -0
- package/dist/requests/collectionContext.d.ts +21 -0
- package/dist/requests/collectionContext.d.ts.map +1 -0
- package/dist/requests/collectionContext.js +30 -0
- package/dist/requests/collectionContext.js.map +1 -0
- package/dist/requests/controllerConsent.d.ts +58 -0
- package/dist/requests/controllerConsent.d.ts.map +1 -0
- package/dist/requests/controllerConsent.js +73 -0
- package/dist/requests/controllerConsent.js.map +1 -0
- package/dist/requests/keystoreContext.d.ts +68 -0
- package/dist/requests/keystoreContext.d.ts.map +1 -0
- package/dist/requests/keystoreContext.js +87 -0
- package/dist/requests/keystoreContext.js.map +1 -0
- package/dist/requests/resourceInput.d.ts +19 -0
- package/dist/requests/resourceInput.d.ts.map +1 -0
- package/dist/requests/resourceInput.js +102 -0
- package/dist/requests/resourceInput.js.map +1 -0
- package/dist/requests/spaceContext.d.ts +127 -0
- package/dist/requests/spaceContext.d.ts.map +1 -0
- package/dist/requests/spaceContext.js +201 -0
- package/dist/requests/spaceContext.js.map +1 -0
- package/dist/routes.d.ts +55 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +306 -0
- package/dist/routes.js.map +1 -0
- package/dist/server.d.ts +20 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +60 -0
- package/dist/server.js.map +1 -0
- package/dist/start.d.ts +7 -0
- package/dist/start.d.ts.map +1 -0
- package/dist/start.js +61 -0
- package/dist/start.js.map +1 -0
- package/dist/storage.d.ts +29 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +47 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.d.ts +915 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/views/home.hbs +9 -0
- package/dist/views/templates/main.hbs +12 -0
- package/dist/zcap.d.ts +267 -0
- package/dist/zcap.d.ts.map +1 -0
- package/dist/zcap.js +478 -0
- package/dist/zcap.js.map +1 -0
- package/package.json +109 -0
- package/src/auth-header-hooks.ts +163 -0
- package/src/authorize.ts +117 -0
- package/src/backends/filesystem.ts +3626 -0
- package/src/backends/postgres.ts +3073 -0
- package/src/backends/postgresSchema.ts +231 -0
- package/src/config.default.ts +657 -0
- package/src/corsProxy.ts +326 -0
- package/src/declarations.d.ts +28 -0
- package/src/digest.ts +223 -0
- package/src/errors.ts +1122 -0
- package/src/index.ts +21 -0
- package/src/lib/atomicFile.ts +176 -0
- package/src/lib/backendRegistry.ts +139 -0
- package/src/lib/backendUsage.ts +79 -0
- package/src/lib/backends.ts +351 -0
- package/src/lib/blindedIndex.ts +466 -0
- package/src/lib/collectionDescription.ts +43 -0
- package/src/lib/cursor.ts +52 -0
- package/src/lib/edvEnvelope.ts +120 -0
- package/src/lib/encryption.ts +472 -0
- package/src/lib/etag.ts +40 -0
- package/src/lib/exportManifest.ts +115 -0
- package/src/lib/importTar.ts +381 -0
- package/src/lib/isJson.ts +18 -0
- package/src/lib/keyEpoch.ts +89 -0
- package/src/lib/keyedMutex.ts +45 -0
- package/src/lib/kmsModule.ts +451 -0
- package/src/lib/kmsRecordCipher.ts +292 -0
- package/src/lib/pagination.ts +22 -0
- package/src/lib/paths.ts +382 -0
- package/src/lib/preconditions.ts +145 -0
- package/src/lib/resourceFileName.ts +69 -0
- package/src/lib/revocations.ts +116 -0
- package/src/lib/validateDid.ts +41 -0
- package/src/lib/validateId.ts +148 -0
- package/src/plugin.ts +288 -0
- package/src/policy.ts +176 -0
- package/src/provisioning.ts +98 -0
- package/src/requests/BackendRequest.ts +219 -0
- package/src/requests/CollectionRequest.ts +899 -0
- package/src/requests/KeyRequest.ts +617 -0
- package/src/requests/KeystoreRequest.ts +325 -0
- package/src/requests/PolicyRequest.ts +169 -0
- package/src/requests/ResourceRequest.ts +649 -0
- package/src/requests/RevocationRequest.ts +267 -0
- package/src/requests/SpaceRequest.ts +686 -0
- package/src/requests/SpacesRepositoryRequest.ts +194 -0
- package/src/requests/collectionContext.ts +41 -0
- package/src/requests/controllerConsent.ts +108 -0
- package/src/requests/keystoreContext.ts +124 -0
- package/src/requests/resourceInput.ts +118 -0
- package/src/requests/spaceContext.ts +311 -0
- package/src/routes.ts +420 -0
- package/src/server.ts +69 -0
- package/src/start.ts +71 -0
- package/src/storage.ts +60 -0
- package/src/types.ts +1016 -0
- package/src/views/home.hbs +9 -0
- package/src/views/templates/main.hbs +12 -0
- package/src/zcap.ts +657 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostgreSQL schema for the `PostgresBackend`: an ordered list of migration
|
|
3
|
+
* scripts plus the tiny hand-rolled runner that applies them idempotently
|
|
4
|
+
* (inside an advisory-locked transaction) on backend `init()`. The whole
|
|
5
|
+
* schema is readable in this one file; there is no external migration tool.
|
|
6
|
+
*
|
|
7
|
+
* Collation note: every identifier or ISO-8601 timestamp column that
|
|
8
|
+
* participates in an `ORDER BY` or keyset `>` comparison is declared
|
|
9
|
+
* `COLLATE "C"` (byte order, which for UTF-8 is code-point order) so Postgres
|
|
10
|
+
* ordering agrees with the JS code-unit comparisons the filesystem backend and
|
|
11
|
+
* the pagination cursors use. (The two orders could theoretically diverge for
|
|
12
|
+
* supplementary-plane characters -- unreachable here because the request layer
|
|
13
|
+
* validates ids as URL-safe ASCII.) Timestamps are stored as the fixed-width
|
|
14
|
+
* ISO-8601 strings the wire model uses (`new Date().toISOString()`), not
|
|
15
|
+
* `timestamptz`, so change-feed checkpoints round-trip byte-identically.
|
|
16
|
+
*/
|
|
17
|
+
import type pg from 'pg'
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Ordered migration scripts. Version `n` is `MIGRATIONS[n - 1]`; append only,
|
|
21
|
+
* never edit an applied entry.
|
|
22
|
+
*/
|
|
23
|
+
export const MIGRATIONS: string[] = [
|
|
24
|
+
// v1: the full WAS + WebKMS surface.
|
|
25
|
+
`
|
|
26
|
+
-- The Spaces tree. 'description' is NULL for a placeholder row created by a
|
|
27
|
+
-- write below the Space level (a resource/policy write to a Space whose
|
|
28
|
+
-- description was never written) -- the analogue of a Space directory
|
|
29
|
+
-- without a '.space.' file; getSpaceDescription treats it as absent.
|
|
30
|
+
-- 'usage_bytes' is the transactional quota counter (spec "Quotas"),
|
|
31
|
+
-- maintained in the same transaction as every content write and delete.
|
|
32
|
+
CREATE TABLE spaces (
|
|
33
|
+
space_id text COLLATE "C" PRIMARY KEY,
|
|
34
|
+
description jsonb,
|
|
35
|
+
usage_bytes bigint NOT NULL DEFAULT 0
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
CREATE TABLE collections (
|
|
39
|
+
space_id text COLLATE "C" NOT NULL
|
|
40
|
+
REFERENCES spaces ON DELETE CASCADE,
|
|
41
|
+
collection_id text COLLATE "C" NOT NULL,
|
|
42
|
+
description jsonb,
|
|
43
|
+
PRIMARY KEY (space_id, collection_id)
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
-- One row per Resource, live or tombstoned. 'content' is the byte-for-byte
|
|
47
|
+
-- representation (JSON stored as its serialized UTF-8 bytes, NOT jsonb --
|
|
48
|
+
-- jsonb normalization would break byte fidelity); NULL on a tombstone.
|
|
49
|
+
-- 'content_type' records the last-known type on a tombstone. 'version' /
|
|
50
|
+
-- 'meta_version' are the two ETag validators; 'custom' is the user-writable
|
|
51
|
+
-- metadata (or the opaque encryption envelope on an encrypted Collection).
|
|
52
|
+
CREATE TABLE resources (
|
|
53
|
+
space_id text COLLATE "C" NOT NULL,
|
|
54
|
+
collection_id text COLLATE "C" NOT NULL,
|
|
55
|
+
resource_id text COLLATE "C" NOT NULL,
|
|
56
|
+
content_type text NOT NULL,
|
|
57
|
+
content bytea,
|
|
58
|
+
is_json boolean NOT NULL,
|
|
59
|
+
size_bytes bigint NOT NULL DEFAULT 0,
|
|
60
|
+
version integer NOT NULL,
|
|
61
|
+
meta_version integer,
|
|
62
|
+
custom jsonb,
|
|
63
|
+
deleted boolean NOT NULL DEFAULT false,
|
|
64
|
+
created_at text COLLATE "C" NOT NULL,
|
|
65
|
+
updated_at text COLLATE "C" NOT NULL,
|
|
66
|
+
PRIMARY KEY (space_id, collection_id, resource_id),
|
|
67
|
+
FOREIGN KEY (space_id, collection_id)
|
|
68
|
+
REFERENCES collections ON DELETE CASCADE
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
-- The changes-feed keyset: (updatedAt, resourceId) ascending within a
|
|
72
|
+
-- collection. Also serves the tie-broken seek.
|
|
73
|
+
CREATE INDEX resources_changes_idx
|
|
74
|
+
ON resources (space_id, collection_id, updated_at, resource_id);
|
|
75
|
+
|
|
76
|
+
-- Policies for all three levels in one table; '' sentinel columns keep the
|
|
77
|
+
-- primary key total (Postgres PKs reject NULL). Space policy: ('', '');
|
|
78
|
+
-- collection policy: (cid, ''); resource policy: (cid, rid).
|
|
79
|
+
CREATE TABLE policies (
|
|
80
|
+
space_id text COLLATE "C" NOT NULL
|
|
81
|
+
REFERENCES spaces ON DELETE CASCADE,
|
|
82
|
+
collection_id text COLLATE "C" NOT NULL DEFAULT '',
|
|
83
|
+
resource_id text COLLATE "C" NOT NULL DEFAULT '',
|
|
84
|
+
policy jsonb NOT NULL,
|
|
85
|
+
PRIMARY KEY (space_id, collection_id, resource_id)
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
-- Registered external backend records; 'record' is the full secret-bearing
|
|
89
|
+
-- StoredBackendRecord (same custody posture as the filesystem file).
|
|
90
|
+
CREATE TABLE backend_records (
|
|
91
|
+
space_id text COLLATE "C" NOT NULL REFERENCES spaces ON DELETE CASCADE,
|
|
92
|
+
backend_id text COLLATE "C" NOT NULL,
|
|
93
|
+
record jsonb NOT NULL,
|
|
94
|
+
PRIMARY KEY (space_id, backend_id)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
-- WebKMS facet: a sibling tree to spaces, exactly as on the filesystem.
|
|
98
|
+
-- 'controller' / 'sequence' / 'kms_module' are denormalized from the
|
|
99
|
+
-- verbatim config for the list filter and the update gates.
|
|
100
|
+
CREATE TABLE keystores (
|
|
101
|
+
keystore_id text COLLATE "C" PRIMARY KEY,
|
|
102
|
+
controller text NOT NULL,
|
|
103
|
+
sequence integer NOT NULL,
|
|
104
|
+
kms_module text NOT NULL,
|
|
105
|
+
config jsonb NOT NULL
|
|
106
|
+
);
|
|
107
|
+
CREATE INDEX keystores_controller_idx ON keystores (controller);
|
|
108
|
+
|
|
109
|
+
-- 'record' is the opaque (possibly envelope-encrypted above the backend)
|
|
110
|
+
-- KmsKeyRecord, stored verbatim; the primary key is the create-only gate.
|
|
111
|
+
CREATE TABLE kms_keys (
|
|
112
|
+
keystore_id text COLLATE "C" NOT NULL
|
|
113
|
+
REFERENCES keystores ON DELETE CASCADE,
|
|
114
|
+
local_id text COLLATE "C" NOT NULL,
|
|
115
|
+
record jsonb NOT NULL,
|
|
116
|
+
PRIMARY KEY (keystore_id, local_id)
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
-- 'expires' is meta.expires (the GC horizon), NULL = never.
|
|
120
|
+
CREATE TABLE revocations (
|
|
121
|
+
keystore_id text COLLATE "C" NOT NULL
|
|
122
|
+
REFERENCES keystores ON DELETE CASCADE,
|
|
123
|
+
delegator text COLLATE "C" NOT NULL,
|
|
124
|
+
capability_id text COLLATE "C" NOT NULL,
|
|
125
|
+
record jsonb NOT NULL,
|
|
126
|
+
expires text COLLATE "C",
|
|
127
|
+
PRIMARY KEY (keystore_id, delegator, capability_id)
|
|
128
|
+
);
|
|
129
|
+
`,
|
|
130
|
+
// v2: denormalize a Space's controller onto its own column for the Spaces
|
|
131
|
+
// count quota (spec "Quotas"). The controller also lives inside 'description'
|
|
132
|
+
// (description->>'controller'), but a dedicated, indexed column keeps the
|
|
133
|
+
// per-controller COUNT(*) cheap and lockable. Backfill from existing rows;
|
|
134
|
+
// writeSpace maintains it on every insert and update.
|
|
135
|
+
`
|
|
136
|
+
ALTER TABLE spaces ADD COLUMN controller text;
|
|
137
|
+
UPDATE spaces SET controller = description->>'controller';
|
|
138
|
+
CREATE INDEX spaces_controller_idx ON spaces (controller);
|
|
139
|
+
`,
|
|
140
|
+
// v3: record a Resource's creator -- the DID of the invoker of its FIRST
|
|
141
|
+
// content write, set once and preserved verbatim thereafter (the spec's
|
|
142
|
+
// OPTIONAL `createdBy`). NULL for a pre-existing row and for one written by
|
|
143
|
+
// a caller with no resolved invoker. Not `COLLATE "C"`: unlike `created_at` /
|
|
144
|
+
// `updated_at`, this column never participates in an `ORDER BY` or keyset
|
|
145
|
+
// comparison.
|
|
146
|
+
`
|
|
147
|
+
ALTER TABLE resources ADD COLUMN created_by text;
|
|
148
|
+
`,
|
|
149
|
+
// v4: Space-scoped zcap revocations -- the WAS route families' sibling of the
|
|
150
|
+
// keystore-scoped `revocations` table above. A separate table (rather than a
|
|
151
|
+
// nullable-FK union over one table) lets each keep its own `ON DELETE CASCADE`
|
|
152
|
+
// to its parent and its own composite primary key; deleting a Space here
|
|
153
|
+
// deletes its revocations. Columns mirror `revocations`, with 'space_id'
|
|
154
|
+
// referencing the spaces tree in place of 'keystore_id'.
|
|
155
|
+
`
|
|
156
|
+
CREATE TABLE space_revocations (
|
|
157
|
+
space_id text COLLATE "C" NOT NULL REFERENCES spaces ON DELETE CASCADE,
|
|
158
|
+
delegator text COLLATE "C" NOT NULL,
|
|
159
|
+
capability_id text COLLATE "C" NOT NULL,
|
|
160
|
+
record jsonb NOT NULL,
|
|
161
|
+
expires text COLLATE "C",
|
|
162
|
+
PRIMARY KEY (space_id, delegator, capability_id)
|
|
163
|
+
);
|
|
164
|
+
`,
|
|
165
|
+
// v5: the client-declared key epoch a Resource's content was encrypted under
|
|
166
|
+
// (multi-recipient encrypted Collections). Stored opaquely: the server never
|
|
167
|
+
// computes or verifies it. NULL when no epoch was declared (a plaintext
|
|
168
|
+
// Collection, or an encrypted write that omitted the stamp). Not `COLLATE "C"`
|
|
169
|
+
// -- it never participates in an `ORDER BY` or keyset comparison.
|
|
170
|
+
`
|
|
171
|
+
ALTER TABLE resources ADD COLUMN epoch text;
|
|
172
|
+
`,
|
|
173
|
+
// v6: the monotonic Collection Description version -- the ETag validator behind
|
|
174
|
+
// conditional (`If-Match`) Collection Description writes, so concurrent
|
|
175
|
+
// recipient edits compare-and-swap instead of clobbering. Kept out of the
|
|
176
|
+
// stored 'description' jsonb (it travels only as the `ETag` header). Backfill
|
|
177
|
+
// existing rows to 1; writeCollection bumps it on every write.
|
|
178
|
+
`
|
|
179
|
+
ALTER TABLE collections ADD COLUMN description_version integer NOT NULL DEFAULT 1;
|
|
180
|
+
`
|
|
181
|
+
]
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Applies any not-yet-applied migrations, inside a transaction holding a
|
|
185
|
+
* schema-scoped advisory lock so concurrent server instances sharing one
|
|
186
|
+
* database serialize their startup migration runs. Idempotent: applied
|
|
187
|
+
* versions are recorded in `schema_migrations` and skipped on the next run.
|
|
188
|
+
* @param options {object}
|
|
189
|
+
* @param options.client {pg.PoolClient} a dedicated client (not the pool);
|
|
190
|
+
* the caller is responsible for releasing it
|
|
191
|
+
* @returns {Promise<void>}
|
|
192
|
+
*/
|
|
193
|
+
export async function applyMigrations({
|
|
194
|
+
client
|
|
195
|
+
}: {
|
|
196
|
+
client: pg.PoolClient
|
|
197
|
+
}): Promise<void> {
|
|
198
|
+
await client.query('BEGIN')
|
|
199
|
+
try {
|
|
200
|
+
// Scope the advisory lock to the active schema so parallel test schemas
|
|
201
|
+
// in one database do not serialize against each other.
|
|
202
|
+
await client.query(
|
|
203
|
+
`SELECT pg_advisory_xact_lock(hashtext(current_schema() || ':was-migrations'))`
|
|
204
|
+
)
|
|
205
|
+
await client.query(`
|
|
206
|
+
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
207
|
+
version integer PRIMARY KEY,
|
|
208
|
+
applied_at timestamptz NOT NULL DEFAULT now()
|
|
209
|
+
)
|
|
210
|
+
`)
|
|
211
|
+
const { rows } = await client.query<{ version: number }>(
|
|
212
|
+
'SELECT version FROM schema_migrations'
|
|
213
|
+
)
|
|
214
|
+
const applied = new Set(rows.map(row => row.version))
|
|
215
|
+
for (let index = 0; index < MIGRATIONS.length; index++) {
|
|
216
|
+
const version = index + 1
|
|
217
|
+
if (applied.has(version)) {
|
|
218
|
+
continue
|
|
219
|
+
}
|
|
220
|
+
await client.query(MIGRATIONS[index]!)
|
|
221
|
+
await client.query(
|
|
222
|
+
'INSERT INTO schema_migrations (version) VALUES ($1)',
|
|
223
|
+
[version]
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
await client.query('COMMIT')
|
|
227
|
+
} catch (err) {
|
|
228
|
+
await client.query('ROLLBACK')
|
|
229
|
+
throw err
|
|
230
|
+
}
|
|
231
|
+
}
|