-
-
Notifications
You must be signed in to change notification settings - Fork 0
Analyst Skills and Teams
IRIS-NG tracks a per-analyst skill profile and uses it to help assemble a case team that covers the skills a case needs.
A catalog of 34 cyber-security / DFIR skills across 8 categories is seeded on
boot (Skill model). Each user has a set of enabled skills (UserSkill — row
presence means enabled; toggling off deletes the row).
Seeding is a slug-keyed upsert, not a match-all create_safe, so editing a
skill's name or description doesn't create a duplicate on the next boot.
Reusable rule: a seed catalog with mutable non-key fields needs a slug/key-keyed upsert, not
create_safe(which matches on all kwargs).
Two surfaces share the same datamgmt helpers:
-
Admin — a Skills tab on the user-edit modal (
server_administrator). -
Self-service — the user's own profile page (
/user/settings), where a user edits their own skills and their own hourly rate.
Two join tables (both with a UNIQUE constraint on the ORM model):
-
CaseAnalystLink—(case_id, user_id, role)where role isleadoranalyst. -
CaseRequiredSkill—(case_id, skill_id).
Lead = the case owner, always. CaseAnalystLink rows are the assigned analysts.
Required skills are derived silently when the team modal opens — there is no
visible "Required skills" section. derive_required_skills_for_case() maps the
case classification name and MISP tag substrings to skill slugs via rule-based
dictionaries (no LLM).
The ✨ Suggest pill runs a greedy set-cover scorer: it repeatedly picks the analyst who covers the most still-uncovered required skills; if no required skills are set, it falls back to ranking by skill count.
The suggestion pool excludes the case owner, the reviewer, and anyone already assigned, so suggestions are always genuinely unassigned candidates.
A coverage page with two sections:
- Analyst Skill Coverage — every active analyst with their skill chips and the categories they cover.
-
Active Cases with Team Assignments — all open cases (sourced from
/manage/cases/list), each showing its lead (owner) and assigned analysts; coverage includes the owner's skills plus each analyst member's skills.
| Method | Path | Purpose |
|---|---|---|
GET / PUT
|
/api/v2/cases/<cid>/team |
Current assignments / replace team |
GET / PUT
|
/api/v2/cases/<cid>/team/skills |
Required skills for the case |
GET |
/api/v2/cases/<cid>/team/suggest |
Skill-coverage-scored suggestions |
GET |
/api/v2/cases/<cid>/team/skills/derive |
Rule-derived required skills |
GET |
/api/v2/teams/analyst-skills |
All active analysts + their skill IDs |
Note: the
Userlogin field is.user, not.user_login— code that builds user-display strings from aUserORM object must use.user(this bit the suggest endpoint once).
-
models/authorization.py—Skill,UserSkill,CaseAnalystLink,CaseRequiredSkill -
datamgmt/case/case_team_db.py—suggest_analysts_for_case,derive_required_skills_for_case -
datamgmt/manage/manage_users_db.py— skill catalog / get / set helpers -
blueprints/rest/v2/teams/__init__.py—/api/v2/teams/analyst-skills -
post_init.py—create_safe_skills(boot-time catalog seeding)