OpenWOP openwop.dev

Companion to 0133-workflow-chain-composition.md. Working document (not normative). Likelihood × Impact each H/M/L; Score = combined severity. Critical/High rows name a mitigation owner.

IDRiskLikelihoodImpactScoreMitigationOwnerStatus
R1Unbounded co-expansion (DoS): a malicious pack composes chains in a cycle or pathological deep nest, driving a host into unbounded recursion at from-chain instantiation.MHHighsub-chain-expansion-bounded invariant (protocol-tier): a self-composing chain rejects sub_chain_cycle; nesting past maxSubChainDepth (default 8) fails closed with the same code. Fully witnessed server-free by chain-subchain-cycle-rejected.test.ts (both guards + the benign-within-bound complement). The workflow-chain analog of RFC 0071 artifact-schema-compile-bounded.Security ArchitectMitigated + witnessed (server-free, now)
R2Cross-tenant child aliasing: a co-registered child is registered under, or reachable from, the wrong tenant, or two tenants instantiating the same pack converge on one shared child workflow → cross-tenant data reach.LHHighsub-chain-child-tenant-scoped invariant (reference-impl-tier): the child MUST be owned only by the parent's tenant; the deterministic id MUST be tenant-scoped (no cross-tenant convergence). Applies the existing CTI-1 isolation to the co-registration path. Graduates reference-impl → protocol when a host witnesses it non-vacuously (chain-subchain-fanout §B).Reference host (openwop-app)Open — mitigated by design; host-pending witness
R3Silent flatten: an unsupported host degrades a runtime sub-chain into an inline splice, changing run semantics + erasing the child as an editable unit without telling the author.MMMedsub_chain_unsupported (422) MUST-refuse rule: a host without capabilities.workflowChainPacks.subChains.supported refuses a subChains-bearing chain, never flattens. chain-subchain-unsupported-refused.test.ts (corpus-contract leg always-on; host-refusal leg gated). Capability gating makes the refusal discoverable.Compatibility ArchitectOpen — mitigated by capability gate; host-refusal leg host-pending
R4Replay divergence: the minted child id or co-registration introduces run-time non-determinism, so a :fork replays against a different child.LHMedChild ids are minted at from-chain instantiate time (a POST), baked into the persisted parent BEFORE any run — the run event log gains no new non-determinism, and :fork replays byte-identically (per replay.md RunSnapshot.variables). Dispatch rides the existing core.subWorkflow/core.dispatch nodes (no new event shape). Documented in the spec §Compatibility.Compatibility ArchitectMitigated by design (instantiate-time minting)
R5Undeclared variable read: a chain reads { type:"variable" } for a name nothing produces, so a downstream node silently receives undefined at run time.MMMedvariable_undeclared closed-world validation: every variable read MUST reference a declared producedVariables[].name or a materialized parameter. validateVariableReads + chain-produced-var-roundtrip.test.ts (declared passes, undeclared rejects, materialized-param passes).Spec ArchitectMitigated + witnessed (server-free, now)
R6producedVariables misused where an edge belongs, eroding the chain-native typed-dataflow model (every hand-off becomes an untyped bag write).MLLowSpec §2.1 "Prefer edges" MUST: a value on a typed output port MUST ride an explicit edge; producedVariables is ONLY for run-bag writes with no typed port. Prose + the "Alternatives considered" (edges-only) rationale.Spec ArchitectOpen — bounded by the prefer-edges MUST
R7External sub-chain trust/version drift: an external subChainRef resolves to a different chain version on re-instantiation, breaking reproducibility or pulling in an unverified pack.MMMedExternal refs resolve + signature-verify like any pack dependency (node-packs.md §Signing); co-registration SHOULD pin the resolved version into the parent's ownership record (Unresolved-Q1, resolved: pin). Unresolvable/unverified → sub_chain_unresolved.Security ArchitectOpen — mitigated (pin SHOULD + signature verify)
R8Reference-host implementation slips, leaving the runtime-child-dispatch legs shape/library-only indefinitely (the RFC 0013 host-leg-soft-skip pattern stalling).MMMedThe library algorithm + 3 server-free scenarios + the bounded-recursion invariant witness the substance now (RFC 0013's own Accepted basis). Accepted §"Status note" names the exact remaining witness (runtime child dispatch on openwop-app) + tracks it in docs/KNOWN-LIMITS.md; the gated scenarios are ready to run the moment a host advertises the capability.Reference host (openwop-app)Open — tracked, path identified
R9Scope creep into arbitrary chain-graph orchestration (conditional sub-chain selection, dynamic fan-out counts) widens the RFC mid-flight.LMLowThis RFC scopes to static subChains[] declaration + config.subChainRef over the existing core.subWorkflow/core.dispatch nodes; dynamic selection rides those nodes' existing runtime semantics, not new chain-layer surface.Compatibility ArchitectOpen — scoped out by design