Skip to main content

Side Effects and External I/O

External effects are separate capabilities, not incidental helpers. A script that can navigate should not automatically gain permission to send chat, invoke commands, contact a server, or persist data.

Candidate capability groups

GroupPurposeDefault posture
hexis.chatSend a visible server chat messagePrompt and rate-limit
hexis.commandsInvoke an allowlisted game/client commandPrompt per command family
hexis.notifyShow a local user notificationAllow with rate limits
hexis.httpCall an approved HTTPS originDeny unless origin is declared
hexis.storageRead/write script-scoped durable stateIsolated quota

These names do not become executable until their own vertical slices pass the acceptance matrix.

Request boundary

Each request must declare enough intent for Hexis to authorize and audit it.

local request = hexis.http.request({
method = "POST",
url = "https://api.example.com/v1/progress",
headers = {["content-type"] = "application/json"},
body = hexis.json.encode({state = "complete"}),
timeout = 5,
max_response_bytes = 65536,
})

local result = hexis.await(request)

The example is proposed syntax. An HTTP capability grant is scoped to normalized HTTPS origins, methods, request/response budgets, redirect policy, and secret references. Scripts never receive raw secret values.

Chat and commands

  • Chat text is length-limited, rate-limited, and visible in the local audit log.
  • Command permission is matched against a parsed command family, not a string prefix that can be bypassed with whitespace or aliases.
  • Server and pack adapters may describe semantic commands, but cannot grant permission.
  • Hexis prevents accidental duplicate sends when an action is retried.
  • Private chat is excluded from diagnostics and AI repair context by default.

HTTP

The engine owns DNS resolution, TLS, redirects, timeouts, byte limits, content type handling, cancellation, and redaction. Lua receives an immutable result, never a Java stream or socket.

Required denials include:

  • non-HTTPS URLs outside an explicit developer mode;
  • loopback, link-local, private-network, and metadata endpoints;
  • undeclared origins or redirect escapes;
  • unbounded bodies, responses, or request duration;
  • direct cookie, credential-store, or filesystem access.

Script-scoped storage

Storage is namespaced by script identity and API major version. Values are structured, size-limited, atomic, and migration-aware. A script cannot enumerate another script's keys or use paths to escape its namespace.

Configuration remains separate from storage: configuration is user-visible and schema-driven; storage is bounded workflow state.

Result and failure contract

Side-effect actions use the standard result envelope. Domain codes include:

CodeMeaning
ORIGIN_DENIEDHTTP origin is outside the capability grant
COMMAND_DENIEDCommand family is not approved
RATE_LIMITEDThe script exceeded an effect budget
RESPONSE_TOO_LARGEHTTP response exceeded its declared limit
STORAGE_QUOTA_EXCEEDEDScript storage cannot accept the write
USER_REJECTEDThe user declined a permission or confirmation

Authentication secrets, private messages, and response bodies are not included in message fields or default telemetry.

Lifecycle and ownership

Requests belong to a scope. Cancellation aborts pending network work where possible, prevents queued chat/commands from sending, and completes the handle exactly once. Storage commits that have begun are atomic rather than partially cancelled.

High-level engine actions do not silently invoke external effects. A workflow that sells inventory through a server menu may use game interaction; reporting that sale to an external service requires a separate HTTP capability.

Acceptance tasks

  1. Send one approved chat message and prove duplicate retry suppression.
  2. Reject an undeclared command alias and normalization bypass.
  3. Cancel an HTTP request during DNS, connect, and response reading.
  4. Block redirects to loopback, private-network, and undeclared origins.
  5. Enforce request, response, time, and rate budgets.
  6. Prove secrets and private chat are absent from logs and AI context.
  7. Crash during a storage update and recover either the old or new value.
  8. Attempt cross-script storage access and prove isolation.
  9. Stop a script with queued effects and prove nothing sends afterward.
  10. Generate the workflow with AI without inventing filesystem or socket APIs.