generated from coulomb/repo-seed
Separated open-cmis-tck and guide-board repositories
This commit is contained in:
247
docs/EXTENSION-SDK.md
Normal file
247
docs/EXTENSION-SDK.md
Normal file
@@ -0,0 +1,247 @@
|
||||
# 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/
|
||||
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.
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user