mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-11 07:06:28 +08:00
0a422aa158
#### PR Dependency Tree * **PR #15165** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added automated backend maintenance for missing blob metadata backfill, document-to-blob reference rebuilding, and unreferenced blob cleanup planning/execution. * Introduced scheduled batch processing (workspace-paged) and paginated object-storage listing. * **Bug Fixes** * Improved reliability of object-storage reads by treating expected “not found” results as non-errors. * Strengthened blob/expired cleanup flows with runtime-driven batching and reduced coupling to metadata synchronization. * **Tests** * Expanded unit and e2e coverage for partial blob metadata and updated runtime/job cleanup test assertions. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
484 lines
15 KiB
JSON
484 lines
15 KiB
JSON
{
|
|
"metrics": {
|
|
"enabled": {
|
|
"type": "Boolean",
|
|
"desc": "Enable metric and tracing collection"
|
|
}
|
|
},
|
|
"crypto": {
|
|
"privateKey": {
|
|
"type": "String",
|
|
"desc": "The private key for used by the crypto module to create signed tokens or encrypt data.",
|
|
"env": "AFFINE_PRIVATE_KEY"
|
|
}
|
|
},
|
|
"job": {
|
|
"queue": {
|
|
"type": "Object",
|
|
"desc": "The config for job queues",
|
|
"link": "https://api.docs.bullmq.io/interfaces/v5.QueueOptions.html"
|
|
},
|
|
"worker": {
|
|
"type": "Object",
|
|
"desc": "The config for job workers",
|
|
"link": "https://api.docs.bullmq.io/interfaces/v5.WorkerOptions.html"
|
|
},
|
|
"queues.copilot": {
|
|
"type": "Object",
|
|
"desc": "The config for copilot job queue"
|
|
},
|
|
"queues.calendar": {
|
|
"type": "Object",
|
|
"desc": "The config for calendar job queue"
|
|
},
|
|
"queues.doc": {
|
|
"type": "Object",
|
|
"desc": "The config for doc job queue"
|
|
},
|
|
"queues.indexer": {
|
|
"type": "Object",
|
|
"desc": "The config for indexer job queue"
|
|
},
|
|
"queues.notification": {
|
|
"type": "Object",
|
|
"desc": "The config for notification job queue"
|
|
},
|
|
"queues.nightly": {
|
|
"type": "Object",
|
|
"desc": "The config for nightly job queue"
|
|
},
|
|
"queues.backendRuntime": {
|
|
"type": "Object",
|
|
"desc": "The config for backend runtime job queue"
|
|
}
|
|
},
|
|
"throttle": {
|
|
"enabled": {
|
|
"type": "Boolean",
|
|
"desc": "Whether the throttler is enabled."
|
|
},
|
|
"throttlers.default": {
|
|
"type": "Object",
|
|
"desc": "The config for the default throttler."
|
|
},
|
|
"throttlers.strict": {
|
|
"type": "Object",
|
|
"desc": "The config for the strict throttler."
|
|
}
|
|
},
|
|
"auth": {
|
|
"allowSignup": {
|
|
"type": "Boolean",
|
|
"desc": "Whether allow new registrations."
|
|
},
|
|
"allowSignupForOauth": {
|
|
"type": "Boolean",
|
|
"desc": "Whether allow new registrations via configured oauth."
|
|
},
|
|
"requireEmailDomainVerification": {
|
|
"type": "Boolean",
|
|
"desc": "Whether require email domain record verification before accessing restricted resources."
|
|
},
|
|
"requireEmailVerification": {
|
|
"type": "Boolean",
|
|
"desc": "Whether require email verification before accessing restricted resources(not implemented)."
|
|
},
|
|
"newAccountShareActionDelay": {
|
|
"type": "Number",
|
|
"desc": "Minimum account age in seconds before new accounts can invite members or create share links."
|
|
},
|
|
"passwordRequirements": {
|
|
"type": "Object",
|
|
"desc": "The password strength requirements when set new password."
|
|
},
|
|
"session.ttl": {
|
|
"type": "Number",
|
|
"desc": "Application auth expiration time in seconds."
|
|
},
|
|
"session.ttr": {
|
|
"type": "Number",
|
|
"desc": "Application auth time to refresh in seconds."
|
|
}
|
|
},
|
|
"mailer": {
|
|
"SMTP.name": {
|
|
"type": "String",
|
|
"desc": "Hostname used for SMTP HELO/EHLO (e.g. mail.example.com). Leave empty to use the system hostname.",
|
|
"env": "MAILER_SERVERNAME"
|
|
},
|
|
"SMTP.host": {
|
|
"type": "String",
|
|
"desc": "Host of the email server (e.g. smtp.gmail.com)",
|
|
"env": "MAILER_HOST"
|
|
},
|
|
"SMTP.port": {
|
|
"type": "Number",
|
|
"desc": "Port of the email server (they commonly are 25, 465 or 587)",
|
|
"env": "MAILER_PORT"
|
|
},
|
|
"SMTP.username": {
|
|
"type": "String",
|
|
"desc": "Username used to authenticate the email server",
|
|
"env": "MAILER_USER"
|
|
},
|
|
"SMTP.password": {
|
|
"type": "String",
|
|
"desc": "Password used to authenticate the email server",
|
|
"env": "MAILER_PASSWORD"
|
|
},
|
|
"SMTP.sender": {
|
|
"type": "String",
|
|
"desc": "Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")",
|
|
"env": "MAILER_SENDER"
|
|
},
|
|
"SMTP.ignoreTLS": {
|
|
"type": "Boolean",
|
|
"desc": "Whether ignore email server's TLS certificate verification. Enable it for self-signed certificates.",
|
|
"env": "MAILER_IGNORE_TLS"
|
|
},
|
|
"fallbackDomains": {
|
|
"type": "Array",
|
|
"desc": "The emails from these domains are always sent using the fallback SMTP server."
|
|
},
|
|
"fallbackSMTP.name": {
|
|
"type": "String",
|
|
"desc": "Hostname used for fallback SMTP HELO/EHLO (e.g. mail.example.com). Leave empty to use the system hostname."
|
|
},
|
|
"fallbackSMTP.host": {
|
|
"type": "String",
|
|
"desc": "Host of the email server (e.g. smtp.gmail.com)"
|
|
},
|
|
"fallbackSMTP.port": {
|
|
"type": "Number",
|
|
"desc": "Port of the email server (they commonly are 25, 465 or 587)"
|
|
},
|
|
"fallbackSMTP.username": {
|
|
"type": "String",
|
|
"desc": "Username used to authenticate the email server"
|
|
},
|
|
"fallbackSMTP.password": {
|
|
"type": "String",
|
|
"desc": "Password used to authenticate the email server"
|
|
},
|
|
"fallbackSMTP.sender": {
|
|
"type": "String",
|
|
"desc": "Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")"
|
|
},
|
|
"fallbackSMTP.ignoreTLS": {
|
|
"type": "Boolean",
|
|
"desc": "Whether ignore email server's TLS certificate verification. Enable it for self-signed certificates."
|
|
}
|
|
},
|
|
"doc": {
|
|
"experimental.yocto": {
|
|
"type": "Boolean",
|
|
"desc": "Use `y-octo` to merge updates at the same time when merging using Yjs."
|
|
},
|
|
"history.interval": {
|
|
"type": "Number",
|
|
"desc": "The minimum time interval in milliseconds of creating a new history snapshot when doc get updated."
|
|
}
|
|
},
|
|
"permission": {
|
|
"readModel": {
|
|
"type": "String",
|
|
"desc": "Permission data source for Rust evaluation",
|
|
"env": "AFFINE_PERMISSION_READ_MODEL"
|
|
},
|
|
"fallbackLegacyLoader": {
|
|
"type": "Boolean",
|
|
"desc": "Fallback from projection loader to legacy loader when projection input loading fails",
|
|
"env": "AFFINE_PERMISSION_FALLBACK_LEGACY_LOADER"
|
|
}
|
|
},
|
|
"storages": {
|
|
"avatar.publicPath": {
|
|
"type": "String",
|
|
"desc": "The public accessible path prefix for user avatars."
|
|
},
|
|
"avatar.storage": {
|
|
"type": "Object",
|
|
"desc": "The config of storage for user avatars."
|
|
},
|
|
"blob.storage": {
|
|
"type": "Object",
|
|
"desc": "The config of storage for all uploaded blobs(images, videos, etc.)."
|
|
}
|
|
},
|
|
"websocket": {
|
|
"transports": {
|
|
"type": "Array",
|
|
"desc": "The enabled transports for accepting websocket traffics.",
|
|
"link": "https://docs.nestjs.com/websockets/gateways#transports"
|
|
},
|
|
"maxHttpBufferSize": {
|
|
"type": "Number",
|
|
"desc": "How many bytes or characters a message can be, before closing the session (to avoid DoS)."
|
|
}
|
|
},
|
|
"server": {
|
|
"name": {
|
|
"type": "String",
|
|
"desc": "A recognizable name for the server. Will be shown when connected with AFFiNE Desktop."
|
|
},
|
|
"externalUrl": {
|
|
"type": "String",
|
|
"desc": "Base url of AFFiNE server, used for generating external urls.\nDefault to be `[server.protocol]://[server.host][:server.port]` if not specified.\n ",
|
|
"env": "AFFINE_SERVER_EXTERNAL_URL"
|
|
},
|
|
"https": {
|
|
"type": "Boolean",
|
|
"desc": "Whether the server is hosted on a ssl enabled domain (https://).",
|
|
"env": "AFFINE_SERVER_HTTPS"
|
|
},
|
|
"host": {
|
|
"type": "String",
|
|
"desc": "Where the server get deployed(FQDN).",
|
|
"env": "AFFINE_SERVER_HOST"
|
|
},
|
|
"hosts": {
|
|
"type": "Array",
|
|
"desc": "Multiple hosts the server will accept requests from."
|
|
},
|
|
"listenAddr": {
|
|
"type": "String",
|
|
"desc": "The address to listen on (e.g., 0.0.0.0 for IPv4, :: for IPv6).",
|
|
"env": "LISTEN_ADDR"
|
|
},
|
|
"port": {
|
|
"type": "Number",
|
|
"desc": "Which port the server will listen on.",
|
|
"env": "AFFINE_SERVER_PORT"
|
|
},
|
|
"path": {
|
|
"type": "String",
|
|
"desc": "Subpath where the server get deployed if there is one.(e.g. /affine)",
|
|
"env": "AFFINE_SERVER_SUB_PATH"
|
|
}
|
|
},
|
|
"flags": {
|
|
"allowGuestDemoWorkspace": {
|
|
"type": "Boolean",
|
|
"desc": "Whether allow guest users to create demo workspaces."
|
|
}
|
|
},
|
|
"docService": {
|
|
"endpoint": {
|
|
"type": "String",
|
|
"desc": "The endpoint of the doc service.",
|
|
"env": "DOC_SERVICE_ENDPOINT"
|
|
}
|
|
},
|
|
"telemetry": {
|
|
"allowedOrigin": {
|
|
"type": "Array",
|
|
"desc": "Allowed origins for telemetry collection."
|
|
},
|
|
"ga4.measurementId": {
|
|
"type": "String",
|
|
"desc": "GA4 Measurement ID for Measurement Protocol.",
|
|
"env": "GA4_MEASUREMENT_ID"
|
|
},
|
|
"ga4.apiSecret": {
|
|
"type": "String",
|
|
"desc": "GA4 API secret for Measurement Protocol.",
|
|
"env": "GA4_API_SECRET"
|
|
},
|
|
"dedupe.ttlHours": {
|
|
"type": "Number",
|
|
"desc": "Telemetry dedupe TTL in hours."
|
|
},
|
|
"dedupe.maxEntries": {
|
|
"type": "Number",
|
|
"desc": "Telemetry dedupe max entries."
|
|
},
|
|
"batch.maxEvents": {
|
|
"type": "Number",
|
|
"desc": "Max events per telemetry batch."
|
|
}
|
|
},
|
|
"client": {
|
|
"versionControl.enabled": {
|
|
"type": "Boolean",
|
|
"desc": "Whether check version of client before accessing the server."
|
|
},
|
|
"versionControl.requiredVersion": {
|
|
"type": "String",
|
|
"desc": "Allowed version range of the app that allowed to access the server. Requires 'client/versionControl.enabled' to be true to take effect."
|
|
}
|
|
},
|
|
"calendar": {
|
|
"google": {
|
|
"type": "Object",
|
|
"desc": "Google Calendar integration config",
|
|
"link": "https://developers.google.com/calendar/api/guides/push"
|
|
},
|
|
"caldav": {
|
|
"type": "Object",
|
|
"desc": "CalDAV integration config"
|
|
}
|
|
},
|
|
"captcha": {
|
|
"enabled": {
|
|
"type": "Boolean",
|
|
"desc": "Check captcha challenge when user authenticating the app."
|
|
},
|
|
"config": {
|
|
"type": "Object",
|
|
"desc": "The config for the captcha plugin."
|
|
}
|
|
},
|
|
"copilot": {
|
|
"enabled": {
|
|
"type": "Boolean",
|
|
"desc": "Whether to enable the copilot plugin. <br> Document: <a href=\"https://docs.affine.pro/self-host-affine/administer/ai\" target=\"_blank\">https://docs.affine.pro/self-host-affine/administer/ai</a>"
|
|
},
|
|
"byok.enabled": {
|
|
"type": "Boolean",
|
|
"desc": "Whether to enable workspace BYOK."
|
|
},
|
|
"byok.allowedProviders": {
|
|
"type": "Array",
|
|
"desc": "The allowlist for workspace BYOK providers."
|
|
},
|
|
"byok.allowCustomEndpoint": {
|
|
"type": "Boolean",
|
|
"desc": "Whether workspace BYOK custom endpoints are accepted."
|
|
},
|
|
"providers.profiles": {
|
|
"type": "Array",
|
|
"desc": "The profile list for copilot providers."
|
|
},
|
|
"providers.defaults": {
|
|
"type": "Object",
|
|
"desc": "The default provider ids for model output types and global fallback."
|
|
},
|
|
"providers.openai": {
|
|
"type": "Object",
|
|
"desc": "The config for the openai provider.",
|
|
"link": "https://github.com/openai/openai-node"
|
|
},
|
|
"providers.cloudflareWorkersAi": {
|
|
"type": "Object",
|
|
"desc": "The config for the Cloudflare Workers AI provider."
|
|
},
|
|
"providers.fal": {
|
|
"type": "Object",
|
|
"desc": "The config for the fal provider."
|
|
},
|
|
"providers.gemini": {
|
|
"type": "Object",
|
|
"desc": "The config for the gemini provider."
|
|
},
|
|
"providers.geminiVertex": {
|
|
"type": "Object",
|
|
"desc": "The config for the gemini provider in Google Vertex AI."
|
|
},
|
|
"providers.anthropic": {
|
|
"type": "Object",
|
|
"desc": "The config for the anthropic provider."
|
|
},
|
|
"providers.anthropicVertex": {
|
|
"type": "Object",
|
|
"desc": "The config for the anthropic provider in Google Vertex AI."
|
|
},
|
|
"unsplash": {
|
|
"type": "Object",
|
|
"desc": "The config for the unsplash key."
|
|
},
|
|
"exa": {
|
|
"type": "Object",
|
|
"desc": "The config for the exa web search key."
|
|
},
|
|
"storage": {
|
|
"type": "Object",
|
|
"desc": "The config for the storage provider."
|
|
}
|
|
},
|
|
"indexer": {
|
|
"enabled": {
|
|
"type": "Boolean",
|
|
"desc": "Enable indexer plugin",
|
|
"env": "AFFINE_INDEXER_ENABLED"
|
|
},
|
|
"provider.type": {
|
|
"type": "String",
|
|
"desc": "Indexer search service provider name",
|
|
"env": "AFFINE_INDEXER_SEARCH_PROVIDER"
|
|
},
|
|
"provider.endpoint": {
|
|
"type": "String",
|
|
"desc": "Indexer search service endpoint",
|
|
"env": "AFFINE_INDEXER_SEARCH_ENDPOINT"
|
|
},
|
|
"provider.apiKey": {
|
|
"type": "String",
|
|
"desc": "Indexer search service api key. Optional for elasticsearch",
|
|
"link": "https://www.elastic.co/guide/server/current/api-key.html",
|
|
"env": "AFFINE_INDEXER_SEARCH_API_KEY"
|
|
},
|
|
"provider.username": {
|
|
"type": "String",
|
|
"desc": "Indexer search service auth username, if not set, basic auth will be disabled. Optional for elasticsearch",
|
|
"link": "https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html",
|
|
"env": "AFFINE_INDEXER_SEARCH_USERNAME"
|
|
},
|
|
"provider.password": {
|
|
"type": "String",
|
|
"desc": "Indexer search service auth password, if not set, basic auth will be disabled. Optional for elasticsearch",
|
|
"env": "AFFINE_INDEXER_SEARCH_PASSWORD"
|
|
},
|
|
"autoIndex.batchSize": {
|
|
"type": "Number",
|
|
"desc": "Number of workspaces automatically indexed per batch"
|
|
}
|
|
},
|
|
"oauth": {
|
|
"providers.google": {
|
|
"type": "Object",
|
|
"desc": "Google OAuth provider config",
|
|
"link": "https://developers.google.com/identity/protocols/oauth2/web-server"
|
|
},
|
|
"providers.github": {
|
|
"type": "Object",
|
|
"desc": "GitHub OAuth provider config",
|
|
"link": "https://docs.github.com/en/apps/oauth-apps"
|
|
},
|
|
"providers.oidc": {
|
|
"type": "Object",
|
|
"desc": "OIDC OAuth provider config",
|
|
"link": "https://openid.net/specs/openid-connect-core-1_0.html"
|
|
},
|
|
"providers.apple": {
|
|
"type": "Object",
|
|
"desc": "Apple OAuth provider config",
|
|
"link": "https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/implementing_sign_in_with_apple_in_your_app"
|
|
}
|
|
},
|
|
"payment": {
|
|
"enabled": {
|
|
"type": "Boolean",
|
|
"desc": "Whether enable payment plugin"
|
|
},
|
|
"showLifetimePrice": {
|
|
"type": "Boolean",
|
|
"desc": "Whether enable lifetime price and allow user to pay for it."
|
|
},
|
|
"stripe": {
|
|
"type": "Object",
|
|
"desc": "Stripe sdk options and credentials",
|
|
"link": "https://docs.stripe.com/api"
|
|
},
|
|
"revenuecat": {
|
|
"type": "Object",
|
|
"desc": "RevenueCat integration configs",
|
|
"link": "https://www.revenuecat.com/docs/"
|
|
}
|
|
},
|
|
"worker": {
|
|
"allowedOrigin": {
|
|
"type": "Array",
|
|
"desc": "Allowed origin"
|
|
}
|
|
}
|
|
} |