diff --git a/.obsidian/plugins/hoarder-sync/data.json b/.obsidian/plugins/hoarder-sync/data.json index 4c14170..9a37d4e 100644 --- a/.obsidian/plugins/hoarder-sync/data.json +++ b/.obsidian/plugins/hoarder-sync/data.json @@ -4,7 +4,7 @@ "syncFolder": "Hoarder", "attachmentsFolder": "Hoarder/attachments", "syncIntervalMinutes": 60, - "lastSyncTimestamp": 1778855393935, + "lastSyncTimestamp": 1778858993803, "updateExistingFiles": false, "excludeArchived": true, "onlyFavorites": false, diff --git a/raw/production__deployment.md b/raw/_processed/production__deployment.md similarity index 100% rename from raw/production__deployment.md rename to raw/_processed/production__deployment.md diff --git a/wiki/_master-index.md b/wiki/_master-index.md index d60f1a6..aecce24 100644 --- a/wiki/_master-index.md +++ b/wiki/_master-index.md @@ -35,7 +35,7 @@ This 3-hop pattern works for hundreds of articles without vector search. | [[wiki/reports/_index\|reports/]] | Weekly and monthly summaries — generate: `uv run python scripts/report-generator.py --weekly` | 1 | | [[wiki/infrastructure/_index\|infrastructure/]] | Server inventory: all 10 SSH hosts — optical, optical-dev, optical-prod, baic, librechat, modocmms, box-cli, aimpress, pve | 12 | | [[wiki/testing/_index\|testing/]] | Web app testing: functional, performance, security, UI types; TDD/BDD/Agile methodologies; Selenium/Cypress/Playwright/JMeter/OWASP ZAP tools | 1 | -| [[wiki/payloadcms/_index\|payloadcms/]] | Full Payload CMS reference — getting started, config, database (Postgres/MongoDB/SQLite), all 22 field types, access control, hooks, authentication (cookies, JWT, API keys, custom strategies, token data), admin UI, custom components, Lexical rich text, live preview, versions/drafts, Local/REST/GraphQL APIs, queries, plugins, jobs queue, upload, ecommerce, production deploy, TypeScript, migration guides, i18n, localization, hierarchy | 123 | +| [[wiki/payloadcms/_index\|payloadcms/]] | Full Payload CMS reference — getting started, config, database (Postgres/MongoDB/SQLite), all 22 field types, access control, hooks, authentication (cookies, JWT, API keys, custom strategies, token data), admin UI, custom components, Lexical rich text, live preview, versions/drafts, Local/REST/GraphQL APIs, queries, plugins, jobs queue, upload, ecommerce, production deploy, TypeScript, migration guides, i18n, localization, hierarchy | 124 | | [[wiki/shared-patterns/_index\|shared-patterns/]] | Oliver Agency standard library patterns: httpx, structlog, pydantic-settings, alembic — reuse before writing from scratch | 4 | | [[wiki/mistakes/_index\|mistakes/]] | Anti-patterns extracted from sessions — per-stack running lists (fastapi, react, docker, postgres, general) — injected at session start | 5 | diff --git a/wiki/payloadcms/_index.md b/wiki/payloadcms/_index.md index d72270d..5a75462 100644 --- a/wiki/payloadcms/_index.md +++ b/wiki/payloadcms/_index.md @@ -29,7 +29,7 @@ | [[wiki/payloadcms/ecommerce-advanced\|Ecommerce — Advanced / Piecemeal Collections API]] | All 8 `create*Collection` factory functions with full prop/access tables + TS types (CurrenciesConfig, Currency, CountryType, InventoryConfig) | raw/ecommerce__advanced.md | 2026-05-15 | | [[wiki/payloadcms/ecommerce-frontend\|Ecommerce — Frontend React Utilities]] | EcommerceProvider, useCart, usePayments (2-step checkout), useAddresses, useCurrency, useEcommerceConfig, useEcommerce; session management (onLogin, onLogout, mergeCart) | raw/ecommerce__frontend.md | 2026-05-15 | | [[wiki/payloadcms/ecommerce-payment-adapters\|Ecommerce — Payment Adapters]] | Payment adapter pattern, Stripe setup + webhooks (local CLI), custom adapter interface (initiatePayment/confirmOrder/group field), client-side adapter, security gotchas | raw/ecommerce__payments.md | 2026-05-15 | -| [[wiki/payloadcms/production\|Production & Performance]] | Deployment, Docker, building without DB, abuse prevention, performance optimization patterns | raw/production__*.md | 2026-05-15 | +| [[wiki/payloadcms/production-deployment\|Production Deployment]] | Deploy anywhere Next.js runs: security checklist, DB options (Cosmos DB compat preset), ephemeral vs persistent file storage, cloud adapters, multi-stage Dockerfile, Docker Compose dev setup | raw/production__deployment.md | 2026-05-15 | | [[wiki/payloadcms/performance-overview\|Performance Optimization]] | DB proximity, indexes, block references, cached instance, direct DB calls, hooks/validation perf, Turbopack, devBundleServerPackages | raw/performance__overview.md | 2026-05-15 | | [[wiki/payloadcms/typescript\|TypeScript]] | Native TS support, `generate:types` CLI, `interfaceName` for reusable interfaces, TS language service plugin | raw/typescript__*.md | 2026-05-15 | | [[wiki/payloadcms/migration-troubleshooting\|Migration & Troubleshooting]] | v2→v3 and v3→v4 migration guides, codemod, dependency dedup fix, hierarchy feature, Vercel Content Link, examples | raw/migration-guide__*.md, troubleshooting, hierarchy, integrations | 2026-05-15 | @@ -125,3 +125,4 @@ | [[wiki/payloadcms/plugin-seo\|SEO Plugin]] | `meta` field group (title/description/image) on collections/globals, auto-generate functions, real-time search preview, custom fields (og:title, json-ld), tabbedUI gotcha, direct field imports | raw/plugins__seo.md | 2026-05-15 | | [[wiki/payloadcms/plugin-stripe\|Stripe Plugin]] | Two-way Stripe↔Payload sync, webhook handlers, REST proxy (dev-only), `sync` auto-hooks, serverless `waitUntil` fix, `skipSync` loop prevention | raw/plugins__stripe.md | 2026-05-15 | | [[wiki/payloadcms/building-without-db-connection\|Building Without a DB Connection]] | Docker build fails when Next.js SSG calls Local API — two-phase `compile`/`generate` build modes, `force-dynamic` escape hatch, `NEXT_PUBLIC_` gotcha | raw/production__building-without-a-db-connection.md | 2026-05-15 | +| [[wiki/payloadcms/production-preventing-abuse\|Production — Preventing API Abuse]] | Login rate limiting (maxLoginAttempts/lockTime), maxDepth, CSRF, CORS, GraphQL complexity limits, malicious file upload mitigation | raw/production__preventing-abuse.md | 2026-05-15 | diff --git a/wiki/payloadcms/production-preventing-abuse.md b/wiki/payloadcms/production-preventing-abuse.md new file mode 100644 index 0000000..f53dad6 --- /dev/null +++ b/wiki/payloadcms/production-preventing-abuse.md @@ -0,0 +1,107 @@ +--- +title: "Production — Preventing API Abuse" +aliases: [payload-abuse-prevention, payload-security-hardening] +tags: [payloadcms, security, production, auth, graphql] +sources: [raw/production__preventing-abuse.md] +created: 2026-05-15 +updated: 2026-05-15 +--- + +## Overview + +Payload ships with several built-in security mechanisms configurable per-application. Always review these before going to production. + +## Login Rate Limiting + +Prevent brute-force attacks by locking accounts after repeated failures. + +```ts +const Users: CollectionConfig = { + slug: 'users', + auth: { + maxLoginAttempts: 5, // lock after 5 failures + lockTime: 600_000, // lock for 10 minutes (ms) + }, +} +``` + +- Set on any Collection with `auth: true` +- User must wait `lockTime` ms before retrying +- Keep `maxLoginAttempts` low — 5 is a reasonable default + +## Max Depth + +Deep relationship population (`depth`) incurs a DB cost and can trigger infinite loops in circular references. + +```ts +export default buildConfig({ + maxDepth: 3, // default is 10 — lower is safer +}) +``` + +- Set globally in `buildConfig` +- Choose the lowest value that doesn't break the dev experience +- Circular collection relationships → depth limit prevents infinite recursion → server crash prevention + +## CSRF Protection + +All requests to the Payload API are verified for authenticity. No extra config required by default. + +- Configured via [[wiki/payloadcms/authentication-cookies|Cookie Strategy]] (`csrf` whitelist) +- Add trusted origins to `csrf` array when operating cross-domain + +## CORS Configuration + +Restrict which origins can call your API: + +```ts +export default buildConfig({ + cors: ['https://myapp.com', 'https://admin.myapp.com'], +}) +``` + +- Full docs: [[wiki/payloadcms/configuration|Payload Config — Overview]] +- Never use `'*'` in production + +## GraphQL Complexity Limits + +GraphQL lets clients write arbitrary queries — protect against expensive ones: + +```ts +export default buildConfig({ + graphQL: { + maxComplexity: 1000, // default field = 1, relationship/upload = 10 + disable: true, // turn off GraphQL entirely if unused + }, +}) +``` + +- Every field adds 1 to complexity score; `relationship` and `upload` fields add 10 +- Requests exceeding `maxComplexity` are rejected before execution +- **Best practice:** disable GraphQL (`graphQL.disable: true`) if not needed — zero attack surface + +See also: [[wiki/payloadcms/graphql-overview|GraphQL API — Overview]] + +## Malicious File Uploads + +Upload collections can be a vector for distributing harmful files. + +**Mitigation checklist:** +- Enable [[wiki/payloadcms/authentication-email|email verification]] before users can register +- Add bot prevention (captcha) at registration +- Restrict `create`/`update` access on upload collections to minimum required roles +- Limit `read` access — prevent user-uploaded files from being publicly served without auth +- Integrate ClamAV (or similar antivirus) via an [[wiki/payloadcms/hooks-collections|afterChange hook]] to scan uploads + +## Key Takeaways + +- **Login brute-force:** set `maxLoginAttempts` + `lockTime` on every auth-enabled collection +- **Depth safety:** lower `maxDepth` from the default 10 to the minimum your app needs +- **GraphQL:** disable entirely if unused (`graphQL.disable: true`); otherwise set `maxComplexity` +- **CORS/CSRF:** restrict origins explicitly — never wildcard in production +- **File uploads:** combine access control + email verification + antivirus hooks + +## Sources + +- [Payload Docs — Preventing Abuse](https://payloadcms.com/docs/production/preventing-abuse) +- `raw/production__preventing-abuse.md`