Docs

Validation rules

What the platform rejects before a smart app runs.

Smart-app code is checked when it is registered or generated. These rules are enforced server-side; the runtime enforces the same limits again.

Size

Source must be at most 131,072 characters (128 KiB).

Timer rules

Global timer APIs the smart-app isolate does not expose (see apps/edge-runtime/src/assets/isolateHelpers.js) — calls would throw at runtime. The prompts steer to runIn / runOnce / runDaily / schedule / unschedule; smaller models still slip back to the JS-standard names occasionally, so we enforce server-side.

match says how the name is detected: call only as name(, identifier as any bare use, method only as .name(.

Banned nameMatch
setTimeoutcall
setIntervalcall
clearTimeoutcall
clearIntervalcall

User restricted rules

Isolate APIs excluded from the end-user AI-automation surface (v1 scope: entity triggers/actions, schedules, presence/mode conditions, push notifications). These EXIST in the isolate — the ban is a product decision, not a missing binding — so match bare identifiers to also catch aliasing.

match says how the name is detected: call only as name(, identifier as any bare use, method only as .name(.

Banned nameMatch
sendSmsidentifier
sendEmailidentifier
httpRequestidentifier
runSmartAppidentifier
pauseSmartAppidentifier
resumeSmartAppidentifier
listSmartAppInstancesidentifier
getChildAppsidentifier
getParentidentifier
getChildAppByIdidentifier
sendToHostSyncidentifier
sendToHostAsyncidentifier

Local time rules

Local-time Date instance methods. The isolate's new Date() runs in the edge-runtime PROCESS timezone (usually UTC), not the home's — so any handler-internal wall-clock logic built on these evaluates in the wrong zone (e.g. "only between 10pm and 6am" firing on UTC hours). The correct idiom is formatDateParts(new Date(), getHomeTimeZone()). Epoch math (Date.now(), .getTime()) and the getUTC* family are TZ-independent and stay allowed.

match says how the name is detected: call only as name(, identifier as any bare use, method only as .name(.

Banned nameMatch
getHoursmethod
getMinutesmethod
getDaymethod
getDatemethod
getMonthmethod
getFullYearmethod
getTimezoneOffsetmethod
toLocaleStringmethod
toLocaleTimeStringmethod
toLocaleDateStringmethod

User automation rules

Timer rules + the user-surface capability ban + the local-time ban, for user-generated code. (The admin chat surface stays timer-only — it emits engineer-facing suggestions, not fail-closed installs.)

match says how the name is detected: call only as name(, identifier as any bare use, method only as .name(.

Banned nameMatch
setTimeoutcall
setIntervalcall
clearTimeoutcall
clearIntervalcall
sendSmsidentifier
sendEmailidentifier
httpRequestidentifier
runSmartAppidentifier
pauseSmartAppidentifier
resumeSmartAppidentifier
listSmartAppInstancesidentifier
getChildAppsidentifier
getParentidentifier
getChildAppByIdidentifier
sendToHostSyncidentifier
sendToHostAsyncidentifier
getHoursmethod
getMinutesmethod
getDaymethod
getDatemethod
getMonthmethod
getFullYearmethod
getTimezoneOffsetmethod
toLocaleStringmethod
toLocaleTimeStringmethod
toLocaleDateStringmethod

Domain state vocabulary

States the validator accepts in subscription filters per domain.

DomainStates
lighton, off
switchon, off
fanon, off
sirenon, off
remoteon, off
input_booleanon, off
binary_sensoron, off
lockunlocked, locked, unlocking, locking
coveropen, closed, opening, closing
valveopen, closed, opening, closing
climateoff, cool, heat, heat_cool, fan_only, dry
media_playerplaying, paused, stopped, buffering
cameraidle, recording, streaming
presencepresent, not_present
sunABOVE_HORIZON, BELOW_HORIZON

Non-entity input types

Input types the validator recognises as non-entity: /type\s*:\s*['"](?:time\|date\|text\|string\|email\|number\|enum\|array\|boolean\|password\|thermostatSchedule)['"]/

Generated from docs-bundle v0.1.0, novon-platform 9ce3486c (2026-10-09).

On this page