progit-plugin-sdk 0.3.0

Plugin SDK for ProGit — sandboxed LuaJIT runtime with capability-based security. LSL-1.0 (file-level copyleft, proprietary plugins allowed via the commercial bridge).
Documentation
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]


## [0.2.1] - 2026-05-09

### Added — Experimental trait surfaces

- **`experimental_diff_renderer` module**`DiffRenderer` trait,
  `DiffRequest`, `DiffResponse`, `DiffLine`, `DiffLineKind`, `DiffView`.
  Runtime-agnostic contract for diff rendering; reuses
  `render::TokenSpan` for styled spans. Consumer:
  `progit-syntax-diff` plugin (in `progit-plugins`).
- **`experimental_fragments` module**`FragmentRenderer` trait,
  `FragmentContext`, `RenderFragment`, `FragmentAction`,
  `FRAGMENT_SLOT_REGISTRY` const. Mechanism for plugins to inject UI
  fragments into existing TUI widgets. Slot identifiers validated
  against the fixed allowlist; plugins cannot invent new slots.
  Consumer: `progit-pr-stacker` plugin.

Both modules ship behind the `experimental_*` namespace per the
"never stabilise an interface before a real consumer has used it
in production" rule. Promotion to `traits::DiffRenderer` /
`traits::FragmentRenderer` lands once the consumer plugins exercise
the API in a shipped release.

6 unit tests added covering serde round-trips and slot-registry
validation. `cargo check` clean; non-breaking, namespace-isolated.

### Added (carried forward — render-time plugin contract)

- **Render-time plugin contract**`progit_plugin_sdk::render` module
  exposes `TokenSpan`, `Rgb`, `HighlightRequest`, `HighlightResponse`.
  `Plugin::highlight()` is a new trait method (default `None`); plugins
  that want to be highlight providers override it.
- LuaPlugin implementation: detects `plugin.highlight = function(req) ... end`
  and round-trips the request/response through serde + mlua.
- Two new SDK harness tests covering `syntax-highlight` v1.0
  end-to-end: coloured-span content invariant + decline-unknown-language.

### Notes

- The render hook is intentionally synchronous and cache-friendly:
  the host caches by `blake3(language || '\0' || content)` so the Lua
  roundtrip happens once per unique line, not once per frame.

## [0.2.0] - 2026-05-06

### Added
- **Sandboxed LuaJIT runtime**`io`, `debug`, `dofile`, `loadfile` are
  removed entirely; `os.execute`, `os.exit`, `os.remove`, `os.rename`,
  `os.tmpname`, `os.setlocale`, `package.loadlib`, `package.searchpath`
  raise a clear error inside the VM (Doctrine 4 enforcement).
- **Memory + instruction caps** via `LuaPluginOptions::{memory_mb,
  max_instructions}`. Default 64 MB / 10 M instructions per hook.
- **Capability-checked HTTP**`http.{get,post,put,delete}` route through
  a single shared `reqwest::blocking::Client` per plugin, gated by the
  manifest's `capabilities.network` and `capabilities.network_allow`
  suffix-match list.
- **Injected `log` table** (`log.debug/info/warn/error`) routed to the
  Rust `log` crate. Back-compat globals `log_info`, `log_warn`, `log_error`
  also provided.
- **Injected `storage` table** (`storage.get/set/delete/keys/clear`)
  scoped to `<repo>/.progit/plugins/<plugin-name>/state.json`.
- **Typed `PluginManifest`** module with `Capabilities`, `SdkVersion`
  (no `semver` crate dependency), and `from_path` / `check_sdk_compat` /
  `check_hooks` helpers.
- **SDK API version** constant `SDK_API_VERSION = "0.2"` and
  manifest-driven compatibility check.
- **Per-plugin failure isolation** in `PluginManager`: 5 consecutive
  errors → automatic quarantine; expose `quarantined_plugins()` and
  `unquarantine(name)` for host-side recovery.

### Changed
- **License**: SDK source now declares LSL-1.0 in every SPDX header to
  match `Cargo.toml`. Earlier headers said Apache-2.0 by mistake.
- **HTTP default timeout**: 30 s → 5 s. Configurable per plugin via
  the manifest's `capabilities.http_timeout_secs`.
- **Single source of truth for events**: `PluginEvent` (and friends —
  `PipelineStatus`, `PipelineState`, `PipelineJob`) moved from the
  ProGit host crate into `progit_plugin_sdk::event`. The host now
  re-exports them. Earlier the two were independent definitions that
  drifted.
- **`http` client** is built once per plugin instead of once per request,
  cutting TLS handshake overhead.
- **Network capability** defaults to *off* in the legacy default
  capability block. v0.1 plugins that called `http.*` without declaring
  `capabilities.network` will now fail with a clear error pointing at
  the manifest.

### Removed
- Dead parallel `Plugin` / `PluginEngine` trait pair and
  `LuaPluginEngine` struct in `progit/src/plugins/{sdk,lua_engine}.rs`.
  These were never wired into the active manager. The SDK is now the
  single source of truth.

### Fixed
- `slack-notify` plugin (1.1.0): rewrote to use the real injected
  `http.post`, `json.encode`, and `log.*` instead of nonexistent
  `progit.http_post` / `log_info` symbols. Now functional end-to-end.

### Security
- Plugins without a `capabilities` block in their manifest get
  legacy-permissive defaults *with network off* and a deprecation
  warning at load time. Future major versions will default to deny.

## [0.1.0] - 2025-12-11

### Added
- Initial release
- Basic plugin infrastructure
- Lua plugin runtime with mlua
- WASM plugin runtime with wasmtime (opt-in)
- Plugin trait system (Plugin, IssuePlugin, SyncPlugin)
- Hook system for issue lifecycle events
- Example Lua plugins (hello-world, jira-sync)

[Unreleased]: https://git.sovereign-society.org/ProGit/progit-plugin-sdk/compare/v0.2.0...HEAD
[0.2.0]: https://git.sovereign-society.org/ProGit/progit-plugin-sdk/compare/v0.1.0...v0.2.0
[0.1.0]: https://git.sovereign-society.org/ProGit/progit-plugin-sdk/releases/tag/v0.1.0