Architecture¶
┌────────────── entrypoints ──────────────┐
invoke ──▶ │ crates/lambda (Lambda, arm64) │
ALB ──▶ │ crates/server (Fargate: HTTP + SQS) │ ──▶ Engine::invoke
SQS ──▶ └─────────────────────────────────────────┘ │
▼
┌───────────── crates/core ──────────────────────────────┐
│ 1. load <tenant>/config.json (policy, vars, limits) │
│ 2. load <tenant>/<script>/<version>.luau (cached) │
│ 3. fresh Luau VM + `native` API for the pinned runtime │
│ 4. sandbox, set limits, call the handler │
└─────────────────────────────────────────────────────────┘
Crates¶
| Crate | Responsibility |
|---|---|
integraal-loader |
ScriptStore trait, S3 implementation, in-memory cache with ETag revalidation. |
integraal-wrappers |
The versioned native API (v1): data, HTTP, XML, JSON, config. |
integraal-core |
The engine: limits, tenant config, VM setup, handler dispatch. |
integraal-lambda |
Lambda entrypoint (binary bootstrap). |
integraal-webhook |
Webhook ingress Lambda: verifies callback tokens and enqueues to SQS. |
integraal-ingress |
Intake Lambda: places each queue message in a worker size class and forwards it to that class's job queue. |
integraal-server |
Fargate entrypoint: HTTP server and SQS poller. |
Script bucket and buckets, different trust levels¶
Details in Buckets.
| Bucket | Contents | Who writes |
|---|---|---|
Script bucket (scripts.bucket) |
scripts and <tenant>/config.json |
operator / deployment pipeline |
Buckets (buckets.map, e.g. In, Out, Backup, Temp) |
tenant data under buckets.prefix<tenant>/ |
tenant scripts and third parties, as the tenant's buckets grants allow |
Scripts can reach only the buckets their config grants, and only their own prefix in each. Because policy lives in the script bucket, a tenant cannot widen its own HTTP allowlist or raise its own limits.
Script caching¶
Scripts are cached in memory per process:
latestis mutable. It is revalidated with a conditionalGET(ETag) at most every 30 s.- Any other version (
v3, a content hash, …) is immutable and never revalidated. config.jsonis treated likelatest.
Isolation model¶
- A fresh Luau state per invocation, then Luau's sandbox mode (read-only globals, no
os/io). - An instruction-count interrupt enforces the wall-clock timeout; a heap limit caps Luau memory.
- Native calls are tenant-scoped: wrappers receive the tenant's context, never a bucket handle.
- Tenant, script and version names are validated (
[A-Za-z0-9._-], no./..).