tangle


git clone https://radroots.dev/git/tangle.git
Log | Files | Refs | README | LICENSE

commit ab51b22ffa78549783bd985df6258157be761712
parent 957fbb4a413264275c5495186c336694ae1fa155
Author: triesap <tyson@radroots.org>
Date:   Fri,  5 Jun 2026 22:42:03 -0700

migrations: add policy schemas

Diffstat:
Mcrates/tangle_store_surreal/src/lib.rs | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 156 insertions(+), 0 deletions(-)

diff --git a/crates/tangle_store_surreal/src/lib.rs b/crates/tangle_store_surreal/src/lib.rs @@ -287,6 +287,7 @@ pub fn base_migration_plan() -> SurrealMigrationPlan { listing_current_schema(), listing_helper_schemas(), search_document_schema(), + policy_schemas(), ]) .expect("base migration plan is strictly ordered") } @@ -561,6 +562,69 @@ DEFINE INDEX IF NOT EXISTS search_doc_body_ft ON TABLE search_doc FIELDS body FU .expect("search document schema is valid") } +pub fn policy_schemas() -> SurrealMigration { + SurrealMigration::new( + "0010_policy", + r#" +DEFINE TABLE IF NOT EXISTS relay_user SCHEMAFULL; +DEFINE FIELD IF NOT EXISTS pubkey ON TABLE relay_user TYPE string; +DEFINE FIELD IF NOT EXISTS role ON TABLE relay_user TYPE string; +DEFINE FIELD IF NOT EXISTS seller_approved ON TABLE relay_user TYPE bool DEFAULT false; +DEFINE FIELD IF NOT EXISTS blocked ON TABLE relay_user TYPE bool DEFAULT false; +DEFINE FIELD IF NOT EXISTS created_at ON TABLE relay_user TYPE int; +DEFINE FIELD IF NOT EXISTS updated_at ON TABLE relay_user TYPE int; +DEFINE INDEX IF NOT EXISTS relay_user_pubkey_uid ON TABLE relay_user COLUMNS pubkey UNIQUE; +DEFINE INDEX IF NOT EXISTS relay_user_role ON TABLE relay_user COLUMNS role; +DEFINE INDEX IF NOT EXISTS relay_user_seller_gate ON TABLE relay_user COLUMNS seller_approved, blocked; + +DEFINE TABLE IF NOT EXISTS hidden_event SCHEMAFULL; +DEFINE FIELD IF NOT EXISTS event_id ON TABLE hidden_event TYPE string; +DEFINE FIELD IF NOT EXISTS reason ON TABLE hidden_event TYPE string; +DEFINE FIELD IF NOT EXISTS source ON TABLE hidden_event TYPE string; +DEFINE FIELD IF NOT EXISTS created_at ON TABLE hidden_event TYPE int; +DEFINE FIELD IF NOT EXISTS admin_pubkey ON TABLE hidden_event TYPE string; +DEFINE INDEX IF NOT EXISTS hidden_event_uid ON TABLE hidden_event COLUMNS event_id UNIQUE; +DEFINE INDEX IF NOT EXISTS hidden_event_created ON TABLE hidden_event COLUMNS created_at; + +DEFINE TABLE IF NOT EXISTS moderation_action SCHEMAFULL; +DEFINE FIELD IF NOT EXISTS action_id ON TABLE moderation_action TYPE string; +DEFINE FIELD IF NOT EXISTS admin_pubkey ON TABLE moderation_action TYPE string; +DEFINE FIELD IF NOT EXISTS target_type ON TABLE moderation_action TYPE string; +DEFINE FIELD IF NOT EXISTS target_ref ON TABLE moderation_action TYPE string; +DEFINE FIELD IF NOT EXISTS action ON TABLE moderation_action TYPE string; +DEFINE FIELD IF NOT EXISTS reason ON TABLE moderation_action TYPE string; +DEFINE FIELD IF NOT EXISTS created_at ON TABLE moderation_action TYPE int; +DEFINE INDEX IF NOT EXISTS moderation_action_target ON TABLE moderation_action COLUMNS target_type, target_ref, created_at; +DEFINE INDEX IF NOT EXISTS moderation_action_admin ON TABLE moderation_action COLUMNS admin_pubkey, created_at; + +DEFINE TABLE IF NOT EXISTS rate_limit_state SCHEMAFULL; +DEFINE FIELD IF NOT EXISTS key ON TABLE rate_limit_state TYPE string; +DEFINE FIELD IF NOT EXISTS state ON TABLE rate_limit_state TYPE string; +DEFINE FIELD IF NOT EXISTS expires_at ON TABLE rate_limit_state TYPE option<int>; +DEFINE FIELD IF NOT EXISTS created_at ON TABLE rate_limit_state TYPE int; +DEFINE FIELD IF NOT EXISTS updated_at ON TABLE rate_limit_state TYPE int; +DEFINE INDEX IF NOT EXISTS rate_limit_state_key_uid ON TABLE rate_limit_state COLUMNS key UNIQUE; +DEFINE INDEX IF NOT EXISTS rate_limit_state_expires ON TABLE rate_limit_state COLUMNS expires_at; + +DEFINE TABLE IF NOT EXISTS import_checkpoint SCHEMAFULL; +DEFINE FIELD IF NOT EXISTS name ON TABLE import_checkpoint TYPE string; +DEFINE FIELD IF NOT EXISTS offset ON TABLE import_checkpoint TYPE int; +DEFINE FIELD IF NOT EXISTS event_id ON TABLE import_checkpoint TYPE option<string>; +DEFINE FIELD IF NOT EXISTS updated_at ON TABLE import_checkpoint TYPE int; +DEFINE INDEX IF NOT EXISTS import_checkpoint_name_uid ON TABLE import_checkpoint COLUMNS name UNIQUE; + +DEFINE TABLE IF NOT EXISTS projection_error SCHEMAFULL; +DEFINE FIELD IF NOT EXISTS event_id ON TABLE projection_error TYPE string; +DEFINE FIELD IF NOT EXISTS projector ON TABLE projection_error TYPE string; +DEFINE FIELD IF NOT EXISTS error ON TABLE projection_error TYPE string; +DEFINE FIELD IF NOT EXISTS created_at ON TABLE projection_error TYPE int; +DEFINE INDEX IF NOT EXISTS projection_error_event ON TABLE projection_error COLUMNS event_id; +DEFINE INDEX IF NOT EXISTS projection_error_projector_created ON TABLE projection_error COLUMNS projector, created_at; +"#, + ) + .expect("policy schemas are valid") +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct AppliedMigration { name: String, @@ -1317,4 +1381,96 @@ mod tests { assert!(info.contains(expected), "missing {expected} in {info}"); } } + + #[tokio::test] + async fn policy_schemas_define_user_moderation_and_rebuild_tables() { + let store = memory_store().await; + store + .apply_plan(&base_migration_plan()) + .await + .expect("apply plan"); + + for (table, expected) in [ + ( + "relay_user", + vec![ + "pubkey", + "role", + "seller_approved", + "blocked", + "created_at", + "updated_at", + "relay_user_pubkey_uid", + "relay_user_seller_gate", + ], + ), + ( + "hidden_event", + vec![ + "event_id", + "reason", + "source", + "created_at", + "admin_pubkey", + "hidden_event_uid", + "hidden_event_created", + ], + ), + ( + "moderation_action", + vec![ + "action_id", + "admin_pubkey", + "target_type", + "target_ref", + "action", + "reason", + "created_at", + "moderation_action_target", + "moderation_action_admin", + ], + ), + ( + "rate_limit_state", + vec![ + "key", + "state", + "expires_at", + "created_at", + "updated_at", + "rate_limit_state_key_uid", + "rate_limit_state_expires", + ], + ), + ( + "import_checkpoint", + vec![ + "name", + "offset", + "event_id", + "updated_at", + "import_checkpoint_name_uid", + ], + ), + ( + "projection_error", + vec![ + "event_id", + "projector", + "error", + "created_at", + "projection_error_event", + "projection_error_projector_created", + ], + ), + ] { + let info = store.table_info(table).await.expect("table info"); + for field in expected { + assert!( + info.contains(field), + "missing {field} in {table} info {info}" + ); + } + } + } }