Skip to content
How-to guide

How to Initialize a Case

Use this guide to open a VulnerabilityCase after validating a report. Initialization seats the case, attaches at least one report, seats at least one participant, and attaches any opening notes. You finish with a case whose roster and report are in place and whose ledger has its genesis entry.


Prerequisites

  • A running Vultron instance you can drive. The demo containers are the quickest route — see Tutorial: Run the Receive-Report Demo for the two steps that get you a container shell.
  • An actor identity on that instance, holding the role each step names.
  • Working knowledge of the ActivityStreams verb, object, and target shape, summarized in Vultron and ActivityPub.
  • Working knowledge of the case model: the objects a case is made of, in The Case Model, and who is allowed to change them, in The CASE_MANAGER and the Case Ledger. Where a guide's messages are case-scoped, they route through the CASE_MANAGER and their results appear on the case ledger.

  • A report at Report Management (RM) state RM.VALID. See How to Report a Vulnerability.

  • The actor Uniform Resource Identifiers (URIs) of any participants you already know about, such as the Reporter.

The exchange

The flowchart below shows the activities case initialization can use. The two as:Add activities branch from Create(VulnerabilityCase) because each attaches a different kind of object to the new case. A participant is not attached: it is invited, and it joins when it accepts.

---
title: Case Creation and the Objects Attached to It
---
flowchart LR
    subgraph as:Create
        CreateCase["Create Case<br/>Create(VulnerabilityCase)"]
    end
    subgraph as:Add
        AddReportToCase["Add Report to Case<br/>Add(VulnerabilityReport)"]
        AddNoteToCase["Post a note to the case<br/>Add(Note)"]
    end
    subgraph as:Invite
        RmInviteToCase["Invite Actor to Case<br/>Invite(Actor)"]
    end
    subgraph as:Accept
        RmAcceptInviteToCase["Accept Invite to Case<br/>Accept(Invite(Actor))"]
    end
    CreateCase --> AddReportToCase
    CreateCase --> RmInviteToCase
    RmInviteToCase --> RmAcceptInviteToCase
    CreateCase --> AddNoteToCase

Seat the case

  1. Send Create(VulnerabilityCase), carrying the new VulnerabilityCase as its object. Set yourself as Case Owner.

    Create case

    Mints the vulnerability case, seats its initial participants and links the report.

    • When… the Case Manager has opened a case for a submitted report
    • Send: Create(VulnerabilityCase)
    • Send to: a participant
    • Sent by: the addressee of the case proposal or vulnerability report offer
    • Reference: Create case
    Example activity
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Create",
      "id": "urn:uuid:abc2d325-41a6-485d-90d7-d3e9c5a7d54e",
      "name": "https://vultron.example/organizations/vendorco Create VendorCo Case #31763808",
      "context": "https://demo.vultron.local/VulnerabilityReport/e28f4965-7838-4644-b4a8-10604c7ee92f",
      "content": "We've created a case from this report.",
      "actor": "https://vultron.example/organizations/vendorco",
      "object": {
        "id": "https://demo.vultron.local/VulnerabilityCase/615c9287-a98d-458f-86e0-7db242389a95",
        "type": "VulnerabilityCase",
        "name": "VendorCo Case #31763808",
        "published": "2026-10-23T20:17:07+00:00",
        "updated": "2026-10-23T20:17:07+00:00",
        "attributedTo": "https://vultron.example/organizations/vendorco",
        "caseParticipants": [
          {
            "id": "urn:uuid:89326be2-5ebf-4da5-baf3-992017977d34",
            "type": "CaseParticipant",
            "name": "VendorCo",
            "published": "2026-10-23T20:17:07+00:00",
            "updated": "2026-10-23T20:17:07+00:00",
            "attributedTo": "https://vultron.example/organizations/vendorco",
            "caseRoles": [
              "vendor"
            ],
            "participantStatuses": [
              {
                "id": "urn:uuid:42d2b2b8-1934-4645-b526-b3ed736f57fd",
                "type": "ParticipantStatus",
                "name": "START vf",
                "context": "urn:uuid:89326be2-5ebf-4da5-baf3-992017977d34",
                "published": "2026-10-23T20:17:07+00:00",
                "updated": "2026-10-23T20:17:07+00:00",
                "attributedTo": "https://vultron.example/organizations/vendorco",
                "rmState": "START",
                "vfState": "vf",
                "caseEngagement": true,
                "cvdRole": [
                  "VENDOR"
                ],
                "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
              }
            ],
            "embargoConsents": [],
            "joined": true,
            "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
          }
        ],
        "actorParticipantIndex": {},
        "vulnerabilityReports": [
          {
            "id": "https://demo.vultron.local/VulnerabilityReport/e28f4965-7838-4644-b4a8-10604c7ee92f",
            "type": "VulnerabilityReport",
            "name": "FDR-8675309",
            "published": "2026-10-23T20:17:06+00:00",
            "updated": "2026-10-23T20:17:06+00:00",
            "content": "I found a vulnerability!",
            "attributedTo": "https://vultron.example/users/finndervul",
            "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
          }
        ],
        "caseStatuses": [
          {
            "id": "urn:uuid:c1f29255-03d7-488b-aa0c-ba942f2c0905",
            "type": "CaseStatus",
            "name": "NONE pxa",
            "context": "https://demo.vultron.local/VulnerabilityCase/615c9287-a98d-458f-86e0-7db242389a95",
            "published": "2026-10-23T20:17:07+00:00",
            "updated": "2026-10-23T20:17:07+00:00",
            "attributedTo": "https://vultron.example/organizations/vendorco",
            "emState": "NONE",
            "pxaState": "pxa",
            "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
          }
        ],
        "notes": [],
        "embargoRegister": [],
        "pendingEmbargoProposalIndex": {},
        "caseActivity": [],
        "genesisHash": "8282781b3e7e5b77efecb468453488039a5b459704c7993297da921025006689",
        "ledgerPosition": {
          "logIndex": -1,
          "entryHash": "8282781b3e7e5b77efecb468453488039a5b459704c7993297da921025006689"
        },
        "parentCases": [],
        "childCases": [],
        "siblingCases": [],
        "activeParticipants": [
          "urn:uuid:89326be2-5ebf-4da5-baf3-992017977d34"
        ],
        "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
      }
    }
    
  2. Attach the report with Add(VulnerabilityReport), targeting the case. Only the Case Owner may send it, and the receiving actor must be the case's CASE_MANAGER, so mint the case through the create-case trigger (which seats the creator as Case Owner and CASE_MANAGER) rather than as a bare Create(VulnerabilityCase).

    Add report to case

    Adds a vulnerability report to the case named by the target.

    • When… the Case Owner links a further report to an existing case
    • Send: Add(VulnerabilityReport)[target=VulnerabilityCase]
    • Send to: the case manager
    • Sent by: the case owner
    • Reference: Add report to case
    Example activity
    {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Add",
      "id": "urn:uuid:1af8e484-b1ec-4204-8928-05811c2ae8d5",
      "name": "https://vultron.example/organizations/vendorco Add FDR-8675309 to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
      "content": "We're adding this report to this case.",
      "actor": "https://vultron.example/organizations/vendorco",
      "target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
      "object": {
        "id": "https://demo.vultron.local/VulnerabilityReport/e28f4965-7838-4644-b4a8-10604c7ee92f",
        "type": "VulnerabilityReport",
        "name": "FDR-8675309",
        "published": "2026-10-23T20:17:06+00:00",
        "updated": "2026-10-23T20:17:06+00:00",
        "content": "I found a vulnerability!",
        "attributedTo": "https://vultron.example/users/finndervul",
        "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
      }
    }
    
  3. Seat each participant you already know by asking the CASE_MANAGER to invite it, naming its roles; it joins when it accepts. See How to Seat a Participant on an Existing Case. Add(CaseParticipant) does not seat a member: it reinstates one the Case Owner removed.

  4. If the case needs opening context, post it as a note with one Add(Note) that targets the case and carries the note inline. Set the note's context to the case as well. See How to Post a Status Update or a Case Note.

If every report, participant, and note is known when you create the case, carry them inline on the Create(VulnerabilityCase) activity and skip steps 2 through 4. Participants carried inline are seated by case initialization itself. The steps are separated here because they are easier to follow one at a time, not because a conformant implementation must emit them individually.

If a participant becomes known later, invite it the same way — see How to Invite an Actor to a Case.

A second report needs its own Add

A case can accumulate reports. When a second report arrives for a case that already has one, attach it with Add(VulnerabilityReport) rather than creating a new case.


Verify

What you sent What to confirm
Create(VulnerabilityCase) The case exists and names you as Case Owner.
Add(VulnerabilityReport) The case lists the report.
Accept(Invite(Actor)) The case roster holds the participant with its roles.
Add(Note) The note appears on the case.

Every one of these is committed to the case ledger by the CASE_MANAGER and fanned out to each participant, so each participant's replica should show the same roster.


See it end to end

Try it: vultron-demo initialize-case

vultron-demo initialize-case

Or with Docker Compose:

DEMO=initialize-case docker compose -f docker/docker-compose.yml run --rm demo

Further reading