Files
guide-board/docs/EXTENSION-SDK.md

314 lines
8.5 KiB
Markdown

# Guide Board Extension SDK
Status: draft
Created: 2026-05-07
## Purpose
This document defines the first extension integration contract for `guide-board`.
It is intentionally small: extensions declare metadata in `extension.json`, the
core discovers them, and runners can produce normalized evidence through a stable
dictionary contract.
## Extension Layout
Bundled incubating extensions live under:
```text
extensions/<extension-id>/
INTENT.md
extension.json
src/
docs/
schemas/
evidence-requests/
checks/
mappings/
profiles/
runners/
normalizers/
reports/
workplans/
```
Production extensions may also live in their own repositories. The repository
root is then the extension root and must contain `extension.json`:
```text
open-cmis-tck/
INTENT.md
extension.json
src/
mappings/
profiles/
runners/
workplans/
```
Pass external extension repos to the core CLI with:
```sh
guide-board --extension-dir ../open-cmis-tck extensions list
```
Multiple `--extension-dir` values are allowed. `GUIDE_BOARD_EXTENSION_PATHS`
may also provide an OS-path-separated list for local automation and containers.
Only `INTENT.md` and `extension.json` are required for discovery. Additional
folders appear as the extension grows.
## Manifest Contract
`extension.json` must validate against:
```text
docs/schemas/extension-manifest.schema.json
```
The key runtime fields are:
- `id`: must match the extension directory name.
- `extension_type`: one of the supported archetypes from the architecture
blueprint.
- `supported_frameworks`: framework IDs this extension can contribute evidence
for.
- `check_groups`: named groups that assessment profiles can select.
- `preflight_runner`: optional runner ID used before selected check groups.
- `runner_entrypoints`: concrete runner declarations.
- `mappings`: mapping set IDs under `mappings/<mapping-id>.json`.
- `certification_boundary`: explicit statement of what the extension does not
certify.
`profile_schemas` may use the original string shorthand for core schemas:
```json
["target-profile", "assessment-profile"]
```
Extensions that need stricter domain-specific validation can add schema
descriptors:
```json
[
"target-profile",
"assessment-profile",
{
"id": "cmis-browser-target",
"profile_kind": "target",
"path": "schemas/cmis-browser-target.schema.json",
"subject_type": "cmis-browser-binding-endpoint",
"description": "Requires the target shape expected by the CMIS Browser Binding harness."
}
]
```
Descriptor fields:
- `id`: stable schema descriptor ID used in validation errors.
- `profile_kind`: `target` or `assessment`.
- `path`: JSON schema path relative to the extension root.
- `subject_type`: optional target-profile selector. When present, the schema is
applied only to targets with that `subject_type`.
- `description`: optional authoring note.
The core validates the generic guide-board schema first, then applies matching
extension-owned schemas during `profile validate-*`, `plan`, and `run`.
Extension schema paths must stay inside the extension root. The baseline
validator intentionally supports the small JSON Schema subset used by
guide-board contracts: `type`, `enum`, `required`, `properties`,
`additionalProperties`, `items`, and `minItems`.
## Runner Entry Points
Runner entry points currently support these kinds:
- `python_module`: load a Python file from the extension directory and call a
function.
- `command`: execute a manifest-declared argv without shell expansion. The core
writes a context JSON file and expects the command to print a JSON runner
result to stdout.
- `external`: declare an external harness that the baseline core cannot execute
yet.
Example:
```json
{
"id": "cmis-browser-preflight",
"kind": "python_module",
"module_path": "src/open_cmis_tck/preflight.py",
"callable": "run",
"command": null,
"description": "Checks whether the CMIS Browser Binding endpoint is reachable."
}
```
Command runner example:
```json
{
"id": "opencmis-tck",
"kind": "command",
"module_path": null,
"callable": null,
"command": ["python3", "runners/opencmis_tck.py", "--context", "{context_json}"],
"description": "Checks dependency posture and prepares OpenCMIS TCK execution."
}
```
Command placeholders:
- `{context_json}`: generated context file for the current step.
- `{root}`: repository root.
- `{run_dir}`: current run directory.
- `{extension_path}`: current extension directory.
The command is executed with the extension directory as its working directory.
The core does not use a shell for command runners.
Runner context values are stable for bundled and external extensions:
- `root`: the guide-board core root.
- `extension_path`: the absolute path to the extension root.
- `run_dir`: the current run output directory.
- `plan`: the immutable run plan snapshot.
## Mapping Sets
Mapping sets connect normalized evidence requirement refs to capability groups,
controls, conformance classes, quality dimensions, or other assessment targets.
Each mapping set lives under:
```text
extensions/<extension-id>/mappings/<mapping-id>.json
```
and validates against:
```text
docs/schemas/mapping-set.schema.json
```
The core does not embed domain policy. It only joins evidence `requirement_refs`
to extension-owned mappings and writes normalized mapping records to:
```text
runs/<run-id>/normalized/mappings.json
```
## Evidence Request Sets
Procedural and hybrid compliance extensions may include evidence request sets
under:
```text
evidence-requests/<request-set-id>.json
```
These files validate against:
```text
docs/schemas/evidence-request-set.schema.json
```
Evidence request sets are for collection guidance and review workflow. They
should reference official requirements by stable IDs or user-held licensed
material, but they must not redistribute proprietary standard text. A starter
template lives at:
```text
extensions/_template/evidence-request-set.json
```
See `docs/COMPLIANCE-EVIDENCE-PACKS.md` for the compliance-pack strategy.
## Expectations And Waivers
Assessment profiles may reference expectation and waiver sets:
```json
{
"expectations_ref": "profiles/expectations/example.json",
"waivers_ref": "profiles/waivers/example.json"
}
```
Expectation sets mark known posture as expected. Waiver sets mark approved,
time-bounded exceptions. Both are applied after findings are generated, and the
assessment package records policy summary counts.
## Python Runner Contract
A Python runner receives one context object and returns one result object.
```python
def run(context: dict) -> dict:
return {
"result": "pass",
"observations": ["Observed the expected condition."],
"facts": {"key": "value"},
"artifact_refs": [],
}
```
Context fields:
- `root`: repository root path as a string.
- `run_dir`: output run directory path as a string.
- `run_id`: current run ID.
- `plan`: full run plan snapshot.
- `step`: the step being executed.
- `target_profile`: target profile snapshot.
- `assessment_profile`: assessment profile snapshot.
- `extension_path`: extension directory path as a string.
- `runner`: manifest runner declaration.
Result fields:
- `result`: one of the guide-board evidence result statuses.
- `observations`: human-readable observations.
- `facts`: structured facts extracted by the runner.
- `artifact_refs`: references to raw artifacts written by the runner.
Artifact refs must be paths relative to the run directory. After runner
execution, the core fingerprints existing artifact refs into the assessment
package `artifact_manifest`.
If a Python runner raises an exception, the core converts that failure into
`infrastructure_error` evidence so the assessment package remains complete.
Preflight runners are gates. If an extension preflight returns `fail`, `blocked`,
or `infrastructure_error`, downstream check groups for that extension are not
executed; they receive `blocked` evidence with `blocked_reason:
preflight_failed`.
## Result Statuses
Initial statuses:
- `pass`
- `fail`
- `warning`
- `manual`
- `not_applicable`
- `skipped`
- `expected_gap`
- `waiver_applied`
- `unsupported_by_design`
- `infrastructure_error`
- `blocked`
- `unknown`
## Current Extension Examples
- `sample-noop`: no runner, used to validate the core contracts.
- `open-cmis-tck`: provides a Python CMIS Browser Binding preflight runner and
declares the future external OpenCMIS TCK runner.
## Next SDK Steps
- Add normalizer plug-in contracts.
- Add extension-owned schema validation for domain-specific target profile
fields.