Skip to content

Commit 898448d

Browse files
authored
Merge pull request #21 from objectql/copilot/implement-salesforce-lc-integration
2 parents 87e254d + c9312eb commit 898448d

File tree

14 files changed

+883
-1
lines changed

14 files changed

+883
-1
lines changed

docs/spec/metadata-format.md

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ Files should use **Snake Case** filenames (e.g., `project_tasks.object.yml`).
7979
| `description` | `string` | Internal description of the object. |
8080
| `fields` | `Map` | Dictionary of field definitions. |
8181
| `actions` | `Map` | Dictionary of custom action definitions. |
82+
| `customizable` | `boolean` | Whether this object can be modified or deleted. System objects (e.g., `user`, `session`) should be set to `false`. **Default: `true`** (if not specified, the object is customizable). |
8283

8384
## 4. Field Definitions
8485

@@ -103,6 +104,7 @@ fields:
103104
| `searchable` | `boolean` | Hint to include this field in global search. |
104105
| `sortable` | `boolean` | Hint that this field can be used for sorting in UI. |
105106
| `description` | `string` | Help text or documentation for the field. |
107+
| `customizable` | `boolean` | Whether this field can be modified or deleted. System fields (e.g., `_id`, `createdAt`, `updatedAt`) should be set to `false`. **Default: `true`** (if not specified, the field is customizable). |
106108

107109
### 4.2 Supported Field Types
108110

@@ -664,3 +666,177 @@ settings:
664666
tabPosition: top
665667
```
666668

669+
## 9. Metadata Protection
670+
671+
Similar to Salesforce and other low-code platforms, ObjectQL supports protecting system metadata from modification or deletion. This is crucial for maintaining system integrity when integrating with authentication systems like better-auth.
672+
673+
### 9.1 Object-Level Protection
674+
675+
Objects can be marked as non-customizable using the `customizable` property:
676+
677+
```yaml
678+
name: user
679+
description: System user for authentication
680+
customizable: false # Prevents modification or deletion of this object
681+
fields:
682+
email:
683+
type: email
684+
required: true
685+
```
686+
687+
When an object is marked as `customizable: false`:
688+
- The object cannot be deleted using `unregister()`
689+
- Attempts to modify the object will throw a validation error
690+
- The object cannot be removed as part of package unregistration
691+
692+
**Use Cases:**
693+
- Authentication objects (user, session, account)
694+
- Core system objects (organization, member)
695+
- Third-party integration objects that must maintain a specific schema
696+
697+
### 9.2 Field-Level Protection
698+
699+
Individual fields can be marked as non-customizable, even within customizable objects:
700+
701+
```yaml
702+
name: user
703+
customizable: true # Allow adding custom fields
704+
fields:
705+
email:
706+
type: email
707+
customizable: false # But protect core system field
708+
createdAt:
709+
type: datetime
710+
customizable: false # Protect audit fields
711+
updatedAt:
712+
type: datetime
713+
customizable: false # Protect audit fields
714+
customField:
715+
type: text
716+
customizable: true # Allow modification of custom fields
717+
```
718+
719+
When a field is marked as `customizable: false`:
720+
- The field cannot be modified or deleted
721+
- Field properties (type, validation rules, etc.) cannot be changed
722+
- The field will always appear in the object schema
723+
724+
**Common Protected Fields:**
725+
- `_id` or `id`: Primary key
726+
- `createdAt`: Record creation timestamp
727+
- `updatedAt`: Record update timestamp
728+
- `createdBy`: User who created the record
729+
- `updatedBy`: User who last updated the record
730+
731+
### 9.3 Better-Auth Integration
732+
733+
All better-auth objects are marked as non-customizable to ensure authentication system integrity:
734+
735+
**Protected Objects:**
736+
- `user`: User accounts and authentication
737+
- `account`: OAuth provider accounts
738+
- `session`: Active user sessions
739+
- `verification`: Email/phone verification tokens
740+
- `invitation`: Organization invitations
741+
- `organization`: Multi-tenant organizations
742+
- `member`: Organization memberships
743+
744+
**Example:**
745+
```yaml
746+
# packages/better-auth/src/user.object.yml
747+
name: user
748+
description: System user for authentication
749+
customizable: false
750+
fields:
751+
email:
752+
type: string
753+
unique: true
754+
password:
755+
type: string
756+
hidden: true
757+
createdAt:
758+
type: datetime
759+
customizable: false
760+
updatedAt:
761+
type: datetime
762+
customizable: false
763+
```
764+
765+
### 9.4 Validation API
766+
767+
The MetadataRegistry provides validation methods to check if metadata can be modified:
768+
769+
```typescript
770+
import { MetadataRegistry } from '@objectql/metadata';
771+
772+
const registry = new MetadataRegistry();
773+
774+
// Check if an object can be modified
775+
try {
776+
registry.validateObjectCustomizable('user');
777+
// Proceed with modification
778+
} catch (error) {
779+
// Error: Cannot modify system object 'user'
780+
}
781+
782+
// Check if a field can be modified
783+
try {
784+
registry.validateFieldCustomizable('user', 'createdAt');
785+
// Proceed with field modification
786+
} catch (error) {
787+
// Error: Cannot modify system field 'createdAt' on object 'user'
788+
}
789+
```
790+
791+
### 9.5 Best Practices
792+
793+
1. **System Objects**: Always mark authentication and core system objects as non-customizable
794+
2. **Audit Fields**: Mark timestamp and user tracking fields as non-customizable
795+
3. **Custom Extensions**: Allow users to add custom fields to system objects by keeping the object customizable but protecting core fields
796+
4. **Documentation**: Clearly document which objects and fields are protected and why
797+
5. **Error Messages**: Provide clear error messages when modification attempts are blocked
798+
799+
### 9.6 Default Behavior
800+
801+
**When the `customizable` property is not specified, it defaults to `true` (customizable).**
802+
803+
This means:
804+
- **Objects without `customizable` property**: Can be modified and deleted
805+
- **Fields without `customizable` property**: Can be modified and deleted
806+
807+
**Examples:**
808+
809+
```yaml
810+
# Object without customizable - defaults to true (customizable)
811+
name: my_custom_object
812+
fields:
813+
title:
814+
type: text
815+
# Field without customizable - defaults to true (customizable)
816+
description:
817+
type: textarea
818+
# Field without customizable - defaults to true (customizable)
819+
```
820+
821+
```yaml
822+
# Explicitly marking as non-customizable
823+
name: user
824+
customizable: false # Must be explicitly set to false to protect
825+
fields:
826+
email:
827+
type: email
828+
customizable: false # Must be explicitly set to false to protect
829+
createdAt:
830+
type: datetime
831+
customizable: false # Must be explicitly set to false to protect
832+
customField:
833+
type: text
834+
# No customizable property - defaults to true (customizable)
835+
```
836+
837+
This default behavior ensures:
838+
1. **Backward Compatibility**: Existing objects and fields without the `customizable` property continue to work as before
839+
2. **Opt-in Protection**: System objects and fields must explicitly opt-in to protection by setting `customizable: false`
840+
3. **Safe Defaults**: User-defined metadata is customizable by default, only system metadata needs protection
841+
842+

examples/README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# ObjectQL Examples
2+
3+
This directory contains example projects and demonstrations for ObjectQL.
4+
5+
## Examples
6+
7+
### 1. Project Management (`project-management/`)
8+
9+
A complete project management application demonstrating:
10+
- Object definitions with fields, relationships, and validations
11+
- Custom actions and lifecycle hooks
12+
- Data modeling best practices
13+
14+
**Run:**
15+
```bash
16+
cd project-management
17+
npm install
18+
npm run build
19+
npm start
20+
```
21+
22+
### 2. Metadata Protection Demo (`metadata-protection-demo.ts`)
23+
24+
A demonstration of ObjectQL's metadata protection feature, similar to Salesforce's approach to protecting system objects and fields.
25+
26+
**Features demonstrated:**
27+
- Marking objects as non-customizable
28+
- Protecting system fields from modification
29+
- Validation of metadata changes
30+
- Better-auth integration protection
31+
32+
**Run:**
33+
```bash
34+
npx ts-node metadata-protection-demo.ts
35+
```
36+
37+
**What you'll see:**
38+
- System objects (like `user`) cannot be modified or deleted
39+
- System fields (like `createdAt`, `updatedAt`) are protected
40+
- Custom objects and fields can be freely modified
41+
- Packages containing system objects cannot be unregistered
42+
- Clear error messages when attempting to modify protected metadata
43+
44+
**Use Cases:**
45+
- Protecting authentication system integrity
46+
- Preventing accidental modification of core system objects
47+
- Maintaining audit trail fields
48+
- Enforcing schema stability for critical infrastructure
49+
50+
## Learn More
51+
52+
- [ObjectQL Documentation](../docs/)
53+
- [Metadata Specification](../docs/spec/metadata-format.md)
54+
- [Metadata Protection Guide](../docs/spec/metadata-format.md#9-metadata-protection)

0 commit comments

Comments
 (0)