Tags & Composition
A threat model rarely stands alone. A product is several features, a feature runs on shared services, and an audit spans a chosen set of models. Mipiti relates models in four ways, each with one job:
| You want to say | Use | Effect on posture |
|---|---|---|
| These models belong together (a product, an audit scope, a portfolio) | Tag | None. A tag is a label for grouping and reporting |
| This model is a part of a bigger one and builds on its baseline | Parent and child (composition) | The child inherits its ancestors' entities and the credit of their controls |
| This model relies on a control another model implements | Delegation to a foundation | The objective is credited while the other model's control stays verified |
| This entity is the same one the model already inherits | Reconciliation | The duplicate collapses onto the inherited entity |
On a model's page, Relate… asks how the model relates to another one and routes to the right mechanism: part of sets the parent, relies on declares a delegation, grouped with adds a tag.
Tags
A tag is a named, overlapping grouping of models in a workspace: a product, an audit scope, a team's portfolio, an ad-hoc selection. A model can carry many tags, and a tag never changes a model's posture or how its controls are credited.
Creating and assigning tags
- Tags in the sidebar lists the workspace's tags. Create Tag takes a name (unique within the workspace) and an optional description.
- On a model's Overview tab, the Tags editor removes a tag, attaches an existing one, or creates a new tag and attaches it in one step.
- On a tag's page, Add Model adds any model in the workspace; Remove takes one out. Removing a model from a tag, or deleting a tag, never deletes a model.
On the Models page every model shows its tags. Click a tag, or pick one in the Tag filter, to see only its models.
A tag's page
| Tab | What it shows |
|---|---|
| Models | The member models |
| Risk | One row per live control objective across the members: risk tier, impact, likelihood, control counts, open findings and coverage. An objective credited through a verified delegation reads as covered, as it does on the model itself |
| Dependencies | The delegations among the members: who relies on whose control, the edge's status, and whether it credits its objective now |
| Compliance | The tag as a compliance scope (below) |
Export downloads the tag's signed auditor report: the dependencies among the members with their status, followed by every member model's full report.
A tag as a compliance scope
Selecting a framework on a tag's Compliance tab selects it for every member, and for every model added to the tag later. Removing the framework from the tag removes it from the members it was propagated to; a member that selected the framework itself keeps it, and so does a model removed from the tag. The report rolls coverage up across the members:
| Requirement scope | Covered when | Example |
|---|---|---|
| System | Any member covers it | "Security architecture is documented" |
| Component | Every member it is relevant to covers it | "Passwords are at least 12 characters" |
A requirement's scope is a property of the requirement, decided once when a framework is first selected on a tag. For component-scope requirements, a relevance analysis decides which members a requirement concerns (a password rule does not concern a file-storage model); a report recomputes it when it finds the members have changed since. Requirements can be excluded for the whole tag ("not applicable to this product"), separately from a model's own exclusions ("not applicable to this feature"). The Per-Model Coverage list ranks members by coverage and links to each model's compliance page.
Model hierarchy (composition)
Threat models compose into a tree. A child model is a part of its parent: a feature built on a platform, a service inside a product. The child inherits what its ancestors already model and only authors what is its own.
Building the tree
- On a model's Composition tab, Position in tree shows its parent and children. Set parent (or Change) picks the parent; choosing none makes the model a root.
- + Create child model generates a new model from a description with this model as its parent.
- Relate… → part of sets the parent from the model's header.
A parent must be in the same workspace, cannot be the model itself or one of its descendants, and the tree has a maximum depth. Both models must have unique entity ids, since inheritance refers to entities by id. Setting or clearing a parent creates no new version; what the subtree inherits is re-evaluated at once.
What a child inherits
A child inherits its ancestors' live trust boundaries, assets, attackers, components, attack paths, assumptions and controls, from the nearest ancestor up. An inherited entity is shown with the model that owns it and is edited on that model; it is read-only on the child. An entity an ancestor deletes stops being inherited.
Control objectives are not inherited; they are computed over the child's effective model, its own entities together with everything it inherits. That gives three kinds of objective:
| Origin | Pairs |
|---|---|
| Own | The child's asset with the child's attacker |
| Inherited | An inherited asset with an inherited attacker |
| Cross | An own asset with an inherited attacker, or the reverse |
A control on an ancestor that is mapped to an objective the child also has credits the child: a mitigation group of inherited controls covers the child's objective exactly as the child's own controls would, and each contribution is shown with its origin and owning model. Reachability is computed over the composed topology, so an inherited trust boundary blocks or admits attackers on the child too. A child with no framework selection of its own uses its nearest ancestor's.
Findings on an ancestor's controls appear on the child read-only, marked with the model they come from, while they are open. They are resolved on the model that owns them. An inherited finding whose gap the child's own model has already closed stops appearing on that child.
The Composition tab
| Section | What it shows |
|---|---|
| Composition health | Reconciliation candidates waiting, open structural findings, inherited findings |
| Coverage | The model's coverage on five dimensions, and the depth-weighted composite across its subtree |
| Composition summary | Live objectives by origin, covered and uncovered counts, and warnings about the tree (a missing parent, a cycle, a chain past the maximum depth) |
| Reconciliation | Entities the child authored that duplicate ones it inherits |
| Lift candidates / Split | Moving an entity up or down the tree |
| Recent lift / split | The lifts and splits on this model, each undoable |
| Position in tree, Subtree | Parent, children, and the whole subtree, loaded as you expand it |
| Inherited from ancestors | Every inherited entity with the model it comes from |
Reconciliation
When a child authors an entity it already inherits (both models name the same "Session Store"), the composed model would count it twice and an ancestor's control would not credit the child's copy. The reconciliation queue lists these pairs:
- Certain: same name and the same structural references (components, trust boundaries). Safe to apply.
- Heuristic: same name, different references. Review the difference before applying.
Apply records that the child's entity is the inherited one. The child keeps its entity, and its composed view leaves it out, so the inherited entity and its controls stand for both. The record is dropped as soon as the pair stops matching (the child's entity is edited apart or deleted, or the model is re-parented away from the ancestor), and the pair returns to the queue. Reject records that the two are different, and the pair leaves the queue; a rejection can be withdrawn.
Lifting and splitting
Lift moves an entity that two sibling subtrees each authored up to the lowest model above both, where it is authored once and inherited by both. A lift is refused when another subtree under that model would receive the entity too, unless you acknowledge that subtree; differences between the two copies' fields are resolved field by field; and what is attached to the entity (assertions, mappings, risk acceptances) moves with it. The two original copies are soft-deleted.
Split is the reverse: it copies an entity from an ancestor down to the descendants you choose, each copy with its attached state, and soft-deletes the ancestor's copy.
Each lift and split bumps the version of every model it touches and can be undone. The undo is previewed first, and is refused, with the reasons, when anything has changed since (the entity was edited, lifted again, or gained new evidence), rather than overwriting later work.
Foundations and delegation
When a model is built on shared services (an auth service, a logging platform, a shared datastore), it should not have to re-prove the same controls. Delegation lets a model rely on a control that is implemented and proven in another model.
This is distinct from the hierarchy, which is about containment (a model being a part of another). Delegation is about reliance: independent models that depend on each other's controls. A product can delegate different objectives to different foundations (auth to one, logging to another) without inheriting any of their threat models.
Manage delegations from the Dependencies tab of a model's detail page.
Declaring a foundation
On a shared-service model, mark it as a foundation and choose which of its controls it advertises as providable. A foundation only ever advertises controls (a proven mechanism), never bare objectives, so anything delegated to it ends at a real, verifiable control.
Two kinds of dependency
- Delegated: your model does not implement an objective itself; the foundation handles it entirely. The objective is credited through the foundation's control.
- Relied upon: your model has its own control, but that control's validity depends on the foundation's control. Your model keeps its obligation; the dependency is recorded as a contingency.
In both cases the credit ends at the foundation's verified control: a delegated objective reads as mitigated only while the provider's control stays verified.
Attaching a foundation
The fastest path: open the Dependencies tab, pick a foundation, and let the platform propose which of your objectives each advertised capability covers. Review the proposed matches, select the ones that fit, and create them in one step. Each one is created as a draft. You can also declare a single dependency directly, or use Relate… → relies on.
Validation before credit
A declared dependency does not credit anything at once. The platform asks whether the foundation's control genuinely satisfies your objective: fully, partially, or not at all. A dependency credits only after that check passes and you confirm it. A partial match is never treated as full coverage, and the platform never quietly changes a "delegated" dependency into a "relied upon" one; it shows the recommendation for you to decide.
Keeping dependencies honest
Dependencies are re-checked as the foundation changes:
- If the foundation's control regresses or is removed, every dependency on it breaks and a finding is raised on the relying model, so the lost coverage is visible.
- If the foundation's control is reworded or reworked, the dependency is validated again against the new mechanism and broken if it no longer holds.
Each foundation also shows who relies on it (on its Dependencies tab), so before you change a shared control you can see which models depend on it. A tag's Dependencies tab shows the same edges across all of its members.
Same workspace only
A model can only delegate to foundations in the same workspace. Delegation never reaches across workspace boundaries: a control's proof lives in its own workspace, and credit must rest on a proof you can inspect.
Components
A component is a deployable unit that bridges security architecture to code organization. It maps trust boundaries (where attackers can reach) to repositories (where the code lives).
Why components?
A threat model may describe a feature that spans several codebases: a backend API, a frontend app, a worker service. Without components, all controls appear in one flat list. With components, each control is scoped to the codebase that implements it.
Adding components
On the model's page, add components with:
- Name: e.g. "Backend API", "Auth Worker"
- Repo URL: e.g.
github.com/org/backend - Path: for monorepos, e.g.
services/auth(optional) - Trust boundaries: the trust boundaries this component operates within
How scoping works
Controls with a component are scoped to it. When a coding agent works in a repository, it matches the git remote URL to a component's repo URL and sees only the controls relevant to its codebase. Unscoped controls are visible to all.
Sharing threat models
To share a single threat model (for example for an open-source component), export it from the model's page. The export includes the model, its controls with their implementation status, and its assumptions. Whether a delegation credits its objective depends on the other model's controls, so a single model's export shows the delegation, not the provider's proof.
For an auditor who needs the full picture across several models, put them in a tag and use the tag's Export: the dependencies among the members with their status, followed by every member's report.
MCP tools
| Tool | Purpose |
|---|---|
list_groups / get_group / list_model_groups |
List the workspace's tags, read one with its members, or list a model's tags |
create_group / delete_group |
Create or delete a tag |
add_model_to_group / remove_model_from_group |
Manage a tag's members |
get_group_dependencies |
The delegations among a tag's members |
get_risk_view, select_compliance_frameworks, get_compliance_report, export_report with scope="tag" |
A tag's risk view, compliance scope and auditor report |
update_threat_model (parent_id / clear_parent), generate_threat_model (parent_id) |
Place a model in the tree |
get_composition |
The composed view: overview, entities, objectives, coverage, attack paths |
get_reachability_verdicts with composed=True |
Reachability over the composed topology |
list_reconciliation_candidates / decide_reconciliation_candidate |
Review, apply, reject or withdraw a rejection of a duplicate |
lift_composition_entity / split_composition_entity / undo_composition_event |
Move an entity up or down the tree, and undo it |
declare_foundation / attach_foundation / manage_reliance / list_reliance |
Foundations and delegation |
add_component / edit_component, get_controls with component_id |
Components and component-scoped controls |