Library & Lifecycle
Categories, statuses, approvals, adaptive → library promotion, and upstream repository sync
Library & Lifecycle
The library is where every published playbook lives — a single searchable, filterable surface at /playbooks. This page covers how playbooks move through the library, how they get there from upstream + from PIVT's adaptive composer, and how categorization, ownership, and approvals work.
Categories
Every library playbook sits under one of six canonical categories:
| Category | Scope |
|---|---|
identity | IAM, user lifecycle, auth, credentials |
endpoint | EDR, process / file / host events |
cloud | CloudTrail, GCP audit, Azure activity |
data | DLP, sensitive-data access |
network | Network flows, lateral movement, egress |
email | Mail gateway, phishing, BEC |
Categories drive two things: the sidebar rail in the library UI (each category gets its own column), and the rule↔playbook auto-association fallback — when a rule doesn't pin a specific playbook but fires against a source that maps to a category, the category's default playbook is offered.
Status lifecycle
submit-for-review
draft ──────────────────▶ in_review
▲ │
│ ┌──────┴──────┐
│ │ │
│ approve reject
│ │ │
│ ▼ ▼
└── edit ◀── live (back to draft with feedback)
│
archive
│
▼
archivedFields on the playbooks row that track this:
| Field | Meaning |
|---|---|
status | draft · in_review · live · archived |
promoted | true only if the row was promoted from an adaptive playbook — see below |
current_version | Points to the latest row in playbook_versions (immutable snapshots) |
Each edit of a live playbook creates a new row in playbook_versions and re-points current_version. playbook_runs always resolve their step list against the version in effect when the run started.
Approvals
Moving from in_review to live requires an approver. The approval flow:
- Author finishes editing in
/playbooks/new, clicks Submit for review in the Review phase. - A
playbook_approvalsrow is created withstatus=pending. - Approvers (any user with
playbooks:publish) see the request in the library's Review filter. - An approver clicks Approve (the playbook's status flips to
live,approved_atstamps now) or Reject with a note (theplaybook_approvalsrow'sstatusbecomesrejected; the playbook returns todraftwith the reviewer's note attached so the author can iterate).
Approvals are one-at-a-time — re-submitting a rejected playbook creates a new approval row; the old one stays in history.
Permissions
Access to playbooks is governed by system-wide RBAC — there are no per-playbook role overrides today. The relevant permissions:
| Permission | Grants |
|---|---|
playbooks:view | Read library + run artifacts |
playbooks:run | Attach a playbook to a case |
playbooks:edit | Create / modify drafts |
playbooks:publish | Approve a submission; promote adaptive |
playbooks:manage | Archive, hard-delete, sync-from-upstream |
A "restricted playbook" concept (per-playbook role overrides) is not scoped today — the UI surfaces an Info tab on each playbook showing the canonical RBAC mapping so analysts know who can do what.
Adaptive playbooks
When the Shadow Investigator (PIVT) wraps investigating a case, it fire-and-forget composes an adaptive playbook summarising the moves it made — the queries, pivots, enrichments, and decisions. Adaptive playbooks:
- Live alongside library entries but with
status=live,promoted=false. - Are filtered into the library's Adaptive tab (separate from hand-authored
liveentries). - Carry the same slash-command shape — they're first-class playbooks, just machine-composed.
Promoting to the library
An analyst reviewing an adaptive playbook can click Promote. This flips promoted=true and moves the entry into the canonical library — visible under its category, usable by any analyst, versioned from here on like any hand-authored playbook.
promoted is adaptive-only. Hand-authored drafts that pass approval stay status=live, promoted=false. The Promoted filter in the library is specifically a track record of the adaptive system — "which of PIVT's compositions turned out to be worth keeping."
Upstream repository sync
The nanos-sh/playbooks upstream repo is the canonical source of stock playbooks. Two modes:
| Mode | Behaviour |
|---|---|
linked | Auto-pull on sync; local edits are NOT preserved (sync overwrites) |
forked | Sync imports into a cache; author copies into the library and owns edits |
Sync flow:
- Admin configures a
playbook_repositoriesrow (git url + ref + access token). - Sync button in the library header (or a scheduled sync if enabled) pulls the repo into
repository_playbooks— a cache, not the library itself. - For each cached entry, the admin hits Import (library UI) to create a
playbooksrow from it.
The same pattern is used for detection rules (rule_repositories) and parsers — see Integrations for the rule-side equivalent.
Archive vs. hard-delete
Two removal actions exist:
| Action | Endpoint | Behaviour |
|---|---|---|
| Archive | DELETE /api/playbooks/{id} | Soft: status=archived, run history preserved, re-activatable |
| Hard delete | DELETE /api/playbooks/{id}/permanent | Row removed entirely; runs keep their cached doc via playbook_versions |
Archive is the default. Hard delete requires type-to-confirm and is intended for accidental creates / test playbooks — once a playbook has real runs attached, archive is the right move (keeps the audit trail).
Rule ↔ playbook association
Detection rules can pin a specific playbook, set themselves to adaptive, or leave it open:
playbook_selector_mode | playbook_id | Behaviour on case creation |
|---|---|---|
specific | non-null | The pinned playbook auto-attaches |
adaptive | null | No attach at create; PIVT composes on wrap-up |
none (or unset) | null | Analysts can manually attach from the case view |
The association is set from the rule editor — both in the form radio group and in the YAML shorthand (playbook: pb_01hz… or playbook: adaptive round-trips between the two). See the rule editor docs for the matching side of the wiring.
Analytics
Each playbook exposes live analytics at GET /api/playbooks/{id}/analytics:
runs_total,runs_this_week,runs_prev_week— usage trendcompletion_rate— % of runs that reached the Close phaseavg_ttr_minutes— median time from attach to run finishstep_completion_histogram— which steps get marked done vs skippeddecision_answer_distribution— for each/decisionstep, how analysts answered
The library's Analytics tab on each playbook renders these directly. The four sort tabs on the library list (Most used, Recently edited, High skip, A–Z) each ORDER BY the matching analytics field server-side.
See also
- Authoring — writing a playbook.
- Templating & runs —
{{...}}grammar +run_context. - Integrations — the rule / parser repository pattern that playbook sync mirrors.