Skip to content

Conversation

@MohamedBassem
Copy link
Collaborator

@MohamedBassem MohamedBassem commented Nov 8, 2025

Add a new "user-uploaded" asset type that allows users to upload and attach their own files to bookmarks from the attachment box in the bookmark preview page.

Changes:

  • Add USER_UPLOADED asset type to database schema
  • Add userUploaded to zAssetTypesSchema for type safety
  • Update attachment permissions to allow attaching/detaching user files
  • Add fileName field to asset schema for displaying custom filenames
  • Add "Upload File" button in AttachmentBox component
  • Display actual filename for user-uploaded files
  • Allow any file type for user uploads (respects existing upload limits)
  • Add Upload icon for user-uploaded files

Fixes #284

Add a new "user-uploaded" asset type that allows users to upload and
attach their own files to bookmarks from the attachment box in the
bookmark preview page.

Changes:
- Add USER_UPLOADED asset type to database schema
- Add userUploaded to zAssetTypesSchema for type safety
- Update attachment permissions to allow attaching/detaching user files
- Add fileName field to asset schema for displaying custom filenames
- Add "Upload File" button in AttachmentBox component
- Display actual filename for user-uploaded files
- Allow any file type for user uploads (respects existing upload limits)
- Add Upload icon for user-uploaded files

Fixes #1863 related asset attachment improvements
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 8, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Adds a new asset type "userUploaded" across schema, types, API, and UI; assets gain an optional fileName; UI prefers fileName when present, adds an "Upload File" control to create userUploaded assets, and prevents inline replace for userUploaded assets.

Changes

Cohort / File(s) Summary
Database & Schema
packages/db/schema.ts, packages/shared/types/bookmarks.ts
Add USER_UPLOADED = "userUploaded" enum member; include "userUploaded" in schema enums; add optional fileName to asset zod schema
API / Models / Routers
packages/trpc/lib/attachments.ts, packages/trpc/models/bookmarks.ts, packages/trpc/routers/assets.ts, packages/trpc/routers/bookmarks.ts
Map DB↔schema asset type for userUploaded; add human-friendly name; allow attach/detach for userUploaded; include fileName in bookmark asset payloads; attachAsset now returns stored asset { id, assetType, fileName }; bookmark serialization now includes fileName
OpenAPI / Spec
packages/open-api/karakeep-openapi-spec.json, packages/open-api/lib/bookmarks.ts
Add "userUploaded" to assetType enums in request/response schemas; add optional fileName (nullable string) to asset objects; change attach request body to { id, assetType } using zAssetTypesSchema
Frontend — Icons
apps/web/lib/attachments.tsx
Add userUploaded entry to ASSET_TYPE_TO_ICON using Upload icon from lucide-react
Frontend — Component changes
apps/web/components/dashboard/preview/AttachmentBox.tsx
Prefer asset fileName for label/download attribute when present; remove inline replace FilePickerButton for userUploaded assets; add bottom-aligned "Upload File" FilePickerButton that uploads and attaches a new userUploaded asset on success; adjust placement within collapsible section

Sequence Diagram

sequenceDiagram
    autonumber
    actor User
    participant UI as AttachmentBox
    participant Picker as FilePickerButton
    participant API as attachAsset
    participant DB as Database

    User->>UI: Click "Upload File"
    UI->>Picker: open file dialog
    Picker->>User: select file
    Picker->>API: attachAsset({ assetType: "userUploaded", file })
    API->>DB: insert asset row (assetType=USER_UPLOADED, fileName)
    DB-->>API: return stored row
    API-->>UI: return asset { id, assetType:"userUploaded", fileName }
    UI->>UI: render new asset using fileName
    UI-->>User: display uploaded file in list
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to: apps/web/components/dashboard/preview/AttachmentBox.tsx (replace gating, fileName vs fallback, upload handler and UI state)
  • Verify DB schema and zod schema alignment in packages/db/schema.ts and packages/shared/types/bookmarks.ts
  • Confirm fileName is selected/returned correctly in packages/trpc/models/bookmarks.ts and packages/trpc/routers/assets.ts
  • Check OpenAPI spec and request/response schema changes in packages/open-api/*

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Add support for user uploaded files' clearly and concisely summarizes the main change: introducing a new feature for user-uploaded file support.
Description check ✅ Passed The description is directly related to the changeset, providing context about the new user-uploaded asset type, the components modified, and linking to issue #284.
Linked Issues check ✅ Passed The PR successfully implements all objectives from issue #284: adds an attachments mechanism for uploading arbitrary file types to bookmarks [#284], supports custom filenames for display and download [#284], and eliminates external dependency by storing files with bookmarks [#284].
Out of Scope Changes check ✅ Passed All changes are scoped to implementing the new userUploaded asset type feature; no unrelated modifications are present beyond the requirements in issue #284.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/karakeep-al-011CUvX24FPQBwqJW9FJQD7X

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8aa5ef5 and 01d8142.

📒 Files selected for processing (4)
  • packages/open-api/karakeep-openapi-spec.json (3 hunks)
  • packages/open-api/lib/bookmarks.ts (2 hunks)
  • packages/trpc/routers/assets.ts (2 hunks)
  • packages/trpc/routers/bookmarks.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/trpc/routers/assets.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use oxlint as the linter for JavaScript/TypeScript code

Files:

  • packages/trpc/routers/bookmarks.ts
  • packages/open-api/lib/bookmarks.ts
packages/trpc/**

📄 CodeRabbit inference engine (AGENTS.md)

tRPC routers and procedures (business logic) reside in packages/trpc

Files:

  • packages/trpc/routers/bookmarks.ts
packages/open-api/**

📄 CodeRabbit inference engine (AGENTS.md)

OpenAPI specifications reside in packages/open-api

Files:

  • packages/open-api/lib/bookmarks.ts
  • packages/open-api/karakeep-openapi-spec.json
🧬 Code graph analysis (1)
packages/open-api/lib/bookmarks.ts (1)
packages/shared/types/bookmarks.ts (1)
  • zAssetTypesSchema (18-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: typecheck
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (4)
packages/trpc/routers/bookmarks.ts (1)

253-257: LGTM!

The addition of fileName to the asset serialization is correct and aligns with the PR objective. The field is properly sourced from the database asset record and included in the response payload.

packages/open-api/karakeep-openapi-spec.json (2)

309-333: LGTM!

The OpenAPI schema correctly extends the bookmark assets array to include:

  • The new userUploaded asset type in the enum
  • The optional fileName field (nullable string)

The schema properly reflects that fileName is optional by not including it in the required fields array.


1673-1786: LGTM!

The attach asset endpoint schemas are correctly updated:

  • Request body accepts id and assetType (including the new userUploaded type)
  • Response includes id, assetType, and the new optional fileName field
  • The asymmetry is correct: clients specify which asset to attach (id + type), and the server returns the full asset details including fileName
packages/open-api/lib/bookmarks.ts (1)

409-448: Public API schema refinement.

The request schema for attaching assets has been refined to explicitly accept only id and assetType, while the response continues to return the full asset details (including fileName). This change:

  • Makes the API more explicit about required fields during attachment
  • Correctly reflects that fileName is derived from the asset record, not provided during attachment
  • Improves API semantics: "attach this asset to this bookmark" vs. "create/define an asset"

Note: If clients were previously sending additional fields beyond id and assetType, they will need to be updated. However, this change aligns with proper API design.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 737b031 and d005690.

📒 Files selected for processing (6)
  • apps/web/components/dashboard/preview/AttachmentBox.tsx (3 hunks)
  • apps/web/lib/attachments.tsx (2 hunks)
  • packages/db/schema.ts (2 hunks)
  • packages/shared/types/bookmarks.ts (1 hunks)
  • packages/trpc/lib/attachments.ts (5 hunks)
  • packages/trpc/models/bookmarks.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use oxlint as the linter for JavaScript/TypeScript code

Files:

  • packages/shared/types/bookmarks.ts
  • apps/web/components/dashboard/preview/AttachmentBox.tsx
  • packages/trpc/models/bookmarks.ts
  • packages/db/schema.ts
  • apps/web/lib/attachments.tsx
  • packages/trpc/lib/attachments.ts
packages/shared/**

📄 CodeRabbit inference engine (AGENTS.md)

Shared code and types reside in packages/shared

Files:

  • packages/shared/types/bookmarks.ts
apps/web/**

📄 CodeRabbit inference engine (AGENTS.md)

The main Next.js web application code resides in apps/web

Files:

  • apps/web/components/dashboard/preview/AttachmentBox.tsx
  • apps/web/lib/attachments.tsx
packages/trpc/**

📄 CodeRabbit inference engine (AGENTS.md)

tRPC routers and procedures (business logic) reside in packages/trpc

Files:

  • packages/trpc/models/bookmarks.ts
  • packages/trpc/lib/attachments.ts
packages/db/**

📄 CodeRabbit inference engine (AGENTS.md)

Database schema and migrations (Drizzle ORM) reside in packages/db

Files:

  • packages/db/schema.ts
🧬 Code graph analysis (1)
apps/web/components/dashboard/preview/AttachmentBox.tsx (2)
packages/trpc/lib/attachments.ts (1)
  • humanFriendlyNameForAssertType (43-57)
packages/shared/utils/assetUtils.ts (1)
  • getAssetUrl (1-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: tests
  • GitHub Check: typecheck
🔇 Additional comments (10)
packages/shared/types/bookmarks.ts (2)

27-27: LGTM: userUploaded asset type added correctly.

The new asset type is properly integrated into the existing enum and follows the naming convention of other asset types.


35-35: LGTM: fileName field properly defined as optional.

The nullish modifier ensures backward compatibility with existing assets that don't have filenames, which is the correct approach.

apps/web/lib/attachments.tsx (1)

7-7: LGTM: Upload icon appropriately mapped for userUploaded assets.

The Upload icon from lucide-react is a good visual representation for user-uploaded files and follows the existing icon mapping pattern.

Also applies to: 22-22

packages/trpc/lib/attachments.ts (3)

19-19: LGTM: Bidirectional mappings correctly implemented.

The USER_UPLOADED asset type is properly mapped in both directions between database and user-facing types, ensuring consistency across the system.

Also applies to: 37-37


53-53: LGTM: Clear and descriptive display name.

"User Uploaded File" accurately describes the asset type and is consistent with the naming pattern of other asset types.


69-69: LGTM: Appropriate permissions for user-uploaded files.

Allowing both attach and detach operations for userUploaded assets makes sense, as users should have full control over files they upload.

Also applies to: 85-85

packages/trpc/models/bookmarks.ts (1)

298-298: LGTM: fileName field properly included in asset loading.

The fileName is correctly populated from the database and will be available to clients consuming bookmark data. The nullish nature of the field is already handled by the schema definition.

apps/web/components/dashboard/preview/AttachmentBox.tsx (3)

104-108: LGTM: Conditional display logic correctly prioritizes fileName.

For userUploaded assets with a fileName, the actual filename is displayed; otherwise, the fallback uses the human-friendly asset type name. This provides better UX for user-uploaded files.


116-120: LGTM: Download attribute properly uses fileName when available.

This ensures that downloaded user-uploaded files retain their original filenames, improving the download experience.


209-232: LGTM: Upload File button correctly implemented.

The new FilePickerButton for uploading user files follows the existing pattern and correctly:

  • Sets assetType to "userUploaded"
  • Doesn't restrict file types (no accept attribute)
  • Uses the attachAsset mutation to associate the uploaded file with the bookmark

Comment on lines 129 to 133
accept={
asset.assetType === "userUploaded"
? undefined
: ".jgp,.JPG,.jpeg,.png,.webp"
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo in file extensions filter.

The accept filter has a typo: ".jgp" should be ".jpg". Note this typo also exists on line 186 in the "Attach a Banner" button.

Apply this diff to fix the typo in both locations:

                  accept={
                    asset.assetType === "userUploaded"
                      ? undefined
-                     : ".jgp,.JPG,.jpeg,.png,.webp"
+                     : ".jpg,.JPG,.jpeg,.png,.webp"
                  }

Also fix line 186:

              loading={isAttaching}
-             accept=".jgp,.JPG,.jpeg,.png,.webp"
+             accept=".jpg,.JPG,.jpeg,.png,.webp"
              multiple={false}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
accept={
asset.assetType === "userUploaded"
? undefined
: ".jgp,.JPG,.jpeg,.png,.webp"
}
accept={
asset.assetType === "userUploaded"
? undefined
: ".jpg,.JPG,.jpeg,.png,.webp"
}
🤖 Prompt for AI Agents
In apps/web/components/dashboard/preview/AttachmentBox.tsx around lines 129-133
and also at line 186, there is a typo in the accept file extensions string
(".jgp" instead of ".jpg"); update both occurrences to use the correct extension
list ".jpg,.JPG,.jpeg,.png,.webp" (preserve casing and the rest of the
conditional logic) so the accept filter correctly allows JPG files.

LINK_VIDEO = "linkVideo",
LINK_HTML_CONTENT = "linkHtmlContent",
BOOKMARK_ASSET = "bookmarkAsset",
USER_UPLOADED = "userUploaded",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

LGTM: USER_UPLOADED asset type properly added to schema.

The new asset type is correctly declared in both the enum definition and the table constraint list, following the existing pattern for other asset types.

Please ensure a database migration has been created to support the new USER_UPLOADED asset type in the schema. Run the following script to check for recent migrations:

Also applies to: 250-250


🏁 Script executed:

#!/bin/bash
# Check for recent migration files that might include the USER_UPLOADED asset type
fd -e sql -e ts migration packages/db | head -20

Length of output: 0


🏁 Script executed:

#!/bin/bash
# Explore packages/db directory structure
echo "=== Directory structure of packages/db ==="
find packages/db -type f -name "*migration*" -o -name "*migrate*" 2>/dev/null | head -20

echo -e "\n=== All files in packages/db ==="
find packages/db -type f | head -30

echo -e "\n=== Search for USER_UPLOADED in packages/db ==="
rg -n "USER_UPLOADED" packages/db/

Length of output: 1600


🏁 Script executed:

#!/bin/bash
# Check the schema.ts file around the lines mentioned
echo "=== Content of schema.ts around lines 231 and 250 ==="
sed -n '225,260p' packages/db/schema.ts

Length of output: 1226


🏁 Script executed:

#!/bin/bash
# Search entire codebase for migration-related patterns
echo "=== Search for migration files/folders ==="
find . -type d -name "*migrat*" 2>/dev/null | grep -v node_modules

echo -e "\n=== Search for USER_UPLOADED in entire codebase ==="
rg -n "USER_UPLOADED" --type ts --type sql 2>/dev/null | head -30

Length of output: 434



---

🏁 Script executed:

```shell
#!/bin/bash
# Check the latest migration file
echo "=== Latest migration file (0026) ==="
cat packages/db/drizzle/0026_silky_imperial_guard.sql

echo -e "\n=== Check for any 0027+ migration files ==="
ls -la packages/db/drizzle/00* 2>/dev/null | tail -5

echo -e "\n=== Check if there are uncommitted migrations ==="
ls -la packages/db/drizzle/ | wc -l

Length of output: 715


🏁 Script executed:

#!/bin/bash
# Search for references to USER_UPLOADED to understand scope
echo "=== All references to USER_UPLOADED in codebase ==="
rg -n "USER_UPLOADED" --type ts --type sql

echo -e "\n=== Check packages/trpc/lib/attachments.ts context ==="
sed -n '15,45p' packages/trpc/lib/attachments.ts

Length of output: 1497


🏁 Script executed:

#!/bin/bash
# Verify schema.ts has the complete AssetTypes enum
echo "=== Complete AssetTypes enum ==="
rg -A 15 "enum AssetTypes" packages/db/schema.ts

Length of output: 501


Missing database migration for USER_UPLOADED asset type.

The schema.ts changes are correct, but there is no corresponding migration file in packages/db/drizzle/. Since USER_UPLOADED is already referenced in packages/trpc/lib/attachments.ts (lines 19, 37), the database schema must be updated to support this new enum value. A migration file needs to be generated to add the USER_UPLOADED enum variant to the assets table's assetType constraint.

🤖 Prompt for AI Agents
In packages/db/schema.ts around line 231, you added USER_UPLOADED to the asset
type enum but did not add a DB migration; create a new migration file under
packages/db/drizzle (timestamped like
<timestamp>_add_user_uploaded_asset_type.sql) that alters the existing Postgres
enum used by the assets table (or updates the CHECK/constraint if you used one)
to include the new value 'userUploaded'—for a Postgres enum use ALTER TYPE
<enum_name> ADD VALUE 'userUploaded'; ensure the migration is
numbered/registered with your migration runner and include a corresponding down
migration or reversible steps if required by your tooling, then run the
migration locally to verify packages/trpc/lib/attachments.ts references work
with the updated schema.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +215 to +219
className="flex w-full items-center justify-center gap-2"
onFileSelect={(file) =>
uploadAsset(file, {
onSuccess: (resp) => {
attachAsset({

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Backend still rejects non whitelisted file types

The new "Upload File" button allows selecting any file, but the upload endpoint (packages/api/utils/upload.tsuploadAsset) still checks SUPPORTED_UPLOAD_ASSET_TYPES and returns "Unsupported asset type" for MIME types outside the existing image/video/pdf list. As a result, attempting to attach a ZIP or DOCX fails even though the UI now advertises arbitrary uploads. Consider widening the whitelist or skipping that check for userUploaded assets so the feature works as described.

Useful? React with 👍 / 👎.

- Fix attachAsset mutation to fetch and return complete asset with fileName
  instead of just returning the input (which lacks fileName)
- Remove replace/edit button for user-uploaded files - users can only
  delete and re-upload instead
- This ensures the filename displays correctly in the UI immediately
  after upload

Fixes fileName propagation issue for user-uploaded assets
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
apps/web/components/dashboard/preview/AttachmentBox.tsx (2)

125-149: Replace logic correctly excludes userUploaded assets.

The condition isAllowedToAttachAsset(asset.assetType) && asset.assetType !== "userUploaded" appropriately prevents inline replacement for user-uploaded files. This is the correct behavior, as user-uploaded files should be deleted and re-uploaded rather than replaced inline.

Note: There is a typo in the accept attribute on line 130 (.jgp should be .jpg), which has already been flagged in a previous review comment.


206-229: Upload File button implementation is correct, but note backend validation issue.

The new "Upload File" button correctly implements the client-side flow for uploading arbitrary files and attaching them as userUploaded assets. However, as noted in a previous review comment, the backend upload endpoint still validates against a whitelist of supported MIME types, which will cause uploads of non-whitelisted files (e.g., DOCX, ZIP) to fail with "Unsupported asset type" errors.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d005690 and 8aa5ef5.

📒 Files selected for processing (2)
  • apps/web/components/dashboard/preview/AttachmentBox.tsx (2 hunks)
  • packages/trpc/routers/assets.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use oxlint as the linter for JavaScript/TypeScript code

Files:

  • apps/web/components/dashboard/preview/AttachmentBox.tsx
  • packages/trpc/routers/assets.ts
apps/web/**

📄 CodeRabbit inference engine (AGENTS.md)

The main Next.js web application code resides in apps/web

Files:

  • apps/web/components/dashboard/preview/AttachmentBox.tsx
packages/trpc/**

📄 CodeRabbit inference engine (AGENTS.md)

tRPC routers and procedures (business logic) reside in packages/trpc

Files:

  • packages/trpc/routers/assets.ts
🧬 Code graph analysis (2)
apps/web/components/dashboard/preview/AttachmentBox.tsx (3)
packages/trpc/lib/attachments.ts (2)
  • humanFriendlyNameForAssertType (43-57)
  • isAllowedToAttachAsset (59-73)
packages/shared/utils/assetUtils.ts (1)
  • getAssetUrl (1-3)
packages/api/utils/upload.ts (1)
  • uploadAsset (41-133)
packages/trpc/routers/assets.ts (2)
packages/db/schema.ts (1)
  • assets (235-270)
packages/trpc/lib/attachments.ts (1)
  • mapDBAssetTypeToUserType (9-23)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: tests
  • GitHub Check: typecheck
🔇 Additional comments (1)
apps/web/components/dashboard/preview/AttachmentBox.tsx (1)

104-120: LGTM! File name display logic is correct.

The conditional logic properly displays the actual fileName for user-uploaded assets when available, and falls back to the human-friendly type name otherwise. The same pattern is correctly applied to both the asset label and the download attribute.

Comment on lines 124 to 138

// Fetch and return the complete asset with fileName
const [updatedAsset] = await ctx.db
.select()
.from(assets)
.where(
and(eq(assets.id, input.asset.id), eq(assets.userId, ctx.user.id)),
)
.limit(1);

return {
id: updatedAsset.id,
assetType: mapDBAssetTypeToUserType(updatedAsset.assetType),
fileName: updatedAsset.fileName,
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add error handling for the asset fetch after update.

After the UPDATE operation, the SELECT query could theoretically return no rows (e.g., if the asset was deleted by a concurrent operation). The array destructuring const [updatedAsset] would result in undefined, and accessing updatedAsset.id, updatedAsset.assetType, or updatedAsset.fileName would throw a runtime error.

Apply this diff to add error handling:

       // Fetch and return the complete asset with fileName
       const [updatedAsset] = await ctx.db
         .select()
         .from(assets)
         .where(
           and(eq(assets.id, input.asset.id), eq(assets.userId, ctx.user.id)),
         )
         .limit(1);
+
+      if (!updatedAsset) {
+        throw new TRPCError({
+          code: "NOT_FOUND",
+          message: "Asset not found after update",
+        });
+      }
 
       return {
         id: updatedAsset.id,
         assetType: mapDBAssetTypeToUserType(updatedAsset.assetType),
         fileName: updatedAsset.fileName,
       };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Fetch and return the complete asset with fileName
const [updatedAsset] = await ctx.db
.select()
.from(assets)
.where(
and(eq(assets.id, input.asset.id), eq(assets.userId, ctx.user.id)),
)
.limit(1);
return {
id: updatedAsset.id,
assetType: mapDBAssetTypeToUserType(updatedAsset.assetType),
fileName: updatedAsset.fileName,
};
// Fetch and return the complete asset with fileName
const [updatedAsset] = await ctx.db
.select()
.from(assets)
.where(
and(eq(assets.id, input.asset.id), eq(assets.userId, ctx.user.id)),
)
.limit(1);
if (!updatedAsset) {
throw new TRPCError({
code: "NOT_FOUND",
message: "Asset not found after update",
});
}
return {
id: updatedAsset.id,
assetType: mapDBAssetTypeToUserType(updatedAsset.assetType),
fileName: updatedAsset.fileName,
};
🤖 Prompt for AI Agents
In packages/trpc/routers/assets.ts around lines 124-138, the SELECT after the
update may return no rows so destructuring yields undefined; add a check after
fetching (if updatedAsset is falsy) and throw a proper TRPCError (e.g.,
NOT_FOUND with a clear message) or return an appropriate error response instead
of accessing properties, ensuring downstream code only reads
id/assetType/fileName when updatedAsset exists.

@MohamedBassem MohamedBassem merged commit 31960fc into main Nov 8, 2025
7 of 9 checks passed
alexlebens pushed a commit to alexlebens/infrastructure that referenced this pull request Nov 14, 2025
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [ghcr.io/karakeep-app/karakeep](https://github.com/karakeep-app/karakeep) | minor | `0.27.1` -> `0.28.0` |

---

### Release Notes

<details>
<summary>karakeep-app/karakeep (ghcr.io/karakeep-app/karakeep)</summary>

### [`v0.28.0`](https://github.com/karakeep-app/karakeep/releases/tag/v0.28.0): 0.28.0

[Compare Source](karakeep-app/karakeep@v0.27.1...v0.28.0)

### 0.28.0 (20k stars ⭐)

Welcome to the 0.28.0 release of Karakeep! We've have hit 20k stars on Github 🎉 (well 21k because I was too late with the release)! Thanks a lot for your support throughout this journey! This release brings a refreshed import pipeline, uploading custom attachments, revamped tags page, inline checklists, and a bunch of quality-of-life touches across the web app, extension and mobile app. Huge thanks to [@&#8203;BOTkirial](https://github.com/BOTkirial), [@&#8203;qixing-jk](https://github.com/qixing-jk), @&#8203;[@&#8203;maya-doshi](https://github.com/maya-doshi), [@&#8203;BenjaminMichaelis](https://github.com/BenjaminMichaelis), [@&#8203;cloudchristoph](https://github.com/cloudchristoph), [@&#8203;claytono](https://github.com/claytono), as usual [@&#8203;xuatz](https://github.com/xuatz) and everyone who shipped code, triaged bugs, or shared feedback for this release.

> If you enjoy using Karakeep, consider supporting the project [here ☕️](https://buymeacoffee.com/mbassem) or via GitHub [here](https://github.com/sponsors/MohamedBassem).

<a href="https://www.buymeacoffee.com/mbassem" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" width="auto" height="50" ></a>

And in case you missed it, we now have a ☁️ managed offering ☁️ for those who don't want to self-host. We're still in private beta (you can signup for access [here](https://tally.so/r/wo8zzx)) and gradually letting more and more users in.

### New Features 🚀

- Revamped import experience with progress tracking ([#&#8203;2001](karakeep-app/karakeep#2001))
- Revamped Tags page that adds search and pagination to better serve users with thousands of tags ([#&#8203;1987](karakeep-app/karakeep#1987))
- You can now upload custom attachments to bookmarks ([#&#8203;2100](karakeep-app/karakeep#2100))
- When deleting a list, you can now optionally delete all its children ([#&#8203;1989](karakeep-app/karakeep#1989))
- Server overview highlights service dependency health.
- Inline checklist toggling for text bookmarks ([#&#8203;1933](karakeep-app/karakeep#1933)) – [@&#8203;BOTkirial](https://github.com/BOTkirial)
- With every release, you'll be prompted to view what's new in that release from inside the app.
- You can now pass custom headers from the mobile app to the server ([#&#8203;2103](karakeep-app/karakeep#2103))
- Extension improvements:
  - Tab bookmark badge indicator by [@&#8203;qixing-jk](https://github.com/qixing-jk) shows when a page is already bookmarked ([#&#8203;1745](karakeep-app/karakeep#1745))
  - You can now write notes directly after saving a bookmark in the extension ([#&#8203;2104](karakeep-app/karakeep#2104))

### UX Improvements ✨

- Grid view controls expose title/tag toggles and image fit options ([#&#8203;1960](karakeep-app/karakeep#1960))
- Bookmark cards can surface saved notes across web and mobile ([#&#8203;2083](karakeep-app/karakeep#2083)) – [@&#8203;xuatz](https://github.com/xuatz)
- Manage Lists modal is searchable for faster sorting ([#&#8203;2029](karakeep-app/karakeep#2029))
- The tags page now has a "Create Tag" button ([#&#8203;1942](karakeep-app/karakeep#1942))
- You can now regenerate the API key without having to recreate it.
- New `title:` seach qualifier for searching bookmarks by title ([#&#8203;1940](karakeep-app/karakeep#1940))

### Fixes 🔧

- ⚠️ (Potentially breaking change) ⚠️ Stricter URL valdaition to protect against SSRF attacks ([#&#8203;2082](karakeep-app/karakeep#2082))
  - Webhook requests now go through the proxy if there's one configured
  - All server-initiated requests (including webhooks) to internal IP addresses are now blocked by default unless explicitly allowed via `CRAWLER_ALLOWED_INTERNAL_HOSTNAMES`. If your webhooks are hitting internal services, you'll have to allowlist them via `CRAWLER_ALLOWED_INTERNAL_HOSTNAMES`.
  - Monolith now honors the configured crawler proxy.
  - Metascraper logo extraction now respects the crawler proxy.
- Crawler memory footprint shrinks with targeted optimizations ([#&#8203;1748](karakeep-app/karakeep#1748))
- Allow karakeep to use newer openai models that was previously failing because of deprecated max\_tokens ([#&#8203;2000](karakeep-app/karakeep#2000)) - [@&#8203;BenjaminMichaelis](https://github.com/BenjaminMichaelis)
  - You'll need to set `INFERENCE_USE_MAX_COMPLETION_TOKENS=true` in your `.env` file to use the new models. This is eventually going to become the default.
- Admin maintenance jobs respect abort signals to stop gracefully
- Search input no longer crashes on percent signs and also works correctly with IME composition
- Fixed a crash when sharing a list publicly that didn't have any bookmarks ([#&#8203;1990](karakeep-app/karakeep#1990))
- Screenshots are now stored as jpegs instead of pngs to reduce file size
- Fixed a bug that was preventing tag merging ([#&#8203;1938](karakeep-app/karakeep#1938))
- RSS imports can apply feed categories as tags ([#&#8203;2031](karakeep-app/karakeep#2031))

### For Developers 🛠️

- Create bookmark API returns 200 instead of 201 when a bookmark already exists
- CLI Improvements:
  - New commands to migrate data from one server to another
  - New command to dump a full account archive
  - A new wipe command to selectively clean up data from the account

### Community Projects 💡

##### [Karakeeper](https://apps.apple.com/us/app/karakeeper-for-karakeep/id6746722790)

3rd Party iOS/Safari Client - *by [@&#8203;simplytoast1](https://github.com/simplytoast1)*

Karakeeper now is providing an alternative iOS native mobile/desktop client for Karakeep beyond its existing functionality of providing a safari extension.

##### [Karakeep Sync](https://github.com/sidoshi/karakeep-sync)

A syncing tool for Karakeep - *by [@&#8203;sidoshi](https://github.com/sidoshi)*

A rust-based syncing tool that syncs: Hacker News upvotes, Reddit saved posts, Github stars and Pinboard bookmarks automatically to Karakeep!

### Screenshots 📸

#### Inline Checklists

<img width="1230" height="806" alt="Screenshot 2025-11-08 at 8  55 18@&#8203;2x" src="https://github.com/user-attachments/assets/c092d903-eb6f-40c6-aee6-1ce6127f67e8" />

#### Import Sessions
<img width="1814" height="762" alt="Screenshot 2025-11-08 at 8  58 21@&#8203;2x" src="https://github.com/user-attachments/assets/dfcb856b-6a63-4d7a-ba4b-ce2ca83bc844" />

#### Service Health Indicators
<img width="1874" height="540" alt="Screenshot 2025-11-08 at 8  56 00@&#8203;2x" src="https://github.com/user-attachments/assets/7835f1ad-239d-477c-8e00-951e4a09f8c6" />

### Upgrading 📦

To upgrade:

- If you're using `KARAKEEP_VERSION=release`, run `docker compose pull && docker compose up -d`.
- If you're pinning it to a specific version, bump the version and then run `docker compose pull && docker compose up -d`.

### All Commits

- fix: standardize US English translations to professional tone - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`4f025f5`](karakeep-app/karakeep@4f025f5a)
- i18n: Sync weblate translations - [@&#8203;weblate](https://github.com/weblate) in [`5387c98`](karakeep-app/karakeep@5387c982)
- tests: fix crawling and search e2e tests ([#&#8203;2105](karakeep-app/karakeep#2105)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`c4bee9f`](karakeep-app/karakeep@c4bee9fe)
- feat(extension): Allow writing notes directly in the extension ([#&#8203;2104](karakeep-app/karakeep#2104)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`098e56a`](karakeep-app/karakeep@098e56a8)
- fix(mobile): fix default address not correctly stored in settings - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`a220319`](karakeep-app/karakeep@a2203196)
- feat(mobile): add custom headers configuration in sign-in screen ([#&#8203;2103](karakeep-app/karakeep#2103)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`ec621bf`](karakeep-app/karakeep@ec621bf5)
- tests: Fix failing test - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`27ed0a1`](karakeep-app/karakeep@27ed0a19)
- feat: Add what's new modal in the sidebar ([#&#8203;2099](karakeep-app/karakeep#2099)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`474f642`](karakeep-app/karakeep@474f6429)
- feat: Add support for user uploaded files ([#&#8203;2100](karakeep-app/karakeep#2100)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`31960fc`](karakeep-app/karakeep@31960fcd)
- refactor: consolidate multiple karakeep plugins into one package ([#&#8203;2101](karakeep-app/karakeep#2101)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`99413db`](karakeep-app/karakeep@99413db0)
- fix: metascraper logo to go through proxy if one configured. fixes [#&#8203;1863](karakeep-app/karakeep#1863) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`737b031`](karakeep-app/karakeep@737b0317)
- feat(extension): add tab bookmark badge indicator ([#&#8203;1745](karakeep-app/karakeep#1745)) - [@&#8203;qixing-jk](https://github.com/qixing-jk) in [`f0b0959`](karakeep-app/karakeep@f0b0959e)
- fix: restore image size in grid layout - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`2056582`](karakeep-app/karakeep@2056582c)
- deps: Upgrade react-query to 5.90 - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`560900b`](karakeep-app/karakeep@560900bb)
- feat: Support inline toggling for todos. fixes [#&#8203;1931](karakeep-app/karakeep#1931) ([#&#8203;1933](karakeep-app/karakeep#1933)) - [@&#8203;BOTkirial](https://github.com/BOTkirial) in [`393bbd9`](karakeep-app/karakeep@393bbd9a)
- fix: fix monolith to respect crawler proxy - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`085c832`](karakeep-app/karakeep@085c832c)
- feat(rss): Add import tags from RSS feed categories ([#&#8203;2031](karakeep-app/karakeep#2031)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`5358682`](karakeep-app/karakeep@5358682a)
- fix: fix crash in search input when query contains a percent. fixes [#&#8203;1941](karakeep-app/karakeep#1941) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`633686b`](karakeep-app/karakeep@633686b5)
- feat: Add view options to show tag/title and control image fit. Fixes [#&#8203;1960](karakeep-app/karakeep#1960) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`34d2b48`](karakeep-app/karakeep@34d2b485)
- refactor: improve the userLocalSetting server functions - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`bb00c99`](karakeep-app/karakeep@bb00c996)
- feat: Make search job timeout configurable - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`965c603`](karakeep-app/karakeep@965c603d)
- feat: display notes on bookmark card ([#&#8203;2083](karakeep-app/karakeep#2083)) - [@&#8203;xuatz](https://github.com/xuatz) in [`33f4077`](karakeep-app/karakeep@33f40779)
- fix: Stricter SSRF validation ([#&#8203;2082](karakeep-app/karakeep#2082)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`b63a49f`](karakeep-app/karakeep@b63a49fc)
- fix: correctly handle composition in search input. fixes [#&#8203;2048](karakeep-app/karakeep#2048) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`c6ebceb`](karakeep-app/karakeep@c6ebceb9)
- fix: browser service connection check using dns instead. Fixes [#&#8203;2080](karakeep-app/karakeep#2080) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`c9c73d4`](karakeep-app/karakeep@c9c73d41)
- fix: More memory optimizations for crawler worker. [#&#8203;1748](karakeep-app/karakeep#1748) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`40d548b`](karakeep-app/karakeep@40d548bd)
- fix: fix screenshot filepath in crawler - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`0704b8b`](karakeep-app/karakeep@0704b8bb)
- docs: Add Azure configuration details for OpenAI-compatible API ([#&#8203;2072](karakeep-app/karakeep#2072)) - [@&#8203;cloudchristoph](https://github.com/cloudchristoph) in [`bd9c933`](karakeep-app/karakeep@bd9c933b)
- fix: Respect abort signal in admin maintenance jobs - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`8a330dc`](karakeep-app/karakeep@8a330dc2)
- deps: Upgrade metascraper plugins - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`e43c7e0`](karakeep-app/karakeep@e43c7e0f)
- deps: Upgrade metascraper-readability 5.49.6 - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`6d234de`](karakeep-app/karakeep@6d234de8)
- feat: Allow configuring inline asset size threshold - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`cf3ffff`](karakeep-app/karakeep@cf3ffff0)
- feat: Add admin maintenance job to migrate large inline HTML ([#&#8203;2071](karakeep-app/karakeep#2071)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`2b769cb`](karakeep-app/karakeep@2b769cba)
- fix(inferance): skip token slicing when content is already witin max length - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`1713600`](karakeep-app/karakeep@17136006)
- refactor: generalize tidy assets queue into admin maintenance ([#&#8203;2059](karakeep-app/karakeep#2059)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`6ea5dd1`](karakeep-app/karakeep@6ea5dd19)
- fix: update OpenAI API to use max\_completion\_tokens instead of max\_tokens ([#&#8203;2000](karakeep-app/karakeep#2000)) - [@&#8203;BenjaminMichaelis](https://github.com/BenjaminMichaelis) in [`046c29d`](karakeep-app/karakeep@046c29dc)
- fix(restate): Fix priority for restate queue - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`8c0aae3`](karakeep-app/karakeep@8c0aae33)
- fix(restate): Ensure that the semaphore and idProvider services are ingress private - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`cdf8121`](karakeep-app/karakeep@cdf81213)
- feat: Add source field to track bookmark creation sources ([#&#8203;2037](karakeep-app/karakeep#2037)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`2defc24`](karakeep-app/karakeep@2defc247)
- feat: support passing multiple proxy values ([#&#8203;2039](karakeep-app/karakeep#2039)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`c14b693`](karakeep-app/karakeep@c14b6934)
- deps: Upgrade oxlint to 1.22 - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`88a7ffe`](karakeep-app/karakeep@88a7ffec)
- feat: Add service dependency checks in the server overview page - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`fda1c85`](karakeep-app/karakeep@fda1c851)
- fix(web): Add w-full to tags editor to prevent unusable narrow width ([#&#8203;2035](karakeep-app/karakeep#2035)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`7ee9416`](karakeep-app/karakeep@7ee9416e)
- fix(api): Return 200 when bookmark already exists instead of 200 - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`f2dec26`](karakeep-app/karakeep@f2dec26f)
- tests: Add a test for the GET /bookmarks/bookmarkId/lists api - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`d578038`](karakeep-app/karakeep@d5780388)
- fix(api): Document the API for getting lists of a bookmark. fixes [#&#8203;2030](karakeep-app/karakeep#2030) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`7f138b9`](karakeep-app/karakeep@7f138b99)
- feat: make list dropdown searchable in Manage Lists modal ([#&#8203;2029](karakeep-app/karakeep#2029)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`87053d2`](karakeep-app/karakeep@87053d2e)
- fix: fix dev script shebang for better compatibility ([#&#8203;2019](karakeep-app/karakeep#2019)) - [@&#8203;maya-doshi](https://github.com/maya-doshi) in [`dcddda5`](karakeep-app/karakeep@dcddda56)
- fix: Correct grammatical errors in prompts ([#&#8203;2020](karakeep-app/karakeep#2020)) - [@&#8203;atsggx](https://github.com/atsggx) in [`f1e8cea`](karakeep-app/karakeep@f1e8cea2)
- docs: Add karakeep-sync to community projects ([#&#8203;1994](karakeep-app/karakeep#1994)) - [@&#8203;sidoshi](https://github.com/sidoshi) in [`36ffbdf`](karakeep-app/karakeep@36ffbdf8)
- fix: round feed refresh hour for idempotency ([#&#8203;2013](karakeep-app/karakeep#2013)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`bae8386`](karakeep-app/karakeep@bae8386d)
- fix: fix show no bookmark page when there isn't search results - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`57d731b`](karakeep-app/karakeep@57d731ba)
- fix: Disable idempotency keys for search - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`b6867be`](karakeep-app/karakeep@b6867be4)
- feat: Restate-based queue plugin ([#&#8203;2011](karakeep-app/karakeep#2011)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`74a1f7b`](karakeep-app/karakeep@74a1f7b6)
- feat: Revamp import experience ([#&#8203;2001](karakeep-app/karakeep#2001)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`4a580d7`](karakeep-app/karakeep@4a580d71)
- docs: Add doc updates for prometheus metrics ([#&#8203;1957](karakeep-app/karakeep#1957)) - [@&#8203;claytono](https://github.com/claytono) in [`5e331a7`](karakeep-app/karakeep@5e331a7d)
- fix: fix public list sharing for empty lists ([#&#8203;1990](karakeep-app/karakeep#1990)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`7df6d94`](karakeep-app/karakeep@7df6d942)
- feat: recursive list delete ([#&#8203;1989](karakeep-app/karakeep#1989)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`7d0b414`](karakeep-app/karakeep@7d0b414f)
- feat: use jpegs for screenshots instead of pngs - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`ed1f24f`](karakeep-app/karakeep@ed1f24f2)
- feat: Stop downloading video/audio in playwright - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`37845f9`](karakeep-app/karakeep@37845f99)
- fix: Abort dangling processing when crawler is aborted ([#&#8203;1988](karakeep-app/karakeep#1988)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`9eecda1`](karakeep-app/karakeep@9eecda18)
- fix: Cleanup temp assets on monolith timeout - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`8dd84ef`](karakeep-app/karakeep@8dd84ef5)
- chore: Silence lint on <a> and <img> tags when it's intentional - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`cdbedf6`](karakeep-app/karakeep@cdbedf6c)
- fix: dont re-enqueue indexing for a bookmark already pending indexing - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`e395ac2`](karakeep-app/karakeep@e395ac27)
- feat: Add tag search and pagination ([#&#8203;1987](karakeep-app/karakeep#1987)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`62f7d90`](karakeep-app/karakeep@62f7d900)
- fix: optimize memory usage of tag listing - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`9fe09bf`](karakeep-app/karakeep@9fe09bfa)
- deps: Upgrade oxlint to 1.16 - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`bbc5e6c`](karakeep-app/karakeep@bbc5e6c2)
- fix: fix bundling liteque in the workers - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`851d3e2`](karakeep-app/karakeep@851d3e29)
- refactor: Move callsites to liteque to be behind a plugin - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`8d32055`](karakeep-app/karakeep@8d320554)
- fix(dev): worker not started properly in helper start script ([#&#8203;1946](karakeep-app/karakeep#1946)) - [@&#8203;xuatz](https://github.com/xuatz) in [`6ba61b4`](karakeep-app/karakeep@6ba61b46)
- feat: Regen api keys - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`7671f4f`](karakeep-app/karakeep@7671f4ff)
- release(cli): Bump CLI version to 0.27.1 - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`69ef2ff`](karakeep-app/karakeep@69ef2ffe)
- feat(cli): Give more targetting options for dump/migrate/wipe - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`6501f69`](karakeep-app/karakeep@6501f69a)
- release(cli): Bump CLI version to 0.27.0 - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`0700aab`](karakeep-app/karakeep@0700aab8)
- feat(cli): Implement a full account dump archive - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`b9a8ca2`](karakeep-app/karakeep@b9a8ca29)
- feat(cli): Implement a wipe command in the CLI - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`bc0e746`](karakeep-app/karakeep@bc0e7461)
- feat: Add scripts to migrate all content from one server to the other - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`783f72c`](karakeep-app/karakeep@783f72cb)
- fix(web): Handle user deletion more gracefully - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`92e357f`](karakeep-app/karakeep@92e357f1)
- feat: A better looking catch all error boundary - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`d53b282`](karakeep-app/karakeep@d53b2826)
- fix(web): fix error when attempting to merge tags. fixes [#&#8203;1938](karakeep-app/karakeep#1938) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`d173b10`](karakeep-app/karakeep@d173b101)
- feat: Add Create Tag button to tags page ([#&#8203;1942](karakeep-app/karakeep#1942)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`820b7e6`](karakeep-app/karakeep@820b7e65)
- chore: fix claude code action - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`c2dcb9d`](karakeep-app/karakeep@c2dcb9dc)
- refactor: strongly type the search plugin interface - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`bf5bf99`](karakeep-app/karakeep@bf5bf996)
- feat(search): add title search qualifier ([#&#8203;1940](karakeep-app/karakeep#1940)) - [@&#8203;MohamedBassem](https://github.com/MohamedBassem) in [`a92ada7`](karakeep-app/karakeep@a92ada77)
- feat(extension): add current tab title while saving from extension ([#&#8203;1930](karakeep-app/karakeep#1930)) - [@&#8203;Abel](https://github.com/Abel) in [`b594ff0`](karakeep-app/karakeep@b594ff09)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0Mi41LjAiLCJ1cGRhdGVkSW5WZXIiOiI0Mi41LjAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbImltYWdlIl19-->

Reviewed-on: https://gitea.alexlebens.dev/alexlebens/infrastructure/pulls/2006
Co-authored-by: Renovate Bot <[email protected]>
Co-committed-by: Renovate Bot <[email protected]>
@MohamedBassem MohamedBassem deleted the claude/karakeep-al-011CUvX24FPQBwqJW9FJQD7X branch November 16, 2025 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Upload and attach files to bookmarks

3 participants