Skip to main content

Metadata Quality

sync and generate both run a metadata lint automatically. It surfaces — but by default doesn't fail on — mutating actions that are missing safety metadata.

What counts as "mutating"​

An action is considered mutating if any of the following is true:

  • It has an explicit destructive flag, or effect: 'destructive'.
  • Its type is submit or state_change.
  • For api_call or custom types, a mutation verb — delete, remove, create, save, submit, update, pay, send, confirm, subscribe, and similar — appears in the action's id, label, or handler name.

What it checks​

For every mutating action, the lint checks whether it declares both effect and riskLevel. If either is missing, it emits a warning.

Example warning:

OrderDetails.deleteOrder (submit): missing effect, riskLevel

(format: screen.actionId (type): missing fields)

Why it matters​

effect and riskLevel — along with the destructive and requiresConfirmation flags — are what let the SDK and the platform gate risky actions behind an explicit user confirmation, instead of relying on fragile label-text heuristics. See Agent actions for what these fields do at runtime.

Default behavior vs. --strict-metadata​

By default, warnings print to the log but don't fail the command. Pass --strict-metadata to sync or generate to make the command exit non-zero when any warning exists:

appilots sync --strict-metadata

This is the recommended setting for CI — see CI integration — so a missing risk annotation fails the build instead of silently shipping.

Fixing a warning​

Declare effect and riskLevel explicitly on the action:

  • effect: 'read' | 'write' | 'destructive'
  • riskLevel: 'low' | 'medium' | 'high'

Either directly in the app's source via registerScreen({ actions: [{ id, label, type, effect, riskLevel }] }) — see SDK: Navigation — or through whatever JSDoc/annotation convention the generator recognizes at the call site. @appilots-destructive is one such annotation the analyzer looks for.