KeiSeiKit-1.0/_primitives/_rust/kei-social-store/src/schema.rs
Parfii-bot 0b645db646 feat(m3): migrate kei-social-store to kei-entity-store engine
5/5 tests preserved. Primary entity = person; orgs + interactions +
relationship_graph stay custom.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 05:55:13 +08:00

66 lines
2.5 KiB
Rust

//! kei-social-store EntitySchema — Layer A convergence.
//!
//! Primary entity = `person` (table `people`). Secondary tables
//! `organizations` and `interactions` ride `custom_migrations`: they are
//! not generic CRUD (orgs use name-keyed upsert; interactions are an
//! append-only log with per-person index) and keep their existing
//! column names byte-for-byte so on-disk DBs written before this
//! migration still open cleanly.
//!
//! FTS columns cover name, handle, email, bio — search verb routes
//! through `fts_people`. The legacy `fts_social` virtual table is
//! replaced; FTS is rebuilt on first open against the new name.
use kei_entity_store::schema::{EdgeKeyKind, EntitySchema, FieldDef};
static FIELDS: &[FieldDef] = &[
FieldDef::pk("id"),
FieldDef::text_nn("name"),
FieldDef::text("email"),
FieldDef::text("handle"),
FieldDef::text("role"),
FieldDef::text("organization"),
FieldDef::text_default("source", "manual"),
FieldDef::text("bio"),
FieldDef::created_at(),
FieldDef::updated_at(),
];
const DDL_SECONDARY: &str = r#"
CREATE UNIQUE INDEX IF NOT EXISTS idx_people_email
ON people(email) WHERE email != '';
CREATE UNIQUE INDEX IF NOT EXISTS idx_people_handle_source
ON people(handle, source) WHERE handle != '';
CREATE TABLE IF NOT EXISTS organizations (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
org_type TEXT DEFAULT 'company',
description TEXT DEFAULT '',
created_at INTEGER NOT NULL
);
CREATE TABLE IF NOT EXISTS interactions (
id INTEGER PRIMARY KEY,
person_id INTEGER NOT NULL REFERENCES people(id) ON DELETE CASCADE,
target_id INTEGER NOT NULL DEFAULT 0,
interaction_type TEXT NOT NULL,
channel TEXT NOT NULL DEFAULT 'manual',
content TEXT DEFAULT '',
timestamp INTEGER NOT NULL,
created_at INTEGER NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_int_person ON interactions(person_id);
"#;
pub static SOCIAL_SCHEMA: EntitySchema = EntitySchema {
name: "person",
table: "people",
fields: FIELDS,
enabled_verbs: &["create", "get", "search", "list"],
fts_columns: Some(&["name", "handle", "email", "bio"]),
edge_table: None, // interactions has bespoke columns — managed by interactions.rs
edge_key_kind: EdgeKeyKind::IntegerPair,
archived_field: None,
custom_migrations: &[DDL_SECONDARY],
};