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
destructiveflag, oreffect: 'destructive'. - Its
typeissubmitorstate_change. - For
api_callorcustomtypes, 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:
VehicleDetails.deleteVehicle (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.