Skip to main content

Validation

Validation happens at two gates: build time (qefro solution build) and publish time (registry). The registry applies the same checks as the build, so a package that builds cleanly is publishable. Fix errors at the first gate — publishing a broken package is impossible by design.

The checklist

Manifest

CheckFailure message pattern
id is kebab-case (lowercase, digits, -, starts with a letter)solution id must be kebab-case
name non-emptysolution name is empty
version non-emptysolution version is empty
Connector dependencies non-emptyempty connector dependency
Every flows entry has a definition in workflows/workflow file missing
Unknown permissions / capabilities valuesunknown capability

Widgets

CheckDetail
Closed widget kind listUnknown type values are rejected (unknown widget type)
Widget ids uniqueDuplicate ids fail
source references resolveEvery data-driven widget must name a declared source
markdown content capcontent larger than 20 KB is rejected
form fields validKnown field types; select requires options

Pages and layouts

CheckDetail
Layout typeMust be grid
Column rangecolumns between 1 and 12 (bad grid columns)
Span rangePlacement spans fit within the layout's column count
Placement referencesEvery placement names a declared widget
CheckDetail
Page referencesEvery entry's page must exist in pages.yaml
Closed icon setIcons outside the host set are rejected — see Navigation

Sources

CheckDetail
Source typeruntime or connector only
Runtime targetsmetrics, executions, workflows
Connector targetsDeclared under connectors/ and exposed by the connector

Assets

CheckDetail
Image extensions onlypng, jpg, jpeg, svg, webp
Executable content rejectedscript, iframe, js kinds and other extensions (executable asset paths)
Manifest references resolveui.logo / ui.icon must point at packaged images

Capabilities

CheckDetail
Known capability namesUnknown names rejected at publish (unknown capability)
Grant preconditionsworkflow.trigger needs workflow.execute; connector.invoke needs ≥ 1 declared connector; ungrantable requests are negotiated away at install

Local validation loop

qefro solution build .

The build performs the full checklist, then assembles and signs the package. Typical failures and fixes:

Error: unknown widget type: sparkline
→ widget kinds are a closed list; pick one of the supported kinds.

Error: icon outside the closed set: utensils
→ use a host icon, e.g. chef-hat. See Navigation.

Error: bad grid columns: 16
→ columns must be between 1 and 12.

Error: executable asset paths: assets/widget.js
→ packages ship data only; remove the file.

Render-time defense

Validation does not make render-time checks redundant. The portal applies defensive schema coercion and clamps values (spans, columns) before render, and an error boundary degrades any broken definition to a scoped error card. The two gates have different jobs:

  • Publish-time validation keeps bad packages out of the registry.
  • Render-time coercion keeps the portal alive if a definition is degenerate.