The NetGoat developer catalog is a selection and trust layer around middleware that is already compiled into an agent binary. It is intentionally not a remote code-execution system: the agent does not download packages, shared objects, WASM modules, JavaScript source, URLs, or artifacts from the catalog.
This lets a publisher release metadata and configuration in the developer portal while keeping the request path portable and auditable. A publisher's verification status or credibility score may help operators decide whether to install a release, but neither changes what an agent is permitted to execute.
The control plane publishes a top-level restart-time snapshot section:
{
"plugins_configured": true,
"plugins": {
"installations": [
{
"plugin_id": "publisher-slug/plugin-slug",
"factory_id": "compiled.factory-id",
"version": "1.0.0",
"sha256": "lowercase-64-character-descriptor-fingerprint",
"api_version": "netgoat.dev/middleware/v1",
"granted_capabilities": ["request.read"],
"config": { "mode": "observe" }
}
]
}
}plugin_id is the canonical catalog package ID: ${publisher.slug}/${plugin.slug}.
The agent accepts an installation only when its package ID, factory ID, version,
sha256, API version, and complete capability set exactly match one descriptor
compiled into the running binary. Grant ordering is normalized, but duplicate,
unknown, missing, or extra grants are rejected.
sha256 is the immutable compiled descriptor fingerprint supplied by an
agent release (descriptor_sha256 in the developer catalog). It is not the
marketplace manifest/audit hash and not the digest of a downloaded file—there
is no downloaded file to verify. Keep a separate manifest hash for release
auditability if the portal records one.
The agent limits selections to 64 installations, each identity field to 128
bytes, factory configuration to a JSON object of at most 16 KiB, and all
configuration together to 256 KiB. config is passed only to the matched
compiled factory; the generic catalog runtime never interprets it as code.
Plugin selections are resolved during startup from local config.yml or the
last persisted control-plane snapshot. An arriving stream update is validated,
persisted, and logged as restart required. It never mutates an in-flight
registry or loads a new factory in a serving process.
Valid plugins run after NetGoat has resolved the trusted client IP and the
target route, so request.read and route.read get the intended metadata.
They run before traffic shaping and proxying. Login and verification endpoints
are deliberately outside this middleware extension point.
This build ships one harmless reference plugin to exercise the full catalog path. It does not inspect requests, has no capabilities, and always allows the request.
| Field | Value |
|---|---|
plugin_id |
netgoat/noop |
factory_id |
builtin.noop |
version |
1.0.0 |
sha256 / descriptor_sha256 |
22d6f9898bf456265c2549c38ef185c11de1da1eeee944bb8e97470ed438d2c0 |
api_version |
netgoat.dev/middleware/v1 |
granted_capabilities |
[] |
Local configuration can select it explicitly:
plugins:
installations:
- plugin_id: netgoat/noop
factory_id: builtin.noop
version: 1.0.0
sha256: 22d6f9898bf456265c2549c38ef185c11de1da1eeee944bb8e97470ed438d2c0
api_version: netgoat.dev/middleware/v1
granted_capabilities: []
config: {}Publishing a catalog release alone never makes code executable. To support a new runtime extension, the agent maintainer must:
- Implement and test the middleware in Go using the v1 SDK.
- Register its factory and immutable descriptor in agent source.
- Release an agent binary containing that descriptor.
- Publish the exact descriptor fingerprint to the catalog release.
- Let an operator select that release and restart the agent.
The middleware SDK's lifecycle, capability, and failure behavior is documented
in middleware-sdk.md. Use dynamic_rules for bounded
administrator-authored JavaScript/TypeScript request policy; do not treat a
developer catalog entry as a route for arbitrary code execution.