Skip to content
Talk to our solutions team

Pointcuts

The Data API block ships twelve pointcut interface declarations. Each names a point in an entity’s lifecycle and fixes the method names and argument list an implementation must provide. meta.svc compiles them into its own binary and serves them read-only under the service name data, which is how a product repository discovers what it is allowed to implement. The data.svc binary neither serves nor reads them.

Pointcut, hook, and the schema-declared block

Section titled “Pointcut, hook, and the schema-declared block”

Three things in this block are easy to confuse.

SurfaceLives inAddressed byAuthored by
Pointcut interface (this page)The block’s source tree, compiled into and served by meta.svcInterface name + method nameThe block; a product implements against it
HookThe engine’s execution chainPhase + priorityGo code compiled into the binary
Entity pointcuts: blockA product’s entity YAMLCanonical method name + order:The schema author

A hook is a Go implementation on the request pipeline — the access gate, computed fields, entity validation, the stateflow guard. Hooks are chosen and ordered by the process that builds the engine; you cannot add one from YAML.

A pointcut interface is the opposite: the block publishes a contract and the implementation lives outside the binary, in a product repository, written in a script language. Nothing about it is negotiated at build time.

The pointcuts: block on an entity is a third thing that shares the word. It is dispatched in process by the hook chain, uses its own canonical method vocabulary, and is declared inside the entity YAML rather than in a separate plugin folder. The interface catalogue below does not apply to it.

The interfaces are compiled into meta.svc as an embedded filesystem and mounted at the virtual path /embed/pointcuts, one YAML file per interface. meta.svc registers that filesystem under the service name data and maps the type pointcut to that path; pointcut is the only capability the Data API block publishes this way.

MethodPathReturns
GET/service/data/type/pointcutAll twelve templates, raw, keyed by file path
GET/service/data/type/pointcut?format=yamlThe same set, parsed into objects
GET/service/data/type/pointcut?array=trueThe same set as a list instead of a map

The response envelope is {"data": …}. Every entry carries two injected keys: _path, the full virtual path, and _name, the file name. In the raw form those two are appended to the file body as extra YAML lines rather than added to a parsed object.

Terminal window
curl -H "X-Api-Key: $API_KEY" "https://meta.example.com/service/data/type/pointcut?format=yaml"

See the meta.svc for authentication, ETags and the version / versionType parameters that apply to every read route.

FileInterfaceMethodsCovers
on_create.yamlOnCreate4Row create
on_update.yamlOnUpdate4Row update
on_delete.yamlOnDelete3Row delete
on_read.yamlOnRead5Row read, plus mask and decrypt passes
on_child_create.yamlOnChildCreate4Child-row mirror of OnCreate
on_child_update.yamlOnChildUpdate4Child-row mirror of OnUpdate
on_child_delete.yamlOnChildDelete3Child-row mirror of OnDelete
on_child_read.yamlOnChildRead5Child-row mirror of OnRead
on_import.yamlOnImport3Bulk import, including the raw-bytes parse step
on_export.yamlOnExport4Export
on_entity_field_create.yamlOnEntityFieldCreate1Field tokenization on create
on_entity_field_update.yamlOnEntityFieldUpdate1Field tokenization on update

Forty-one methods across the twelve interfaces. Names are case-sensitive.

InterfaceMethodSignature
OnCreateValidateBeforeCreate(ctx, entity, payload, params)
OnCreateAugmentBeforeCreate(ctx, entity, payload, params)
OnCreateExecuteOnCreateSuccess(ctx, payload, params)
OnCreateExecuteOnCreateFailure(ctx, payload, params)
OnUpdateValidateBeforeUpdate(ctx, entity, payload, params)
OnUpdateAugmentBeforeUpdate(ctx, entity, payload, params)
OnUpdateExecuteOnUpdateSuccess(ctx, payload, params)
OnUpdateExecuteOnUpdateFailure(ctx, payload, params)
OnDeleteExecuteBeforeDelete(ctx, entity, payload, params)
OnDeleteExecuteOnDeleteSuccess(ctx, payload, params)
OnDeleteExecuteOnDeleteFailure(ctx, payload, params)
OnReadExecuteBeforeRead(ctx, entity, payload, params)
OnReadMaskAfterRead(ctx, entity, payload, params)
OnReadDecryptAfterRead(ctx, entity, payload, params)
OnReadExecuteOnReadSuccess(ctx, payload, params)
OnReadExecuteOnReadFailure(ctx, payload, params)
OnChildCreateValidateBeforeChildCreate(ctx, entity, payload, params)
OnChildCreateAugmentBeforeChildCreate(ctx, entity, payload, params)
OnChildCreateExecuteOnChildCreateSuccess(ctx, payload, params)
OnChildCreateExecuteOnChildCreateFailure(ctx, payload, params)
OnChildUpdateValidateBeforeChildUpdate(ctx, entity, payload, params)
OnChildUpdateAugmentBeforeChildUpdate(ctx, entity, payload, params)
OnChildUpdateExecuteOnChildUpdateSuccess(ctx, payload, params)
OnChildUpdateExecuteOnChildUpdateFailure(ctx, payload, params)
OnChildDeleteExecuteBeforeChildDelete(ctx, entity, payload, params)
OnChildDeleteExecuteOnChildDeleteSuccess(ctx, payload, params)
OnChildDeleteExecuteOnChildDeleteFailure(ctx, payload, params)
OnChildReadExecuteBeforeChildRead(ctx, entity, payload, params)
OnChildReadMaskAfterChildRead(ctx, entity, payload, params)
OnChildReadDecryptAfterChildRead(ctx, entity, payload, params)
OnChildReadExecuteOnChildReadSuccess(ctx, payload, params)
OnChildReadExecuteOnChildReadFailure(ctx, payload, params)
OnImportParseBeforeImport(ctx, type, payload, params)payload is bytes
OnImportExecuteOnImportSuccess(ctx, payload, params)
OnImportExecuteOnImportFailure(ctx, payload, params)
OnExportValidateBeforeExport(ctx, entity, payload, params)
OnExportAugmentBeforeExport(ctx, entity, payload, params)
OnExportExecuteOnExportSuccess(ctx, payload, params)
OnExportExecuteOnExportFailure(ctx, payload, params)
OnEntityFieldCreateTokenize(ctx, entity, payload, params)
OnEntityFieldUpdateTokenize(ctx, entity, payload, params)
ArgumentDeclared typePresent on
ctxmap of stringEvery method
entitystringEvery method except Execute*Success / Execute*Failure and ParseBeforeImport
typestringParseBeforeImport only, in the slot entity occupies elsewhere
payloadmap of anybytes on ParseBeforeImportEvery method
paramsarray of anyEvery method

Each file declares one interface name and its method list. Arguments are ordered, and each carries a type with an optional subtype for the element or value type. The shipped Data API templates use four types: map (with subtype string or any), string, array (subtype any) and bytes.

---
name: OnCreate
methods:
- name: ValidateBeforeCreate
arguments:
- name: ctx
type: map
subtype: string
- name: entity
type: string
- name: payload
type: map
subtype: any
- name: params
type: array
subtype: any
- name: ExecuteOnCreateSuccess
arguments:
- name: ctx
type: map
subtype: string
- name: payload
type: map
subtype: any
- name: params
type: array
subtype: any

The route is read-only, and a product cannot add an interface or a method — the catalogue is fixed by the meta.svc build that serves it. The one exception is operator-side: a repository named data in meta.svc’s services: configuration is loaded before the embedded set and takes its place entirely.

A product implements a pointcut as a plugin under data/plugins/. The directory scan is one level deep and the manifest file name is fixed: data/plugins/<name>/plugin.yaml. Nested directories and any other file name are ignored.

data/
plugins/
dummyplugin/
plugin.yaml
plugin.js
---
name: dummyplugin
meta:
entities:
- product
- bug
service: data
active: true
category:
- compute
implements:
- name: OnCreate
priority: 100
methods:
- ExecuteOnCreateSuccess
- ExecuteOnCreateFailure
language: js
capabilities:
- network:
- public
- memory:
max: 5M
tags:
- compute
- operations
arguments:
- name: params
value: ~
config:
type: stdout

The script file exports one function per declared method, with the signature the template fixes:

function ExecuteOnCreateSuccess(ctx, payload, params) {
console.log("dummyplugin: create succeeded", ctx, payload, params);
}
function ExecuteOnCreateFailure(ctx, payload, params) {
console.log("dummyplugin: create failed", ctx, payload, params);
}

meta.svc reads exactly two keys and injects a third. Everything else is returned verbatim to whichever block consumes the declaration.

KeyRead by meta.svcMeaning
serviceYes — the filterWhich block the plugin targets. Compared case-insensitively; anything other than data is excluded from the Data API listing
nameYes — the map keyPlugin name. The listing is keyed by it, so it is required
pathInjectedThe plugin’s directory. Added to the parsed object only — the default raw form returns the file text unchanged
implements[].nameNoInterface name from the catalogue above
implements[].methodsNoThe subset of that interface’s methods this plugin provides
implements[].priorityNoOrdering among plugins bound to the same interface
languageNoScript runtime. The shipped examples use js
meta.entitiesNoEntities the plugin is scoped to
activeNoAuthor’s enable flag
category, tagsNoCatalogue labels
capabilitiesNoDeclared resource and network needs
argumentsNoDeclared argument defaults, merged with call arguments by the consuming block
configNoFree-form plugin configuration
MethodPathReturns
GET/product/{id}/service/data/type/pluginEvery plugin.yaml under data/plugins/ whose service: is data, keyed by name

Add ?format=yaml for parsed objects and ?array=true for a list, the same as the template routes.

ConcernPage
Where product definitions live on diskSchema sources
The hook chain, and the entity pointcuts: block that runs on itHooks and the execution pipeline
Guards that do run on every requestAccess rules
Masking and classification, and what is enforcedField protection
Serving, versioning and authenticating definitionsmeta.svc
Endpoint-level HTTP referenceData API reference