# schema/schema _(no submodules)_ ## Purpose Owns the SurrealQL DDL the vault plugin applies during `onInit` — the first leg of the 3-way plug-and-play contract. `VAULT_OWNERSHIP_SCHEMA` defines two tables (`vault_item` and `vault_share`) plus their indexes; `applyVaultSchemaViaRunner` and `applyVaultSchema` provide the two application paths the plugin uses (preferred runner path; direct `db.execute` fallback). Original — the `@suaveplan/vault` library encapsulates the encrypted container but exposes no opinion about the HTTP-layer ownership store. ## Features - Two tables; `vault_item` is the active surface, `vault_share` is forward-declared so the future sharing-routes follow-up plugin lands without a database migration churn. - Three indexes covering the listing patterns the plugin actually uses: per-owner-by-kind and per-owner-by-created-descending. The share index is forward-declared too. - `DEFINE TABLE OVERWRITE` + `DEFINE FIELD OVERWRITE` everywhere — the schema is idempotent. Re-applying on every cold start is safe and costs only the brief metadata-replace. - `MigrationRunner` is the preferred application path because it records the apply in `_migrations` and gives the operator a single audit log of every DDL change. - The direct `db.execute` fallback path raises a typed `VaultPluginError(VAULT_PLUGIN_SCHEMA_APPLY_FAILED)` with the original error as `cause` for telemetry surfacing. ## Usage: Basic ```ts import { applyVaultSchema, VAULT_OWNERSHIP_SCHEMA, } from "@suaveplan/api-plugin-vault"; await applyVaultSchema(surrealAdapter); ``` ## Usage: Advanced ```ts import { applyVaultSchemaViaRunner, VAULT_OWNERSHIP_SCHEMA, } from "@suaveplan/api-plugin-vault"; import { createMigrationRunner } from "@suaveplan/api-migrations"; const runner = createMigrationRunner({ adapter: surrealqlAdapter }); await applyVaultSchemaViaRunner(runner); // _migrations now lists `0000-vault-ownership-schema` ``` ## API Reference ### `VAULT_OWNERSHIP_SCHEMA: string` Frozen DDL string. Contains the two `DEFINE TABLE`s and three `DEFINE INDEX`es plus every per-field declaration. ### `SurrealLikeExecutor` Structural interface — `{ execute(query: string): Promise }`. Matches `@suaveplan/surrealdb`'s `SurrealAdapter.execute`. ### `applyVaultSchema(db: SurrealLikeExecutor): Promise` Direct application path. Throws `VaultPluginError(VAULT_PLUGIN_SCHEMA_APPLY_FAILED)` on failure with the original error as `cause`. ### `applyVaultSchemaViaRunner(runner: MigrationRunner): Promise` Runner-mediated application path. Records the apply in the operator's migration log. Same error contract. ## Implementation Notes - The schema does NOT define any view, function, or event — those cross plugin boundaries. The vault plugin owns the bare ownership store; cross-plugin views (e.g. "all items shared with me") belong in the sharing follow-up. - `metadata` is `option` so absent metadata stores as `NONE` and zero-cost; clients can attach arbitrary JSON metadata without schema churn. - Indexes are NOT marked `UNIQUE` — there is no uniqueness constraint on `(ownerId, kind)`; multiple items of the same kind per owner are normal. - The `containerKey` field is the opaque id used to look up the encrypted body inside `@suaveplan/vault`'s container. Generated by `vaultService` at create time; never returned to the wire.