Architecture

Guide for contributors working on HappyView itself. For a user-facing overview, see the Introduction.

System overview

Queries go through the query handler to the database (SQLite by default, or Postgres). Writes go through the procedure handler to the user's PDS, then HappyView indexes the record locally. Real-time record events stream in via Jetstream; historical records are backfilled in-process by discovering repos via the relay's listReposByCollection and fetching records directly from each PDS. Labelers are external services that emit content labels over a direct WebSocket connection — they operate out-of-band, outside the relay/repo system. Spaces provide permissioned data containers with membership-gated access, per-user repo state tracking (LtHash + signed commits), and cross-service credential-based authentication.

Request flow

Reads (queries)

Writes (procedures)

Admin endpoints

Data flow

Real-time indexing

Backfill

Database schema

records

ColumnTypeDescription
uritext (PK)AT URI (at://did/collection/rkey)
didtextAuthor DID
collectiontextLexicon NSID
rkeytextRecord key
recordjsonbRecord value
cidtextContent identifier
indexed_attimestamptzWhen HappyView indexed this record

lexicons

ColumnTypeDescription
idtext (PK)Lexicon NSID
revisionintegerIncremented on upsert
lexicon_jsonjsonbRaw lexicon definition
lexicon_typetextrecord, query, procedure, definitions
backfillbooleanWhether to backfill on upload
target_collectiontextFor queries/procedures: which record collection
created_attimestamptz
updated_attimestamptz

users

ColumnTypeDescription
iduuid (PK)
didtext (unique)User's atproto DID
is_superbooleanWhether this is the super user (only one allowed)
created_attimestamptz
last_used_attimestamptzUpdated on each authenticated request

user_permissions

ColumnTypeDescription
user_iduuid (FK)References users.id
permissiontextPermission string (e.g. lexicons:create)
(PK)Composite primary key: (user_id, permission)

api_keys

ColumnTypeDescription
iduuid (PK)
user_iduuid (FK)References users.id
nametextDescriptive label
key_hashtextSHA-256 hash of the full key
key_prefixtextFirst 11 characters for display
permissionstext[]Permissions granted to this key
created_attimestamptz
last_used_attimestamptz
revoked_attimestamptzSet when revoked (soft delete)

oauth_sessions

ColumnTypeDescription
didtext (PK)User's atproto DID
session_datatextSerialized OAuth session (managed by atrium)
created_attimestamptz
updated_attimestamptz

oauth_state

ColumnTypeDescription
state_keytext (PK)OAuth state parameter
state_datatextSerialized state (managed by atrium)
created_attimestamptz

instance_settings

ColumnTypeDescription
keytext (PK)Setting name (e.g. app_name)
valuetextSetting value
updated_attimestamptzLast modified

event_logs

ColumnTypeDescription
iduuid (PK)
event_typetextCategory.action format (e.g. user.created)
severitytextinfo, warn, or error
actor_didtextDID of the user who triggered the event
subjecttextWhat was affected (DID, NSID, URI, etc.)
detailjsonbEvent-specific data
created_attimestamptz

script_variables

ColumnTypeDescription
keytext (PK)Variable name
valuetextVariable value (encrypted at rest)
created_attimestamptz
updated_attimestamptz

spaces

ColumnTypeDescription
idtext (PK)Internal space identifier
didtextThe space's own DID
authority_didtextDID that controls the space
creator_didtextDID of the user who created the space
type_nsidtextSpace type as an NSID
skeytextSpace key (differentiates spaces of the same type)
display_nametextHuman-readable name (optional)
descriptiontextDescription (optional)
mint_policytextmember-list, public, or managing-app
app_accesstext (JSON){"type":"open"} or {"type":"allowList","allowed":[...]}
managing_app_didtextDID of the managing app (optional)
configtext (JSON)Space config (membershipPublic, recordsPublic, extras)
revisiontextCurrent revision TID
created_attext
updated_attext

space_members

ColumnTypeDescription
idtext (PK)
space_idtext (FK)References spaces.id
didtextMember's DID (or space URI for delegation)
accesstextread, read_self, or write
is_delegationbooleanWhether this member is a delegated space
granted_bytextDID of who granted membership
created_attext

space_records

ColumnTypeDescription
uritext (PK)at:// URI of the record
space_idtext (FK)References spaces.id
author_didtextDID of the record author
collectiontextLexicon NSID
rkeytextRecord key
recordjsonbRecord value
cidtextContent identifier
indexed_attext

space_repo_state

ColumnTypeDescription
idtext (PK)
space_idtext (FK)References spaces.id
author_didtextDID of the repo author
lthash_statebytea2048-byte LtHash state
revtextCurrent revision
hashbyteaContent hash
ikmbyteaInput keying material for deniable signatures
sigbyteaSignature
macbyteaMessage authentication code
updated_attext

space_record_oplog

ColumnTypeDescription
idtext (PK)
space_idtext (FK)References spaces.id
author_didtextDID of the operation author
revtextRevision this operation belongs to
idxintegerIndex within the revision
actiontextcreate, update, or delete
collectiontextLexicon NSID
rkeytextRecord key
cidtextContent identifier (for create/update)
prevtextPrevious CID (for update/delete)
created_attext

space_notify_registrations

ColumnTypeDescription
idtext (PK)
space_idtext (FK)References spaces.id
author_didtextFilter by author DID (optional)
endpointtextNotification endpoint URL
registered_bytextDID of who registered
expires_attextWhen the registration expires
created_attext

space_invites

ColumnTypeDescription
idtext (PK)
space_idtext (FK)References spaces.id
token_hashtextSHA-256 hash of the invite token
created_bytextDID of the user who created the invite
accesstextAccess level granted: read, read_self, write
max_usesinteger?Maximum number of uses (null = unlimited)
usesintegerCurrent use count
expires_attext?Expiry timestamp (null = never)
revokedbooleanWhether the invite has been revoked
created_attext

space_credentials

ColumnTypeDescription
idtext (PK)
space_idtext (FK)References spaces.id
issued_totextDID the credential was issued to
token_hashtextHash of the credential token
expires_attextWhen the credential expires
created_attext

space_dids

ColumnTypeDescription
idtext (PK)
didtextThe space's DID
space_idtext (FK)References spaces.id
signing_key_enctextEncrypted signing key (AES-256-GCM)
rotation_key_enctextEncrypted rotation key (AES-256-GCM)
created_bytextDID of who provisioned the key
created_attext

service_identity

ColumnTypeDescription
idinteger (PK)Always 1 (singleton)
modetextdid_web, did_plc, or linked_account
didtextThe service's DID
signing_key_enctextEncrypted signing key
rotation_key_enctext?Encrypted rotation key (did:plc only)
attached_account_didtext?Linked account DID (linked_account mode)
setup_completebooleanWhether setup has been finalized
created_attext
updated_attext

service_entries

ColumnTypeDescription
idinteger (PK)
fragment_idtextDID document fragment identifier
service_typetextService type (e.g. AtprotoAppView)
access_modetextall or scoped to specific XRPCs
created_attext
updated_attext

service_entry_xrpcs

ColumnTypeDescription
service_entry_idinteger (FK)References service_entries.id
lexicon_idtextLexicon NSID this entry handles

verification_methods

ColumnTypeDescription
idtext (PK)
fragment_idtextDID document fragment (e.g. #atproto_space)
key_typetextAlways Multikey
public_key_multibasetextPublic key in multibase encoding
private_key_enctextEncrypted private key (AES-256-GCM)
created_attext

backfill_jobs

ColumnTypeDescription
iduuid (PK)
collectiontextTarget collection (null = all)
didtextTarget DID (null = all)
statustextpending, running, pausing, paused, cancelling, cancelled, completed, failed
stagetextpending, discovering_repos, resolving_and_fetching, completed, failed, cancelled
total_reposintegerTotal DIDs discovered
resolved_reposintegerDIDs with PDS endpoint resolved
processed_reposintegerDIDs with records fetched
total_recordsintegerTotal records indexed
errortextError message if failed
started_attimestamptz
completed_attimestamptz
created_attimestamptz

Testing

# Unit tests (no database needed)
cargo test --lib

# All tests including end-to-end (SQLite by default)
cargo test

# Or run against Postgres
docker compose -f docker-compose.test.yml up -d
TEST_DATABASE_URL=postgres://happyview:happyview@localhost:5433/happyview_test cargo test
docker compose -f docker-compose.test.yml down

End-to-end tests use wiremock to mock external services (PLC directory, PDSes) and a real database for full integration coverage. By default tests use SQLite; set TEST_DATABASE_URL to a Postgres connection string to test against Postgres.