---
name: ssp
description: Workflow primer for the SSP asset spine in your GRCITSM Halo tenant — Capability / Component / Control Implementation / Implemented Requirement / Implementation Statement / Set Parameter / system_information. Covers the write chain, framework-CF three-phase write, AFUUID idempotency, ODP values as first-class Set Parameter assets, the CHANGE-PLAN approval gate, and read-side audit heuristics. Per-surface detail, payload examples, routing table, and failure modes live in reference-docs/ssp-write-surfaces.md. Use whenever composing tool calls that touch SSP documentation assets.
---

# ssp — SSP Asset Workflow Primer

## References

| Reference | Type | Location | When to Use |
|---|---|---|---|
| `grcitsm` | Skill | `plugins/grcitsm-analyst/skills/grcitsm/` | Broader Halo MCP catalog workflow (ticket-side) |
| `halo-bulk-update` | Skill | `plugins/grcitsm-analyst/skills/halo-bulk-update/` | Six-phase methodology for >20-row bulk operations |
| `halo-ssp-asset-model` | Skill | `plugins/grcitsm-analyst/skills/halo-ssp-asset-model/` | Field schema, allowed values, relationships |
| `halo-ssp-asset-write-conventions` | Skill | `plugins/grcitsm-analyst/skills/halo-ssp-asset-write-conventions/` | The eight write rules |
| `ssp-capability-seed-list` | Skill | `plugins/grcitsm-analyst/skills/ssp-capability-seed-list/` | The 15 Capabilities + starter Component mappings |
| `ssp-brand-voice` | Skill | `plugins/grcitsm-analyst/skills/ssp-brand-voice/` | Voice for render-time prose only — never Halo-stored narrative |
| `ssp-generate` | Skill | `plugins/grcitsm-analyst/skills/ssp-generate/` | Read-side pipeline consuming the spine |
| SSP write surfaces | Reference | `reference-docs/ssp-write-surfaces.md` | Per-surface table, library mechanics, payload examples, routing, failure modes, KB/Validations, catalog point-lookups |
| Read-audit detail | Reference | `reference-docs/ssp-read-audit-disciplines.md` | absent_fields / verbatim-preservation / set_parameters shape detail |
| Write semantics | Reference | `reference-docs/halo-platform/write-semantics.md` | Null-handling (§2), lookup rules (§3), framework CFs (§4-5), payload cliff (§8), verify (§11) |
| Narrative doctrine | Reference | `reference-docs/halo-platform/ssp-narrative-doctrine.md` | by-who taxonomy (§1), inheritance rules (§2), status vocabulary (§3) |

A thin operational primer for composing Halo MCP calls against the SSP asset spine: which tool, in what order, and the failure modes that span tools. Per-surface detail: `reference-docs/ssp-write-surfaces.md`; companions per the References table.

## When to load this skill

- Composing any `create_asset` / `update_asset` / `set_asset_relationships` / `update_system_information` call for SSP documentation.
- Running `/ssp-ingest` or any precursor workflow proposing writes to the spine.
- SSP-graph routing questions (framework CFs on the IS, its parent IR, or its parent Component?).
- Reading or composing the `/ssp-ingest` CHANGE-PLAN.

## OSCAL ↔ Halo terminology

**Naming overlap:** the Halo Implementation Statement asset is OSCAL `by-component`, NOT OSCAL `statement` (the sub-control-part layer, captured as flat IDs in the IS Requirements CF). Halo IR = OSCAL `implemented-requirement`; Halo SP = OSCAL `set-parameter` (per-control via rel 12 / Scope=`Control`, system-wide via rel 11 / Scope=`System`). Full mapping table: `reference-docs/halo-ssp-asset-schemas.md`.

Catalog side: a baseline is an OSCAL **Profile** — `CTBaselines` the header, `CTControlBaselines` its include-controls membership, `CTControlParameters` the modify layer, `CTControlDetails` + `CTControlRequirements` the catalog it resolves against.

## The SSP write surfaces

The spine has **six asset types** (Capability 178, Component 173, Control Implementation 192, Implemented Requirement 190, Implementation Statement 191, Set Parameter 193) plus the Site-level `system_information` surface (via `update_system_information`). Per-surface table with AFUUID shapes and parent/child links: `reference-docs/ssp-write-surfaces.md`.

Null-handling: `update_asset` is **merge-on-omit** — omitted entries preserve; a sent entry replaces that field's whole value, so read-merge-write is required only when ADDING to a multi-select. Full doctrine incl. the param-templated-runbook exception: `reference-docs/halo-platform/write-semantics.md` §2.

Field IDs cited throughout (Asset Field ids 209/213/229/236-239, framework CF ids 382/383/384/399/400/503/597) are standard GRCITSM tenant schema — provisioned identically on any tenant with the GRCITSM integration runbook loaded.

## Library-first sourcing (CTComponents + CTImplementationStatements)

Two reusable definition libraries seed the spine BEFORE any net-new authoring — check coverage first; author from scratch only where the library has no entry, logging each gap as a backfill candidate. **The AFUUID is the library key:** Component `CMPN-<CFComponentAcronym>` and IS `IS-<CFISAcronym>` are library-acronym-verbatim, so resolution is mechanical both ways — strip the prefix for the lookup key; the lookup's `[Component]` column names the rel-8 parent (a derivation, never a judgment), and `CFComponentCapability` drives rel 6. Library definitions are templates, NOT live assets. IS instantiation is **verbatim by default**; tailoring is a reviewed CHANGE-PLAN deviation. Mechanics: `reference-docs/ssp-write-surfaces.md` § Library-first sourcing.

## The canonical SSP write chain

`update_asset` is **pass-through** — caller composes the full /api/Asset JSON body as the `payload` parameter. Halo resolves `name` → integer ID for lookup CFs at write time, so submit `{id:"0", name:"<display>"}` and let Halo fill in the real ID.

New-asset chain (per asset): `asset_types` → `create_asset(inventory_number=<AFUUID>, assettype_id, client_id, site_id)` → `asset_type_fields` → `update_asset` (identity + narrative + framework Controls/KSIs) → second `update_asset` for Requirements (IS only) → `set_asset_relationships` (**rel 8 / 9 only**, plus non-FedRAMP-Controls rel 12; the rest is reconciler-owned) → `get_asset` verify. Then the end-of-run IR Description rollup. Full chain + payload examples: `reference-docs/ssp-write-surfaces.md`.

The three-phase framework-CF write (baseline → controls tier → requirements tier): **CFBaseline alone first; Controls + KSIs + Rules + CMMC Controls in the next call; Requirements last** — the Requirements lookup filters against the row's CURRENT Controls value (`reference-docs/halo-platform/write-semantics.md` §5.1).

## Routing — when to write at which layer

Functional area → Capability (Proposed-New path if not in the 15); tool/service → Component; new baseline on `Site.CFBaselines` → CI; control/KSI in scope → IR; per-(Component × requirement) narrative → IS; ODP VALUE → Set Parameter (never IS prose); front-matter → `system_information` only; user roles → `system_pocs`. Full table: `reference-docs/ssp-write-surfaces.md` § Routing.

## The CHANGE-PLAN approval gate

`/ssp-ingest` produces a CHANGE-PLAN listing every proposed write with field-level diffs and source citations, rendered in-chat and saved to `outputs/ssp-ingest-{date}-{run-id}/change-plan.md`. The agent pauses with:

```
Apply? (yes / no / approve rows X,Y,Z only)
```

Rules for the Phase-6 compose → apply after approval (the approved plan rides the [[halo-action-pipeline]] — `ssp_compile.py` compiles the structural manifests, the `ssp-writer` composer emits the residual actions, and `/grcitsm-analyst:halo-apply` is the only thing that writes):
- **Never compose rows the user did not approve.** Partial approval drops the un-approved rows entirely.
- **Spine order** from [[halo-ssp-asset-write-conventions]] Rule 5 is realized structurally: the compiler emits in spine order with `needs` edges, and the command runs the reconcilers at their spine positions around the apply — never as actions.
- **Multi-pass framework CFs are one CHANGE-PLAN row but multiple `needs`-chained actions** — surface the call count in the plan.
- **`get_asset` verify at least 10% of applied writes** (sampling per Rule 7) in the post-apply verify pass; verification failures halt with the offending asset surfaced.
- **No agent_note / inline footer / external provenance** — citation lives in the CHANGE-PLAN file plus Halo's native change history (`write-semantics.md` §11); the pipeline's `state/progress.jsonl` is the write ledger.

## Failure modes to recognize

Symptom → cause → fix table (cleared fields, dropped Requirements, lookup-filter drops + the `display:""` non-persistence signature, payload cliff, missing rel-7 links, the FRR both-ends rule, more): `reference-docs/ssp-write-surfaces.md` § Failure modes.

## Deterministic spine reconcile (MCP)

Six zero-parameter Execute-a-Runbook MCP tools rebuild/repair the spine across every Site; the five relationship reconcilers ALSO fire on Halo `Asset created` / `Asset updated` events. Never hand-create Capabilities / CIs / IRs, and never hand-wire rel 6 / 10 / 7 / 12 / 11. Run in order: (1) `reconcile_ssp_assets` — missing Capabilities / CIs / IRs + framework CFs (all 4 IR dimensions incl. Rules); (2) `_cap_component` — rel 6, driven by the Component's `inventory_number` (`CMPN-<CFComponentAcronym>`) + the library row's `CFComponentCapability`; (3) `_ci_ir` — rel 10, baseline-scoped; (4) `_ir_is` — rel 7 on shared Controls / KSIs / **Rules** / CMMC (four CF branches; Requirements CFs are NOT matched); (5) `_ir_sp` — rel 12, **FedRAMP Controls only**; (6) `_ci_sp` — rel 11. All idempotent and execute-and-wait. They do NOT create Implementation Statements or populate IS framework CFs — that stays with the IS-creation pipeline (see the FRR gotcha in the failure-modes table).

**Write fields, not edges.** Only three relationships are ever hand-wired: rel 8 (Component→IS), rel 9 (Cloud Asset→Component), and rel 12 for KSI-/CMMC-/Rule-scoped Set Parameters. Everything else derives from driver fields, so read back with `get_asset` before concluding an edge is missing. Ownership map + missing-reconciler fallback: `reference-docs/ssp-spine-reference.md`.

## KB articles, Validations, and catalog point-lookups

A KB article associates with **exactly one documentary Component** (`Policy` / `Process/Procedure` / `Plan` / `Guidance` / `Standard` / `Document`) whose Title matches the article exactly — never with an IR or IS; the Component's relationships are what place the article in the spine ([[halo-ssp-asset-model]]). KB writes require `faqlists` (id 1 default); KB reads go through `get_asset(...).kbs[]` (the KB search tools are currently blind on this integration); `create_validations` is RUNS-ONLY (definitions live on the type-49 ticket). Catalog point-lookups validate (Control ID, Baseline) pairs pre-write. Full conventions: `reference-docs/ssp-write-surfaces.md`.

## AFUUID — the idempotency key

Every SSP-spine asset carries an AFUUID landing in TWO surfaces on every create: top-level `inventory_number` (`Device.dinvno`) AND UUID Asset Field id=209 — same string; Title (id=213) holds the human-readable form. Skipping either breaks idempotency lookups **and, on Components, the rel-6 reconciler**. Cloud/Hardware Asset rows are exempt (real identifiers). Full shapes, `<CATALOGSHORT>` resolution, and the no-control-IDs rule: [[halo-ssp-asset-write-conventions]] Rule 2 / Rule 4 — do not re-derive.

## Quick-reference

- Asset-type dtypes + relationship ids: `reference-docs/halo-platform/data-model.md` §8. Lookup/CF write shapes, validate-V/W forms, KSI family stripping, status ints, verify doctrine: `reference-docs/halo-platform/write-semantics.md` §3, §5, §11. Title/AFUUID shapes + SP field ids: `reference-docs/halo-ssp-asset-schemas.md`.
- Global Custom Fields (standard GRCITSM tenant schema): 6 framework CFs (CFAFedRAMPControls 382, CFAFedRAMPKSIs 384, **CFAFedRAMPRules 597**, CFACMMCControls 383, CFAFedRAMPRequirements 399, CFACMMCRequirements 400) + **CFBaseline 503** (single-select scalar, name-string only). `CFAFedRAMPRules` (FRR, 3-3-3 shape e.g. `VDR-TFR-KEV`) is carried on IRs **and** IS assets.

## Read-side audit disciplines (per-control shape rules)

The read-side pipeline ([[ssp-generate]] + the ssp-author agent) emits per-control records read shape-first downstream; findings route to `gaps.md`. The value semantics — by-who taxonomy + decision rule, inheritance rules, status vocabulary, anti-patterns — are corpus-owned: `reference-docs/halo-platform/ssp-narrative-doctrine.md`. Below are the Halo-specific derivation heuristics.

### `absent_fields` — null + flag, never default

An absent Halo field emits as `null` AND joins the per-control `absent_fields` array — never invent a default; `"Not Assessed"` only where Halo explicitly records it (`ssp-narrative-doctrine.md` §3). Every entry surfaces in `gaps.md`. Detail: `reference-docs/ssp-read-audit-disciplines.md`.

### `by-who` — four-step Halo CF walk

Per-control `by-who` ∈ {`by-the-system`, `by-the-organization`, `by-the-system-and-organization`, `inherited`} (taxonomy, decision rule, and anti-patterns: `ssp-narrative-doctrine.md` §1). Resolve in order:
1. Component owner / responsibility CF if present → use directly.
2. Capability description scope: subsystem-scoped → `by-the-system`; organizational-process-scoped → `by-the-organization`; mixed → `by-the-system-and-organization`.
3. Component type: asset-backed (Service/Software/Hardware) leans `by-the-system`; Process/Procedure/Policy/Plan leans `by-the-organization`.
4. Inheritance fields: non-null `inherited_from` / CSP provider → `inherited` regardless of (1)-(3).

If genuinely ambiguous, set `by-who: null` and add `"by-who"` to `absent_fields` — never default (`ssp-narrative-doctrine.md` §1).

### `inheritance` — Halo field sources for the `{type, provider, crm_reference}` shape

Shape and documentation rules: `ssp-narrative-doctrine.md` §2. Halo sources: `provider` pulls from the Component / Capability CSP-provider CF; `crm_reference` pulls from the Component / Capability CRM-reference CF; if not stored, `null` — never inferred from context. Absent values surface in `absent_fields`.

### Verbatim implementation-language preservation

IS narrative (field 229) emits verbatim into the per-control record — never paraphrase, summarize, condense, or rewrite. [[ssp-brand-voice]] applies only to render-time prose the agent composes, never to Halo-stored narrative. Detail: `reference-docs/ssp-read-audit-disciplines.md`.

### `set_parameters` — read ODP values from SP assets, never from IS prose

Per-control ODP values come from the linked Set Parameter assets (rel 12 on the IR, rel 11 on the CI), emitted as a `set_parameters` array — never parsed out of IS narrative. An ODP slot with no linked SP emits `null` + `absent_fields` + `gaps.md` (expected for CMMC/20x, which carry no catalog ODP prose). Entry shape and walk detail: `reference-docs/ssp-read-audit-disciplines.md`.

### Mapping corroboration + active-inventory cross-check

Two graph-walk audits — [[halo-ssp-asset-model]] § Audit checks: the `mapping_corroborated` flag (drives gap analysis) and decommissioned-asset surfacing.
