Sandbox & isolation#

Model izolacji#

Każdy plugin działa w osobnym sandboxie Lua z:

  • Izolowanym środowiskiem (własna przestrzeń zmiennych)
  • Śledzeniem zasobów (timery, eventy, MQTT, registry)
  • Automatycznym czyszczeniem przy unload
  • Ograniczonym dostępem do systemu
┌─────────────────────────────────────────┐
│           Plugin Manager (vCLU)         │
├──────────┬──────────┬───────────────────┤
│ weather  │ telegram │ sun-position      │
│ timers[] │ timers[] │ timers[]          │
│ events[] │ events[] │ events[]          │
│ mqtt[]   │ mqtt[]   │ mqtt[]            │
│ reg[]    │ reg[]    │ reg[]             │
└──────────┴──────────┴───────────────────┘

Dostępne API#

Każdy plugin ma dostęp do bezpiecznego podzbioru Lua i vCLU API:

Lua standard#

print, pairs, ipairs, type, tostring, tonumber, pcall, error, assert, string.*, table.*, math.*, os.time, os.date, os.difftime, os.clock

vCLU API#

Plugin, EventBus, JSON, Logger, HTTP, MQTT, setTimeout, setInterval, clearInterval, _ / _registry (odczyt dowolny, zapis tylko own namespace)

Zablokowane#

FunkcjaPowód
os.execute()Brak dostępu do shell
io.*Brak dostępu do plików
loadfile(), dofile(), load()Brak dynamicznego ładowania kodu
rawset(), rawget()Brak obejścia ochrony
debug.*Brak debug API

Śledzenie zasobów#

System automatycznie śledzi wszystkie zasoby tworzone przez plugin:

ZasóbTworzenieAutomatyczne czyszczenie
Timeryplugin:setTimeout(), plugin:setInterval()Usunięcie wszystkich timerów
Eventyplugin:on()Wyrejestrowanie subskrypcji
MQTTplugin:mqttSubscribe()Wyrejestrowanie subskrypcji
Registryplugin:upsertObject()Usunięcie obiektów z namespace
Throttleplugin:emit({throttle = ...})Wyczyszczenie stanu

Auto-cleanup#

Przy unload pluginu (wyłączenie, odinstalowanie, zmiana konfiguracji) system automatycznie czyści wszystkie zasoby.

Plugin nie musi ręcznie czyścić timerów, eventów ani MQTT w onCleanup():

plugin:onCleanup(function()
    -- Timery, eventy, MQTT — auto-czyszczone!
    -- Tutaj tylko własne zasoby (np. zamknięcie połączeń)
    plugin:log("info", "Plugin stopped")
end)

Write protection#

Registry ma ochronę zapisu — plugin może pisać tylko do swojego namespace:

-- Format: plugins.{namespace}.{shortId}.{path}

-- OK — własny namespace:
plugin:upsertObject("sensor", {})
-- → plugins.vclu.weather.sensor ✓

-- BŁĄD — cudzy namespace:
_registry["CLU.DOUT1"] = something
-- → error: Plugin can only write to own namespace ✗

-- OK — odczyt dowolny:
local lamp = _:get("CLU.DOUT1")  -- ✓

Komunikacja między pluginami#

Pluginy mogą się komunikować przez:

Events (rekomendowane)#

-- Plugin A emituje
plugin:emit("weather:changed", {temp = 22.5})

-- Plugin B subskrybuje
plugin:on("weather:changed", function(data)
    plugin:log("info", "Temp: " .. data.temp)
end)

Public API#

-- Plugin B wywołuje metody Plugin A
local weather = Plugin.getPlugin("@vclu/weather")
if weather and weather:isReady() then
    local temp = weather:getTemperature()
end

Registry (read-only)#

-- Plugin B czyta obiekt Plugin A
local data = plugin:getObject("plugins.vclu.weather.current")
if data then
    plugin:log("info", "Weather data: " .. data.temp)
end

Limity#

ZasóbLimit
TimeryBez limitu (śledzone, auto-cleanup)
HTTP requestsBez limitu (timeout per-request)
MQTT subscriptionsBez limitu (śledzone)
Registry objectsTylko w own namespace
KV StorePer-plugin, na dysku
SiećTylko HTTP/HTTPS i MQTT
FilesystemBrak dostępu
SystemBrak os.execute