Chapter IV · Lua.ex integration / Lesson 23 of 27 Host integration

Private host context

You'll learn: Pass authenticated context to deflua handlers without exposing it to Lua scripts.

Lua.put_private(lua, :user_id, 42) stores host state inside the VM that *Lua scripts cannot see*. In a deflua body taking state, Lua.get_private!(state, :user_id) reads it back. This is the pattern for multi-tenant sandboxes: auth, tenant id, and API keys stay on the host side; the script sees only return values.

Elixir · your app
Reference only
defmodule Account do
  use Lua.API, scope: "account"

  deflua balance(), state do
    user_id = Lua.get_private!(state, :user_id)
    {[fetch_balance(user_id)], state}
  end
end

lua =
  Lua.new()
  |> Lua.load_api(Account)
  |> Lua.put_private(:user_id, 42)

{[bal], _} = Lua.eval!(lua, "return account.balance()")
put-private.lua
Output idle
Hit Run to execute.
Try it: Print type(user_id) from Lua — it stays nil. Now write a malicious-looking snippet that *tries* to read the user id (return _G.user_id) and confirm it can't.