Skip to content

Connect to Muster: its incidents open on the map and run from there - #59

Merged
0b3l1X-SolidGeeks merged 8 commits into
mainfrom
claude/strata-incident-muster-entlk7
Oct 28, 2026
Merged

0b3l1X-SolidGeeks merged 8 commits into
mainfrom
claude/strata-incident-muster-entlk7

Conversation

@0b3l1X-SolidGeeks

@0b3l1X-SolidGeeks 0b3l1X-SolidGeeks commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Follows #58 (incident mode, merged). It needs SolidGeeks/muster#21 on the Muster side.

What changes

Server. Set MUSTER_URL, MUSTER_USER, MUSTER_PASSWORD (or MUSTER_PASSWORD_FILE) and MUSTER_POLL_SECONDS (default 10). server/muster.js then:

  • signs in to Muster with an analyst account, keeps the session and opens it again on 401;
  • reads the incidents every few seconds and sends a muster event when they change;
  • passes calls on:
    • GET /api/muster and GET /api/muster/incidents/{id}: every role;
    • POST /api/muster/incidents/{id}/advance|tasks|strata: contributors and up.

Muster's refusals reach the user as they are, and an unreachable Muster gives a 502 with a clear message. The author of each log entry is set by the server, not by the page. api/me gains muster: {url}.

Interface. The incident sheet of an IS lists the Muster responses linked to it, or naming its assets, and offers the others with Open on this IS.

  • Opening marks the assets the incident names (by name or Strata id). Unknown ones are listed, and a CVE parameter selects the assets carrying it.
  • Running: the playbook frozen in the incident runs from the map, with the targets Muster stores on each step.
  • Both ways: answers, finished steps and tasks move the response in Muster, and what Muster's analysts do shows on the map within seconds.
  • Effects: a decision answered anywhere applies its effects once, tracked by the number of steps already seen.
  • Reporting back: marks and flows cut go to Muster's timeline and to the Assets hit (Strata) section of its report.

One incident, its own assets. Opening another incident on an IS puts the marks and cuts of the previous one aside, with a line in the timeline. Marks made by hand before any incident stay.

Without MUSTER_URL nothing changes: the example incidents from #58 stay. A run points to Muster only when it carries a Muster id, so examples saved before this change keep working (that was a regression on this branch, fixed and tested).

Known limit

A decision answered in Muster marks the assets in Strata when a contributor next has that IS open in Strata, not on the server. Nothing is lost in between. This is documented.

Tests

  • npm test: 76 pass. New: tests/muster.test.mjs runs a real Strata against a stand-in Muster and covers:

    • sign-in kept, and re-opened after a 401;
    • roles;
    • a Muster refusal passed on;
    • the CSRF header and the server-set author;
    • an unreachable Muster.

    Unit tests cover the conversion of a Muster incident into a run, answers applied once, the link between incidents and IS, and putting marks aside.

  • npm run test:e2e: both pass locally.

  • End to end with a real Muster (muster#21) on both sides:

    • a ransomware incident declared in Muster with two Lyon assets, run from Strata (step, decision, task, flow cut), all visible in Muster's timeline;
    • a PB-010 decision answered in Muster marking hmi-01 and jump-win suspected in Strata;
    • Muster's report listing them.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Ke7yEW5dhDYFVpV2cdgs87

Mark assets compromised, suspected or contained, from their sheet or from
a Muster playbook decision. The incident sheet lists who to call, the
flows to cut (ranked, with the firewall where to cut each), what depends
on the assets hit and what an attacker reaches next, plus a timeline.
The 3D model and the 2D diagram ring the assets hit and draw the flows
to cut. A Muster incident opens on the map; each playbook step points at
it through `targets` selectors, and decisions can mark assets.

Each asset sheet gets anonymised AI prompts: major risks, and a guide
that has a public AI write response playbooks in muster/v1 YAML. Names,
addresses, contacts and the IS name become placeholders, a leak check
runs on the text, and pasted answers get the real names back locally.

Server: GET/PUT /api/incidents (contributors and up, no proposal), kept
in incidents.json with an `incidents` live event. `npm run build:online`
writes the whole interface as one page that runs without a server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ke7yEW5dhDYFVpV2cdgs87
Signed-off-by: Claude <noreply@anthropic.com>
Inside a host page the api/me request could stay unanswered, and the map
waited for it forever on "Loading". The one-page build no longer sends it.
three.js is now imported by absolute URL from jsDelivr's ES module builds,
with no import map, and an error at start-up shows on the page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ke7yEW5dhDYFVpV2cdgs87
Signed-off-by: Claude <noreply@anthropic.com>
With MUSTER_URL, MUSTER_USER and MUSTER_PASSWORD, the server signs in to
Muster with an analyst account, reads its incidents every few seconds
and passes calls on (api/muster: read for every role, act for
contributors and up). The incident sheet lists the responses linked to
the IS, or naming its assets, and offers the others.

Opening one marks the assets it names; the playbook then runs from the
map with the targets Muster stores on each step. Answers, finished
steps and tasks move the response in Muster, what Muster's analysts do
shows on the map, and a decision answered anywhere applies its effects.
Marks and flows cut go to Muster's timeline, written by the Strata
account with the name of the person who did them. Without MUSTER_URL
the two example incidents stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ke7yEW5dhDYFVpV2cdgs87
Signed-off-by: Claude <noreply@anthropic.com>
Example runs were saved with source "muster", so with the Muster code in
place the sheet waited for a Muster incident that does not exist and
showed no step. A run now points to Muster only with a Muster id; the
examples, including those saved by the previous version, run as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ke7yEW5dhDYFVpV2cdgs87
Signed-off-by: Claude <noreply@anthropic.com>
Opening another incident on an IS puts the marks and cuts of the previous
one aside, with a line in the timeline; marks made by hand before any
incident was opened stay. The incident keeps which incident its marks
belong to (`from`), on the server too, so Muster's report of a new
incident lists only its own assets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ke7yEW5dhDYFVpV2cdgs87
Signed-off-by: Claude <noreply@anthropic.com>
@0b3l1X-SolidGeeks
0b3l1X-SolidGeeks force-pushed the claude/strata-incident-muster-entlk7 branch from 4acb91d to 87db00c Compare October 27, 2026 21:33
@0b3l1X-SolidGeeks
0b3l1X-SolidGeeks force-pushed the claude/strata-incident-mode branch from def9437 to 17efdce Compare October 27, 2026 21:33
The build took the three script tags out of index.html with a regular
expression, which CodeQL flags (it would miss forms such as
"</script >"). It now removes exactly the three tags it inlines, and
stops if index.html loads any other script.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ke7yEW5dhDYFVpV2cdgs87
Signed-off-by: Claude <noreply@anthropic.com>
Signed-off-by: Claude <noreply@anthropic.com>
Base automatically changed from claude/strata-incident-mode to main October 28, 2026 10:15
…branch

Signed-off-by: Claude <noreply@anthropic.com>
@0b3l1X-SolidGeeks
0b3l1X-SolidGeeks merged commit 4bfbfb5 into main Oct 28, 2026
10 checks passed
@0b3l1X-SolidGeeks
0b3l1X-SolidGeeks deleted the claude/strata-incident-muster-entlk7 branch October 28, 2026 10:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants