···11--- Based on https://github.com/blacksky-algorithms/rsky/blob/main/rsky-pds/src/account_manager/helpers/account.rs
22--- blacksky-algorithms/rsky is licensed under the Apache License 2.0
33--- Modified for SQLite backend
44-/* Based heavily on account-manager, did-cache, sequencer, and actor-store migrations
55- from the canonical TS implementation. */
66-77--- account-manager implementation
88--- Create App Password Table
99-CREATE TABLE IF NOT EXISTS app_password (
1010- did character varying NOT NULL,
1111- name character varying NOT NULL,
1212- "password" character varying NOT NULL,
1313- "createdAt" character varying NOT NULL
1414-);
1515-1616-ALTER TABLE ONLY app_password
1717- DROP CONSTRAINT IF EXISTS app_password_pkey;
1818-ALTER TABLE ONLY app_password
1919- ADD CONSTRAINT app_password_pkey PRIMARY KEY (did, name);
2020-2121--- Create Invite Code Table
2222-CREATE TABLE IF NOT EXISTS invite_code (
2323- code character varying PRIMARY KEY,
2424- "availableUses" integer NOT NULL,
2525- disabled smallint NOT NULL DEFAULT 0,
2626- "forAccount" character varying NOT NULL,
2727- "createdBy" character varying NOT NULL,
2828- "createdAt" character varying NOT NULL
2929-);
3030-CREATE INDEX invite_code_for_user_idx
3131- ON invite_code("forAccount");
3232-3333--- Create Invite Code Use Table
3434-CREATE TABLE IF NOT EXISTS invite_code_use (
3535- code character varying NOT NULL,
3636- "usedBy" character varying NOT NULL,
3737- "usedAt" character varying NOT NULL
3838-);
3939-4040-ALTER TABLE ONLY invite_code_use
4141- DROP CONSTRAINT IF EXISTS invite_code_use_pkey;
4242-ALTER TABLE ONLY invite_code_use
4343- ADD CONSTRAINT invite_code_use_pkey PRIMARY KEY (code, "usedBy");
4444-4545--- Create Refresh Token Table
4646-CREATE TABLE IF NOT EXISTS refresh_token (
4747- id character varying PRIMARY KEY,
4848- did character varying NOT NULL,
4949- "expiresAt" character varying NOT NULL,
5050- "nextId" character varying,
5151- "appPasswordName" character varying
5252-);
5353-CREATE INDEX refresh_token_did_idx -- Aids in refresh token cleanup
5454- ON refresh_token(did);
5555-5656--- Create Actor Table
5757-CREATE TABLE IF NOT EXISTS actor (
5858- did character varying PRIMARY KEY,
5959- handle character varying,
6060- "createdAt" character varying NOT NULL,
6161- "takedownRef" character varying,
6262- "deactivatedAt" character varying,
6363- "deleteAfter" character varying
6464-);
6565-CREATE UNIQUE INDEX actor_handle_lower_idx
6666- ON actor (LOWER(handle));
6767-CREATE INDEX actor_cursor_idx
6868- ON actor("createdAt", did);
6969-7070--- Create Account Table
7171-CREATE TABLE IF NOT EXISTS account (
7272- did character varying PRIMARY KEY,
7373- email character varying NOT NULL,
7474- "recoveryKey" character varying, -- For storing Bring Your Own Key
7575- "password" character varying NOT NULL,
7676- "createdAt" character varying NOT NULL,
7777- "invitesDisabled" smallint NOT NULL DEFAULT 0,
7878- "emailConfirmedAt" character varying
7979-);
8080-CREATE UNIQUE INDEX account_email_lower_idx
8181- ON account (LOWER(email));
8282-CREATE INDEX account_cursor_idx
8383- ON account("createdAt", did);
8484-8585--- Create Email Token Table
8686-CREATE TABLE IF NOT EXISTS email_token (
8787- purpose character varying NOT NULL,
8888- did character varying NOT NULL,
8989- token character varying NOT NULL,
9090- "requestedAt" character varying NOT NULL
9191-);
9292-ALTER TABLE ONLY email_token
9393- DROP CONSTRAINT IF EXISTS email_token_pkey;
9494-ALTER TABLE ONLY email_token
9595- ADD CONSTRAINT email_token_pkey PRIMARY KEY (purpose, did);
9696-CREATE UNIQUE INDEX email_token_purpose_token_unique
9797- ON email_token (purpose, token);
9898-9999-100100--- actor-store implementation
101101--- Create Repo Root Table
102102-CREATE TABLE IF NOT EXISTS repo_root (
103103- did character varying PRIMARY KEY,
104104- cid character varying NOT NULL,
105105- rev character varying NOT NULL,
106106- "indexedAt" character varying NOT NULL
107107-);
108108-109109--- Create Repo Block Table
110110-CREATE TABLE IF NOT EXISTS repo_block (
111111- cid character varying NOT NULL,
112112- did character varying NOT NULL,
113113- "repoRev" character varying NOT NULL,
114114- size integer NOT NULL,
115115- content bytea NOT NULL
116116-);
117117-ALTER TABLE ONLY repo_block
118118- ADD CONSTRAINT repo_block_pkey PRIMARY KEY (cid, did);
119119-CREATE INDEX repo_block_repo_rev_idx
120120- ON repo_block("repoRev", cid);
121121-122122--- Create Record Table
123123-CREATE TABLE IF NOT EXISTS record (
124124- uri character varying PRIMARY KEY,
125125- cid character varying NOT NULL,
126126- did character varying NOT NULL,
127127- collection character varying NOT NULL,
128128- "rkey" character varying NOT NULL,
129129- "repoRev" character varying,
130130- "indexedAt" character varying NOT NULL,
131131- "takedownRef" character varying
132132-);
133133-CREATE INDEX record_did_cid_idx
134134- ON record(cid);
135135-CREATE INDEX record_did_collection_idx
136136- ON record(collection);
137137-CREATE INDEX record_repo_rev_idx
138138- ON record("repoRev");
139139-140140--- Create Blob Table
141141-CREATE TABLE IF NOT EXISTS blob (
142142- cid character varying NOT NULL,
143143- did character varying NOT NULL,
144144- "mimeType" character varying NOT NULL,
145145- size integer NOT NULL,
146146- "tempKey" character varying,
147147- width integer,
148148- height integer,
149149- "createdAt" character varying NOT NULL,
150150- "takedownRef" character varying
151151-);
152152-ALTER TABLE ONLY blob
153153- ADD CONSTRAINT blob_pkey PRIMARY KEY (cid, did);
154154-CREATE INDEX blob_tempkey_idx
155155- ON blob("tempKey");
156156-157157--- Create Record Blob Table
158158-CREATE TABLE IF NOT EXISTS record_blob (
159159- "blobCid" character varying NOT NULL,
160160- "recordUri" character varying NOT NULL,
161161- did character varying NOT NULL
162162-);
163163-ALTER TABLE ONLY record_blob
164164- DROP CONSTRAINT IF EXISTS record_blob_pkey;
165165-ALTER TABLE ONLY record_blob
166166- ADD CONSTRAINT record_blob_pkey PRIMARY KEY ("blobCid","recordUri");
167167-168168--- Create Backlink Table
169169-CREATE TABLE IF NOT EXISTS backlink (
170170- uri character varying NOT NULL,
171171- path character varying NOT NULL,
172172- "linkTo" character varying NOT NULL
173173-);
174174-ALTER TABLE ONLY backlink
175175- DROP CONSTRAINT IF EXISTS backlink_pkey;
176176-ALTER TABLE ONLY backlink
177177- ADD CONSTRAINT backlink_pkey PRIMARY KEY (uri, path);
178178-CREATE INDEX backlink_link_to_idx
179179- ON backlink(path, "linkTo");
180180-181181--- Create Account Preferences Table
182182-CREATE TABLE IF NOT EXISTS account_pref (
183183- id SERIAL PRIMARY KEY,
184184- did character varying NOT NULL,
185185- name character varying NOT NULL,
186186- "valueJson" text
187187-);
188188-189189--- did-cache implementation
190190--- Create DID Cache Table
191191-CREATE TABLE IF NOT EXISTS did_doc (
192192- did character varying PRIMARY KEY,
193193- doc text NOT NULL,
194194- "updatedAt" bigint NOT NULL
195195-);
196196-197197--- sequencer implementation
198198--- Create Repo Sequence Table
199199-CREATE TABLE IF NOT EXISTS repo_seq (
200200- seq bigserial PRIMARY KEY,
201201- did character varying NOT NULL,
202202- "eventType" character varying NOT NULL,
203203- event bytea NOT NULL,
204204- invalidated smallint NOT NULL DEFAULT 0,
205205- "sequencedAt" character varying NOT NULL
206206-);
207207-CREATE INDEX repo_seq_did_idx -- for filtering seqs based on did
208208- ON repo_seq(did);
209209-CREATE INDEX repo_seq_event_type_idx -- for filtering seqs based on event type
210210- ON repo_seq("eventType");
211211-CREATE INDEX repo_seq_sequenced_at_index -- for entering into the seq stream at a particular time
212212- ON repo_seq("sequencedAt");
213213-214214--- OAuth schema
215215-CREATE TABLE IF NOT EXISTS authorization_request
216216-(
217217- id character varying NOT NULL,
218218- did character varying,
219219- "deviceId" character varying,
220220- "clientId" character varying NOT NULL,
221221- "clientAuth" character varying NOT NULL,
222222- parameters character varying NOT NULL,
223223- "expiresAt" Timestamptz NOT NULL,
224224- code character varying
225225-);
226226-227227-ALTER TABLE ONLY authorization_request
228228- DROP CONSTRAINT IF EXISTS authorization_request_code_idx;
229229-ALTER TABLE ONLY authorization_request
230230- ADD CONSTRAINT authorization_request_code_idx PRIMARY KEY (id);
231231-232232--- TODO expires at index
233233-234234-CREATE TABLE IF NOT EXISTS device
235235-(
236236- id character varying NOT NULL,
237237- "sessionId" character varying unique,
238238- "userAgent" character varying,
239239- "ipAddress" character varying NOT NULL,
240240- "lastSeenAt" Timestamptz NOT NULL
241241-);
242242-243243-ALTER TABLE ONLY device
244244- DROP CONSTRAINT IF EXISTS pds_idx;
245245-ALTER TABLE ONLY device
246246- ADD CONSTRAINT pds_idx PRIMARY KEY (id);
247247-248248-CREATE TABLE IF NOT EXISTS device_account
249249-(
250250- did character varying NOT NULL,
251251- "deviceId" character varying NOT NULL,
252252- "authenticatedAt" Timestamptz NOT NULL,
253253- remember boolean NOT NULL,
254254- "authorizedClients" character varying NOT NULL
255255-);
256256-257257-ALTER TABLE ONLY device_account
258258- DROP CONSTRAINT IF EXISTS device_account_pk;
259259-ALTER TABLE ONLY device_account
260260- ADD CONSTRAINT device_account_pk PRIMARY KEY ("deviceId", did);
261261-262262---TODO add foreign key constraints
263263-264264-CREATE TABLE IF NOT EXISTS token
265265-(
266266- id character varying NOT NULL, --TODO
267267- did character varying NOT NULL,
268268- "tokenId" character varying NOT NULL unique,
269269- "createdAt" Timestamptz NOT NULL,
270270- "updatedAt" Timestamptz NOT NULL,
271271- "expiresAt" Timestamptz NOT NULL,
272272- "clientId" character varying NOT NULL,
273273- "clientAuth" character varying NOT NULL,
274274- "deviceId" character varying,
275275- parameters character varying NOT NULL,
276276- details character varying,
277277- code character varying,
278278- "currentRefreshToken" character varying unique
279279-);
280280-281281-ALTER TABLE ONLY token
282282- DROP CONSTRAINT IF EXISTS token_idx;
283283-ALTER TABLE ONLY token
284284- ADD CONSTRAINT token_idx PRIMARY KEY (id);
285285-286286-CREATE TABLE IF NOT EXISTS used_refresh_token
287287-(
288288- "refreshToken" character varying NOT NULL,
289289- "tokenId" character varying NOT NULL
290290-);
291291-292292-ALTER TABLE ONLY used_refresh_token
293293- DROP CONSTRAINT IF EXISTS used_refresh_token_pk;
294294-ALTER TABLE ONLY used_refresh_token
295295- ADD CONSTRAINT used_refresh_token_pk PRIMARY KEY ("refreshToken");
-7
migrations/20250104202448_init.down.sql
···11-DROP TABLE IF EXISTS invites;
22-33-DROP TABLE IF EXISTS handles;
44-55-DROP TABLE IF EXISTS accounts;
66-77-DROP TABLE IF EXISTS sessions;
-29
migrations/20250104202448_init.up.sql
···11-CREATE TABLE IF NOT EXISTS accounts (
22- did TEXT PRIMARY KEY NOT NULL,
33- email TEXT NOT NULL UNIQUE,
44- password TEXT NOT NULL,
55- root TEXT NOT NULL,
66- rev TEXT NOT NULL,
77- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
88-);
99-1010-CREATE TABLE IF NOT EXISTS handles (
1111- handle TEXT PRIMARY KEY NOT NULL,
1212- did TEXT NOT NULL,
1313- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
1414- FOREIGN KEY (did) REFERENCES accounts(did)
1515-);
1616-1717-CREATE TABLE IF NOT EXISTS invites (
1818- id TEXT PRIMARY KEY NOT NULL,
1919- did TEXT,
2020- count INTEGER NOT NULL DEFAULT 1,
2121- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
2222-);
2323-2424-CREATE TABLE IF NOT EXISTS sessions (
2525- id TEXT PRIMARY KEY NOT NULL,
2626- did TEXT NOT NULL,
2727- created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
2828- FOREIGN KEY (did) REFERENCES accounts(did)
2929-);
···11-CREATE TABLE IF NOT EXISTS blob_ref (
22- -- N.B: There is a hidden `rowid` field inserted by sqlite.
33- cid TEXT NOT NULL,
44- did TEXT NOT NULL,
55- record TEXT
66-);
···11-CREATE TABLE IF NOT EXISTS oauth_par_requests (
22- request_uri TEXT PRIMARY KEY NOT NULL,
33- client_id TEXT NOT NULL,
44- response_type TEXT NOT NULL,
55- code_challenge TEXT NOT NULL,
66- code_challenge_method TEXT NOT NULL,
77- state TEXT,
88- login_hint TEXT,
99- scope TEXT,
1010- redirect_uri TEXT,
1111- response_mode TEXT,
1212- display TEXT,
1313- created_at INTEGER NOT NULL,
1414- expires_at INTEGER NOT NULL
1515-);
1616-CREATE TABLE IF NOT EXISTS oauth_authorization_codes (
1717- code TEXT PRIMARY KEY NOT NULL,
1818- client_id TEXT NOT NULL,
1919- subject TEXT NOT NULL,
2020- code_challenge TEXT NOT NULL,
2121- code_challenge_method TEXT NOT NULL,
2222- redirect_uri TEXT NOT NULL,
2323- scope TEXT,
2424- created_at INTEGER NOT NULL,
2525- expires_at INTEGER NOT NULL,
2626- used BOOLEAN NOT NULL DEFAULT FALSE
2727-);
2828-CREATE TABLE IF NOT EXISTS oauth_refresh_tokens (
2929- token TEXT PRIMARY KEY NOT NULL,
3030- client_id TEXT NOT NULL,
3131- subject TEXT NOT NULL,
3232- dpop_thumbprint TEXT NOT NULL,
3333- scope TEXT,
3434- created_at INTEGER NOT NULL,
3535- expires_at INTEGER NOT NULL,
3636- revoked BOOLEAN NOT NULL DEFAULT FALSE
3737-);
-6
migrations/20250502032700_jti.down.sql
···11-DROP INDEX IF EXISTS idx_jtis_expires_at;
22-DROP INDEX IF EXISTS idx_refresh_tokens_expires_at;
33-DROP INDEX IF EXISTS idx_auth_codes_expires_at;
44-DROP INDEX IF EXISTS idx_par_expires_at;
55-66-DROP TABLE IF EXISTS oauth_used_jtis;
-13
migrations/20250502032700_jti.up.sql
···11--- Table for tracking used JTIs to prevent replay attacks
22-CREATE TABLE IF NOT EXISTS oauth_used_jtis (
33- jti TEXT PRIMARY KEY NOT NULL,
44- issuer TEXT NOT NULL,
55- created_at INTEGER NOT NULL,
66- expires_at INTEGER NOT NULL
77-);
88-99--- Create indexes for faster lookups and cleanup
1010-CREATE INDEX IF NOT EXISTS idx_par_expires_at ON oauth_par_requests(expires_at);
1111-CREATE INDEX IF NOT EXISTS idx_auth_codes_expires_at ON oauth_authorization_codes(expires_at);
1212-CREATE INDEX IF NOT EXISTS idx_refresh_tokens_expires_at ON oauth_refresh_tokens(expires_at);
1313-CREATE INDEX IF NOT EXISTS idx_jtis_expires_at ON oauth_used_jtis(expires_at);
-16
migrations/20250508251242_actor_store.down.sql
···11--- Drop indexes
22-DROP INDEX IF EXISTS idx_backlink_link_to;
33-DROP INDEX IF EXISTS idx_blob_tempkey;
44-DROP INDEX IF EXISTS idx_record_repo_rev;
55-DROP INDEX IF EXISTS idx_record_collection;
66-DROP INDEX IF EXISTS idx_record_cid;
77-DROP INDEX IF EXISTS idx_repo_block_repo_rev;
88-99--- Drop tables
1010-DROP TABLE IF EXISTS account_pref;
1111-DROP TABLE IF EXISTS backlink;
1212-DROP TABLE IF EXISTS record_blob;
1313-DROP TABLE IF EXISTS blob;
1414-DROP TABLE IF EXISTS record;
1515-DROP TABLE IF EXISTS repo_block;
1616-DROP TABLE IF EXISTS repo_root;
-70
migrations/20250508251242_actor_store.up.sql
···11--- Actor store schema matching TypeScript implementation
22-33--- Repository root information
44-CREATE TABLE IF NOT EXISTS repo_root (
55- did TEXT PRIMARY KEY NOT NULL,
66- cid TEXT NOT NULL,
77- rev TEXT NOT NULL,
88- indexedAt TEXT NOT NULL
99-);
1010-1111--- Repository blocks (IPLD blocks)
1212-CREATE TABLE IF NOT EXISTS repo_block (
1313- cid TEXT PRIMARY KEY NOT NULL,
1414- repoRev TEXT NOT NULL,
1515- size INTEGER NOT NULL,
1616- content BLOB NOT NULL
1717-);
1818-1919--- Record index
2020-CREATE TABLE IF NOT EXISTS record (
2121- uri TEXT PRIMARY KEY NOT NULL,
2222- cid TEXT NOT NULL,
2323- collection TEXT NOT NULL,
2424- rkey TEXT NOT NULL,
2525- repoRev TEXT NOT NULL,
2626- indexedAt TEXT NOT NULL,
2727- takedownRef TEXT
2828-);
2929-3030--- Blob storage metadata
3131-CREATE TABLE IF NOT EXISTS blob (
3232- cid TEXT PRIMARY KEY NOT NULL,
3333- mimeType TEXT NOT NULL,
3434- size INTEGER NOT NULL,
3535- tempKey TEXT,
3636- width INTEGER,
3737- height INTEGER,
3838- createdAt TEXT NOT NULL,
3939- takedownRef TEXT
4040-);
4141-4242--- Record-blob associations
4343-CREATE TABLE IF NOT EXISTS record_blob (
4444- blobCid TEXT NOT NULL,
4545- recordUri TEXT NOT NULL,
4646- PRIMARY KEY (blobCid, recordUri)
4747-);
4848-4949--- Backlinks between records
5050-CREATE TABLE IF NOT EXISTS backlink (
5151- uri TEXT NOT NULL,
5252- path TEXT NOT NULL,
5353- linkTo TEXT NOT NULL,
5454- PRIMARY KEY (uri, path)
5555-);
5656-5757--- User preferences
5858-CREATE TABLE IF NOT EXISTS account_pref (
5959- id INTEGER PRIMARY KEY AUTOINCREMENT,
6060- name TEXT NOT NULL,
6161- valueJson TEXT NOT NULL
6262-);
6363-6464--- Create indexes
6565-CREATE INDEX IF NOT EXISTS idx_repo_block_repo_rev ON repo_block(repoRev, cid);
6666-CREATE INDEX IF NOT EXISTS idx_record_cid ON record(cid);
6767-CREATE INDEX IF NOT EXISTS idx_record_collection ON record(collection);
6868-CREATE INDEX IF NOT EXISTS idx_record_repo_rev ON record(repoRev);
6969-CREATE INDEX IF NOT EXISTS idx_blob_tempkey ON blob(tempKey);
7070-CREATE INDEX IF NOT EXISTS idx_backlink_link_to ON backlink(path, linkTo);
-15
migrations/20250508252057_blockstore.up.sql
···11- CREATE TABLE IF NOT EXISTS blocks (
22- cid TEXT PRIMARY KEY NOT NULL,
33- data BLOB NOT NULL,
44- multicodec INTEGER NOT NULL,
55- multihash INTEGER NOT NULL
66- );
77- CREATE TABLE IF NOT EXISTS tree_nodes (
88- repo_did TEXT NOT NULL,
99- key TEXT NOT NULL,
1010- value_cid TEXT NOT NULL,
1111- PRIMARY KEY (repo_did, key),
1212- FOREIGN KEY (value_cid) REFERENCES blocks(cid)
1313- );
1414- CREATE INDEX IF NOT EXISTS idx_blocks_cid ON blocks(cid);
1515- CREATE INDEX IF NOT EXISTS idx_tree_nodes_repo ON tree_nodes(repo_did);
-5
migrations/20250510222500_actor_migration.up.sql
···11-CREATE TABLE IF NOT EXISTS actor_migration (
22- id INTEGER PRIMARY KEY AUTOINCREMENT,
33- name TEXT NOT NULL,
44- appliedAt TEXT NOT NULL
55-);