Official Plugins
Official plugins are public WebAssembly Component Model packages published by
the Sigil project under the
sigil-plugins GitHub organization. Their
immutable releases carry keyless provenance that Sigil verifies before
installation and pins in the project lock.
Run this command for the live inventory:
sigil plugin list-remotesigil plugin add is the normal way to adopt one. Run it in the project that
contains .sigil/sigil.toml; it downloads the package when necessary, declares
the exact project dependency, writes the reproducibility lock, and generates
the matching LuaLS stub.
| Plugin | Release | What it does | Requested host capabilities |
|---|---|---|---|
codec | 1.1.2 | Reference plugin that echoes a u32 | None |
mysql | 0.1.2 | Bounded MySQL 8.4 text-protocol driver | Network and named secrets |
s3 | 0.1.0 | Bounded, read-only S3-compatible object fetch | Network |
parquet | 0.1.0 | Parquet metadata inspection and typed scalar reads | None |
Codec 1.1.2
Section titled “Codec 1.1.2”Codec is the small, capability-free reference plugin. It is useful for checking
that plugin installation, locking, LuaLS generation, and the Component Model
runtime work end to end. It is not a general-purpose codec library: its current
interface exports one echo-u32 function.
return { title = "Codec plugin is available", priority = "P1", policy = { capabilities = { "wasm.codec" } },
run = function() local codec = require("wasm.codec") expect(codec["echo-u32"](42) == 42) end,}View the immutable Codec 1.1.2 release.
MySQL 0.1.2
Section titled “MySQL 0.1.2”MySQL is a bounded MySQL 8.4 Classic Protocol driver. Sigil owns endpoint resolution, TCP, TLS verification, timeouts, byte quotas, secret grants, cancellation, and teardown; the component sees only a logical endpoint and the names of specifically granted secrets.
Expose the credential names to scenarios, grant those names to this plugin,
and map its logical database endpoint to the lane-local service:
[scenario.env]MYSQL_USER = { from = "MYSQL_USER" }MYSQL_PASSWORD = { from = "MYSQL_PASSWORD" }
[plugins.grants.mysql]secrets = ["MYSQL_USER", "MYSQL_PASSWORD"]
[plugins.grants.mysql.network.database]target = "mysql:3306"tls = "upgrade"tls_server_name = "mysql"tls_ca_file = ".sigil/certs/mysql-ca.pem"connect_timeout = "5s"io_timeout = "10s"max_connections = 2max_bytes = "16MiB"Then connect and issue a text query:
return { title = "MySQL responds to a query", priority = "P1", policy = { capabilities = { "wasm.mysql" } },
run = function() local mysql = require("wasm.mysql") local connection, connect_error = mysql.connect({ endpoint = "database", ["username-secret"] = "MYSQL_USER", ["password-secret"] = "MYSQL_PASSWORD", database = "app", }) expect(connect_error == nil, connect_error and connect_error.message)
local result, query_error = connection:query("SELECT 'ready' AS marker") expect(query_error == nil, query_error and query_error.message) expect(result.tag == "rows")
connection:close() end,}The experimental sigil:sql/[email protected] interface supports TLS upgrade,
caching_sha2_password, text queries, and one result. It does not support
prepared statements, the binary protocol, multi-statements or multi-results,
retry, reconnect, or LOCAL INFILE.
View the immutable MySQL 0.1.2 release.
S3 0.1.0
Section titled “S3 0.1.0”S3 performs one bounded, path-style HTTP GET from an S3-compatible object
store such as MinIO. It is read-only and accepts anonymous access or a
caller-supplied presigned query. It does not accept access keys, sign requests,
follow redirects, list buckets, issue ranges, or write objects.
Map the guest-visible object-store endpoint to MinIO. The host byte quota
includes request and response framing, so this example budgets 4 MiB for the
object plus bounded wire overhead:
[plugins.grants.s3.network.object-store]target = "minio:9000"tls = "disabled"connect_timeout = "5s"io_timeout = "10s"max_connections = 1max_bytes = "4172KiB"return { title = "Read an object from MinIO", priority = "P1", policy = { capabilities = { "wasm.s3" } },
run = function() local s3 = require("wasm.s3") local bytes, download_error = s3["get-object"]({ endpoint = "object-store", bucket = "results", key = "run/output.parquet", ["max-bytes"] = 4 * 1024 * 1024, })
expect(download_error == nil, download_error and download_error.message) expect(bytes ~= nil) end,}The Lua max-bytes argument limits the decoded object body; the network
grant’s max_bytes limits aggregate request and response bytes on the wire.
Before I/O, S3 asks the host to reserve the body ceiling plus exactly 64 KiB of
possible response framing. The grant must therefore exceed the Lua ceiling by
at least 65,536 bytes—65,535 bytes is refused—and request bytes need separate
headroom. The example uses another 12 KiB for an 8 KiB presigned query, a
percent-expanded key, endpoint, and HTTP framing: 4 MiB + 64 KiB + 12 KiB =
4,172 KiB.
A reservation that does not fit is an uncatchable
PLUGIN_RESOURCE_LIMIT/plugin_infrastructure failure. A response body that
exceeds the plugin’s Lua ceiling instead returns nil, {class = "limit", ...}
with no partial bytes. That typed result is catchable by design, so scenarios
must assert the error return as the sample does rather than relying on
pcall. The maximum object body is 16 MiB. The logical endpoint is also the
HTTP Host, so a presigned query must target that in-environment name.
View the immutable S3 0.1.0 release.
Parquet 0.1.0
Section titled “Parquet 0.1.0”Parquet accepts a complete file as a binary Lua string, reports flat leaf metadata, and reads one typed scalar cell by column path and zero-based row index. It has no filesystem or network capability. The intended object-store flow composes it with S3 in the scenario, without making either plugin depend on the other:
Use the S3 endpoint grant from the preceding section, then pass the downloaded bytes directly to Parquet:
return { title = "Read one value from a Parquet object", priority = "P1", policy = { capabilities = { "wasm.s3", "wasm.parquet" } },
run = function() local s3 = require("wasm.s3") local parquet = require("wasm.parquet")
local bytes, download_error = s3["get-object"]({ endpoint = "object-store", bucket = "results", key = "run/output.parquet", ["max-bytes"] = 4 * 1024 * 1024, }) expect(download_error == nil, download_error and download_error.message)
local cell, read_error = parquet["read-cell"](bytes, { column = "total", row = 1, }) expect(read_error == nil, read_error and read_error.message) expect(cell.tag == "floating") expect(cell.value == 27.75) end,}Version 0.1 supports required or optional non-repeated scalar columns, plain or dictionary encoding, and uncompressed or Snappy pages. Nested or repeated columns, INT96, nanosecond temporal values, external column chunks, and other compression codecs fail explicitly. Input is capped at 16 MiB.
View the immutable Parquet 0.1.0 release.
Commit the dependency generation
Section titled “Commit the dependency generation”After adding plugins, commit the complete reproducibility generation and lint the scenarios:
git add .sigil/sigil.toml .sigil/sigil.plugins.lock .sigil/types/wasmsigil scenario lintSee Using Plugins for locking, syncing, updates, removal, third-party sources, and CI behavior.