4.3 KiB
File: COMMIT_04_DB_SCHEMA.md
Commit 4: SurrealDB Schema & Permissions
Objective
Define the SurrealDB "App View Cache" schemas. This includes:
- Defining trusted JWT access using our app's secret key.
- Defining the user and node tables.
- Defining the links_to graph relation table.
- Crucially: Implementing row-level security (PERMISSIONS) that uses the did claim from our JWT (minted in Commit 03) to ensure users can only access their own data.
- Defining the vector index for AI-powered linking.
Implementation Specification
1. Create db/schema.surql
Create a file at /db/schema.surql. This script should be executed against the SurrealDB instance to initialize the schema.
SQL
-- --------------------------------------------------
-- Ponderants :: SurrealDB Schema
-- --------------------------------------------------
-- --------------------------------------------------
-- Access Control (JWT)
-- --------------------------------------------------
-- Define the JWT access method. This tells SurrealDB to trust
-- JWTs signed by our Next.js backend using the HS512 algorithm
-- and the secret key provided in the environment.
-- (Note: DEFINE TOKEN is deprecated as of 2.x) [12]
DEFINE ACCESS app_jwt
ON DATABASE
TYPE JWT
ALGORITHM HS512
KEY $env.SURREALDB_JWT_SECRET; [13]
-- --------------------------------------------------
-- Table: user
-- --------------------------------------------------
-- Stores basic user information, cached from ATproto.
DEFINE TABLE user SCHEMAFULL;
-- The user's decentralized identifier (DID) is their primary key.
DEFINE FIELD did ON TABLE user TYPE string
ASSERT $value!= NONE;
DEFINE FIELD handle ON TABLE user TYPE string;
-- Ensure DIDs are unique.
DEFINE INDEX user_did_idx ON TABLE user COLUMNS did UNIQUE;
-- --------------------------------------------------
-- Table: node
-- --------------------------------------------------
-- Stores a single "thought node." This is the cache record for
-- the com.ponderants.node lexicon.
DEFINE TABLE node SCHEMAFULL
-- THIS IS THE CORE SECURITY MODEL:
-- Users can only perform actions on nodes where the
-- node's 'user_did' field matches the 'did' claim
-- from their validated JWT ('$token.did'). [12]
PERMISSIONS
FOR select, create, update, delete
WHERE user_did = $token.did;
-- Foreign key linking to the user table (via DID).
DEFINE FIELD user_did ON TABLE node TYPE string
ASSERT $value!= NONE;
-- The canonical URI of the record on the ATproto PDS.
DEFINE FIELD atp_uri ON TABLE node TYPE string;
DEFINE FIELD title ON TABLE node TYPE string;
DEFINE FIELD body ON TABLE node TYPE string;
-- The AI-generated vector embedding for the 'body'. [14]
-- We use array<number> for the vector.
DEFINE FIELD embedding ON TABLE node TYPE array<number>;
-- The 3D coordinates calculated by UMAP.
DEFINE FIELD coords_3d ON TABLE node TYPE array<number>
-- Must be a 3-point array [x, y, z] or empty.
ASSERT $value = NONE OR array::len($value) = 3;
-- Define the vector search index.
-- We use MTREE (or HNSW) for high-performance k-NN search.
-- The dimension (1536) MUST match the output of the
-- 'gemini-embedding-001' model.
DEFINE INDEX node_embedding_idx ON TABLE node FIELDS embedding MTREE DIMENSION 1536;
-- --------------------------------------------------
-- Relation: links_to
-- --------------------------------------------------
-- This is a graph edge table, relating (node)->(node).
DEFINE TABLE links_to SCHEMAFULL
-- Security for graph edges: A user can only create/view/delete
-- links between two nodes that BOTH belong to them.
PERMISSIONS
FOR select, create, delete
WHERE
(SELECT user_did FROM $from) = $token.did
AND
(SELECT user_did FROM $to) = $token.did;
-- (No fields needed, it's a simple relation)
-- Example usage: RELATE (node:1)-[links_to]->(node:2);
Test Specification
This commit contains no UI or API routes. The schemas defined here will be validated by the tests in subsequent commits (e.g., Commit 06 and Commit 10), which will attempt to write and read data according to these rules.