SIS CLI
Flow & Skin Guide
sis workflow composes the engine’s capabilities (scan, ingest-risk, safe-text, extract, CDR
sanitise/verify, egress) into a typed workflow over a single artefact, expressed as a YAML DAG. sis skin validates a bundle (a flow plus a capability allow-list, defaults, and UI/egress presets).
It is composition, not scripting: there is no custom code, no loops, no raw finding-kind predicates. A flow wires registered capabilities with typed I/O, declarative guards over typed assessment fields, bounded member fan-out, registered join strategies, and lint-enforced side-effect boundaries.
The three verbs
sis workflow lint <flow.yml> # validate against the capability registry (no execution)
sis workflow run <flow.yml> <input> # evaluate over one input (egress is a DRY no-op by default)
sis workflow run <flow.yml> <input> --live-egress <DIR> # perform real egress, confined under DIR
sis workflow simulate <flow.yml> <dir> # run over a directory, report per-file dispositions
sis workflow bundle lint <bundle-dir> # validate a skin bundle (flow lints + only allow-listed caps)
sis workflow lint is the security boundary: it rejects unregistered capabilities, unbounded member maps,
unregistered join strategies, a release path that bypasses verify_rescan, duplicate node ids, a guard
whose producer does not dominate it, and an egress destination that is not a single normal id (so a
--live-egress write can never escape the root).
Reading sis workflow lint output
Lint prints, per flow:
runtime_status:— what the flow actually does today, not just that it parses. One of:lint_only— validated but not executed by this runner (refused byflow run).dry_run— runs, but capability nodes are recorded no-ops; guards read precomputed scalars.live_egress_original_bytes— runs with real egress, writing the original input bytes.live_typed_outputs— runs with typed node outputs feeding guards and egress writing the intended artefact (the most complete mode).
known_gap:— declared gaps between the graph and the current runtime.declared_only:— a capability the flow uses that the current runner records but does not execute.guarded:— the effective condition (conjunction of dominating guards) on each consequence node.
Always read runtime_status before trusting a flow’s behaviour: a flow can lint clean and still be
dry_run.
Egress safety
flow runis a dry no-op by default — it computes dispositions and writes nothing.--live-egress <DIR>performs real writes, confined under DIR: destinations are validated to a single normal id and the joined path is canonicalised and confirmed under the root before any write.- Destructive actions (quarantine, release) are content-addressed and remain explicit/policy-gated;
flow runrefuses alint_onlyflow rather than silently fail-closing.
Guards and joins
- A guard is one typed comparison over a registered assessment scalar (e.g.
ingest_risk.label,verdict.label, or a producer node’s output viafrom: <node>). Multi-axis conditions are chained guards (conjunction); disjunction is converging branches. No AND/OR/NOT in a predicate. - member_map fans a capability out over a container’s members (email attachments, archive entries),
bounded by
max_members/max_depth. - A join rolls member results up via a registered strategy (
worst_disposition_wins,all_must_release,any_block_blocks); a followingfrom: <join>guard routes on the roll-up.
Committed flows (examples to copy)
In the repo’s flows/ (and skin bundles under skins/):
ai-rag-ingestion-guard— scan → ingest-risk → safe_text → extract → guard → index/quarantineemail-attachment-gateway— member_map over attachments → join → quarantine the message if any blockcdr-release-gateway— scan → cdr_sanitize → verify_rescan → release the disarmed artefact or quarantinedesktop-guardian— scan → guard on verdict → quarantine or allow-opensharepoint-intake— file-share intake routing
Related guides
sis docs cdr— the sanitise/verify capabilities a CDR flow composessis docs assess— the assessment a guard branches onsis docs extract— the safe-text/extract capability in the AI/RAG flow- — capability/crate boundaries