|
2 | 2 |
|
3 | 3 | All notable changes to this project are documented in this file. |
4 | 4 |
|
| 5 | +## v0.4.0 — Architecture Re-shape + Hardening |
| 6 | + |
| 7 | +### Architecture |
| 8 | +- **`@agentplugins/contract`** — new package: zod schema as single source of truth for the plugin manifest; TS types derived via `z.infer`; `manifest.schema.json` generated at build time via `zod-to-json-schema`. Eliminates the 4-copy drift class (previously: `spec/v1/manifest.schema.json`, `packages/schema/src/types.ts`, `packages/core/src/types.ts`, and inline zod). |
| 9 | +- **`@agentplugins/compile`** — new shared codegen kernel with secure emit primitives (`emitCommandHandler`, `emitInlineHandler`, `sanitizeName`, `sanitizeJoin`, `mapHook`). All adapters route through this kernel — a capability now ships by editing one schema field + one kernel path, not 8 files. |
| 10 | +- **`core` facade** — `@agentplugins/core/src/index.ts` re-exports from `contract`/`compile`; public API unchanged; sibling repos (`agentplugins-{goal,btw,flow,caveman,ponytail}`) unaffected. (Store isolation into its own `@agentplugins/store` package is planned for v0.5.0.) |
| 11 | +- `ARCHITECTURE.md` at repo root documents the ports-&-adapters hexagonal compiler pipeline with mermaid diagrams: package dependency graph, compile pipeline (manifest→validate→IR→emit→files), distribute pipeline (source→fetch→install→link), and the adapter port contract. |
| 12 | + |
| 13 | +### Authoring primitives |
| 14 | + |
| 15 | +- **`continueWith`** — chained prompt injection via the `stop` hook. OpenCode adapter uses `ctx.session.sendMessage`; PiMono adapter uses `pi.sendUserMessage`. Per-session iteration capped at 20 by default; lint rule (`continueWithSafetyRule`) inspects inline handler source at build time. |
| 16 | +- **`nativeEntry` / `nativeCopies`** — native artifact passthrough for non-JS plugin artifacts. Build command resolves and writes `nativeCopies` entries; adapters expose them in their output. |
| 17 | +- **`adapterOverrides`** — runtime adapter override via `manifest.adapterOverrides.opencode` / `manifest.adapterOverrides.pimono`. Paths are sanitized against the plugin root at compile time; a runtime trust warning is emitted. |
| 18 | +- **`capabilities: ['subprocess']`** — gates the child-process lint block. The `handlerSafetyRule` lint rule scans `command` handler strings for subprocess patterns; the gate only fires when the capability is absent. |
| 19 | +- Inline handlers auto-wrapped as command scripts for Codex and Kimi adapters. |
| 20 | + |
| 21 | +### Multi-artifact linking |
| 22 | +- Multi-artifact `dist` linking for OpenCode: multiple compiled artifacts per plugin. |
| 23 | +- Per-skill flat linking for Pi / Skills.sh compatibility. |
| 24 | + |
| 25 | +### Security hardening |
| 26 | + |
| 27 | +| Class | Fix | |
| 28 | +|---|---| |
| 29 | +| **RCE (template-literal injection)** | `emitCommandHandler` uses plain string + arg-array `execSync`; no shell template literals, no `shell:true`. Structurally eliminated — not patched per adapter. | |
| 30 | +| **Path traversal — plugin name** | `sanitizeName()` rejects `..`/absolute/non-kebab at `addPluginFromSource` install time. | |
| 31 | +| **Path traversal — `nativeCopies` from/to** | `sanitizeJoin()` validates both src and dst paths resolve inside the plugin root in `build` command. | |
| 32 | +| **Path traversal — SKILL.md frontmatter** | `sanitizeName()` applied to `name:` field from `SKILL.md` frontmatter before any symlink/write. | |
| 33 | +| **Path traversal — `adapterOverrides` / handler `source`** | `sanitizeJoin(pluginRoot, path)` applied at compile time; runtime trust warning emitted. | |
| 34 | +| **SSRF bypass** | `safe-fetch` re-validates every redirect hop against allow-list + private-IP check. | |
| 35 | +| **Arbitrary script execution at install** | `evaluateScriptPolicy()` runs on `add` / `import --write`; denylisted lifecycle scripts block the install. | |
| 36 | +| **Integrity never verified** | `verifyIntegrity()` called on install when `manifest.integrity` is declared. | |
| 37 | +| **Git clone URL injection** | `cloneRepo` validates `https://github.com/...` before URL interpolation. | |
| 38 | +| **Symlink clobber** | `unlinkSync` only; `rmSync` never on user dirs; `lstatSync` guard. | |
| 39 | +| **Install idempotency** | `unlinkAll()` factors pre-delete for compiled + skills + native + symlink artifacts; stale links never left behind. | |
| 40 | +| **Silent partial installs** | Symlink failures collected, warned at summary, `process.exitCode=1`. | |
| 41 | + |
| 42 | +### Bug fixes |
| 43 | + |
| 44 | +- `subagentStop` collision fixed; dead `agentCommand`/`agentCwd` passthrough removed. |
| 45 | +- `sidecar` marked experimental (`x-experimental`) in schema and docs. |
| 46 | +- `recompile-installed` dogfood script moved from `cli/src/commands/` → `scripts/`. |
| 47 | +- Two OpenCode test failures (stale `Bun.$` assertions) corrected to `execSync (curl)`. |
| 48 | +- Example logger `package.json` no longer carries a version field in its internal manifest. |
| 49 | +- CLI version read from `package.json` instead of hardcoded string. |
| 50 | + |
| 51 | +### Breaking changes |
| 52 | + |
| 53 | +- **`spawnChild`** removed from `@agentplugins/compile` and `@agentplugins/core`. It had zero callers; no adapter used it. Any external consumer importing it directly will break — the replacement is to use `node:child_process.spawn` directly with sandboxing. |
| 54 | +- **`@agentplugins/contract`** is a new published package. Its API (`PluginManifest` zod schema, derived types, `manifest.schema.json`) is stable from this release. `core` re-exports remain the preferred consumer entry. |
| 55 | + |
5 | 56 | ## v0.3.0 — Tier-1 Parity Wins + Compat Ingestor + Security |
6 | 57 |
|
7 | 58 | ### Tier-1 parity wins (3.1–3.6) |
|
0 commit comments