chore(agent): configure AI agents and tools

Add configuration for BMad, Claude, OpenCode, and other AI agent tools and workflows.
This commit is contained in:
2026-02-11 11:51:23 +08:00
parent 9c2181f743
commit ad8e2e313e
977 changed files with 157625 additions and 0 deletions

View File

@@ -0,0 +1,242 @@
# Access Control Reference
## Overview
Access control functions determine WHO can do WHAT with documents:
```ts
type Access = (args: AccessArgs) => boolean | Where | Promise<boolean | Where>
```
Returns:
- `true` - Full access
- `false` - No access
- `Where` query - Filtered access (row-level security)
## Collection-Level Access
```ts
export const Posts: CollectionConfig = {
slug: 'posts',
access: {
create: isLoggedIn,
read: isPublishedOrAdmin,
update: isAdminOrAuthor,
delete: isAdmin,
},
fields: [...],
}
```
## Common Patterns
### Public Read, Admin Write
```ts
const isAdmin: Access = ({ req }) => {
return req.user?.roles?.includes('admin') ?? false
}
const isLoggedIn: Access = ({ req }) => {
return !!req.user
}
access: {
create: isLoggedIn,
read: () => true, // Public
update: isAdmin,
delete: isAdmin,
}
```
### Row-Level Security (User's Own Documents)
```ts
const ownDocsOnly: Access = ({ req }) => {
if (!req.user) return false
// Admins see everything
if (req.user.roles?.includes('admin')) return true
// Others see only their own
return {
author: { equals: req.user.id },
}
}
access: {
read: ownDocsOnly,
update: ownDocsOnly,
delete: ownDocsOnly,
}
```
### Complex Queries
```ts
const publishedOrOwn: Access = ({ req }) => {
// Not logged in: published only
if (!req.user) {
return { status: { equals: 'published' } }
}
// Admin: see all
if (req.user.roles?.includes('admin')) return true
// Others: published OR own drafts
return {
or: [
{ status: { equals: 'published' } },
{ author: { equals: req.user.id } },
],
}
}
```
## Field-Level Access
Control access to specific fields:
```ts
{
name: 'internalNotes',
type: 'textarea',
access: {
read: ({ req }) => req.user?.roles?.includes('admin'),
update: ({ req }) => req.user?.roles?.includes('admin'),
},
}
```
### Hide Field Completely
```ts
{
name: 'secretKey',
type: 'text',
access: {
read: () => false, // Never returned in API
update: ({ req }) => req.user?.roles?.includes('admin'),
},
}
```
## Access Control Arguments
```ts
type AccessArgs = {
req: PayloadRequest
id?: string | number // Document ID (for update/delete)
data?: Record<string, unknown> // Incoming data (for create/update)
}
```
## RBAC (Role-Based Access Control)
```ts
// Define roles
type Role = 'admin' | 'editor' | 'author' | 'subscriber'
// Helper functions
const hasRole = (req: PayloadRequest, role: Role): boolean => {
return req.user?.roles?.includes(role) ?? false
}
const hasAnyRole = (req: PayloadRequest, roles: Role[]): boolean => {
return roles.some(role => hasRole(req, role))
}
// Use in access control
const canEdit: Access = ({ req }) => {
return hasAnyRole(req, ['admin', 'editor'])
}
const canPublish: Access = ({ req }) => {
return hasAnyRole(req, ['admin', 'editor'])
}
const canDelete: Access = ({ req }) => {
return hasRole(req, 'admin')
}
```
## Multi-Tenant Access
```ts
// Users belong to organizations
const sameOrgOnly: Access = ({ req }) => {
if (!req.user) return false
// Super admin sees all
if (req.user.roles?.includes('super-admin')) return true
// Others see only their org's data
return {
organization: { equals: req.user.organization },
}
}
// Apply to collection
access: {
create: ({ req }) => !!req.user,
read: sameOrgOnly,
update: sameOrgOnly,
delete: sameOrgOnly,
}
```
## Global Access
For singleton documents:
```ts
export const Settings: GlobalConfig = {
slug: 'settings',
access: {
read: () => true,
update: ({ req }) => req.user?.roles?.includes('admin'),
},
fields: [...],
}
```
## Important: Local API Access Control
**Local API bypasses access control by default!**
```ts
// ❌ SECURITY BUG: Access control bypassed
await payload.find({
collection: 'posts',
user: someUser,
})
// ✅ SECURE: Explicitly enforce access control
await payload.find({
collection: 'posts',
user: someUser,
overrideAccess: false, // REQUIRED
})
```
## Access Control with req.context
Share state between access checks and hooks:
```ts
const conditionalAccess: Access = ({ req }) => {
// Check context set by middleware or previous operation
if (req.context?.bypassAuth) return true
return req.user?.roles?.includes('admin')
}
```
## Best Practices
1. **Default to restrictive** - Start with `false`, add permissions
2. **Use query constraints for row-level** - More efficient than filtering after
3. **Keep logic in reusable functions** - DRY across collections
4. **Test with different user types** - Admin, regular user, anonymous
5. **Remember Local API default** - Always use `overrideAccess: false` for user-facing operations
6. **Document your access rules** - Complex logic needs comments