Skip to content
Reference

Case Management Messages

These messages drive the lifecycle of a VulnerabilityCase, the record of one Coordinated Vulnerability Disclosure (CVD) case, and its roster of participants. They have no formal-protocol shorthand — the 28-symbol formal message set addresses state-machine transitions, not the case-infrastructure layer that supports them (see ADR-0083).

All messages on this page operate on a case that already exists. For the pre-existence bootstrap (vendor → case-actor service) see Case Proposal. For the ledger mechanism that replicates these activities to all participants see Ledger Replication.

Two authorities appear below, and they are distinct roles rather than one actor. The Case Owner decides for the case: who is admitted, which roles they hold, and whether an ownership transfer is offered. The CASE_MANAGER is the case's single-writer authority: it mints and updates the VulnerabilityCase object, records every case-scoped message in the ledger, and delivers case snapshots to participants (spec §5.4.1 Single-Writer Authority, ADR-0088). The CASE_MANAGER acts on the Case Owner's behalf; the two roles are often held by the same actor but need not be.

When the CASE_MANAGER refuses one of these messages because a precondition does not hold, it answers the sender with the refusal notice: a Reject of the refused message, with the reason in summary (CLP-02-005, CLP-05-001). It records nothing of the refused message in the ledger. It sends no answer when the sender may not send the message at all, or when the message repeats one whose effect is already in place. A refused Offer or Invite is answered with a Reject of it, which the sender reads as the decline of its request. The close-case decline is the one message on this page with an answer of its own, so it gets no refusal notice. The 300-level introduction is The Case Manager and the Case Ledger.

Occasions

When… Send Send to Sent by Distinguished by Details
the Case Manager has opened a case for a submitted report Create(VulnerabilityCase) a participant the addressee of the case proposal or vulnerability report offer — Create case
the Case Owner links a further report to an existing case Add(VulnerabilityReport)[target=VulnerabilityCase] the case manager the case owner — Add report to case
the Case Manager records the new Case Owner once a case ownership transfer is accepted Update(VulnerabilityCase) a participant not handled — Update case owner
the Case Owner offers a CVD role on the case to another participant Offer(CaseParticipantRole)[context=VulnerabilityCase] the case manager the case owner — Offer case participant role
a participant accepts a role offered to it on the case Accept(Offer(CaseParticipantRole)[context=VulnerabilityCase]) the case manager the addressee of the case participant role offer — Accept case participant role
a participant declines a role offered to it on the case Reject(Offer(CaseParticipantRole)[context=VulnerabilityCase]) the case manager the addressee of the case participant role offer — Reject case participant role
the Case Owner proposes to transfer ownership of the case to another actor Offer(Offer(VulnerabilityCase)) the case manager the case owner — Propose case ownership transfer
the Case Manager offers the case to the actor the Case Owner proposed Offer(VulnerabilityCase) a participant the case manager — Offer case ownership transfer
an actor accepts an offer of case ownership Accept(Offer(VulnerabilityCase)) the case manager the addressee of the vulnerability case offer — Accept case ownership transfer
an actor declines an offer of case ownership Reject(Offer(VulnerabilityCase)) the case manager the addressee of the vulnerability case offer — Reject case ownership transfer
the Case Owner withdraws its proposal while the offer of case ownership is open Undo(Offer(Offer(VulnerabilityCase))) the case manager the case owner — Withdraw case ownership transfer
the Case Manager invites an actor to join the case Invite(Actor)[target=VulnerabilityCaseStub] a participant the case manager — Invite actor to case
an invited actor agrees to join the case Accept(Invite(Actor)[target=VulnerabilityCaseStub]) the case manager the invitee — Accept invite to case
an invited actor declines to join the case Reject(Invite(Actor)[target=VulnerabilityCaseStub]) the case manager the invitee — Reject invite to case
the Case Manager has replayed the case ledger to a newly joined Participant Invite(Actor)[target=VulnerabilityCase] a participant the case manager — Send Full-Case Invite
a Participant asked by a Full-Case Invite judges the case valid Accept(Invite(Actor)[target=VulnerabilityCase]) the case manager the invitee — Accept Full-Case Invite
a Participant asked by a Full-Case Invite judges the case invalid TentativeReject(Invite(Actor)[target=VulnerabilityCase]) the case manager the invitee — Tentatively reject Full-Case Invite
a Participant asked by a Full-Case Invite closes the case Reject(Invite(Actor)[target=VulnerabilityCase]) the case manager the invitee — Reject Full-Case Invite
the Case Manager has admitted a new Participant to the case Announce(VulnerabilityCase) a participant the case manager — Announce vulnerability case
a Participant ends its participation in the case Leave(VulnerabilityCase) the case manager the case owner or a participant — Close case
the Case Owner reinstates a removed Participant Add(CaseParticipant)[target=VulnerabilityCase] the case manager the case owner — Add case participant to case
the Case Owner removes a Participant from active participation Remove(CaseParticipant)[target=VulnerabilityCase] the case manager the case owner — Remove case participant from case
the Case Manager creates a participant record, such as the inert record for the invitee of a stub Invite Create(CaseParticipant) a participant not handled — Create case participant
the Case Manager changes a participant record, such as moving the CASE_OWNER role on an ownership transfer Update(CaseParticipant) a participant not handled — Update case participant

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
  • Seen in: How to Initialize a Case
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Create",
  "id": "urn:uuid:2d83f8af-f1f2-487a-8496-2090b22a9e9d",
  "name": "https://vultron.example/organizations/vendorco Create VendorCo Case #66422217",
  "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/b99c8adc-c7c4-49c9-87c2-55161f9dd173",
    "type": "VulnerabilityCase",
    "name": "VendorCo Case #66422217",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "caseParticipants": [
      {
        "id": "urn:uuid:6c481f76-a941-418b-9282-81cd0d29f01a",
        "type": "CaseParticipant",
        "name": "VendorCo",
        "published": "2026-10-23T20:17:36+00:00",
        "updated": "2026-10-23T20:17:36+00:00",
        "attributedTo": "https://vultron.example/organizations/vendorco",
        "caseRoles": [
          "vendor"
        ],
        "participantStatuses": [
          {
            "id": "urn:uuid:1ad0f95f-ba4a-4654-997b-a9ab4f555cf2",
            "type": "ParticipantStatus",
            "name": "START vf",
            "context": "urn:uuid:6c481f76-a941-418b-9282-81cd0d29f01a",
            "published": "2026-10-23T20:17:36+00:00",
            "updated": "2026-10-23T20:17:36+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:f32a33f7-6ce6-4cbd-aeed-57065f6a45c5",
        "type": "CaseStatus",
        "name": "NONE pxa",
        "context": "https://demo.vultron.local/VulnerabilityCase/b99c8adc-c7c4-49c9-87c2-55161f9dd173",
        "published": "2026-10-23T20:17:36+00:00",
        "updated": "2026-10-23T20:17:36+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": "bbd83e4b4e0d5fbcdf4a55ac52cbc261e39efe3bee79d0c86ef3387952585cc2",
    "ledgerPosition": {
      "logIndex": -1,
      "entryHash": "bbd83e4b4e0d5fbcdf4a55ac52cbc261e39efe3bee79d0c86ef3387952585cc2"
    },
    "parentCases": [],
    "childCases": [],
    "siblingCases": [],
    "activeParticipants": [
      "urn:uuid:6c481f76-a941-418b-9282-81cd0d29f01a"
    ],
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Recipients: the CASE_MANAGER sends the completed case to the report receiver (the Case Owner) only (CBT-01-010, CM-22-001, CM-22-002). The report receiver then sends the report submitter a Create(VulnerabilityCase) as itself, which names the CASE_MANAGER and is the trust bootstrap (spec §4.5 Trust and Bootstrap Semantics; CBT-01-001, ADR-0132).
  • Who is named where: the actor of the Create is the CASE_MANAGER that mints the case, and the case's attributedTo is the Case Owner (CP-09-001, CM-02-008). The two coincide when the Case Owner creates its own case, as in the example above. When a case-actor service creates the case from a Case Proposal, the service is the actor and attributedTo names the proposing actor, never the service itself. Every owner check reads attributedTo, and an ownership transfer rewrites it (CM-21-002).
  • Triggering transition: none — object construction precedes protocol state.
  • Example artifact: create_case.json.

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
  • Seen in: How to Initialize a Case
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Add",
  "id": "urn:uuid:1ad9e287-7886-4546-a144-cc42fef5903b",
  "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"
  }
}
  • Triggering transition: none — a report can be added at any Report Management (RM) state.
  • Who may send: the CASE_MANAGER admits it only from the Case Owner, and a participant replica accepts it only from the CASE_MANAGER. Any other sender is refused and the report is not attached.
  • Example artifact: add_report_to_case.json.

Offer case participant role

Offers one role on the case to the participant named by the target. The Case Manager records the offer and forwards it to that participant.

  • When… the Case Owner offers a CVD role on the case to another participant
  • Send: Offer(CaseParticipantRole)[context=VulnerabilityCase]
  • Send to: the case manager
  • Sent by: the case owner
  • Seen in: How to Delegate a Role to Another Participant
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Offer",
  "id": "urn:uuid:4c983ba4-c67e-4c86-aa2f-919590bae74e",
  "name": "https://vultron.example/organizations/vendorco Offer urn:uuid:3000af2a-9167-4afe-b4ff-097cb9a72715 to Coordinator LLC",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "content": "We're offering the coordinator role on case VendorCo Case #70930046 to Coordinator LLC.",
  "to": [
    "https://vultron.example/case-actors/vendorco-case-actor"
  ],
  "actor": "https://vultron.example/organizations/vendorco",
  "target": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Organization",
    "id": "https://vultron.example/organizations/coordinator",
    "name": "Coordinator LLC",
    "published": "2026-10-23T20:17:06+00:00",
    "updated": "2026-10-23T20:17:06+00:00",
    "inbox": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "OrderedCollection",
      "id": "https://vultron.example/organizations/coordinator/inbox",
      "items": []
    },
    "outbox": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "OrderedCollection",
      "id": "https://vultron.example/organizations/coordinator/outbox",
      "items": []
    }
  },
  "object": {
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld",
    "type": "CaseParticipantRole",
    "id": "urn:uuid:3000af2a-9167-4afe-b4ff-097cb9a72715",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "role": "coordinator"
  }
}
  • Routing: the offer is addressed to the CASE_MANAGER only, never to the target (CM-33-001). The CASE_MANAGER records it in the ledger and then forwards it to the target as its own Offer(CaseParticipantRole), with the Case Owner in attributedTo and inReplyTo naming the recorded offer. The target acts only on that forward, and answers the CASE_MANAGER, not the Case Owner (CM-33-004). Nothing is granted until the CASE_MANAGER records the target's Accept (CM-02-016).
  • Who may send: the Case Owner only; the CASE_MANAGER refuses an offer from any other sender (CM-33-002). CASE_OWNER and CASE_MANAGER cannot be offered, and the CASE_MANAGER also refuses an offer with no readable role, one whose target is not a participant, one whose target is the CASE_MANAGER itself, and one of a role the target already holds (CM-33-003). A refused offer is not recorded and not forwarded. The CASE_MANAGER answers an offer refused for its role or target with the refusal notice, and an offer from any other sender with nothing.
  • Object type: the object type alone identifies the activity as a role offer rather than an ownership-transfer offer (ADR-0039). Roles are granted through the case's authority chain (§11.1 Role Assignment).
  • Target: the participant offered the role; the context is the case.
  • Forward example: forward_case_participant_role.json.
  • Triggering transition: none — roster action, not a state-machine event.
  • Example artifact: offer_case_participant_role.json.

The CaseParticipantRole object carries the role. This offer is distinct from Offer(CaseParticipant), which forwards an actor recommendation to the Case Owner and is covered under Offer case participant.

Accept case participant role

Accepts the offered role. The participant holds the role once the Case Manager records the acceptance.

  • When… a participant accepts a role offered to it on the case
  • Send: Accept(Offer(CaseParticipantRole)[context=VulnerabilityCase])
  • Send to: the case manager
  • Sent by: the addressee of the case participant role offer
  • Seen in: How to Delegate a Role to Another Participant
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Accept",
  "id": "urn:uuid:ae0ea138-bc17-42c0-933a-ee1fa50e764a",
  "name": "https://vultron.example/organizations/coordinator Accept https://vultron.example/case-actors/vendorco-case-actor Offer urn:uuid:872a3639-60da-43e2-88f4-ff3ddd94543e to Coordinator LLC",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "content": "We're accepting the role you offered.",
  "to": [
    "https://vultron.example/case-actors/vendorco-case-actor"
  ],
  "actor": "https://vultron.example/organizations/coordinator",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Offer",
    "id": "urn:uuid:a6ab57df-3123-4a98-b813-586555caa296",
    "name": "https://vultron.example/case-actors/vendorco-case-actor Offer urn:uuid:872a3639-60da-43e2-88f4-ff3ddd94543e to Coordinator LLC",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "inReplyTo": "urn:uuid:e0b11d1e-345d-41ec-afaa-1230c17ed782",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "content": "We're offering the coordinator role on case VendorCo Case #70930046 to Coordinator LLC.",
    "to": [
      "https://vultron.example/organizations/coordinator"
    ],
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "actor": "https://vultron.example/case-actors/vendorco-case-actor",
    "target": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Organization",
      "id": "https://vultron.example/organizations/coordinator",
      "name": "Coordinator LLC",
      "published": "2026-10-23T20:17:06+00:00",
      "updated": "2026-10-23T20:17:06+00:00",
      "inbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/inbox",
        "items": []
      },
      "outbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/outbox",
        "items": []
      }
    },
    "object": {
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld",
      "type": "CaseParticipantRole",
      "id": "urn:uuid:872a3639-60da-43e2-88f4-ff3ddd94543e",
      "published": "2026-10-23T20:17:36+00:00",
      "updated": "2026-10-23T20:17:36+00:00",
      "role": "coordinator"
    }
  }
}
  • Routing: the Accept goes to the CASE_MANAGER only, never to the Case Owner that made the offer (CM-33-004). Its object is the CASE_MANAGER's forward, which the CASE_MANAGER matches to the recorded offer through the forward's inReplyTo, never through the copy the Accept carries.
  • Who may send: the target of the recorded offer only, and only while that offer is open: until the CASE_MANAGER records an Accept or Reject of it (CM-33-005). The CASE_MANAGER refuses an Accept from any other sender, one to an offer that is no longer open, and one whose carried offer names another role or target, with no ledger entry and no role change. When the CASE_MANAGER refuses an Accept because the offer is no longer open or its carried offer differs, it answers with the refusal notice. It answers an Accept from any other sender with nothing. A redelivery of the Accept that closed the offer changes nothing.
  • Effect: the CASE_MANAGER records the Accept in the ledger as accept_case_participant_role, grants the role on its own copy of the case, and announces the entry to every participant, each of which grants the role when it replays the entry (CM-33-006, CM-02-016).
  • Triggering transition: none — roster action.
  • Example artifact: accept_case_participant_role.json.

Reject case participant role

Declines the offered role. The roster does not change.

  • When… a participant declines a role offered to it on the case
  • Send: Reject(Offer(CaseParticipantRole)[context=VulnerabilityCase])
  • Send to: the case manager
  • Sent by: the addressee of the case participant role offer
  • Seen in: How to Delegate a Role to Another Participant
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Reject",
  "id": "urn:uuid:d8aecbfa-f316-456f-91da-59138be79598",
  "name": "https://vultron.example/organizations/coordinator Reject https://vultron.example/case-actors/vendorco-case-actor Offer urn:uuid:fef74e31-1edb-4283-8a9e-6c2fa2ddc443 to Coordinator LLC",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "content": "We're declining the role you offered.",
  "to": [
    "https://vultron.example/case-actors/vendorco-case-actor"
  ],
  "actor": "https://vultron.example/organizations/coordinator",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Offer",
    "id": "urn:uuid:7445830a-a326-431d-98fe-eb545db63577",
    "name": "https://vultron.example/case-actors/vendorco-case-actor Offer urn:uuid:fef74e31-1edb-4283-8a9e-6c2fa2ddc443 to Coordinator LLC",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "inReplyTo": "urn:uuid:0fb097be-85c0-469a-b31e-0ad41107da04",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "content": "We're offering the coordinator role on case VendorCo Case #70930046 to Coordinator LLC.",
    "to": [
      "https://vultron.example/organizations/coordinator"
    ],
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "actor": "https://vultron.example/case-actors/vendorco-case-actor",
    "target": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Organization",
      "id": "https://vultron.example/organizations/coordinator",
      "name": "Coordinator LLC",
      "published": "2026-10-23T20:17:06+00:00",
      "updated": "2026-10-23T20:17:06+00:00",
      "inbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/inbox",
        "items": []
      },
      "outbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/outbox",
        "items": []
      }
    },
    "object": {
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld",
      "type": "CaseParticipantRole",
      "id": "urn:uuid:fef74e31-1edb-4283-8a9e-6c2fa2ddc443",
      "published": "2026-10-23T20:17:36+00:00",
      "updated": "2026-10-23T20:17:36+00:00",
      "role": "coordinator"
    }
  }
}
  • Routing: as for the Accept, the Reject goes to the CASE_MANAGER only, and names the forward it answers (CM-33-004).
  • Who may send: as for the Accept, the target of the recorded offer only, while that offer is open (CM-33-005). The CASE_MANAGER answers a refused Reject as it does a refused Accept.
  • Effect: the CASE_MANAGER records the Reject in the ledger as reject_case_participant_role and announces the entry to every participant (CM-33-006). The entry closes the offer; no role changes.
  • Triggering transition: none — roster action.
  • Example artifact: reject_case_participant_role.json.

The dedicated object type is preferred over a target-field discriminator (SE-08-003), and the earlier wire format Offer(VulnerabilityCase, target=CaseParticipant) for offering a role has been removed.

Propose case ownership transfer

Asks the Case Manager to offer the case to another actor, for example from a Reporter to a Coordinator. The inner Offer names the case, the new owner as its target and, optionally, an endTime after which the Case Manager refuses an answer: the offer is then closed, with nothing recorded or sent. The Case Manager makes the offer itself.

  • When… the Case Owner proposes to transfer ownership of the case to another actor
  • Send: Offer(Offer(VulnerabilityCase))
  • Send to: the case manager
  • Sent by: the case owner
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Offer",
  "id": "urn:uuid:f66cb8a8-5c85-4afc-b1e3-0198baeebeaf",
  "name": "https://vultron.example/organizations/vendorco Offer https://vultron.example/organizations/vendorco Offer VendorCo Case #70930046 to https://vultron.example/organizations/coordinator",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "content": "Please offer ownership of case VendorCo Case #70930046 to the coordinator.",
  "to": [
    "https://vultron.example/case-actors/vendorco-case-actor"
  ],
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Offer",
    "id": "urn:uuid:67cb34f2-c212-419d-a48b-8c6767488ece",
    "name": "https://vultron.example/organizations/vendorco Offer VendorCo Case #70930046 to https://vultron.example/organizations/coordinator",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "actor": "https://vultron.example/organizations/vendorco",
    "target": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Actor",
      "id": "https://vultron.example/organizations/coordinator",
      "published": "2026-10-23T20:17:36+00:00",
      "updated": "2026-10-23T20:17:36+00:00",
      "inbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/inbox",
        "items": []
      },
      "outbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/outbox",
        "items": []
      }
    },
    "object": {
      "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
      "type": "VulnerabilityCase",
      "name": "VendorCo Case #70930046",
      "published": "2026-10-23T20:17:06+00:00",
      "updated": "2026-10-23T20:17:06+00:00",
      "attributedTo": "https://vultron.example/organizations/vendorco",
      "caseParticipants": [],
      "actorParticipantIndex": {},
      "vulnerabilityReports": [],
      "caseStatuses": [
        {
          "id": "urn:uuid:b1433c7d-659a-48f4-bd42-4fe704585f61",
          "type": "CaseStatus",
          "name": "NONE pxa",
          "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
          "published": "2026-10-23T20:17:06+00:00",
          "updated": "2026-10-23T20:17:06+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": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37",
      "ledgerPosition": {
        "logIndex": -1,
        "entryHash": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37"
      },
      "parentCases": [],
      "childCases": [],
      "siblingCases": [],
      "activeParticipants": [],
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
    }
  }
}
  • Routing: the proposal is addressed to the CASE_MANAGER, never to the proposed new owner (CM-21-005); see Case Ownership Transfer. The CASE_MANAGER admits it only from the Case Owner, and only while no offer for the case is open (CM-21-019, CM-21-014). It refuses a proposal whose inner offer names another case, or no actor it can address, and ignores any id, actor or to inside the inner offer.
  • Context: the case the proposal is about; the inner offer's object must be that case.
  • Trigger: the Case Owner sends it with POST /actors/{actor_id}/trigger/offer-case-ownership-transfer, which returns the proposal (TRIG-11-001, Trigger API Reference).
  • Effect: the CASE_MANAGER records the proposal in the ledger and makes the offer below itself (ADR-0148).
  • Triggering transition: none — ownership transfer is a roster operation.
  • Example artifact: propose_case_ownership_transfer.json.

Offer case ownership transfer

Offers the case to the actor named by the target, on the Case Owner's behalf: attributedTo names the owner. This is the one offer of the transfer, the one the new owner accepts or rejects. It carries the proposal's endTime, if any.

  • When… the Case Manager offers the case to the actor the Case Owner proposed
  • Send: Offer(VulnerabilityCase)
  • Send to: a participant
  • Sent by: the case manager
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Offer",
  "id": "urn:uuid:0389b310-b3b3-494c-ad71-3050a8829ac2",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Offer VendorCo Case #70930046 to https://vultron.example/organizations/coordinator",
  "content": "We're offering to transfer ownership of case VendorCo Case #70930046 to you.",
  "to": [
    "https://vultron.example/organizations/coordinator"
  ],
  "attributedTo": "https://vultron.example/organizations/vendorco",
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "target": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Actor",
    "id": "https://vultron.example/organizations/coordinator",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "inbox": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "OrderedCollection",
      "id": "https://vultron.example/organizations/coordinator/inbox",
      "items": []
    },
    "outbox": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "OrderedCollection",
      "id": "https://vultron.example/organizations/coordinator/outbox",
      "items": []
    }
  },
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "type": "VulnerabilityCase",
    "name": "VendorCo Case #70930046",
    "published": "2026-10-23T20:17:06+00:00",
    "updated": "2026-10-23T20:17:06+00:00",
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "caseParticipants": [],
    "actorParticipantIndex": {},
    "vulnerabilityReports": [],
    "caseStatuses": [
      {
        "id": "urn:uuid:b1433c7d-659a-48f4-bd42-4fe704585f61",
        "type": "CaseStatus",
        "name": "NONE pxa",
        "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "published": "2026-10-23T20:17:06+00:00",
        "updated": "2026-10-23T20:17:06+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": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37",
    "ledgerPosition": {
      "logIndex": -1,
      "entryHash": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37"
    },
    "parentCases": [],
    "childCases": [],
    "siblingCases": [],
    "activeParticipants": [],
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Routing: the CASE_MANAGER makes the offer from the owner's proposal and records it in the ledger (§11.3 Case Ownership Transfer, CM-21-005). It is the one offer of the transfer: its id is one the CASE_MANAGER derives from the proposal, and the proposed new owner answers it by that id. A participant takes it only from the CASE_MANAGER (CM-21-019).
  • Target: the proposed new owner, as a full actor object.
  • Triggering transition: none — ownership transfer is a roster operation.
  • Example artifact: offer_case_ownership_transfer.json.

Accept case ownership transfer

Accepts the ownership transfer offer.

  • When… an actor accepts an offer of case ownership
  • Send: Accept(Offer(VulnerabilityCase))
  • Send to: the case manager
  • Sent by: the addressee of the vulnerability case offer
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Accept",
  "id": "urn:uuid:046aa90b-2ec8-41e5-a8fc-21d524ed69bc",
  "name": "https://vultron.example/organizations/coordinator Accept https://vultron.example/case-actors/vendorco-case-actor Offer VendorCo Case #70930046 to https://vultron.example/organizations/coordinator",
  "content": "We're accepting your offer to transfer ownership of case VendorCo Case #70930046 to us.",
  "actor": "https://vultron.example/organizations/coordinator",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Offer",
    "id": "urn:uuid:1a57d5e4-ec59-44c5-b790-9bfd648fe609",
    "name": "https://vultron.example/case-actors/vendorco-case-actor Offer VendorCo Case #70930046 to https://vultron.example/organizations/coordinator",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "content": "We're offering to transfer ownership of case VendorCo Case #70930046 to you.",
    "to": [
      "https://vultron.example/organizations/coordinator"
    ],
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "actor": "https://vultron.example/case-actors/vendorco-case-actor",
    "target": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Actor",
      "id": "https://vultron.example/organizations/coordinator",
      "published": "2026-10-23T20:17:36+00:00",
      "updated": "2026-10-23T20:17:36+00:00",
      "inbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/inbox",
        "items": []
      },
      "outbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/outbox",
        "items": []
      }
    },
    "object": {
      "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
      "type": "VulnerabilityCase",
      "name": "VendorCo Case #70930046",
      "published": "2026-10-23T20:17:06+00:00",
      "updated": "2026-10-23T20:17:06+00:00",
      "attributedTo": "https://vultron.example/organizations/vendorco",
      "caseParticipants": [],
      "actorParticipantIndex": {},
      "vulnerabilityReports": [],
      "caseStatuses": [
        {
          "id": "urn:uuid:b1433c7d-659a-48f4-bd42-4fe704585f61",
          "type": "CaseStatus",
          "name": "NONE pxa",
          "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
          "published": "2026-10-23T20:17:06+00:00",
          "updated": "2026-10-23T20:17:06+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": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37",
      "ledgerPosition": {
        "logIndex": -1,
        "entryHash": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37"
      },
      "parentCases": [],
      "childCases": [],
      "siblingCases": [],
      "activeParticipants": [],
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
    }
  }
}

Reject case ownership transfer

Declines the ownership transfer offer. The current Case Owner keeps the case.

  • When… an actor declines an offer of case ownership
  • Send: Reject(Offer(VulnerabilityCase))
  • Send to: the case manager
  • Sent by: the addressee of the vulnerability case offer
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Reject",
  "id": "urn:uuid:08bab7d2-6fd7-4ac6-a2d3-966ecd728380",
  "name": "https://vultron.example/organizations/coordinator Reject https://vultron.example/case-actors/vendorco-case-actor Offer VendorCo Case #70930046 to https://vultron.example/organizations/coordinator",
  "content": "We're declining your offer to transfer ownership of case VendorCo Case #70930046 to us.",
  "actor": "https://vultron.example/organizations/coordinator",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Offer",
    "id": "urn:uuid:05998af0-997e-4520-ad6a-fb4f24a16ca0",
    "name": "https://vultron.example/case-actors/vendorco-case-actor Offer VendorCo Case #70930046 to https://vultron.example/organizations/coordinator",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "content": "We're offering to transfer ownership of case VendorCo Case #70930046 to you.",
    "to": [
      "https://vultron.example/organizations/coordinator"
    ],
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "actor": "https://vultron.example/case-actors/vendorco-case-actor",
    "target": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Actor",
      "id": "https://vultron.example/organizations/coordinator",
      "published": "2026-10-23T20:17:36+00:00",
      "updated": "2026-10-23T20:17:36+00:00",
      "inbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/inbox",
        "items": []
      },
      "outbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/outbox",
        "items": []
      }
    },
    "object": {
      "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
      "type": "VulnerabilityCase",
      "name": "VendorCo Case #70930046",
      "published": "2026-10-23T20:17:06+00:00",
      "updated": "2026-10-23T20:17:06+00:00",
      "attributedTo": "https://vultron.example/organizations/vendorco",
      "caseParticipants": [],
      "actorParticipantIndex": {},
      "vulnerabilityReports": [],
      "caseStatuses": [
        {
          "id": "urn:uuid:b1433c7d-659a-48f4-bd42-4fe704585f61",
          "type": "CaseStatus",
          "name": "NONE pxa",
          "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
          "published": "2026-10-23T20:17:06+00:00",
          "updated": "2026-10-23T20:17:06+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": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37",
      "ledgerPosition": {
        "logIndex": -1,
        "entryHash": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37"
      },
      "parentCases": [],
      "childCases": [],
      "siblingCases": [],
      "activeParticipants": [],
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
    }
  }
}
  • Routing: the Reject is addressed to the CASE_MANAGER, not to the actor that made the offer (CM-21-010). The CASE_MANAGER acts on it only when it comes from the proposed owner of an open offer it recorded (CM-21-013). It records the Reject in the ledger and sends the entry to every participant, which closes the offer (CM-21-012).
  • Trigger: the recipient sends it with POST /actors/{actor_id}/trigger/reject-case-ownership-transfer, whose body names the offer_id it declines (TRIG-11-005, Trigger API Reference).
  • Triggering transition: none — roster operation.
  • Example artifact: reject_case_ownership_transfer.json.

Withdraw case ownership transfer

Withdraws the proposal, and with it the Case Manager's offer, before the offer is answered. The current Case Owner keeps the case.

  • When… the Case Owner withdraws its proposal while the offer of case ownership is open
  • Send: Undo(Offer(Offer(VulnerabilityCase)))
  • Send to: the case manager
  • Sent by: the case owner
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Undo",
  "id": "urn:uuid:951fcaab-f5c3-4be8-9e37-daa4d6fef5bd",
  "name": "https://vultron.example/organizations/vendorco Undo https://vultron.example/organizations/vendorco Offer https://vultron.example/organizations/vendorco Offer VendorCo Case #70930046 to https://vultron.example/organizations/coordinator",
  "content": "We're withdrawing our proposal to transfer ownership of case VendorCo Case #70930046.",
  "to": [
    "https://vultron.example/case-actors/vendorco-case-actor"
  ],
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Offer",
    "id": "urn:uuid:520ff546-e021-49bc-90bd-285224f1f7d3",
    "name": "https://vultron.example/organizations/vendorco Offer https://vultron.example/organizations/vendorco Offer VendorCo Case #70930046 to https://vultron.example/organizations/coordinator",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "content": "Please offer ownership of case VendorCo Case #70930046 to the coordinator.",
    "to": [
      "https://vultron.example/case-actors/vendorco-case-actor"
    ],
    "actor": "https://vultron.example/organizations/vendorco",
    "object": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Offer",
      "id": "urn:uuid:6a63cd48-5d96-41c6-9c8b-be70f64188a3",
      "name": "https://vultron.example/organizations/vendorco Offer VendorCo Case #70930046 to https://vultron.example/organizations/coordinator",
      "published": "2026-10-23T20:17:36+00:00",
      "updated": "2026-10-23T20:17:36+00:00",
      "actor": "https://vultron.example/organizations/vendorco",
      "target": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "Actor",
        "id": "https://vultron.example/organizations/coordinator",
        "published": "2026-10-23T20:17:36+00:00",
        "updated": "2026-10-23T20:17:36+00:00",
        "inbox": {
          "@context": "https://www.w3.org/ns/activitystreams",
          "type": "OrderedCollection",
          "id": "https://vultron.example/organizations/coordinator/inbox",
          "items": []
        },
        "outbox": {
          "@context": "https://www.w3.org/ns/activitystreams",
          "type": "OrderedCollection",
          "id": "https://vultron.example/organizations/coordinator/outbox",
          "items": []
        }
      },
      "object": {
        "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "type": "VulnerabilityCase",
        "name": "VendorCo Case #70930046",
        "published": "2026-10-23T20:17:06+00:00",
        "updated": "2026-10-23T20:17:06+00:00",
        "attributedTo": "https://vultron.example/organizations/vendorco",
        "caseParticipants": [],
        "actorParticipantIndex": {},
        "vulnerabilityReports": [],
        "caseStatuses": [
          {
            "id": "urn:uuid:b1433c7d-659a-48f4-bd42-4fe704585f61",
            "type": "CaseStatus",
            "name": "NONE pxa",
            "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
            "published": "2026-10-23T20:17:06+00:00",
            "updated": "2026-10-23T20:17:06+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": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37",
        "ledgerPosition": {
          "logIndex": -1,
          "entryHash": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37"
        },
        "parentCases": [],
        "childCases": [],
        "siblingCases": [],
        "activeParticipants": [],
        "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
      }
    }
  }
}
  • Routing: the withdrawal is addressed to the CASE_MANAGER (CM-21-015). It is an Undo of the owner's own proposal: the CASE_MANAGER withdraws the offer it made from that proposal, and acts only when the withdrawal comes from the Case Owner that offer was made for, while the offer is open. It records the withdrawal in the ledger and sends the entry to every participant, which closes the offer: the proposed owner can no longer accept it, and the case may be offered again (CM-21-014). A withdrawal from anyone else, or of an offer already answered or withdrawn, is refused with nothing recorded. The CASE_MANAGER answers a withdrawal of an offer already answered or withdrawn with the refusal notice, and a withdrawal from anyone else with nothing.
  • Trigger: the Case Owner sends it with POST /actors/{actor_id}/trigger/withdraw-case-ownership-transfer, whose body names, as offer_id, the proposal it withdraws (TRIG-11-006, Trigger API Reference).
  • Triggering transition: none — roster operation.
  • Example artifact: undo_case_ownership_transfer.json.

Invite actor to case

Sends a Stub Invite carrying the case stub and the embargo terms the invitee would agree to.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Invite",
  "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/invitation/1",
  "name": "https://vultron.example/organizations/vendorco Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/stub",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "content": "We're inviting you to participate in VendorCo Case #70930046.",
  "to": "https://vultron.example/organizations/coordinator",
  "actor": "https://vultron.example/organizations/vendorco",
  "target": {
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld",
    "type": "VulnerabilityCaseStub",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/stub",
    "summary": "A memory-corruption vulnerability in widget — details shared after acceptance.",
    "caseId": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0"
  },
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Organization",
    "id": "https://vultron.example/organizations/coordinator",
    "name": "Coordinator LLC",
    "published": "2026-10-23T20:17:06+00:00",
    "updated": "2026-10-23T20:17:06+00:00",
    "inbox": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "OrderedCollection",
      "id": "https://vultron.example/organizations/coordinator/inbox",
      "items": []
    },
    "outbox": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "OrderedCollection",
      "id": "https://vultron.example/organizations/coordinator/outbox",
      "items": []
    }
  }
}
  • Who decides: the Case Owner decides whom to invite; a participant that wants a third party brought in sends a recommendation instead (Suggest actor to case). See §11.2 Invitation and Acceptance.
  • Triggering transition: none — roster action.
  • Object and target: the object is the actor being invited, and the target is the case stub, of type VulnerabilityCaseStub. The stub carries the case identifier in its caseId and a required summary field: the owner-chosen description the invitee reads before deciding whether to accept (CM-11-013, CM-17-010, MV-10-001). The factory raises VultronActivityConstructionError when VulnerabilityCase.stub_summary is not set, and the receiver refuses a stub with an absent or blank summary. The Invite names at least one CVD role for the invitee, and the CASE_MANAGER refuses to send one with an empty role list (CM-11-019). The Invite carries its reply deadline in endTime, which the CASE_MANAGER sets the way it sets an embargo Invite's deadline: the Invite's published time plus the configured RSVP window, capped at the end of the active embargo (CM-11-014, CM-28-012). When the deadline passes, the Invite closes and the invitee's record does not change. A reply after the deadline is still processed: an Accept joins the invitee and a Reject closes the record. The CASE_MANAGER can re-invite an actor with a fresh stub Invite on the same record and a new deadline, and the fresh Invite's inReplyTo names the earlier one (CM-11-015). A re-invite of a participant that has closed is refused. When the active embargo is activated, revised or terminated while a stub Invite is outstanding, the CASE_MANAGER sends a replacement with the current terms and a new deadline. The replacement names the Invite it supersedes in the standard AS2 inReplyTo property. The replacement is also an invitation to the embargo now in force: the CASE_MANAGER marks the invitee's consent row for that embargo INVITED with the replacement's deadline, and records the row as its own ledger entry after the replacement's. With no embargo in force, no consent row changes. An Accept of the superseded Invite is refused, naming the replacement, and a Reject of it is honored (CM-11-016).
  • Ask kind: the Invite closes on Accept or Reject of it (INVITE_ACTOR_TO_CASE_REPLY_TYPES), and its expiry is stale: a late reply is still processed (ASK-03-008).
  • Example artifact: invite_to_case.json.

Accept invite to case

Accepts the Stub Invite. The actor joins the case at RM Received.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Accept",
  "id": "urn:uuid:0c11531b-131a-4cb2-ba36-cf1cd021a822",
  "name": "https://vultron.example/organizations/coordinator Accept https://vultron.example/organizations/vendorco Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/stub",
  "inReplyTo": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/invitation/1",
  "content": "We're accepting your invitation to participate in VendorCo Case #70930046.",
  "to": "https://vultron.example/organizations/vendorco",
  "actor": "https://vultron.example/organizations/coordinator",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Invite",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/invitation/1",
    "name": "https://vultron.example/organizations/vendorco Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/stub",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We're inviting you to participate in VendorCo Case #70930046.",
    "to": "https://vultron.example/organizations/coordinator",
    "actor": "https://vultron.example/organizations/vendorco",
    "target": {
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld",
      "type": "VulnerabilityCaseStub",
      "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/stub",
      "summary": "A memory-corruption vulnerability in widget — details shared after acceptance.",
      "caseId": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0"
    },
    "object": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Organization",
      "id": "https://vultron.example/organizations/coordinator",
      "name": "Coordinator LLC",
      "published": "2026-10-23T20:17:06+00:00",
      "updated": "2026-10-23T20:17:06+00:00",
      "inbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/inbox",
        "items": []
      },
      "outbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/outbox",
        "items": []
      }
    }
  }
}
  • Effects: the CASE_MANAGER records the acceptance in the ledger, marks the participant's existing record joined, and then sends Announce(VulnerabilityCase) to seed the new participant's replica (CM-17-004). An Accept from an invitee with no participant record is refused with a reported reason and writes nothing, because an Accept never creates a participant (CM-11-021). The Accept is the ledger entry for its own effects (the consent row and joined), which a replica applies; the record's creation and a vendor's VF status have their own entries; the CASE_MANAGER sends no Add(CaseParticipant) for it (CM-31-012).
  • What it does not do: it joins the case and consents to the active embargo; it does not judge the case. The participant judges the case by answering the Full-Case Invite that follows.
  • Example artifact: accept_invite_to_case.json.

Reject invite to case

Rejects the Stub Invite, which closes the invitee's participant record.

  • When… an invited actor declines to join the case
  • Send: Reject(Invite(Actor)[target=VulnerabilityCaseStub])
  • Send to: the case manager
  • Sent by: the invitee
  • Seen in: How to Invite an Actor to a Case
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Reject",
  "id": "urn:uuid:0386a685-1647-41b5-ba97-c2d9988b48cc",
  "name": "https://vultron.example/organizations/coordinator Reject https://vultron.example/organizations/vendorco Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/stub",
  "inReplyTo": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/invitation/1",
  "content": "Thanks for the invitation, but we're declining to participate in VendorCo Case #70930046.",
  "to": "https://vultron.example/organizations/vendorco",
  "actor": "https://vultron.example/organizations/coordinator",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Invite",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/invitation/1",
    "name": "https://vultron.example/organizations/vendorco Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/stub",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We're inviting you to participate in VendorCo Case #70930046.",
    "to": "https://vultron.example/organizations/coordinator",
    "actor": "https://vultron.example/organizations/vendorco",
    "target": {
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld",
      "type": "VulnerabilityCaseStub",
      "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/stub",
      "summary": "A memory-corruption vulnerability in widget — details shared after acceptance.",
      "caseId": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0"
    },
    "object": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Organization",
      "id": "https://vultron.example/organizations/coordinator",
      "name": "Coordinator LLC",
      "published": "2026-10-23T20:17:06+00:00",
      "updated": "2026-10-23T20:17:06+00:00",
      "inbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/inbox",
        "items": []
      },
      "outbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/outbox",
        "items": []
      }
    }
  }
}
  • Effects: the CASE_MANAGER moves the invitee's record to RM Closed and keeps it, and the participant stays inert (CM-11-007). A Reject from an invitee that has no participant record is refused with a reported reason, not ignored (CM-11-018).
  • Triggering transition: none — roster action.
  • Example artifact: reject_invite_to_case.json.

Send Full-Case Invite

Sends the Full-Case Invite, which asks the Participant to judge the case. It carries the Case Manager's ledger position as the floor the reply must reach.

  • When… the Case Manager has replayed the case ledger to a newly joined Participant
  • Send: Invite(Actor)[target=VulnerabilityCase]
  • Send to: a participant
  • Sent by: the case manager
  • Seen in: How to Manage a Case Roster
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Invite",
  "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/full-case-invitation/1",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "content": "{\"logIndex\":4,\"entryHash\":\"b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5\"}",
  "to": "https://vultron.example/organizations/coordinator",
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Organization",
    "id": "https://vultron.example/organizations/coordinator",
    "name": "Coordinator LLC",
    "published": "2026-10-23T20:17:06+00:00",
    "updated": "2026-10-23T20:17:06+00:00",
    "inbox": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "OrderedCollection",
      "id": "https://vultron.example/organizations/coordinator/inbox",
      "items": []
    },
    "outbox": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "OrderedCollection",
      "id": "https://vultron.example/organizations/coordinator/outbox",
      "items": []
    }
  }
}
  • Sequence: after a participant joins, the CASE_MANAGER sends Announce(VulnerabilityCase), starts the ledger replay, and then asks the participant to judge the case with the full-case Invite (CM-11-010, ADR-0121). The participant already holds the case, so the Invite names it by URI and asks one question: is this case valid?
  • Triggering transition: none — the Invite asks; the reply moves RM.
  • Object and target: the object is the participant, and the target is the plain case URI (AKM-02-003). The CASE_MANAGER's ledger position when it issued the Invite travels in the standard AS2 content field, as the JSON dump of the LedgerPosition model, for example {"logIndex":3,"entryHash":"<hash>"}. It is a floor: the participant's reply must reach at least this point in the ledger (VAM-04-011). An empty ledger is logIndex -1 with the case's genesisHash as entryHash (CLP-08-004).
  • Ask kind: the Invite closes on Accept, TentativeReject or Reject of it (INVITE_ACTOR_TO_FULL_CASE_REPLY_TYPES).

Accept Full-Case Invite

Accepts the Full-Case Invite, which records RM Valid. It carries the sender's own ledger position.

  • When… a Participant asked by a Full-Case Invite judges the case valid
  • Send: Accept(Invite(Actor)[target=VulnerabilityCase])
  • Send to: the case manager
  • Sent by: the invitee
  • Seen in: How to Manage a Case Roster
  • Formal definition: Report Valid (RV)
  • Mapping status: expansion
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Accept",
  "id": "urn:uuid:d4da2f6a-6bdb-4135-ab2b-96ac19ddbc2d",
  "name": "https://vultron.example/organizations/coordinator Accept https://vultron.example/case-actors/vendorco-case-actor Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "inReplyTo": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/full-case-invitation/1",
  "content": "{\"logIndex\":4,\"entryHash\":\"b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5\"}",
  "to": "https://vultron.example/case-actors/vendorco-case-actor",
  "actor": "https://vultron.example/organizations/coordinator",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Invite",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/full-case-invitation/1",
    "name": "https://vultron.example/case-actors/vendorco-case-actor Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "content": "{\"logIndex\":4,\"entryHash\":\"b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5\"}",
    "to": "https://vultron.example/organizations/coordinator",
    "actor": "https://vultron.example/case-actors/vendorco-case-actor",
    "target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "object": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Organization",
      "id": "https://vultron.example/organizations/coordinator",
      "name": "Coordinator LLC",
      "published": "2026-10-23T20:17:06+00:00",
      "updated": "2026-10-23T20:17:06+00:00",
      "inbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/inbox",
        "items": []
      },
      "outbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/outbox",
        "items": []
      }
    }
  }
}
  • Effects: the participant judges the case valid (Validate report), and the CASE_MANAGER records RM Received → Valid (CM-11-011).
  • Ledger position: the reply carries the participant's own ledger position in content, in the same form as the Invite (VAM-04-012). The CASE_MANAGER refuses a reply whose position is behind the Invite's, or names an entry its ledger does not hold, and writes nothing (CM-11-012). It also refuses, and writes nothing for, a reply from an inert participant that has not joined the case (CM-11-012).

Tentatively reject Full-Case Invite

Tentatively rejects the Full-Case Invite, which records RM Invalid. It carries the sender's own ledger position.

  • When… a Participant asked by a Full-Case Invite judges the case invalid
  • Send: TentativeReject(Invite(Actor)[target=VulnerabilityCase])
  • Send to: the case manager
  • Sent by: the invitee
  • Seen in: How to Manage a Case Roster
  • Formal definition: Report Invalid (RI)
  • Mapping status: expansion
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "TentativeReject",
  "id": "urn:uuid:b6b2744a-0218-4ab9-a33f-9e753d1cfb4d",
  "name": "https://vultron.example/organizations/coordinator TentativeReject https://vultron.example/case-actors/vendorco-case-actor Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "inReplyTo": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/full-case-invitation/1",
  "content": "{\"logIndex\":4,\"entryHash\":\"b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5\"}",
  "to": "https://vultron.example/case-actors/vendorco-case-actor",
  "actor": "https://vultron.example/organizations/coordinator",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Invite",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/full-case-invitation/1",
    "name": "https://vultron.example/case-actors/vendorco-case-actor Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "content": "{\"logIndex\":4,\"entryHash\":\"b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5\"}",
    "to": "https://vultron.example/organizations/coordinator",
    "actor": "https://vultron.example/case-actors/vendorco-case-actor",
    "target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "object": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Organization",
      "id": "https://vultron.example/organizations/coordinator",
      "name": "Coordinator LLC",
      "published": "2026-10-23T20:17:06+00:00",
      "updated": "2026-10-23T20:17:06+00:00",
      "inbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/inbox",
        "items": []
      },
      "outbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/outbox",
        "items": []
      }
    }
  }
}
  • Effects: the participant judges the case invalid (Invalidate report), and the CASE_MANAGER records RM Received → Invalid. The stub Invite has no TentativeReject, because accepting a stub judges nothing (CM-11-007).
  • Ledger position: the reply carries the participant's ledger position in content (VAM-04-013).

Reject Full-Case Invite

Rejects the Full-Case Invite, which records RM Closed. It carries the sender's own ledger position.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Reject",
  "id": "urn:uuid:3572e36d-10a4-4cb5-9edf-6e8219bbcd00",
  "name": "https://vultron.example/organizations/coordinator Reject https://vultron.example/case-actors/vendorco-case-actor Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "inReplyTo": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/full-case-invitation/1",
  "content": "{\"logIndex\":4,\"entryHash\":\"b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5\"}",
  "to": "https://vultron.example/case-actors/vendorco-case-actor",
  "actor": "https://vultron.example/organizations/coordinator",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Invite",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/full-case-invitation/1",
    "name": "https://vultron.example/case-actors/vendorco-case-actor Invite Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "content": "{\"logIndex\":4,\"entryHash\":\"b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5b2c3d4e5\"}",
    "to": "https://vultron.example/organizations/coordinator",
    "actor": "https://vultron.example/case-actors/vendorco-case-actor",
    "target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "object": {
      "@context": "https://www.w3.org/ns/activitystreams",
      "type": "Organization",
      "id": "https://vultron.example/organizations/coordinator",
      "name": "Coordinator LLC",
      "published": "2026-10-23T20:17:06+00:00",
      "updated": "2026-10-23T20:17:06+00:00",
      "inbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/inbox",
        "items": []
      },
      "outbox": {
        "@context": "https://www.w3.org/ns/activitystreams",
        "type": "OrderedCollection",
        "id": "https://vultron.example/organizations/coordinator/outbox",
        "items": []
      }
    }
  }
}
  • Effects: the participant closes the case (Close report), and the CASE_MANAGER records RM Received → Closed; the participant stops receiving case content.
  • Ledger position: the reply carries the participant's ledger position in content (VAM-04-014).

Announce vulnerability case

Sends the full case to the newly admitted Participant once its acceptance clears the embargo consent checks.

  • When… the Case Manager has admitted a new Participant to the case
  • Send: Announce(VulnerabilityCase)
  • Send to: a participant
  • Sent by: the case manager
  • Seen in: How to Invite an Actor to a Case
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Announce",
  "id": "urn:uuid:67cf4db9-4a9f-44b4-a3eb-8df58c509e98",
  "name": "https://vultron.example/organizations/vendorco Announce VendorCo Case #70930046",
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "type": "VulnerabilityCase",
    "name": "VendorCo Case #70930046",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "caseParticipants": [
      {
        "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/finndervul",
        "type": "CaseParticipant",
        "name": "Finn der Vul",
        "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "published": "2026-10-23T20:17:36+00:00",
        "updated": "2026-10-23T20:17:36+00:00",
        "attributedTo": "https://vultron.example/users/finndervul",
        "caseRoles": [
          "reporter"
        ],
        "participantStatuses": [
          {
            "id": "urn:uuid:3717fff4-921c-4f09-b980-539e29dbec82",
            "type": "ParticipantStatus",
            "name": "START",
            "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
            "published": "2026-10-23T20:17:36+00:00",
            "updated": "2026-10-23T20:17:36+00:00",
            "attributedTo": "https://vultron.example/users/finndervul",
            "rmState": "START",
            "caseEngagement": true,
            "cvdRole": [
              "REPORTER"
            ],
            "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
          }
        ],
        "embargoConsents": [],
        "joined": true,
        "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
      },
      {
        "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/vendorco",
        "type": "CaseParticipant",
        "name": "VendorCo",
        "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "published": "2026-10-23T20:17:36+00:00",
        "updated": "2026-10-23T20:17:36+00:00",
        "attributedTo": "https://vultron.example/organizations/vendorco",
        "caseRoles": [
          "vendor"
        ],
        "participantStatuses": [
          {
            "id": "urn:uuid:689b6114-4c3f-4f40-b1fa-413a983349c2",
            "type": "ParticipantStatus",
            "name": "RECEIVED Vf",
            "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
            "published": "2026-10-23T20:17:36+00:00",
            "updated": "2026-10-23T20:17:36+00:00",
            "attributedTo": "https://vultron.example/organizations/vendorco",
            "rmState": "RECEIVED",
            "vfState": "Vf",
            "caseEngagement": true,
            "cvdRole": [
              "OBSERVER"
            ],
            "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
          }
        ],
        "embargoConsents": [],
        "joined": true,
        "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
      }
    ],
    "actorParticipantIndex": {
      "https://vultron.example/users/finndervul": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/finndervul",
      "https://vultron.example/organizations/vendorco": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/vendorco"
    },
    "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:3d742875-fb18-4f5b-bf70-d527f00c051f",
        "type": "CaseStatus",
        "name": "NONE pxa",
        "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "published": "2026-10-23T20:17:36+00:00",
        "updated": "2026-10-23T20:17:36+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": "44022100933d18ff4496372d09554b76ea0558594eb798558c2bbedde9796b86",
    "ledgerPosition": {
      "logIndex": -1,
      "entryHash": "44022100933d18ff4496372d09554b76ea0558594eb798558c2bbedde9796b86"
    },
    "parentCases": [],
    "childCases": [],
    "siblingCases": [],
    "activeParticipants": [
      "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/finndervul",
      "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/vendorco"
    ],
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Contents: the full VulnerabilityCase object is delivered inline so the recipient can seed its local replica (PCR-02-002). The same activity delivers a full case snapshot at every later lifecycle stage (PCR-02-001).
  • Triggering transition: none — roster action following invite acceptance.
  • Example artifact: announce_case.json.

Close case

Leaves the case, moving the sender's RM state to Closed.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Leave",
  "id": "urn:uuid:855bdc98-183b-4a03-a4aa-d659c157fca0",
  "name": "https://vultron.example/organizations/vendorco Leave VendorCo Case #70930046",
  "content": "We're closing this case.",
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "type": "VulnerabilityCase",
    "name": "VendorCo Case #70930046",
    "published": "2026-10-23T20:17:06+00:00",
    "updated": "2026-10-23T20:17:06+00:00",
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "caseParticipants": [],
    "actorParticipantIndex": {},
    "vulnerabilityReports": [],
    "caseStatuses": [
      {
        "id": "urn:uuid:b1433c7d-659a-48f4-bd42-4fe704585f61",
        "type": "CaseStatus",
        "name": "NONE pxa",
        "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "published": "2026-10-23T20:17:06+00:00",
        "updated": "2026-10-23T20:17:06+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": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37",
    "ledgerPosition": {
      "logIndex": -1,
      "entryHash": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37"
    },
    "parentCases": [],
    "childCases": [],
    "siblingCases": [],
    "activeParticipants": [],
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Triggering transition: RM: A → C.
  • Decline: while the case holds an active embargo, the CASE_MANAGER declines the Case Owner's close with a Reject of the Leave and records nothing (CM-23-011). That decline is the answer to the refusal, so the CASE_MANAGER sends no refusal notice as well.
  • Example artifact: close_case.json.

Add case participant to case

Asks the Case Manager to reinstate the participant record named by the object. The Participant becomes active again and receives the ledger entries it missed.

  • When… the Case Owner reinstates a removed Participant
  • Send: Add(CaseParticipant)[target=VulnerabilityCase]
  • Send to: the case manager
  • Sent by: the case owner
  • Seen in: How to Manage a Case Roster
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Add",
  "id": "urn:uuid:f2b82742-75f7-40d7-a727-c66743942f54",
  "name": "https://vultron.example/organizations/vendorco Add Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "content": "We're reinstating the coordinator in this case.",
  "actor": "https://vultron.example/organizations/vendorco",
  "target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/coordinator",
    "type": "CaseParticipant",
    "name": "Coordinator LLC",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "attributedTo": "https://vultron.example/organizations/coordinator",
    "caseRoles": [
      "coordinator"
    ],
    "participantStatuses": [
      {
        "id": "urn:uuid:a48478c3-912d-4551-8b74-88e4727d5813",
        "type": "ParticipantStatus",
        "name": "START",
        "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "published": "2026-10-23T20:17:36+00:00",
        "updated": "2026-10-23T20:17:36+00:00",
        "attributedTo": "https://vultron.example/organizations/coordinator",
        "rmState": "START",
        "caseEngagement": true,
        "cvdRole": [
          "COORDINATOR"
        ],
        "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
      }
    ],
    "embargoConsents": [],
    "joined": true,
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Reinstatement: it clears the participant's removal fact, so it is entitled to case content again; it does not ask the participant to accept again. Add(CaseParticipant) does not seat a new member: an actor joins a case by accepting its stub Invite (see Accept Invite to Case).
  • Triggering transition: none — the participant's record loses its removal fact.
  • Who may send: The CASE_MANAGER admits it only from the Case Owner. It refuses an Add that names a participant that is not removed, a participant that never joined the case, or no participant of the case. It also refuses an Add whose participant gives an attributedTo other than the actor of the record it names, because each replica finds its own copy of the record by that actor. A participant replica accepts it only from the CASE_MANAGER, as the direct notice below, and writes nothing from it.
  • Ledger: the Case Owner's received Add is the one ledger entry for the reinstatement. Every replica applies the reinstatement from that entry, the reinstated participant's own included.
  • Catch-up: once the participant is active again, the CASE_MANAGER sends it every ledger entry committed after its removal entry, in log order, so its copy of the ledger has no gap. A participant that is not a signatory to the active embargo stays inert: the CASE_MANAGER sends it that embargo's Invite instead, and the catch-up waits until it accepts.
  • Notice: the CASE_MANAGER also sends the reinstated participant a direct Add(CaseParticipant) naming it, with actor set to the CASE_MANAGER and attributedTo set to the Case Owner. The notice is not ledgered.
  • Spec: Participant Removal.

The example above shows a Vendor that holds the Case Owner role reinstating a Coordinator. The wire shape is the same whatever roles the participant holds; only caseRoles on the attached object differs.

Remove case participant from case

Asks the Case Manager to remove the participant record named by the object. The removed Participant receives a direct notice.

  • When… the Case Owner removes a Participant from active participation
  • Send: Remove(CaseParticipant)[target=VulnerabilityCase]
  • Send to: the case manager
  • Sent by: the case owner
  • Seen in: How to Manage a Case Roster
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Remove",
  "id": "urn:uuid:e5cf9b71-8cc5-41b3-8ca6-e4a62d576ecd",
  "name": "https://vultron.example/organizations/vendorco Remove Coordinator LLC to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "summary": "Vendor is removing the coordinator from the case.",
  "actor": "https://vultron.example/organizations/vendorco",
  "target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/coordinator",
    "type": "CaseParticipant",
    "name": "Coordinator LLC",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "attributedTo": "https://vultron.example/organizations/coordinator",
    "caseRoles": [
      "coordinator"
    ],
    "participantStatuses": [
      {
        "id": "urn:uuid:0c339dac-289e-4c3f-b924-19b5a33525b5",
        "type": "ParticipantStatus",
        "name": "START",
        "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "published": "2026-10-23T20:17:36+00:00",
        "updated": "2026-10-23T20:17:36+00:00",
        "attributedTo": "https://vultron.example/organizations/coordinator",
        "rmState": "START",
        "caseEngagement": true,
        "cvdRole": [
          "COORDINATOR"
        ],
        "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
      }
    ],
    "embargoConsents": [],
    "joined": true,
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Removal: it withdraws the participant's entitlement to case content; the participant's record stays on the case roster.
  • Triggering transition: none — the participant's record gains a removal fact.
  • Target: the case MUST be named in target; a Remove that names the case only in origin is not recognized as this message.
  • Who may send: The CASE_MANAGER admits it only from the Case Owner. It refuses a removal of the CASE_MANAGER's or the Case Owner's participant, and a removal that names no participant of the case. It also refuses a removal whose participant gives an attributedTo other than the actor of the record it names, because each replica finds its own copy of the record by that actor. A participant replica accepts it only from the CASE_MANAGER, as the direct notice below, and writes nothing from it.
  • Ledger: the Case Owner's received Remove is the one ledger entry for the removal. Every replica applies the removal from that entry, the removed participant's own included.
  • Notice: the CASE_MANAGER then sends the removed participant a direct Remove(CaseParticipant) naming it, with actor set to the CASE_MANAGER and attributedTo set to the Case Owner. The notice is not ledgered.
  • Spec: Participant Removal.
  • Example artifact: remove_participant_from_case.json.

Update case owner

Carries the case with its new owner in attributedTo. The Case Manager commits it after the Accept of the transfer and after each participant record whose CASE_OWNER role moved.

  • When… the Case Manager records the new Case Owner once a case ownership transfer is accepted
  • Send: Update(VulnerabilityCase)
  • Send to: a participant
  • Sent by: not handled
  • Mapping status: none

Each participant learns of it from the case ledger, so it is addressed to nobody.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Update",
  "id": "urn:uuid:de789c98-24bd-434a-935d-894888a8cd5f",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Update VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "type": "VulnerabilityCase",
    "name": "VendorCo Case #70930046",
    "published": "2026-10-23T20:17:06+00:00",
    "updated": "2026-10-23T20:17:06+00:00",
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "caseParticipants": [],
    "actorParticipantIndex": {},
    "vulnerabilityReports": [],
    "caseStatuses": [
      {
        "id": "urn:uuid:b1433c7d-659a-48f4-bd42-4fe704585f61",
        "type": "CaseStatus",
        "name": "NONE pxa",
        "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "published": "2026-10-23T20:17:06+00:00",
        "updated": "2026-10-23T20:17:06+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": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37",
    "ledgerPosition": {
      "logIndex": -1,
      "entryHash": "3f3a0359462714e6979b2d77ae6e953e1381472e9bef61933073af26469fad37"
    },
    "parentCases": [],
    "childCases": [],
    "siblingCases": [],
    "activeParticipants": [],
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Protocol role: every change the CASE_MANAGER makes to the case file is its own ledger entry (CLP-07-013), and an Update carrying the case in full is the shape such an entry takes for a change to a case field. The prototype commits one such entry, update_case_owner, when an ownership transfer changes the case owner (CM-21-002), and replicas copy it from the ledger fan-out (§5.4.2 Routing Topology). A participant that wants a change made asks the CASE_MANAGER; it does not send Update to the CASE_MANAGER or to its peers.
  • On receipt: the activity is recognized, but no use case handles it, so an inbox reports "no use case found" and changes nothing.
  • Triggering transition: none — metadata change, not a state transition.

Create case participant

Carries the new participant record in full: its roles, statuses, joined mark and consent rows.

  • When… the Case Manager creates a participant record, such as the inert record for the invitee of a stub Invite
  • Send: Create(CaseParticipant)
  • Send to: a participant
  • Sent by: not handled
  • Mapping status: none

Each participant learns of it from the case ledger, so it is addressed to nobody.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Create",
  "id": "urn:uuid:f96a849d-a824-4111-9237-b2c4d833aa5c",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Create as_CaseParticipant urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/https://vultron.example/organizations/coordinator from https://vultron.example/organizations/coordinator in urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/https://vultron.example/organizations/coordinator",
    "type": "CaseParticipant",
    "name": "Coordinator LLC",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "attributedTo": "https://vultron.example/organizations/coordinator",
    "caseRoles": [
      "coordinator"
    ],
    "participantStatuses": [
      {
        "id": "urn:uuid:95cf3e5d-67af-4bb4-8b86-ffd91d348976",
        "type": "ParticipantStatus",
        "name": "START",
        "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "published": "2026-10-23T20:17:36+00:00",
        "updated": "2026-10-23T20:17:36+00:00",
        "attributedTo": "https://vultron.example/organizations/coordinator",
        "rmState": "START",
        "caseEngagement": true,
        "cvdRole": [
          "COORDINATOR"
        ],
        "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
      }
    ],
    "embargoConsents": [],
    "joined": true,
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Protocol role: a participant record comes into existence only as the CASE_MANAGER's consequence of an act it records (ADR-0137, VAM-01-011). The CASE_MANAGER creates the invitee's participant record when it sends a stub Invite, and commits that creation as its own entry, carrying the record in full (CLP-07-013). Replicas copy the record from the ledger fan-out (§5.4.2 Routing Topology). An actor joins a case by accepting its stub Invite (see Accept Invite to Case).
  • On receipt: the activity is recognized, but no use case handles it, so an inbox reports "no use case found" and changes nothing (VAM-01-010).
  • Triggering transition: none — object construction.

Update case participant

Carries the changed participant record in full, as the Case Manager stored it.

  • When… the Case Manager changes a participant record, such as moving the CASE_OWNER role on an ownership transfer
  • Send: Update(CaseParticipant)
  • Send to: a participant
  • Sent by: not handled
  • Mapping status: none

Each participant learns of it from the case ledger, so it is addressed to nobody.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Update",
  "id": "urn:uuid:9868eec3-4a8a-418d-92ea-d0bf76eb4089",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Update Coordinator LLC",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants/https://vultron.example/organizations/coordinator",
    "type": "CaseParticipant",
    "name": "Coordinator LLC",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:36+00:00",
    "updated": "2026-10-23T20:17:36+00:00",
    "attributedTo": "https://vultron.example/organizations/coordinator",
    "caseRoles": [
      "coordinator",
      "case_owner"
    ],
    "participantStatuses": [
      {
        "id": "urn:uuid:f0fef5e4-1ce4-41d9-a6f6-826e9d09569f",
        "type": "ParticipantStatus",
        "name": "START",
        "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
        "published": "2026-10-23T20:17:36+00:00",
        "updated": "2026-10-23T20:17:36+00:00",
        "attributedTo": "https://vultron.example/organizations/coordinator",
        "rmState": "START",
        "caseEngagement": true,
        "cvdRole": [
          "COORDINATOR"
        ],
        "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
      }
    ],
    "embargoConsents": [],
    "joined": true,
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Protocol role: the CASE_MANAGER commits each participant record it changes as its own entry, after the act that caused the change (CLP-07-013). An ownership transfer moves the CASE_OWNER role this way, one entry for each record that changed (CM-21-002). Replicas store the record as the CASE_MANAGER stored it.
  • On receipt: the activity is recognized, but no use case handles it, so an inbox reports "no use case found" and changes nothing.
  • Triggering transition: none — the record changes as the act's consequence.