forked from mirror/crumbs-original
Bumps deps to clear all 69 pnpm audit findings (nodemailer 8->9 for the raw-option SSRF/arbitrary-file-read CVE; svelte, hono/express/qs chain, linkify-it, and the rest resolved within their existing semver ranges via a lockfile refresh). Caps the previously-unbounded cookie override at <1 so it can't silently jump to the API-incompatible 2.x line again. Hardens the MCP upload_image tool, which fetched an arbitrary caller- supplied URL and stored whatever content-type came back with no checks: - validates every resolved DNS record (not just the first) against private/loopback/link-local/multicast ranges, then pins the actual connection to the validated address so a second, unvalidated lookup at connect time can't be used for DNS-rebinding SSRF - rejects non-image content-types and enforces the same 10MB cap as the manual upload endpoint - adds X-Content-Type-Options: nosniff to both attachment-serving routes as defense in depth Also validates the admin role field server-side (previously trusted the client-supplied string), and fixes two incidental regressions surfaced by the dependency bump: StarterKit now bundles its own Link/Underline extensions (disabled to avoid duplicate registration), and FormattingToolbar could call methods on an already-destroyed editor instance during the markdown-mode toggle race. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
890 lines
16 KiB
JSON
890 lines
16 KiB
JSON
{
|
|
"openapi": "3.1.0",
|
|
"info": {
|
|
"title": "Crumbs API",
|
|
"description": "Auto-generated API spec for crumbs",
|
|
"version": "0.31.0",
|
|
"contact": {
|
|
"name": "Bretzel",
|
|
"url": "https://bretzel.app"
|
|
}
|
|
},
|
|
"servers": [
|
|
{
|
|
"url": "/",
|
|
"description": "Current instance"
|
|
}
|
|
],
|
|
"security": [
|
|
{
|
|
"sessionCookie": []
|
|
}
|
|
],
|
|
"paths": {
|
|
"/api/admin/users": {
|
|
"get": {
|
|
"tags": [
|
|
"Admin"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Admin"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/admin/users/{id}": {
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"patch": {
|
|
"tags": [
|
|
"Admin"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Admin"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/account": {
|
|
"delete": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/login": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/logout": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/oauth/{provider}": {
|
|
"parameters": [
|
|
{
|
|
"name": "provider",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"get": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/oauth/{provider}/callback": {
|
|
"parameters": [
|
|
{
|
|
"name": "provider",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"get": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/password": {
|
|
"put": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/profile": {
|
|
"put": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/sessions": {
|
|
"get": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/auth/setup": {
|
|
"post": {
|
|
"tags": [
|
|
"Auth"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/mcp": {
|
|
"post": {
|
|
"tags": [
|
|
"Mcp"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"get": {
|
|
"tags": [
|
|
"Mcp"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Mcp"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/notes": {
|
|
"get": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/notes/reorder": {
|
|
"post": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/notes/{id}": {
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"get": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
},
|
|
"patch": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/notes/{id}/attachments": {
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"get": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"patch": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/notes/{id}/collaborators": {
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"get": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/notes/{id}/share": {
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"post": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/notes/{id}/versions": {
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"get": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/notes/{id}/versions/{versionId}": {
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "versionId",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"get": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/notes/{id}/versions/{versionId}/restore": {
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "versionId",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"post": {
|
|
"tags": [
|
|
"Notes"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/preferences": {
|
|
"get": {
|
|
"tags": [
|
|
"Preferences"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
},
|
|
"put": {
|
|
"tags": [
|
|
"Preferences"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/search": {
|
|
"get": {
|
|
"tags": [
|
|
"Search"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/settings/api-keys": {
|
|
"get": {
|
|
"tags": [
|
|
"Settings"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
},
|
|
"post": {
|
|
"tags": [
|
|
"Settings"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/settings/api-keys/{id}": {
|
|
"parameters": [
|
|
{
|
|
"name": "id",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"delete": {
|
|
"tags": [
|
|
"Settings"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/shared/{token}": {
|
|
"parameters": [
|
|
{
|
|
"name": "token",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"get": {
|
|
"tags": [
|
|
"Shared"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/shared/{token}/attachment/{attachmentId}": {
|
|
"parameters": [
|
|
{
|
|
"name": "token",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
{
|
|
"name": "attachmentId",
|
|
"in": "path",
|
|
"required": true,
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"get": {
|
|
"tags": [
|
|
"Shared"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/sync": {
|
|
"post": {
|
|
"tags": [
|
|
"Sync"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
},
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "object"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"get": {
|
|
"tags": [
|
|
"Sync"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/tags": {
|
|
"get": {
|
|
"tags": [
|
|
"Tags"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/users/search": {
|
|
"get": {
|
|
"tags": [
|
|
"Users"
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "Success"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"components": {
|
|
"securitySchemes": {
|
|
"sessionCookie": {
|
|
"type": "apiKey",
|
|
"in": "cookie",
|
|
"name": "session"
|
|
}
|
|
}
|
|
}
|
|
}
|