diff --git a/skills/base44-cli/SKILL.md b/skills/base44-cli/SKILL.md index a726ee0..1358947 100644 --- a/skills/base44-cli/SKILL.md +++ b/skills/base44-cli/SKILL.md @@ -126,20 +126,34 @@ my-app/ **config.jsonc example:** ```jsonc { - "name": "My App", - "description": "App description", - "entitiesDir": "./entities", - "functionsDir": "./functions", - "agentsDir": "./agents", - "site": { - "installCommand": "npm install", - "buildCommand": "npm run build", - "serveCommand": "npm run dev", - "outputDirectory": "./dist" + "name": "My App", // Required: project name + "description": "App description", // Optional: project description + "entitiesDir": "./entities", // Optional: default "entities" + "functionsDir": "./functions", // Optional: default "functions" + "agentsDir": "./agents", // Optional: default "agents" + "site": { // Optional: site deployment config + "installCommand": "npm install", // Optional: install dependencies + "buildCommand": "npm run build", // Optional: build command + "serveCommand": "npm run dev", // Optional: local dev server + "outputDirectory": "./dist" // Optional: build output directory } } ``` +**Config properties:** + +| Property | Description | Default | +|----------|-------------|---------| +| `name` | Project name (required) | - | +| `description` | Project description | - | +| `entitiesDir` | Directory for entity schemas | `"entities"` | +| `functionsDir` | Directory for backend functions | `"functions"` | +| `agentsDir` | Directory for agent configs | `"agents"` | +| `site.installCommand` | Command to install dependencies | - | +| `site.buildCommand` | Command to build the project | - | +| `site.serveCommand` | Command to run dev server | - | +| `site.outputDirectory` | Build output directory for deployment | - | + ## Installation Install the Base44 CLI as a dev dependency in your project: @@ -210,9 +224,10 @@ ALWAYS follow this exact structure when creating entity files: } ``` -**Field types:** `string`, `number`, `boolean`, `array` -**String formats:** `date`, `date-time`, `email`, `uri`, `richtext` +**Field types:** `string`, `number`, `integer`, `boolean`, `array`, `object`, `binary` +**String formats:** `date`, `date-time`, `time`, `email`, `uri`, `hostname`, `ipv4`, `ipv6`, `uuid`, `file`, `regex`, `richtext` **For enums:** Add `"enum": ["value1", "value2"]` and optionally `"default": "value1"` +**Entity names:** Must be alphanumeric only (pattern: `/^[a-zA-Z0-9]+$/`) For complete documentation, see [entities-create.md](references/entities-create.md). @@ -255,7 +270,13 @@ Agents are conversational AI assistants that can interact with users, access you } ``` -**Naming rules:** Agent names must be lowercase alphanumeric with underscores only (e.g., `support_agent`, `order_bot`) +**Naming rules:** +- Agent names must match pattern: `/^[a-z0-9_]+$/` (lowercase alphanumeric with underscores, 1-100 chars) +- Valid: `support_agent`, `order_bot` +- Invalid: `Support-Agent`, `OrderBot` + +**Required fields:** `name`, `description`, `instructions` +**Optional fields:** `tool_configs` (defaults to `[]`), `whatsapp_greeting` **Tool config types:** - **Entity tools**: `entity_name` + `allowed_operations` (array of: `read`, `create`, `update`, `delete`) diff --git a/skills/base44-cli/references/agents-push.md b/skills/base44-cli/references/agents-push.md index afeee0c..fa2795b 100644 --- a/skills/base44-cli/references/agents-push.md +++ b/skills/base44-cli/references/agents-push.md @@ -70,21 +70,21 @@ Each agent file should be a `.jsonc` file in `base44/agents/` with this structur ```jsonc { - "name": "agent_name", - "description": "Brief description of what this agent does", - "instructions": "Detailed instructions for the agent's behavior", - "tool_configs": [ + "name": "agent_name", // Required: lowercase alphanumeric with underscores, 1-100 chars + "description": "Brief description of what this agent does", // Required: min 1 char + "instructions": "Detailed instructions for the agent's behavior", // Required: min 1 char + "tool_configs": [ // Optional: defaults to [] // Entity tool - gives agent access to entity operations { "entity_name": "Task", "allowed_operations": ["read", "create", "update", "delete"] }, // Backend function tool - gives agent access to a function { "function_name": "send_email", "description": "Send an email notification" } ], - "whatsapp_greeting": "Hello! How can I help you today?" + "whatsapp_greeting": "Hello! How can I help you today?" // Optional } ``` **Naming rules:** -- **Agent names** must be lowercase alphanumeric with underscores only +- **Agent names** must match pattern: `/^[a-z0-9_]+$/` (lowercase alphanumeric with underscores only, 1-100 characters) - Valid: `support_agent`, `order_bot`, `task_helper` - Invalid: `Support-Agent`, `OrderBot`, `task helper` - **Agent file names** must use underscores (matching the agent name) @@ -94,6 +94,13 @@ Each agent file should be a `.jsonc` file in `base44/agents/` with this structur - Valid: `"entity_name": "Task"`, `"entity_name": "TeamMember"` - Invalid: `"entity_name": "task"`, `"entity_name": "team_member"` +**Required fields:** +- `name`: Required, must follow naming rules above +- `description`: Required, minimum 1 character +- `instructions`: Required, minimum 1 character +- `tool_configs`: Optional, defaults to empty array +- `whatsapp_greeting`: Optional + ### Common Mistake: Wrong tool_configs Format **WRONG** - Do NOT use `tools` with `type` and `entity`: diff --git a/skills/base44-cli/references/entities-create.md b/skills/base44-cli/references/entities-create.md index efb6297..29b40aa 100644 --- a/skills/base44-cli/references/entities-create.md +++ b/skills/base44-cli/references/entities-create.md @@ -116,7 +116,7 @@ With format: } ``` -Available formats: `date`, `date-time`, `email`, `uri`, `richtext` +Available formats: `date`, `date-time`, `time`, `email`, `uri`, `hostname`, `ipv4`, `ipv6`, `uuid`, `file`, `regex`, `richtext` ### String with Enum @@ -143,6 +143,32 @@ Constrained to specific values: } ``` +### Integer + +For whole numbers only: +```jsonc +{ + "quantity": { + "type": "integer", + "description": "Item quantity", + "minimum": 0, + "maximum": 1000 + } +} +``` + +### Binary + +For file/blob data: +```jsonc +{ + "attachment": { + "type": "binary", + "description": "File attachment" + } +} +``` + ### Boolean ```jsonc @@ -188,15 +214,23 @@ Constrained to specific values: ## Field Properties -| Property | Description | -| ------------- | ------------------------------------------------------------ | -| `type` | Data type: `string`, `number`, `boolean`, `array`, `object` | -| `description` | Human-readable description of the field | -| `enum` | Array of allowed values (for strings) | -| `default` | Default value when not provided | -| `format` | Format hint: `date`, `date-time`, `email`, `uri`, `richtext` | -| `items` | Schema for array items | -| `properties` | Nested properties for object types | +| Property | Description | +| ------------- | ---------------------------------------------------------------------------------------- | +| `type` | Data type: `string`, `number`, `integer`, `boolean`, `array`, `object`, `binary` | +| `description` | Human-readable description of the field | +| `enum` | Array of allowed values (for strings) | +| `enumNames` | Human-readable labels for enum values (same order as `enum`) | +| `default` | Default value when not provided | +| `format` | Format hint: `date`, `date-time`, `time`, `email`, `uri`, `hostname`, `ipv4`, `ipv6`, `uuid`, `file`, `regex`, `richtext` | +| `items` | Schema for array items | +| `properties` | Nested properties for object types | +| `$ref` | Reference to another schema definition | +| `minLength` | Minimum string length | +| `maxLength` | Maximum string length | +| `pattern` | Regex pattern for string validation | +| `minimum` | Minimum value for numbers | +| `maximum` | Maximum value for numbers | +| `rls` | Field-level security rules (see Field Level Security section) | ## Complete Example @@ -252,7 +286,10 @@ Here's a complete entity definition for a Task: ## Naming Conventions -- **Entity name**: Use PascalCase (e.g., `Task`, `TeamMember`, `ActivityLog`) +- **Entity name**: Use PascalCase with alphanumeric characters only (e.g., `Task`, `TeamMember`, `ActivityLog`) + - Must match pattern: `/^[a-zA-Z0-9]+$/` + - Valid: `Task`, `TeamMember`, `Order123` + - Invalid: `Team_Member`, `Team-Member`, `Team Member` - **File name**: Use kebab-case matching the entity (e.g., `task.jsonc`, `team-member.jsonc`, `activity-log.jsonc`) - **Field names**: Use snake_case (e.g., `board_id`, `user_email`, `due_date`) @@ -281,7 +318,7 @@ Row Level Security (RLS) controls which records users can access based on their ### RLS Operations -RLS supports four operations: +RLS supports five operations: | Operation | Description | |-----------|-------------| @@ -289,6 +326,7 @@ RLS supports four operations: | `read` | Control who can view records | | `update` | Control who can modify records | | `delete` | Control who can remove records | +| `write` | Shorthand for `create`, `update`, and `delete` combined | ### Permission Values @@ -339,8 +377,9 @@ There are two condition types you can use: ``` **Important limitations:** -- Only **simple equality** is supported (no operators like `$ne`, `$gt`, `$in`, etc.) -- MongoDB-style operators (`$and`, `$or`, `$in`, `$nin`, `$ne`) are **NOT supported** in JSON schema RLS +- `user_condition` only supports **simple equality** (e.g., `{ "role": "admin" }`) +- For `data.*` field comparisons, you can use operators: `$in`, `$nin`, `$ne`, `$all` +- Logical operators `$or`, `$and`, `$nor` are available for combining conditions - You cannot filter by entity field values directly (e.g., `{"status": "published"}`) - Only user-related conditions are allowed @@ -433,12 +472,15 @@ There are two condition types you can use: ### Limitations -- **No MongoDB operators:** `$and`, `$or`, `$in`, `$nin`, `$ne`, `$gt`, `$lt`, `$regex`, `$expr`, `$where` are NOT supported +- **user_condition is equality only:** `user_condition` only supports exact match (e.g., `{ "role": "admin" }`) - no operators +- **No comparison operators on user_condition:** `$gt`, `$lt`, `$regex`, `$expr`, `$where` are NOT supported for user conditions - **No entity field filtering:** Cannot filter by entity field values (e.g., `{"status": "published"}`) -- **Simple equality only:** `user_condition` only supports exact match (e.g., `{ "role": "admin" }`) -- **Single condition per operation:** Each operation can only have one condition (no combining multiple rules) - **No deeply nested templates:** Templates like `{{user.data.profile.department}}` may not work +**Supported operators:** +- **Logical operators:** `$or`, `$and`, `$nor` for combining multiple conditions +- **Field operators (for `data.*` fields only):** `$in`, `$nin`, `$ne`, `$all` + ### Complex Access Patterns For complex access patterns that require multiple conditions (e.g., "owner OR admin"), you have two options: @@ -449,11 +491,55 @@ For complex access patterns that require multiple conditions (e.g., "owner OR ad ## Field Level Security (FLS) -**Note:** Field Level Security (FLS) is **NOT currently available** in Base44. You can only set security rules for entire entities (rows/records), not for individual fields within those records. +Field Level Security allows you to control access to individual fields within an entity. FLS rules are defined within each field's schema using the `rls` property. + +### FLS Operations + +FLS supports the same operations as entity-level RLS: + +| Operation | Description | +|-----------|-------------| +| `create` | Control who can set this field when creating records | +| `read` | Control who can view this field | +| `update` | Control who can modify this field | +| `delete` | Control who can clear this field | +| `write` | Shorthand for `create`, `update`, and `delete` combined | + +### FLS Example + +```jsonc +{ + "name": "Employee", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Employee name" + }, + "salary": { + "type": "number", + "description": "Employee salary", + "rls": { + "read": { "user_condition": { "role": "hr" } }, + "update": { "user_condition": { "role": "hr" } } + } + }, + "department": { + "type": "string", + "description": "Department name" + } + }, + "required": ["name"] +} +``` + +In this example, only users with the `hr` role can read or update the `salary` field. All users with access to the entity can read/update other fields. + +### FLS Notes -If you need different access levels for different fields, the recommended approach is to split your data into separate entities: -- Public data in one entity (with `read: true`) -- Protected data in another entity (with appropriate RLS rules) +- If no field-level RLS is defined, the field inherits the entity-level RLS rules +- FLS rules follow the same condition format as entity-level RLS +- Use FLS for sensitive fields like salary, SSN, or internal notes ## Pushing Entities diff --git a/skills/base44-cli/references/functions-create.md b/skills/base44-cli/references/functions-create.md index dac539f..c523cdc 100644 --- a/skills/base44-cli/references/functions-create.md +++ b/skills/base44-cli/references/functions-create.md @@ -41,8 +41,8 @@ Each function requires a `function.jsonc` configuration file: | Property | Description | Required | |----------|-------------|----------| -| `name` | Function name (must not contain dots) | Yes | -| `entry` | Entry point file path relative to the function directory | Yes | +| `name` | Function name (must match `/^[^.]+$/` - no dots allowed) | Yes | +| `entry` | Entry point file path relative to the function directory (min 1 char) | Yes | ## Entry Point File @@ -197,7 +197,9 @@ Deno.serve(async (req) => { ## Naming Conventions - **Directory name**: Use kebab-case (e.g., `process-order`, `send-notification`) -- **Function name**: Match the directory name, no dots allowed +- **Function name**: Match the directory name, must match pattern `/^[^.]+$/` (no dots allowed) + - Valid: `process-order`, `send_notification`, `myFunction` + - Invalid: `process.order`, `send.notification.v2` - **Entry file**: Typically `index.ts` or `index.js` ## Deploying Functions diff --git a/skills/base44-cli/references/rls-examples.md b/skills/base44-cli/references/rls-examples.md index 9052d91..7d3ef42 100644 --- a/skills/base44-cli/references/rls-examples.md +++ b/skills/base44-cli/references/rls-examples.md @@ -2,10 +2,15 @@ Practical Row-Level Security patterns for common application types. -**Important:** Base44 RLS in JSON schema format only supports simple conditions. MongoDB-style operators (`$or`, `$and`, `$in`, etc.) are **NOT supported**. For complex access patterns, use the Base44 Dashboard UI or implement logic in backend functions. +**Important:** Base44 RLS supports: +- **Logical operators:** `$or`, `$and`, `$nor` for combining conditions +- **Field operators (for `data.*` fields):** `$in`, `$nin`, `$ne`, `$all` +- **user_condition:** Equality only (no operators) ## Contents - [Simple Patterns (JSON Schema)](#simple-patterns-json-schema) +- [Using Operators](#using-operators) +- [Field-Level Security Examples](#field-level-security-examples) - [Complex Patterns (Dashboard UI or Backend)](#complex-patterns-dashboard-ui-or-backend) - [Best Practices](#best-practices) @@ -173,74 +178,257 @@ Anyone can read, only logged-in users can create/edit their own records. --- -## Complex Patterns (Dashboard UI or Backend) +## Using Operators -These patterns require multiple conditions and **cannot be implemented in JSON schema**. Use the Base44 Dashboard UI or backend functions instead. +### Logical Operators -### Owner OR Admin access +Combine multiple conditions using `$or`, `$and`, or `$nor`: -**Requirement:** Users can access their own records, OR admins can access all records. +**Owner OR Admin access:** +```jsonc +{ + "name": "Document", + "type": "object", + "properties": { + "title": { "type": "string" }, + "content": { "type": "string" } + }, + "rls": { + "create": true, + "read": { + "$or": [ + { "created_by": "{{user.email}}" }, + { "user_condition": { "role": "admin" } } + ] + }, + "update": { + "$or": [ + { "created_by": "{{user.email}}" }, + { "user_condition": { "role": "admin" } } + ] + }, + "delete": { "user_condition": { "role": "admin" } } + } +} +``` -**JSON Schema limitation:** Cannot combine conditions with OR logic. +**Multiple roles with $or:** +```jsonc +{ + "rls": { + "read": { + "$or": [ + { "user_condition": { "role": "admin" } }, + { "user_condition": { "role": "manager" } }, + { "user_condition": { "role": "hr" } } + ] + } + } +} +``` -**Solution options:** -1. **Dashboard UI:** Add two rules to the read operation - one for "Creator only" and one for "User property check" with role = admin -2. **Backend function:** Implement custom access logic that checks both conditions +### Field Operators for data.* Fields -### Bidirectional Relationships (e.g., Friendships, Matches) +Use `$in`, `$nin`, `$ne`, `$all` for comparing entity data fields: -**Requirement:** Either party in a relationship should have access. +**Access based on tags ($in):** +```jsonc +{ + "rls": { + "read": { + "data.category": { "$in": ["public", "shared"] } + } + } +} +``` -**JSON Schema limitation:** Cannot check if user matches field A OR field B. +**Exclude specific statuses ($nin):** +```jsonc +{ + "rls": { + "read": { + "data.status": { "$nin": ["archived", "deleted"] } + } + } +} +``` -**Solution options:** -1. **Dashboard UI:** Add multiple rules matching different fields -2. **Backend function:** Query with custom logic -3. **Entity redesign:** Store two records per relationship (one for each party) +**Not equal ($ne):** +```jsonc +{ + "rls": { + "read": { + "data.visibility": { "$ne": "private" } + } + } +} +``` + +**All tags must match ($all):** +```jsonc +{ + "rls": { + "read": { + "data.required_tags": { "$all": ["approved", "reviewed"] } + } + } +} +``` -### Multi-role Access +### Combining Logical and Field Operators -**Requirement:** Multiple roles (hr, admin, manager) should have access. +```jsonc +{ + "rls": { + "read": { + "$and": [ + { "data.status": { "$ne": "draft" } }, + { + "$or": [ + { "created_by": "{{user.email}}" }, + { "data.visibility": "public" } + ] + } + ] + } + } +} +``` -**JSON Schema limitation:** Cannot specify multiple roles. +--- -**Solution options:** -1. **Dashboard UI:** Add separate rules for each role -2. **Backend function:** Check if user role is in allowed list +## Field-Level Security Examples -### Conditional Field-based Access +Control access to specific fields within an entity. -**Requirement:** Access depends on entity field value (e.g., `is_public: true`). +### Sensitive Salary Field -**JSON Schema limitation:** Cannot filter by entity field values, only user-related conditions. +```jsonc +{ + "name": "Employee", + "type": "object", + "properties": { + "name": { "type": "string" }, + "email": { "type": "string", "format": "email" }, + "salary": { + "type": "number", + "description": "Annual salary", + "rls": { + "read": { "user_condition": { "role": "hr" } }, + "write": { "user_condition": { "role": "hr" } } + } + }, + "performance_notes": { + "type": "string", + "description": "Manager notes", + "rls": { + "read": { + "$or": [ + { "user_condition": { "role": "manager" } }, + { "user_condition": { "role": "hr" } } + ] + }, + "write": { "user_condition": { "role": "manager" } } + } + } + } +} +``` + +### Admin-Only Internal Fields + +```jsonc +{ + "name": "Order", + "type": "object", + "properties": { + "order_number": { "type": "string" }, + "total": { "type": "number" }, + "internal_notes": { + "type": "string", + "description": "Internal processing notes", + "rls": { + "read": { "user_condition": { "role": "admin" } }, + "write": { "user_condition": { "role": "admin" } } + } + }, + "profit_margin": { + "type": "number", + "description": "Profit margin percentage", + "rls": { + "read": { "user_condition": { "role": "admin" } }, + "write": false + } + } + } +} +``` + +--- + +## Complex Patterns (Dashboard UI or Backend) + +Some patterns may still require the Dashboard UI or backend functions. + +### Bidirectional Relationships (e.g., Friendships, Matches) + +**Requirement:** Either party in a relationship should have access. + +**Now possible with $or:** +```jsonc +{ + "rls": { + "read": { + "$or": [ + { "data.user_a_email": "{{user.email}}" }, + { "data.user_b_email": "{{user.email}}" } + ] + } + } +} +``` + +**Alternative solutions:** +1. **Entity redesign:** Store two records per relationship (one for each party) +2. **Backend function:** Query with custom logic + +### Complex Business Logic + +**Requirement:** Access depends on multiple entity fields with complex conditions. + +**JSON Schema limitation:** While operators help, very complex business logic may still be hard to express. **Solution options:** -1. **Separate entities:** Create PublicPosts and PrivatePosts entities -2. **Backend function:** Filter based on field values +1. **Backend function:** Implement custom access logic +2. **Combine simpler rules:** Break complex rules into simpler entity-level and field-level rules --- ## Best Practices -### Entity Separation Strategy +### Security Strategy -Since RLS has limitations, split data strategically: +Use a combination of entity-level RLS and field-level security: -| Data Type | Entity | RLS Pattern | -|-----------|--------|-------------| -| User-editable | UserProfile | Owner-only | -| Billing/subscription | Subscription | Admin-managed | -| Public content | PublicPost | Read: true | -| Private content | PrivateNote | Owner-only | +| Data Type | Approach | Example | +|-----------|----------|---------| +| User-editable | Entity RLS: Owner-only | UserProfile with `created_by` check | +| Sensitive fields | Field-level RLS | Salary field with HR role check | +| Multi-role access | `$or` with user_condition | Admin OR Manager access | +| Conditional access | Field operators | `$in`, `$ne` on data fields | +| Public content | Entity RLS: `read: true` | PublicPost | +| Private content | Entity RLS: Owner-only | PrivateNote | ### When to Use Each Approach | Requirement | Approach | |-------------|----------| | Single condition (owner, admin, department) | JSON Schema RLS | -| Multiple OR conditions | Dashboard UI | -| Complex business logic | Backend functions | -| Field-value filtering | Backend functions | +| Multiple OR/AND conditions | JSON Schema RLS with `$or`/`$and` | +| Field value checks with `$in`/`$ne`/etc. | JSON Schema RLS for `data.*` fields | +| Field-level access control | JSON Schema FLS (field-level `rls`) | +| Complex comparison operators (`$gt`, `$lt`) | Backend functions | +| Very complex business logic | Backend functions | ### Common Role Patterns @@ -251,13 +439,25 @@ Since RLS has limitations, split data strategically: | `manager` | Department-scoped access | | `user` | Own records only | +### Supported Operators Summary + +| Operator | Supported | Notes | +|----------|-----------|-------| +| `$or` | Yes | Combine multiple conditions | +| `$and` | Yes | All conditions must match | +| `$nor` | Yes | None of the conditions match | +| `$in` | Yes | For `data.*` fields only | +| `$nin` | Yes | For `data.*` fields only | +| `$ne` | Yes | For `data.*` fields only | +| `$all` | Yes | For `data.*` fields only | +| `$gt`, `$lt`, `$gte`, `$lte` | No | Use backend functions | +| `$regex` | No | Use backend functions | + ### Limitations Summary | Not Supported | Alternative | |---------------|-------------| -| `$or`, `$and` operators | Dashboard UI rules | -| `$in`, `$nin` operators | Backend functions | -| `$ne`, `$gt`, `$lt` operators | Backend functions | -| Entity field filtering | Separate entities or backend | +| Operators on `user_condition` | Use equality only for user checks | +| Comparison operators (`$gt`, `$lt`) | Backend functions | +| Regex matching (`$regex`) | Backend functions | | Cross-entity relationships | Backend functions | -| Field-level security | Separate entities |