What Is the Purpose of the Models Directory in Karakeep?
The models directory in Karakeep serves as the domain-model layer that encapsulates database access, business logic, and security rules for core entities like users, bookmarks, and tags.
The karakeep-app/karakeep repository organizes its backend logic within the packages/trpc/models folder, which functions as the central data-access layer for the application. This directory isolates all database interactions and domain logic from the tRPC routing layer, ensuring that security checks, validation rules, and transactional safety remain consistent across the API surface.
Architectural Role and Design Philosophy
The models directory implements a domain-model pattern where each file defines a class representing a core system entity. Unlike simple data transfer objects, these classes bundle data access methods with business logic, acting as the sole authority for how the application interacts with the database schema defined in @karakeep/db/schema.
Each model class shares a standardized constructor signature:
constructor(protected ctx: AuthedContext, public <entity>: typeof <table>.$inferSelect)
The ctx parameter carries the authenticated user session and a Drizzle ORM database instance, enabling every method to enforce per-user security boundaries automatically. This design keeps the tRPC routers thin, delegating complex operations to these domain models while maintaining strict authorization checks.
Core Domain Models and Responsibilities
The packages/trpc/models directory contains specialized classes for every major entity in the system:
-
User(users.ts): Handles authentication flows including sign-up, password reset, email verification, and settings updates. It encapsulates user-specific permission checks and statistics aggregation while managing theTRPCError({ code: "FORBIDDEN" })pattern for unauthorized access attempts. -
Bookmark(bookmarks.ts): Provides the primary interface for creating, retrieving, and modifying bookmarks. It manages content assembly, ownership validation, and integrates with theWebhooks.serviceto notify external systems of changes. -
Tag(tags.ts): Manages tag creation, filtering, and pagination while enforcing per-user isolation. It provides usage statistics and cleanup utilities for orphaned tags via methods likedeleteUnused. -
Asset(assets.ts): Supplies lifecycle management for file attachments, including listing, attachment/detachment logic viaattachAsset, type translation, and cleanup of orphaned files. -
List(lists.ts): Manages user-defined collections of bookmarks, handling creation, retrieval, and sharing logic. -
Rules(rules.ts): Stores user-specific automation rules such as auto-tagging and summarization triggers.
Specialized service modules handle cross-cutting concerns:
Webhooks.service(webhooks.service.ts): Delivers webhook callbacks when bookmarks change.Webhooks.repo(webhooks.repo.ts): Persists webhook subscription records.ImportSessions(importSessions.service.ts): Manages bulk import workflows for RSS feeds and other sources.Highlights(highlights.ts): Manages text annotations on bookmark assets.Feeds(feeds.ts): Controls RSS feed integration and polling schedules.Backups(backups.ts): Handles backup scheduling and retrieval operations.
Security Patterns and Side-Effects
Every model method receives an AuthedContext object containing the current user identity and database connection. This pattern ensures that queries automatically filter by userId, preventing data leakage between accounts. The models also handle side-effects transactionally, such as re-indexing search data after bookmark updates or sending verification emails during user creation.
Practical Usage Examples
The tRPC routers consume these models to expose the public API. Below are typical interaction patterns from the Karakeep source code:
Creating a New User
// Used in the signup tRPC procedure
await User.create(ctx, {
name: "Alice",
email: "alice@example.com",
password: "s3cr3t",
});
Retrieving a Bookmark with Ownership Validation
// Ensures the caller can view the specific bookmark
const bm = await Bookmark.bareFromId(ctx, "bookmark-123");
Attaching Assets to Bookmarks
await Asset.attachAsset(ctx, {
bookmarkId: "bookmark-123",
asset: { id: "asset-456", assetType: "AVATAR" },
});
Querying Tags with Pagination
const { tags, nextCursor } = await Tag.getAll(ctx, {
nameContains: "project",
sortBy: "usage",
pagination: { page: 0, limit: 20 },
});
Administrative Cleanup Operations
// Admin-only helper to remove unused tags
const removedCount = await Tag.deleteUnused(ctx);
Each call internally uses the Drizzle ORM to fetch or modify rows, respecting the current user's permissions while triggering necessary side-effects like search re-indexing or webhook delivery.
Summary
- The
packages/trpc/modelsdirectory acts as the domain-model layer for the Karakeep monorepo, separating data access from routing logic. - Each file defines a class (e.g.,
User,Bookmark,Tag) that encapsulates database queries, business rules, and security validation. - Models accept an
AuthedContextparameter to enforce per-user data isolation automatically across all operations. - The layer handles side-effects such as email delivery, webhook notifications, and search indexing within transactional boundaries.
- Key files include
users.ts,bookmarks.ts,tags.ts,assets.ts, and service modules likewebhooks.service.tsandimportSessions.service.ts.
Frequently Asked Questions
What is the models directory in Karakeep responsible for?
The models directory in Karakeep is responsible for defining the domain-model layer that contains all database access logic, business rules, and security checks. Located at packages/trpc/models, each file implements a class representing a core entity (User, Bookmark, Tag, etc.) that the tRPC routers use to serve API requests while enforcing per-user permissions.
How does the Karakeep models directory enforce security?
Security enforcement happens through the AuthedContext pattern passed to every model constructor. This context object contains the authenticated user and database connection, allowing methods to automatically filter queries by userId and throw TRPCError({ code: "FORBIDDEN" }) when callers attempt to access resources they don't own, as seen in the Tag and Bookmark models.
What is the relationship between the models directory and tRPC routers in Karakeep?
The tRPC routers in Karakeep act as thin controllers that delegate all business logic to the models directory. While routers handle request/response formatting and validation, they import classes from packages/trpc/models to perform actual data operations, ensuring consistent application of business rules across the API surface without duplicating logic.
Which files are included in the Karakeep models directory?
The models directory includes entity classes like users.ts, bookmarks.ts, tags.ts, assets.ts, and lists.ts, plus service-specific files such as webhooks.service.ts, webhooks.repo.ts, rules.ts, importSessions.service.ts, highlights.ts, feeds.ts, and backups.ts. Each file focuses on a specific domain area while sharing the common constructor pattern with AuthedContext and Drizzle ORM integration.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →