Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion demos/wasi.tape
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Enter
Sleep 500ms
Show

Type "wago add wago-org/wasi"
Type "wago add github.com/wago-org/wasi"
Sleep 240ms
Enter
Sleep 7s
Expand Down
5 changes: 4 additions & 1 deletion guides/embed/imports-and-artifacts.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,7 @@ if err := rt.Close(); err != nil {
}
```

`Close` is idempotent. Runtime close stops plugins and internal services, but direct instances remain caller-owned.
`Close` is idempotent. Closing explicitly keeps error ownership local. Runtime
close is also a final safety boundary: it closes and drains every still-live
runtime-created instance before stopping plugins. A retained instance handle is
closed afterward, and calling `Close` on it again is safe.
10 changes: 8 additions & 2 deletions guides/host-functions/authority-and-references.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,14 @@ Runtime `Policy` controls guest capabilities and coarse declared resource limits

`HostModule` represents one active synchronous call. Do not store it, send it to another goroutine, or use it as a long-lived instance handle.

Plugins with the required privileged capability can resolve the exact caller while the callback is active. Forged, expired, and cross-runtime values fail closed.
Plugins that separately receive `host.caller.identify` can resolve an opaque,
comparable instance identity while the callback is active. The identity grants
no invoke, close, memory, export, or management operation. Forged, expired, and
cross-runtime `HostModule` values fail closed.

## Reusable host APIs

Use `WithImports` for an application-specific bridge. Package a shared namespace as a plugin so imports, capabilities, configuration, ordering, and cleanup are registered once and reviewed through the manager.
Use `WithImports` for an application-specific bridge. Package a shared namespace
as a plugin so exact import-module scope, guest capabilities, configuration,
dependencies, ordering, and cleanup are registered once and reviewed through
the manager.
11 changes: 8 additions & 3 deletions guides/plugins.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
---
description: Add, review, update, lock, and publish Wago plugins without hiding their host authority.
description: Add, review, compose, update, lock, and publish Wago plugins without hiding their host authority.
---

# Use plugins

Plugins provide host imports, lifecycle hooks, managed instances, module transforms, and compiler extensions. They are Go code compiled into your runtime, so review them like any other native dependency.
Plugins provide host imports, lifecycle integrations, managed instances, module transforms, compiler extensions, and typed services for other plugins. They are Go code compiled into your runtime, so review them like any other native dependency.

Wago resolves explicit package dependencies and typed, major-versioned Contracts
as one graph. It reviews exact scoped Plugin Authorities before downloading or
building new code, then publishes the manifest, lock graph, and generated runtime
in one transaction.

## Pick a topic

Expand All @@ -13,7 +18,7 @@ Plugins provide host imports, lifecycle hooks, managed instances, module transfo
Add a plugin locally or globally and select it at run time.
</Card>
<Card title="Grants and lockfiles" href="/guides/plugins/grants-and-lockfiles" icon="fa-code">
Review privileged API access, guest capabilities, and reproducible state.
Review exact Authorities, dependency and Contract bindings, guest capabilities, and reproducible state.
</Card>
<Card title="Update and rebuild" href="/guides/plugins/update-and-rebuild" icon="fa-right-left">
Check for updates, review changes, and reproduce the locked runtime.
Expand Down
135 changes: 107 additions & 28 deletions guides/plugins/grants-and-lockfiles.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,140 @@
---
description: Review Wago plugin capabilities, guest authority, manifests, lockfiles, and resource budgets.
description: Review exact Wago Plugin Authorities, dependencies, typed Contracts, lockfiles, and resource limits.
---

# Review plugin grants and lockfiles
# Review Authorities, Contracts, and the lockfile

The manifest records what your project asks for. The lockfile records the exact plugin versions, capabilities, and runtime result you reviewed.
The manifest records direct project intent. The lockfile records the complete
resolution and every authority-bearing decision you reviewed.

## Manifest and lockfile
## Manifest and lock graph

`wago.json` records what the project wants:
`wago.json` contains canonical Plugin IDs and semantic-version ranges:

```json
{
"$schema": "https://wago.sh/v0/schema.json",
"$schema": "https://wago.sh/v1/schema.json",
"plugins": {
"wago-org/wasi": "^0.0.0"
"github.com/JairusSW/pool": "^0.1.0"
}
}
```

`wago-lock.json` records what Wago resolved and what you approved: exact versions, required and granted capabilities, budgets, and opaque plugin configuration.
Pool requires Workers. Wago resolves Workers once as a transitive plugin and
records the exact Pool-to-Workers Contract binding in `wago-lock.json`. The lock
also contains source versions and Go checksums, release and definition digests,
published Authority Requests, reviewed Authority Grants, configuration, and the
complete dependency graph.

Commit both files. Review lockfile changes like a native dependency update.

## Review grants
## Inspect before changing

```sh
wago plugin inspect wago-org/wasi
wago plugin grant wago-org/wasi
wago plugin tree
wago plugin list --json
wago plugin inspect github.com/JairusSW/pool
wago plugin inspect github.com/wago-org/workers
```

Automation should name the decision:
JSON listing and inspection are side-effect-free. They read immutable
definitions and selections; they do not call plugin factories, registration,
or lifecycle code.

## Review exact Authorities

An Authority is one exact privileged Wago integration. Its dots group related
names for display only—parents, wildcards, descendants, and future Authorities
are never implied.

| Authority | Authorizes |
|---|---|
| `host.import.define` | Define host functions in specifically granted import modules. |
| `host.caller.identify` | Resolve an opaque identity during a synchronous host call. |
| `host.arguments.read` | Read guest arguments owned by this Runtime. |
| `runtime.close.observe` | Observe logical runtime close. |
| `module.source.transform` | Replace source bytes before compilation. |
| `module.compile.observe` | Correlate source processing with compile success or failure through opaque identities. |
| `module.close.observe` | Observe logical close of a runtime-bound module. |
| `instance.instantiate.intercept` | Reject a request, or attach fallible identity-keyed state after initialization and before the start function. |
| `instance.instantiate.observe` | Observe successful or failed instantiation. |
| `instance.close.observe` | Observe exact-instance logical close. |
| `instance.invoke.intercept` | Inspect or reject a runtime-managed call. |
| `instance.invoke.observe` | Observe results and traps. |
| `instance.manage` | Create and own a bounded set of managed instances. |
| `core.module.compile` | Compile core modules for an execution-model plugin. |
| `core.instance.instantiate` | Instantiate and own core modules within reviewed limits. |
| `core.funcref.create` | Create typed host function references. |
| `compiler.type.define` | Define types in specifically granted namespaces. |
| `compiler.instruction.define` | Define instructions in specifically granted Wasm modules. |

Every request has a `required` or `optional` mode, a human explanation, and any
scope Wago can enforce. A required Authority must have a grant, but you can
still narrow its modules or limits. An optional Authority may be denied
entirely. A plugin that cannot operate under the reviewed scope fails before the
plan commits.

Interactive add and update show one consolidated review. For automation, name
each decision and scope explicitly rather than accepting a wildcard policy:

```sh
wago plugin add wago-org/wasi \
--allow host.imports \
wago add github.com/wago-org/workers \
--allow instance.manage \
--scopes '{"github.com/wago-org/workers":{"instance.manage":{"maxInstances":4,"maxMemoryBytes":268435456}}}' \
--accept-contracts \
--no-input
```

`--allow-all` and `--deny-all` are available, but an explicit capability list is easier to review.
`--scopes` is one strict JSON object keyed first by full Plugin ID and then by
exact Authority. Add and update may narrow direct or resolved transitive
plugins; `wago plugin grant <full-plugin-id>` may revise only that exact existing
selection. A scope override can never add a module, raise a requested limit, or
name an Authority the definition did not request. Instance-owning limits are
positive; zero does not mean unlimited. `maxMemoryBytes` bounds the aggregate
declared maximum across all live instances owned through that handle.

## Privileged plugin capabilities
## Typed cross-plugin Contracts

| Capability | Authorizes |
|---|---|
| `host.imports` | Host functions and active caller resolution |
| `host.environment` | Wago's narrow host environment |
| `module.compile` | Compile transforms and observations |
| `instance.lifecycle` | Instance creation and close hooks |
| `instance.invoke` | Runtime-managed call hooks |
| `runtime.lifecycle` | Runtime shutdown and cleanup |
| `instance.manage` | Restricted managed instances |
Plugins call each other through typed Contracts identified by a canonical ID
and positive incompatible major version. A consumer declares one of:

- `required`: exactly one provider;
- `optional`: zero or one provider; or
- `many`: every selected provider in the exact reviewed binding order.

The package requirement selects and links a provider package. The Contract
binds the interface among selected providers. Both edges participate in one
cycle-checked graph, and the exact binding is stored in the lockfile.

Some grants include budgets such as a live instance cap or per-instance declared memory limit.
Wago rejects missing required providers, incompatible majors, duplicate single
providers, altered locked bindings, and cycles before any factory runs.
Contract calls use callback leases rather than raw `Get` values. During close,
a consumer can still use its dependencies from its own `Stop`; before provider
teardown, Wago rejects new calls and waits for in-flight calls to finish.

Compile observers receive an opaque digest of the final source bytes after all
transformers. The precompiled `Runtime.Module` path reports a zero digest because
the source is unavailable. `Module.Close` ends only the runtime-bound wrapper,
emits one close event, and leaves ownership of the caller-visible compiled
artifact with its caller.

## Plugin authority and guest authority

Plugin grants control access to privileged Wago APIs. Guest capabilities such as `fs.read` and `net.outbound` describe what the module may use. Runtime `Policy` applies the guest layer.
Plugin Authorities control access to privileged Wago integration handles. Guest
capabilities such as `fs.read` and `net.outbound` describe what a Wasm module may
use, and Runtime `Policy` applies that guest layer.

Neither layer turns arbitrary plugin Go code into a sandbox. Plugins are native
open-source dependencies linked into the host and must still be audited as
such.

## Verify locked state in CI

```sh
wago plugin rebuild --locked
```

Neither layer turns arbitrary plugin Go code into a sandbox. Plugins remain native open-source dependencies.
Locked rebuilding verifies reachability, dependency ranges, checksums, release
fingerprints, provider catalogs, definition digests, grants, configuration,
Contract bindings, target compatibility, and the dry-run Plugin Plan before it
reproduces the artifact without changing project state.
24 changes: 17 additions & 7 deletions guides/plugins/install-and-scope.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,21 @@ Install plugins locally for one project or globally for your machine, then choos

```sh
wago init --run
wago add wago-org/wasi
wago add github.com/wago-org/wasi
```

`wago add` is the short form of `wago plugin add`. Wago resolves the package, asks you to review its capabilities, writes project state, and rebuilds the selected runtime.
`wago add` is the short form of `wago plugin add`. Wago resolves direct and
transitive packages, verifies typed Contract providers, and presents one review
of exact sources, scoped Authorities, and bindings. It stages the download,
provider catalog, generated runtime, and complete dry-run plan before atomically
replacing project state. A failure leaves the previous runtime usable.

## Local scope

Local plugins belong to the nearest `wago.json`:

```sh
wago plugin add --local wago-org/wasi
wago plugin add --local github.com/wago-org/wasi
```

Use local scope for applications and repositories. The dependency and authority travel with the project.
Expand All @@ -30,7 +34,7 @@ Use local scope for applications and repositories. The dependency and authority
Global plugins are shared across your user account:

```sh
wago plugin add --global wago-org/wasi
wago plugin add --global github.com/wago-org/wasi
```

This works well for personal tools used across unrelated directories.
Expand All @@ -46,14 +50,20 @@ wago run --bare --invoke fib fib.wasm 20
- `--local` uses the project plugin set.
- `--global` uses the shared user-wide set.
- `--bare` uses neither.
- `--plugin name,other` adds plugins for one command.

If a plugin becomes part of the application, add it to `wago.json` instead of leaving it in shell history.
Add plugins to `wago.json` before running so resolution, Authorities, and
Contract bindings remain reviewable and reproducible.

## Inspect the selection

```sh
wago status
wago plugin list
wago plugin inspect wago-org/wasi
wago plugin list --json
wago plugin tree
wago plugin inspect github.com/wago-org/wasi
```

`tree` shows why every transitive plugin was selected. JSON listing and
inspection report exact definitions, Authority Grants, Contract bindings, and
activation order without starting plugin code.
40 changes: 35 additions & 5 deletions guides/plugins/publish.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ description: Initialize, review, authenticate, and publish an open-source Wago p

# Publish a Wago plugin

Package a reusable Wago extension, preview exactly what will ship, then publish it to the public plugin registry.
Package a reusable Wago plugin, preview exactly what will ship, then publish it to the public plugin registry.

Publishing requires a public GitHub repository and a Wago registry account. The dry run works before login.

## Create the manifest
## Scaffold the plugin

```sh
wago init --plugin \
Expand All @@ -21,7 +21,16 @@ wago init --plugin \
--yes
```

A publishable manifest points to public source and includes an SPDX license. Wago plugins are deliberately open source.
The scaffold creates a v1 manifest, one-method plugin, immutable
`PluginDefinition`, explicit `/register` catalog, canonical
`wago.providers.json`, and drift tests. A publishable manifest points to public source, includes an SPDX
license and structured author, and keeps discovery metadata under `package`.
Wago plugins are deliberately open source.

Declare every privileged Wago integration as an exact Authority with a human
reason and enforceable scope. Declare package requirements separately from
typed, major-versioned Contracts. Provider catalogs return values from
`Providers()`; they never self-register from `init`.

## Authenticate

Expand All @@ -30,11 +39,32 @@ wago auth login
wago auth whoami
```

## Preview and publish
## Snapshot, tag, and publish

```sh
wago plugin catalog
wago plugin catalog --check
git add wago.json wago.providers.json register
git commit -m "Prepare plugin v0.1.0"
git tag v0.1.0
git push origin HEAD v0.1.0
wago plugin publish --dry-run --json
wago plugin publish
```

Publishing uses `wago.json` and Git `HEAD` by default. Flags can override the manifest, commit, release notes, category, and tags.
`wago plugin catalog` executes the current checkout's explicit catalog and
writes its canonical, digest-bearing snapshot. Commit that file before tagging;
`--check` is the CI-friendly drift gate. The provider artifact uses
`https://wago.sh/v1/providers.schema.json`.

The publish dry run only prints the planned mutation. Actual publishing first
checks the local catalog against the committed snapshot, then downloads the
exact tagged Go module. Its `wago.json` package metadata and
`wago.providers.json` must match the local release, and its `h1:` checksum is
sent with the request. Local code runs only for the local drift check; Wago does
not execute code from the downloaded tag.

The registry independently downloads that same exact module and checksum, reads
both artifacts without executing plugin code, and rejects any mismatch.
Consumers later review the stored immutable definitions before plugin code is
downloaded or built; linked definitions must match their reviewed digests.
Loading