Database Schema Definition
Relevant source files
The following files were used as context for generating this wiki page:
The Database Schema Definition for Barekey is built on Convex, a Backend-as-a-Service (BaaS) that provides a reactive database layer. The schema defines the structure for managing users, multi-tenant organizations (managed primarily via Clerk), projects, environments (stages), and encrypted secrets. The architecture utilizes envelope encryption where sensitive data is encrypted at the application layer before being stored in the database.
Sources: AGENTS.md:12-20, pkg/convex/schema.ts:1-4
Core Data Model Architecture
The data model is structured to support multi-tenancy where projects and variables are strictly owned by organizations (teams). While users are tracked for identity and auditing, only organizations can own projects. The schema relies on high-level entities: users, projects, projectStages, projectKeys, and projectVariables.
Entity Relationship Diagram
The following diagram illustrates the relationships between the primary tables in the Convex database.
Sources: pkg/convex/schema.ts:4-53, AGENTS.md:43-48
Table Definitions
Users
The users table tracks individual identities synchronized from Clerk. It stores metadata and internal slugs for routing.
| Field | Type | Description |
|---|---|---|
clerkUserId | v.string() | Primary identifier from Clerk auth provider. |
slug | v.string() | URL-friendly unique identifier for the user. |
email | v.union(v.string(), v.null()) | User's primary email address. |
lastSeenAtMs | v.number() | Timestamp of the user's last activity. |
Sources: pkg/convex/schema.ts:5-15
Projects
Projects are the primary containers for secrets. Each project belongs to a specific orgId (Organization ID).
| Field | Type | Description |
|---|---|---|
orgId | v.string() | The ID of the owning organization (from Clerk). |
name | v.string() | Human-readable name of the project. |
slug | v.string() | Unique slug within the organization. |
createdByClerkUserId | v.string() | The user who initialized the project. |
Sources: pkg/convex/schema.ts:18-27, pkg/convex/projects.ts:103-111
Project Stages
Stages represent environments such as "development", "staging", or "production". Variables are scoped to these stages. By default, every new project is initialized with three standard stages.
Sources: pkg/convex/project_stages.ts:50-65, pkg/convex/projects.ts:91-101
Project Variables
This table stores the actual secrets. Values are never stored in plaintext; they use the encryptedValue field which contains data encrypted via the project's Data Encryption Key (DEK).
| Field | Type | Description |
|---|---|---|
projectId | v.id("projects") | Reference to the parent project. |
stageSlug | v.string() | The environment slug this variable belongs to. |
name | v.string() | The variable key (e.g., DATABASE_URL). |
kind | v.literal("secret") | Discriminated union for variable types. |
encryptedValue | v.string() | The secret value encrypted at rest. |
Sources: pkg/convex/schema.ts:44-54, AGENTS.md:65-71
Indexing Strategy
Convex requires explicit index definitions for efficient querying. The schema defines several composite indexes to support organization-level and project-level filtering without using .filter().
// Example: Variable lookup by project and stage
projectVariables: defineTable({ ... })
.index("by_project_id_and_stage_slug", ["projectId", "stageSlug"])
.index("by_project_id_and_stage_slug_and_name", ["projectId", "stageSlug", "name"])
.index("by_org_id_and_project_id", ["orgId", "projectId"])
Sources: pkg/convex/schema.ts:55-57, AGENTS.md:143-144
Encryption Model at Rest
Barekey implements envelope encryption. The schema supports this through the projectKeys table, which stores the Project DEK (Data Encryption Key). This DEK is itself encrypted by a Master KEK (Key Encryption Key).
Note: The KEK is stored encrypted at rest in Convex for the MVP phase.
Sources: AGENTS.md:52-60, pkg/convex/schema.ts:36-42
Summary
The Database Schema Definition provides a robust foundation for multi-tenant secret management. By enforcing organization-level ownership and stage-based scoping, the system ensures strict data isolation. The integration of application-level encryption directly into the table definitions (via encryptedValue and projectKeys) aligns the database structure with the project's core security requirements.