# Mission Core Plugin SDK

This directory owns the versioned host/plugin contract. It is an independently
installable in-tree package; it is not yet published to a package registry.

`missioncore_plugin_sdk.v0alpha2` is the first executable backend-neutral
contract layer. It uses closed, deeply immutable Pydantic models and exports
JSON Schema for TypeScript, Rust, or other consumers. Nested mappings and
collections are frozen after validation, and `model_copy(update=...)` is
revalidated before a new contract is returned. Import the explicit version:

```python
from missioncore_plugin_sdk import v0alpha2 as sdk

request = sdk.OperationRequest.model_validate(document)
schemas = sdk.contract_json_schemas()
```

For an isolated editable install:

```bash
uv pip install -e packages/plugin-sdk
python -m missioncore_plugin_sdk.v0alpha2 > plugin-sdk-v0alpha2.schema-bundle.json
```

## Contract generations

The host accepts the original one-model v1alpha1 manifest and the additive
v1alpha2 manifest. v1alpha2 permits one or more models, requires plugin-local
compatibility-profile coverage for every model, and retains one reviewed
`transitional-in-process` backend entrypoint plus a safe `state.read` action.
The separate SDK v0alpha2 package establishes executable contracts for:

- stable and provisional device identities, transport aliases, and execution
  node bindings;
- independently revisioned enrollment, connectivity, and acquisition states;
- operation policy, request, acknowledgement, progress, completion, failure,
  timeout, cancellation, secret reference, and idempotency boundaries;
- immutable runtime descriptor, activation handshake, lifecycle health,
  action-invocation and action-result envelopes used by the active backend
  dispatcher;
- canonical point cloud, pose, image, encoded video, and device-status streams;
- immutable evidence handles, raw transport records, lineage, and store
  protocol;
- firmware/profile compatibility assessments that fail closed before active
  device control;
- deterministic JSON Schema export for non-Python consumers.

The contracts deliberately contain no MQTT topic, BLE UUID, protobuf type,
concrete viewer, or XGRIDS-specific field. Those belong to a plugin
compatibility profile and adapter.

Current host implementation references:

- `apps/control-station/src/core/device-plugins/frontendSdk.ts` — current
  public TypeScript/React host surface for statically reviewed UI contributions;
- `plugins/xgrids-k1/frontend/` — first physically plugin-owned consumer of
  that frontend surface;
- `apps/control-station/src/core/runtime/` — normalized runtime envelope;
- `src/k1link/web/plugin_catalog.py` — strict backend manifest validation;
- `src/k1link/web/plugin_runtime.py` — transport protocol, laboratory in-process
  implementation and host-owned SDK-envelope action dispatcher;
- `src/k1link/web/device_plugin_composition.py` — manifest factory loader and
  fail-closed descriptor/handshake checks;
- `docs/adr/0011-laboratory-plugin-runtime-handshake-and-transport-seam.md` —
  accepted control-plane seam and its explicit laboratory limits.

The existing lifecycle is fail-closed: a backend runtime stays `starting` until
its ID, version, host API and exact action set pass the handshake; inactive
provider shells perform no I/O; events are scoped by plugin ID; and selection
cannot change until the active plugin confirms teardown. `ready` health means
only that this control-plane contract is admitted. Process isolation remains a
later host milestone. v0alpha2 models secret references and operation policy,
but host authorization and the actual secret vault remain separate
implementation responsibilities.

The React surface is not yet an independently published npm package. Its alias
is intentionally narrow so plugin source cannot import Control Station
implementation paths; packaging and signing it belong to the supervisor/bundle
milestone.

## Version policy

v0alpha2 may receive additive fields while it remains experimental. A breaking
wire or semantic change creates a new explicit module (for example
`v0alpha3`); recorded documents keep their original `api_version`. Published
field meanings and enum values are never silently redefined.
