Docs/Memory Schema
Reference

Memory Schema

Categories, tags, TypeScript types, ciphertext format, shared vaults, and AI enrichment fields.

Categories

Every memory belongs to one of six categories, mapped to the six MNEMOS product modules. Categories determine vault module routing, graph colouring, and MCP recall filtering.

CategoryModuleUse for
contextMODULE_01General notes, second-brain context, anything that doesn't fit elsewhere
relationshipMODULE_02People, connections, interactions, pre-meeting context
goalMODULE_03Objectives, milestones, kanban items, aspirations
decisionMODULE_04Choices made, reasoning recorded, outcomes tracked
healthMODULE_05Mood, energy, sleep, symptoms, patterns over time
apiMODULE_06Externally ingested via API gateway (plaintext, not wallet-encrypted)

Tags

Tags are free-form strings stored unencrypted for fast filtering and search.

Format rules

  • Lowercase, hyphens only — follow-up not follow up
  • Max 10 tags per memory
  • Max 50 characters per tag

Suggested conventions

text
# People (relationship module)
danno, alice, team-engineering

# Projects / work
q2-review, mnemos-launch, client-acme

# Time
weekly, monthly, 2026-q1

# Status / action
follow-up, in-progress, completed, blocked, archived

TypeScript types

Full type definitions from src/lib/types.ts:

typescript
/** Categories map to the six MNEMOS product modules */
export type MemoryCategory =
  | "relationship"  // MODULE_02
  | "goal"          // MODULE_03
  | "decision"      // MODULE_04
  | "health"        // MODULE_05
  | "context"       // MODULE_01 — general second-brain context
  | "api";          // MODULE_06 — third-party API writes

/** Raw storage record (server-side, contains ciphertext) */
export interface MemoryStreamContent {
  ciphertext:    string;           // AES-256-GCM blob: base64url(iv) + "." + base64url(ct)
  walletAddress: string;           // owner wallet (lowercase)
  category:      MemoryCategory;
  tags:          string[];         // unencrypted, used for filtering
  title?:        string;           // AI-generated, stored unencrypted
  createdAt:     string;           // ISO timestamp
  updatedAt:     string;           // ISO timestamp
  deletedAt?:    string;           // set on soft delete
  vaultId?:      string;           // shared vault FK — undefined for personal memories
}

/** Hydrated record returned by the API (post-decrypt on client) */
export interface MemoryRecord {
  streamId:      string;           // "mem_" + nanoid(8)
  content?:      string;           // decrypted plaintext — only after client-side decrypt
  title?:        string;           // AI-generated title (always present if enriched)
  walletAddress: string;
  category:      MemoryCategory;
  tags:          string[];
  createdAt:     string;
  updatedAt:     string;
  deletedAt?:    string;
  ciphertext:    string;           // always present — raw encrypted blob
  vaultId?:      string;
}

Ciphertext format

text
Format: base64url(iv[12 bytes]) + "." + base64url(AES-GCM ciphertext)

Example:
  "aBcD1234EFGH.xYz9876uvWXabcdef..."
   ^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^
   12-byte IV    encrypted content + 16-byte GCM auth tag

Properties:
  - New random 96-bit IV per write → same plaintext never produces same ciphertext
  - GCM auth tag: any tampering causes decryption to throw (integrity guarantee)
  - base64url encoding: URL-safe, no padding

Shared vault types

Shared vaults use ECDH P-256 key exchange so multiple wallets can read the same encrypted content without sharing private keys.

typescript
export interface SharedVault {
  id:           string;
  name:         string;
  ownerWallet:  string;
  createdAt:    string;
  updatedAt:    string;
  members?:     VaultMember[];
}

export interface VaultMember {
  vaultId:          string;
  walletAddress:    string;
  role:             "owner" | "writer" | "viewer";
  wrappedVaultKey:  string;  // AES-GCM wrapped vault key: base64url(iv).base64url(wrapped)
  ephemeralPubkey:  string;  // SPKI base64url P-256 public key used during wrapping
  joinedAt:         string;
}

export interface VaultInvite {
  id:               string;
  vaultId:          string;
  inviteeWallet:    string;
  role:             "owner" | "writer" | "viewer";
  wrappedVaultKey:  string;
  ephemeralPubkey:  string;
  status:           "pending" | "accepted" | "declined" | "revoked";
  createdAt:        string;
  expiresAt?:       string;
}

Session memory (MCP bridge)

When you sync to the AI Vault Bridge, decrypted plaintext is temporarily cached server-side so MCP tools can recall it. This cache is separate from your encrypted vault storage.

typescript
export interface SessionMemory {
  id:        string;
  title?:    string;
  content:   string;    // decrypted plaintext — only in session cache
  category:  string;
  tags:      string[];
  createdAt: string;
}

export interface SessionData {
  walletAddress: string;
  memories:      SessionMemory[];
  syncedAt:      string;
  expiresAt:     string;   // 60 minutes from sync time
}
NOTE
Session memories are stored in a separate session cache (not the main memories table) and automatically expire. Revoking the session immediately clears this cache.