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.
| Surface | Lives in | Addressed by | Authored by |
|---|---|---|---|
| Pointcut interface (this page) | The block’s source tree, compiled into and served by meta.svc | Interface name + method name | The block; a product implements against it |
| Hook | The engine’s execution chain | Phase + priority | Go code compiled into the binary |
Entity pointcuts: block | A product’s entity YAML | Canonical 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.
Where the templates are served from
Section titled “Where the templates are served from”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.
| Method | Path | Returns |
|---|---|---|
| GET | /service/data/type/pointcut | All twelve templates, raw, keyed by file path |
| GET | /service/data/type/pointcut?format=yaml | The same set, parsed into objects |
| GET | /service/data/type/pointcut?array=true | The 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.
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.
The twelve interfaces
Section titled “The twelve interfaces”| File | Interface | Methods | Covers |
|---|---|---|---|
on_create.yaml | OnCreate | 4 | Row create |
on_update.yaml | OnUpdate | 4 | Row update |
on_delete.yaml | OnDelete | 3 | Row delete |
on_read.yaml | OnRead | 5 | Row read, plus mask and decrypt passes |
on_child_create.yaml | OnChildCreate | 4 | Child-row mirror of OnCreate |
on_child_update.yaml | OnChildUpdate | 4 | Child-row mirror of OnUpdate |
on_child_delete.yaml | OnChildDelete | 3 | Child-row mirror of OnDelete |
on_child_read.yaml | OnChildRead | 5 | Child-row mirror of OnRead |
on_import.yaml | OnImport | 3 | Bulk import, including the raw-bytes parse step |
on_export.yaml | OnExport | 4 | Export |
on_entity_field_create.yaml | OnEntityFieldCreate | 1 | Field tokenization on create |
on_entity_field_update.yaml | OnEntityFieldUpdate | 1 | Field tokenization on update |
Method catalogue
Section titled “Method catalogue”Forty-one methods across the twelve interfaces. Names are case-sensitive.
| Interface | Method | Signature |
|---|---|---|
OnCreate | ValidateBeforeCreate | (ctx, entity, payload, params) |
OnCreate | AugmentBeforeCreate | (ctx, entity, payload, params) |
OnCreate | ExecuteOnCreateSuccess | (ctx, payload, params) |
OnCreate | ExecuteOnCreateFailure | (ctx, payload, params) |
OnUpdate | ValidateBeforeUpdate | (ctx, entity, payload, params) |
OnUpdate | AugmentBeforeUpdate | (ctx, entity, payload, params) |
OnUpdate | ExecuteOnUpdateSuccess | (ctx, payload, params) |
OnUpdate | ExecuteOnUpdateFailure | (ctx, payload, params) |
OnDelete | ExecuteBeforeDelete | (ctx, entity, payload, params) |
OnDelete | ExecuteOnDeleteSuccess | (ctx, payload, params) |
OnDelete | ExecuteOnDeleteFailure | (ctx, payload, params) |
OnRead | ExecuteBeforeRead | (ctx, entity, payload, params) |
OnRead | MaskAfterRead | (ctx, entity, payload, params) |
OnRead | DecryptAfterRead | (ctx, entity, payload, params) |
OnRead | ExecuteOnReadSuccess | (ctx, payload, params) |
OnRead | ExecuteOnReadFailure | (ctx, payload, params) |
OnChildCreate | ValidateBeforeChildCreate | (ctx, entity, payload, params) |
OnChildCreate | AugmentBeforeChildCreate | (ctx, entity, payload, params) |
OnChildCreate | ExecuteOnChildCreateSuccess | (ctx, payload, params) |
OnChildCreate | ExecuteOnChildCreateFailure | (ctx, payload, params) |
OnChildUpdate | ValidateBeforeChildUpdate | (ctx, entity, payload, params) |
OnChildUpdate | AugmentBeforeChildUpdate | (ctx, entity, payload, params) |
OnChildUpdate | ExecuteOnChildUpdateSuccess | (ctx, payload, params) |
OnChildUpdate | ExecuteOnChildUpdateFailure | (ctx, payload, params) |
OnChildDelete | ExecuteBeforeChildDelete | (ctx, entity, payload, params) |
OnChildDelete | ExecuteOnChildDeleteSuccess | (ctx, payload, params) |
OnChildDelete | ExecuteOnChildDeleteFailure | (ctx, payload, params) |
OnChildRead | ExecuteBeforeChildRead | (ctx, entity, payload, params) |
OnChildRead | MaskAfterChildRead | (ctx, entity, payload, params) |
OnChildRead | DecryptAfterChildRead | (ctx, entity, payload, params) |
OnChildRead | ExecuteOnChildReadSuccess | (ctx, payload, params) |
OnChildRead | ExecuteOnChildReadFailure | (ctx, payload, params) |
OnImport | ParseBeforeImport | (ctx, type, payload, params) — payload is bytes |
OnImport | ExecuteOnImportSuccess | (ctx, payload, params) |
OnImport | ExecuteOnImportFailure | (ctx, payload, params) |
OnExport | ValidateBeforeExport | (ctx, entity, payload, params) |
OnExport | AugmentBeforeExport | (ctx, entity, payload, params) |
OnExport | ExecuteOnExportSuccess | (ctx, payload, params) |
OnExport | ExecuteOnExportFailure | (ctx, payload, params) |
OnEntityFieldCreate | Tokenize | (ctx, entity, payload, params) |
OnEntityFieldUpdate | Tokenize | (ctx, entity, payload, params) |
Arguments
Section titled “Arguments”| Argument | Declared type | Present on |
|---|---|---|
ctx | map of string | Every method |
entity | string | Every method except Execute*Success / Execute*Failure and ParseBeforeImport |
type | string | ParseBeforeImport only, in the slot entity occupies elsewhere |
payload | map of any — bytes on ParseBeforeImport | Every method |
params | array of any | Every method |
Template file format
Section titled “Template file format”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: OnCreatemethods:- 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: anyThe 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.
Implementing one in a product
Section titled “Implementing one in a product”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: dummypluginmeta: entities: - product - bugservice: dataactive: truecategory:- computeimplements:- name: OnCreate priority: 100 methods: - ExecuteOnCreateSuccess - ExecuteOnCreateFailurelanguage: jscapabilities:- network: - public- memory: max: 5Mtags:- compute- operationsarguments:- name: params value: ~config: type: stdoutThe 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);}Declaration keys
Section titled “Declaration keys”meta.svc reads exactly two keys and injects a third. Everything else is returned verbatim to whichever block consumes the declaration.
| Key | Read by meta.svc | Meaning |
|---|---|---|
service | Yes — the filter | Which block the plugin targets. Compared case-insensitively; anything other than data is excluded from the Data API listing |
name | Yes — the map key | Plugin name. The listing is keyed by it, so it is required |
path | Injected | The plugin’s directory. Added to the parsed object only — the default raw form returns the file text unchanged |
implements[].name | No | Interface name from the catalogue above |
implements[].methods | No | The subset of that interface’s methods this plugin provides |
implements[].priority | No | Ordering among plugins bound to the same interface |
language | No | Script runtime. The shipped examples use js |
meta.entities | No | Entities the plugin is scoped to |
active | No | Author’s enable flag |
category, tags | No | Catalogue labels |
capabilities | No | Declared resource and network needs |
arguments | No | Declared argument defaults, merged with call arguments by the consuming block |
config | No | Free-form plugin configuration |
Reading a product’s declarations
Section titled “Reading a product’s declarations”| Method | Path | Returns |
|---|---|---|
| GET | /product/{id}/service/data/type/plugin | Every 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.
Related
Section titled “Related”| Concern | Page |
|---|---|
| Where product definitions live on disk | Schema sources |
The hook chain, and the entity pointcuts: block that runs on it | Hooks and the execution pipeline |
| Guards that do run on every request | Access rules |
| Masking and classification, and what is enforced | Field protection |
| Serving, versioning and authenticating definitions | meta.svc |
| Endpoint-level HTTP reference | Data API reference |