Skip to content

11 — Generated CRUD API

The generated CRUD API is the runtime API layer that uses the published entity model to create, read, update, delete, tag, relate, and query entities.

It is not code generation in the traditional sense. It is model-driven runtime behavior.

Goal

Enable a new entity type to become usable without writing bespoke CRUD endpoints.

Example:

  1. Admin defines entity type room.
  2. Admin defines properties and hierarchy rules.
  3. Admin publishes model.
  4. Runtime API can create, read, update, delete, and list room entities.
  5. Frontend can render basic forms and tables for rooms.

Generic Entity Create

Endpoint:

text
POST /api/entities

Input:

json
{
  "entityTypeKey": "asset",
  "parentEntityId": "uuid",
  "templateKey": "bacnet_controller",
  "properties": {
    "hostname": "AHU-01",
    "ip_address": "192.168.1.50",
    "bacnet_device_id": 12001
  },
  "tags": ["criticality_high", "vendor_trend"]
}

Backend behavior:

  1. Resolve published model.
  2. Resolve entity type.
  3. Validate parent and hierarchy rules.
  4. Validate template.
  5. Validate property values.
  6. Validate tags.
  7. Check permissions and root scope.
  8. Create entity and values in transaction.
  9. Write audit event.

Generic Entity Update

Endpoint:

text
PATCH /api/entities/:entityId

Should allow:

  • updating display metadata,
  • updating property values,
  • updating tags,
  • optionally moving parent if entity.move is allowed.

Dangerous operations such as subtree move should have explicit endpoints.

Generic Entity List

Endpoint:

text
GET /api/entities?type=asset&parentEntityId=...&q=...

Supported filters:

  • entity type,
  • root scope,
  • parent,
  • descendants of,
  • tags,
  • property filters,
  • created/updated dates,
  • deleted state.

The backend must translate filters safely into SQL.

Property Filtering

Property filters should be explicit and typed.

Example:

json
{
  "filters": [
    {
      "propertyKey": "ip_address",
      "operator": "equals",
      "value": "192.168.1.50"
    },
    {
      "propertyKey": "commissioning_status",
      "operator": "in",
      "value": ["blocked", "in_progress"]
    }
  ]
}

Only filterable properties should be queryable.

Avoid Arbitrary Query APIs Initially

Do not expose a completely arbitrary user-defined query language in Alpha.

Start with controlled filters.

Future versions can introduce:

  • saved views,
  • advanced filters,
  • query builder UI,
  • reporting DSL,
  • external data joins.

Generated API Is Still Governed

The generic API must enforce:

  • root scope,
  • permissions,
  • published model validation,
  • lifecycle rules,
  • Vault boundaries,
  • audit events,
  • rate limits where needed.

When To Use Custom APIs

Use custom APIs for workflows with domain behavior.

Examples:

  • reveal secret,
  • rotate secret,
  • launch remote session,
  • import from Simpro,
  • bulk commissioning workflow,
  • approval flow,
  • operational report generation.

The generated CRUD API handles common entity data operations. It should not replace application services.