Skip to content

Commit 9135644

Browse files
SpecBridge v0.7.1: extension SDK, registry, and community ecosystem (#9)
* feat(extension-sdk): add extension manifest, protocol, and stdio server SDK * feat(extensions): add extension host with checksums, install, grants, and process isolation * feat(extensions): add conformance framework and analyzer CLI integration * feat(extensions): integrate verifier, exporter, runner proxy, and template providers * feat(extensions): add scaffold, deterministic packaging, extension and registry CLI * feat(registry): add reference extensions, repository registry index, and gallery * feat(mcp): add read-only extension and registry tools plus the extensions plugin skill * docs: add v0.7.1 ecosystem section, changelog, and extension smoke coverage * test: update assertions for implemented spec export and SBV026 * fix(examples): commit reference extension entrypoints excluded by the dist ignore rule
1 parent 08577c5 commit 9135644

189 files changed

Lines changed: 29376 additions & 2718 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude-plugin/marketplace.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"name": "specbridge",
1010
"source": "./integrations/claude-code-plugin/specbridge",
1111
"description": "Kiro-compatible spec workflows, verified interactive task execution, and deterministic drift checks.",
12-
"version": "0.7.0",
12+
"version": "0.7.1",
1313
"license": "MIT",
1414
"keywords": [
1515
"spec-driven-development",

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ dist/
1111
# The Claude Code plugin ships its reproducible bundle in-repo too, so
1212
# installing the plugin straight from the GitHub marketplace source works.
1313
!integrations/claude-code-plugin/specbridge/dist/
14+
# Reference extensions ship their committed self-contained entrypoints;
15+
# locally built archives stay ignored.
16+
!examples/extensions/*/dist/
17+
examples/extensions/*/dist/*.zip
1418

1519
# Test output
1620
coverage/

CHANGELOG.md

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,111 @@
11
# Changelog
22

3+
## 0.7.1
4+
5+
Added:
6+
7+
- Versioned extension manifest (`specbridge-extension.json`, schema 1.0.0)
8+
covering five stable extension kinds: template-provider, analyzer,
9+
verifier, exporter, and runner.
10+
- Publishable extension SDK (`@specbridge/extension-sdk`): manifest,
11+
protocol, permission, and diagnostic schemas; a stdio extension server
12+
with input/output validation, cancellation, and clean shutdown; typed
13+
helpers per kind; in-process testing utilities.
14+
- Out-of-process extension protocol (JSON-RPC 2.0 over JSON Lines, protocol
15+
1.0.0): initialize handshake with identity and capability validation,
16+
invocation, cancellation, shutdown, structured errors, bounded messages.
17+
- Explicit extension permission model (specRead, repositoryRead,
18+
repositoryWrite, network, childProcess, explicit environment-variable
19+
names) with permission-aware input boundaries per kind.
20+
- Permission-hash acceptance: enabling requires
21+
`--accept-permissions <hash>`, deterministically bound to the extension
22+
ID, version, manifest hash, and normalized permissions; any manifest
23+
change invalidates prior grants (SBE018).
24+
- Analyzer extensions (`spec analyze --extension <id>`, repeatable) with
25+
namespaced rule IDs (`<extension-id>/<RULE>`) that never overwrite
26+
built-in diagnostics.
27+
- Verifier extensions via explicit per-spec policy (`extensionVerifiers`);
28+
results land in the verification report and reach the gate only through
29+
the new built-in rollup rule SBV026 (required failure fails, optional
30+
warns).
31+
- Exporter extensions (`spec export --extension <id> --output <dir>`):
32+
candidate files only, previewed by default, written atomically after
33+
explicit `--yes`, never overwriting, recorded append-only.
34+
- Runner extensions behind an extension-runner proxy implementing the
35+
frozen v0.6.0 `AgentRunner` contract, wired through a new
36+
backward-compatible `"runner": "extension"` profile variant (disabled by
37+
default, preview support level, never auto-selected).
38+
- Template-provider extensions: data-only v0.7.0-format template packs
39+
contributed to the catalog as `extension:<extension-id>/<template-id>`,
40+
with ambiguity errors instead of shadowing.
41+
- Local extension installation from directories and archives (atomic,
42+
versioned side-by-side, disabled after install, zero code execution),
43+
plus explicit enablement/disablement and recoverable uninstall.
44+
- Extension conformance framework (`extension conformance --yes`) with
45+
common protocol checks and kind-specific checks, recorded per install.
46+
- Deterministic extension packaging
47+
(`<id>-<version>.specbridge-extension.zip`, store-method, fixed
48+
timestamps, sorted entries, regenerated checksums, printed SHA-256).
49+
- Local (built-in + `--file`) and HTTPS registry indexes with a validated
50+
atomic cache under `.specbridge/registry-cache/` and explicit
51+
`registry update <name> --network`.
52+
- Extension and registry CLI command groups (`specbridge extension …`,
53+
`specbridge registry …`) including scaffold for every kind.
54+
- Seven read-only MCP discovery tools: extension_list, extension_search,
55+
extension_show, extension_doctor, registry_list, registry_search,
56+
registry_show (37 MCP tools total).
57+
- Claude Code `/specbridge:extensions` Skill (discovery only).
58+
- Generated extension gallery (`docs/extensions.md`) with CI drift check,
59+
repository registry index (`registry/`), and five maintained reference
60+
extensions under `examples/extensions/`.
61+
- Stable error code registries: SBE001–SBE030 (extensions) and
62+
SBR001–SBR015 (registry), every error with remediation.
63+
64+
Security:
65+
66+
- No in-process third-party code execution: no dynamic import of installed
67+
extensions, no `eval`, no `Function`; the only executable surface is the
68+
declared entrypoint launched as `node <entrypoint>` (argv array, no
69+
shell) in a child process.
70+
- No package-manager lifecycle scripts: install/postinstall/prepare
71+
declarations in a bundled package.json are validation errors and are
72+
never executed.
73+
- No automatic enablement, no automatic updates, no automatic registry
74+
network access; remote installs and updates require an explicit
75+
`--network`.
76+
- Manifest-bound permission grants with stale-grant detection.
77+
- SHA-256 archive and per-file integrity checks; installed files are
78+
revalidated after extraction.
79+
- Symlink and path-traversal rejection everywhere packages are read,
80+
extracted, installed, or exported.
81+
- Bounded archive extraction (50 MB archive, 100 MB extracted, 1,000
82+
files) with CRC verification and declared-size enforcement.
83+
- Protocol stdout isolation: stdout is protocol-only, logs go to stderr,
84+
corruption terminates the process without crashing SpecBridge.
85+
- Startup (10 s) and operation (default 5 min) timeouts, cooperative
86+
cancellation, SIGTERM→SIGKILL cleanup, bounded stdout/stderr capture.
87+
- Sanitized child environment with an explicit variable allowlist; granted
88+
secret values are redacted from retained logs.
89+
- Extensions cannot approve stages, complete tasks, change evidence, or
90+
disable built-in protected-path rules.
91+
92+
Limitations:
93+
94+
- Process isolation and permission declarations are safety boundaries and
95+
audit mechanisms, not an OS sandbox; enabled executable extensions run
96+
as local code with the user's operating-system permissions.
97+
- Checksums prove integrity, not publisher identity.
98+
- Registry listing is not endorsement.
99+
- Registry archive URLs in the repository index use a documented
100+
placeholder host until a real hosted registry exists.
101+
102+
Deferred to v1.0:
103+
104+
- Stable publishing workflow and release automation.
105+
- Cross-platform installation verification.
106+
- Final security audit and performance hardening.
107+
- Schema migration guarantees and public launch assets.
108+
3109
## 0.7.0
4110

5111
Added:

README.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,34 @@ stay readable, migration is explicit — see
565565
[docs/runners.md](docs/runners.md)). Never commit API keys; SpecBridge
566566
stores no credentials of any kind.
567567

568+
## Extension ecosystem (v0.7.1)
569+
570+
Extend SpecBridge without modifying the core. Five stable extension kinds —
571+
template-provider, analyzer, verifier, exporter, and runner — run out of
572+
process behind a versioned stdio protocol, install disabled, and run only
573+
after you accept their declared permissions (bound to the manifest hash):
574+
575+
```bash
576+
specbridge extension scaffold security-analyzer \
577+
--kind analyzer \
578+
--output ./security-analyzer
579+
580+
specbridge extension conformance ./security-analyzer --yes
581+
582+
specbridge extension package ./security-analyzer
583+
```
584+
585+
Discover cached registry extensions (offline; updates are explicit):
586+
587+
```bash
588+
specbridge registry search security
589+
```
590+
591+
Extensions can never approve stages, mark tasks complete, alter evidence, or
592+
disable protected-path rules; process isolation is a safety boundary, not an
593+
OS sandbox, and checksums prove integrity, not publisher identity. See
594+
[docs/extensions.md](docs/extensions.md).
595+
568596
## Security and privacy
569597

570598
- Default commands are read-only and fully offline; no telemetry, no network.
@@ -579,7 +607,7 @@ stores no credentials of any kind.
579607
secrets or environment variables.
580608
- Full model: [docs/security.md](docs/security.md).
581609

582-
## Limitations (v0.7.0)
610+
## Limitations (v0.7.1)
583611

584612
- The MCP server is stdio-only and local-only: no HTTP/SSE/WebSocket
585613
transport, no OAuth, no cloud hosting. One server process serves one

docs/extensions.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# SpecBridge extensions
2+
3+
SpecBridge v0.7.1 adds a secure extension ecosystem: third parties extend
4+
SpecBridge **without modifying the core**. Executable extensions always run
5+
out of process behind a versioned stdio protocol, install disabled, and can
6+
run only after the user explicitly accepts their declared permissions.
7+
8+
Five stable extension kinds exist:
9+
10+
| Kind | What it does | Executable |
11+
| --- | --- | --- |
12+
| `template-provider` | Contributes v0.7.0-format spec template packs | No — data-only |
13+
| `analyzer` | Returns diagnostics for bounded spec content | Yes |
14+
| `verifier` | Returns diagnostics for a bounded verification context | Yes |
15+
| `exporter` | Returns candidate output files; SpecBridge writes them | Yes |
16+
| `runner` | An out-of-process adapter behind the frozen v0.6.0 runner contract | Yes |
17+
18+
Extensions can never approve stages, mark tasks complete, change evidence, or
19+
disable built-in protected-path rules. Their output is never task-completion
20+
evidence. See [extensions/overview.md](extensions/overview.md) for the
21+
architecture and [extensions/security.md](extensions/security.md) for the
22+
threat model and the honest limitations: **process isolation and permission
23+
declarations are safety boundaries and audit mechanisms, not an OS sandbox**,
24+
and **checksums prove integrity, not publisher identity**.
25+
26+
## Gallery
27+
28+
<!-- BEGIN GENERATED EXTENSION GALLERY (pnpm generate:extension-gallery) -->
29+
30+
Registry: **specbridge-examples** (5 extensions). Listing is not endorsement; review permissions before enabling.
31+
32+
| Extension | Kind | Version | Description | Permissions | SpecBridge | Source |
33+
| --- | --- | --- | --- | --- | --- | --- |
34+
| `example-analyzer` | analyzer | 1.0.0 | Deterministic spec diagnostics contributed by the example-analyzer analyzer extension. | specRead | `>=0.7.1 <1.0.0` | [source](https://github.com/HelloThisWorld/specbridge) |
35+
| `example-exporter` | exporter | 1.0.0 | Candidate export files produced by the example-exporter exporter extension. | specRead | `>=0.7.1 <1.0.0` | [source](https://github.com/HelloThisWorld/specbridge) |
36+
| `example-runner` | runner | 1.0.0 | An out-of-process runner adapter provided by the example-runner extension. | specRead, repositoryRead, repositoryWrite | `>=0.7.1 <1.0.0` | [source](https://github.com/HelloThisWorld/specbridge) |
37+
| `example-template-provider` | template-provider | 1.0.0 | Spec template packs contributed by the example-template-provider template-provider extension. | none | `>=0.7.1 <1.0.0` | [source](https://github.com/HelloThisWorld/specbridge) |
38+
| `example-verifier` | verifier | 1.0.0 | Verification diagnostics contributed by the example-verifier verifier extension. | specRead | `>=0.7.1 <1.0.0` | [source](https://github.com/HelloThisWorld/specbridge) |
39+
40+
<!-- END GENERATED EXTENSION GALLERY -->
41+
42+
The reference extensions above live in [`examples/extensions/`](../examples/extensions)
43+
and are maintained with SpecBridge itself — reference implementations, not
44+
production recommendations.
45+
46+
## Try it
47+
48+
```bash
49+
# Discover (offline; searches the built-in and cached registry indexes)
50+
specbridge registry search analyzer
51+
52+
# Install from a local archive or directory — installs disabled, runs no code
53+
specbridge extension install ./example-analyzer-1.0.0.specbridge-extension.zip
54+
specbridge extension show example-analyzer
55+
56+
# Enable by accepting the exact permission hash shown by `show`
57+
specbridge extension enable example-analyzer --accept-permissions <hash>
58+
59+
# Use it
60+
specbridge spec analyze my-spec --extension example-analyzer
61+
```
62+
63+
## Build your own
64+
65+
```bash
66+
specbridge extension scaffold my-analyzer --kind analyzer --output ./my-analyzer
67+
specbridge extension validate ./my-analyzer
68+
specbridge extension conformance ./my-analyzer --yes
69+
specbridge extension package ./my-analyzer
70+
```
71+
72+
Guides: [creating analyzers](extensions/creating-analyzers.md) ·
73+
[verifiers](extensions/creating-verifiers.md) ·
74+
[exporters](extensions/creating-exporters.md) ·
75+
[runners](extensions/creating-runners.md) ·
76+
[template providers](extensions/creating-template-providers.md) ·
77+
[packaging](extensions/packaging.md) ·
78+
[publishing](extensions/publishing.md) ·
79+
[registry contribution](extensions/registry-contribution.md)
80+
81+
Contributions enter the community index via
82+
[`registry/CONTRIBUTING.md`](../registry/CONTRIBUTING.md).

docs/extensions/manifest.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Extension manifest reference
2+
3+
Every extension package carries a `specbridge-extension.json` at its root.
4+
The manifest is parsed with a strict schema — unknown fields are rejected,
5+
every string is length-bounded, and documents above **256 KB** fail before
6+
parsing (`SBE008`). Validation never executes anything; all findings are
7+
reported at once as `SBE` issues.
8+
9+
## Full example
10+
11+
The maintained reference analyzer
12+
(`examples/extensions/example-analyzer/specbridge-extension.json`):
13+
14+
```json
15+
{
16+
"schemaVersion": "1.0.0",
17+
"protocolVersion": "1.0.0",
18+
"id": "example-analyzer",
19+
"version": "1.0.0",
20+
"displayName": "example-analyzer",
21+
"description": "Deterministic spec diagnostics contributed by the example-analyzer analyzer extension.",
22+
"kind": "analyzer",
23+
"entrypoint": "dist/extension.cjs",
24+
"compatibility": {
25+
"specbridge": ">=0.7.1 <1.0.0",
26+
"extensionSdk": ">=0.7.1 <1.0.0"
27+
},
28+
"capabilities": {
29+
"operations": ["analyzer.analyze"]
30+
},
31+
"permissions": {
32+
"specRead": true,
33+
"repositoryRead": false,
34+
"repositoryWrite": false,
35+
"network": false,
36+
"childProcess": false,
37+
"environmentVariables": []
38+
},
39+
"license": "MIT",
40+
"keywords": ["analyzer", "specbridge-extension"]
41+
}
42+
```
43+
44+
## Required fields
45+
46+
| Field | Rules |
47+
| --- | --- |
48+
| `schemaVersion` | Strict `X.Y.Z`; supported major is `1` (`SBE005` otherwise) |
49+
| `protocolVersion` | Strict `X.Y.Z`; major must match the supported protocol `1.0.0` (`SBE007`) |
50+
| `id` | Extension ID grammar below; max 64 characters (`SBE003`) |
51+
| `version` | Strict `X.Y.Z` — no ranges, no prerelease tags |
52+
| `displayName` | 1–100 characters |
53+
| `description` | 1–500 characters |
54+
| `kind` | One of `template-provider`, `analyzer`, `verifier`, `exporter`, `runner` |
55+
| `compatibility.specbridge` | A validated semver range the running SpecBridge must satisfy (`SBE006` at load time) |
56+
| `capabilities.operations` | Operations declared for this kind (table below); max 16, no duplicates |
57+
| `permissions` | All six permission fields, explicitly (see [permissions.md](permissions.md)) |
58+
| `license` | 1–100 characters (SPDX identifier recommended) |
59+
60+
## Optional fields
61+
62+
`entrypoint` (rules below), `compatibility.extensionSdk` (semver range),
63+
`author` (`{name, email?, url?}`), `homepage` and `repository` (must be
64+
`https://` URLs), `keywords` (max 12, each max 30 characters), `deprecated`
65+
(boolean), `replacement` (a valid extension ID; warns unless `deprecated` is
66+
true), `examples` (max 5), `configurationSchema` (a JSON object describing
67+
the extension's `configuration` input), and `minimumNodeVersion` (`X.Y.Z`).
68+
69+
## Entrypoint rules
70+
71+
- **Required** for executable kinds (`analyzer`, `verifier`, `exporter`,
72+
`runner`) — missing is `SBE012`.
73+
- **Forbidden** for `template-provider` — data-only packages must not declare
74+
one (`SBE004`).
75+
- Must be a relative, forward-slash path to a `.cjs`, `.mjs`, or `.js` file
76+
inside the package: no `..`, no leading `/`, no drive letters, no
77+
backslashes, no null bytes. The declared file must exist in the package,
78+
and symlinks anywhere on the entrypoint path are rejected at run time
79+
(`SBE011`).
80+
81+
The host always runs the entrypoint as `node <entrypoint>` in a fresh child
82+
process — an entrypoint is never imported into the SpecBridge process.
83+
84+
## Extension ID grammar
85+
86+
`^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$`, at most 64 characters: lowercase letters
87+
and digits in hyphen-separated segments, starting with a letter. IDs double
88+
as store directory names, registry keys, and the namespace prefix for
89+
diagnostic rule IDs, so the grammar is deliberately restrictive.
90+
91+
| Example | Verdict |
92+
| --- | --- |
93+
| `security-analyzer`, `jira-exporter`, `runner2` | Valid |
94+
| `Security-Analyzer` | Invalid — uppercase |
95+
| `security_analyzer` | Invalid — underscore |
96+
| `-analyzer`, `analyzer-` | Invalid — leading/trailing hyphen |
97+
| `security--analyzer` | Invalid — consecutive hyphens |
98+
| `2fast` | Invalid — starts with a digit |
99+
| `sec/analyzer` | Invalid — path separator |
100+
101+
## Operations per kind
102+
103+
| Kind | Required | Optional |
104+
| --- | --- | --- |
105+
| `template-provider` | none — must declare **no** operations | none |
106+
| `analyzer` | `analyzer.analyze` ||
107+
| `verifier` | `verifier.verify` ||
108+
| `exporter` | `exporter.export` ||
109+
| `runner` | `runner.detect` | `runner.generateStage`, `runner.refineStage`, `runner.executeTask`, `runner.resumeTask`, `runner.listModels` |
110+
111+
Declaring an operation outside the kind's list is `SBE021`. Declared
112+
operations are a ceiling, not a suggestion: the host only ever invokes
113+
declared operations, and an extension reporting undeclared operations at
114+
runtime fails the handshake.
115+
116+
`template-provider` manifests are additionally rejected when they request
117+
`repositoryRead`, `repositoryWrite`, `network`, `childProcess`, or any
118+
environment variable — data-only packages get no permissions.

0 commit comments

Comments
 (0)