How to Post a Status Update or a Case Note
Use this guide to tell the other participants something: that your fix is ready, that the vulnerability is now public, or anything that needs narrative rather than a state change.
A status update is one as:Add(ParticipantStatus) that carries your new status inline and attaches it to your own participant record.
A note is sent the same way: one as:Add that carries the note inline.
You finish with the update committed to the case ledger and replicated to every participant.
Prerequisites
- A running Vultron instance you can drive. The demo containers are the quickest route — see Tutorial: Run the Receive-Report Demo for the two steps that get you a container shell.
- An actor identity on that instance, holding the role each step names.
- Working knowledge of the ActivityStreams verb, object, and target shape, summarized in Vultron and ActivityPub.
-
Working knowledge of the case model: the objects a case is made of, in The Case Model, and who is allowed to change them, in The CASE_MANAGER and the Case Ledger. Where a guide's messages are case-scoped, they route through the CASE_MANAGER and their results appear on the case ledger.
-
A case you are seated on, and your own
CaseParticipantrecord. - For a participant status, the dimension you are reporting:
vfStateanddStateapply only to a Vendor or a Deployer. The letters in these fields are the substates of the CVD Case State Model.
Report your own progress
Use a participant status for anything that is true of you rather than of the case.
Vendor Awareness (CV), Fix Readiness (CF) and Fix Deployed (CD) are all implemented in ActivityStreams as Add(ParticipantStatus).
Which one you are sending is determined by the field you set, not by a different activity.
In every case, send Add(ParticipantStatus) targeting your own participant record, with the new status inline as its object.
Set the status's context to the case your participant record belongs to: the CASE_MANAGER acts on the case of the participant record you target, and refuses a status whose context names another case (HP-08-008).
The protocol names Add(ParticipantStatus) as the one form; a received Create(ParticipantStatus) is not a protocol message (VAM-01-011), and this implementation's inbox refuses it as an unrecognized activity (VAM-01-010).
Report that a vendor now knows
Set vfState from vf to Vf.
That is Vendor Awareness (CV).
Vendor Awareness (CV)
Announces that the report has reached the Vendor whose participant record is the target.
- When… a Vendor becomes aware of the vulnerability
- Send:
Add(ParticipantStatus)[target=CaseParticipant] - Send to: the case manager
- Sent by: the case manager or the case owner or the participant status's author (usually: vendor)
- Distinguished by:
vfState=Vf - Reference: Vendor Awareness (CV)
Example activity
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Add",
"id": "urn:uuid:1b17de31-54f6-44e8-ad1f-1f44d8c38e81",
"name": "https://vultron.example/organizations/vendor Add ACCEPTED Vf NONE pxa to https://vultron.example/cases/1/participants/vendor",
"actor": "https://vultron.example/organizations/vendor",
"target": "https://vultron.example/cases/1/participants/vendor",
"object": {
"id": "https://vultron.example/cases/1/participants/vendor/status/2",
"type": "ParticipantStatus",
"name": "ACCEPTED Vf NONE pxa",
"context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"attributedTo": "https://vultron.example/organizations/vendor",
"rmState": "ACCEPTED",
"vfState": "Vf",
"caseEngagement": true,
"cvdRole": [
"VENDOR"
],
"caseStatus": {
"id": "https://vultron.example/cases/1/status/1",
"type": "CaseStatus",
"name": "NONE pxa",
"context": "https://vultron.example/cases/1",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"emState": "NONE",
"pxaState": "pxa",
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
},
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
}
}
Report that a fix is ready
Set vfState from Vf to VF.
That is Fix Readiness (CF).
Fix Readiness (CF)
Announces that the Vendor whose participant record is the target has a fix ready.
- When… a Vendor has a fix ready
- Send:
Add(ParticipantStatus)[target=CaseParticipant] - Send to: the case manager
- Sent by: the case manager or the case owner or the participant status's author (usually: vendor)
- Distinguished by:
vfState=VF - Reference: Fix Readiness (CF)
Example activity
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Add",
"id": "urn:uuid:91d0f03f-54f3-455b-b5d0-2ab4671b250c",
"name": "https://vultron.example/organizations/vendor Add ACCEPTED VF NONE pxa to https://vultron.example/cases/1/participants/vendor",
"actor": "https://vultron.example/organizations/vendor",
"target": "https://vultron.example/cases/1/participants/vendor",
"object": {
"id": "https://vultron.example/cases/1/participants/vendor/status/3",
"type": "ParticipantStatus",
"name": "ACCEPTED VF NONE pxa",
"context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"attributedTo": "https://vultron.example/organizations/vendor",
"rmState": "ACCEPTED",
"vfState": "VF",
"caseEngagement": true,
"cvdRole": [
"VENDOR"
],
"caseStatus": {
"id": "https://vultron.example/cases/1/status/1",
"type": "CaseStatus",
"name": "NONE pxa",
"context": "https://vultron.example/cases/1",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"emState": "NONE",
"pxaState": "pxa",
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
},
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
}
}
Report that a fix is deployed
Set dState from d to D.
That is Fix Deployed (CD).
Fix Deployed (CD)
Announces that the Deployer whose participant record is the target has deployed the fix.
- When… a Deployer has deployed the fix
- Send:
Add(ParticipantStatus)[target=CaseParticipant] - Send to: the case manager
- Sent by: the case manager or the case owner or the participant status's author (usually: deployer)
- Distinguished by:
dState=D - Reference: Fix Deployed (CD)
Example activity
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Add",
"id": "urn:uuid:9b26208a-dc37-4e6a-a16b-045f563e0387",
"name": "https://vultron.example/organizations/deployer Add ACCEPTED D NONE pxa to https://vultron.example/cases/1/participants/deployer",
"actor": "https://vultron.example/organizations/deployer",
"target": "https://vultron.example/cases/1/participants/deployer",
"object": {
"id": "https://vultron.example/cases/1/participants/deployer/status/4",
"type": "ParticipantStatus",
"name": "ACCEPTED D NONE pxa",
"context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"attributedTo": "https://vultron.example/organizations/deployer",
"rmState": "ACCEPTED",
"dState": "D",
"caseEngagement": true,
"cvdRole": [
"DEPLOYER"
],
"caseStatus": {
"id": "https://vultron.example/cases/1/status/1",
"type": "CaseStatus",
"name": "NONE pxa",
"context": "https://vultron.example/cases/1",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"emState": "NONE",
"pxaState": "pxa",
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
},
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
}
}
Send only your own status.
Participant status is self-declaratory, so a participant asserting another participant's state is a protocol violation outside the narrow externally-evidenced exceptions (PRM-06-001, ADR-0121).
The CASE_MANAGER refuses an Add(ParticipantStatus) that targets another participant's record, whatever it carries, and commits nothing (RSH-08-007).
The only exceptions are the on-behalf assertions: a CASE_MANAGER or Case Owner may move a vendor from vf to Vf, or a deployer from d to D, if the status changes nothing else (PRM-06-003, PRM-06-004).
A sender other than the record's participant, the CASE_MANAGER or the Case Owner is refused with no answer (HP-01-006).
A CASE_MANAGER or Case Owner whose on-behalf status asserts more than that gets a Reject naming why (CLP-05-001).
Report something true of the case
Public awareness, exploit publication, and observed attacks are properties of the vulnerability rather than of any one participant. You report your own view of them in your participant status.
Public Awareness (CP), Exploit Public (CX) and Attacks Observed (CA) all set pxaState in the case status that your participant status embeds.
Which one you are sending is determined by which letter in it changes case.
Send Add(ParticipantStatus) targeting your own participant record, with the new status inline as its object, and make the change to pxaState in its embedded case status.
Only the CASE_MANAGER sends Add(CaseStatus), inside a case ledger entry, as its record of the case status it adopted (RSH-04-001).
A receiver refuses an Add(CaseStatus) from any other sender (RSH-04-005).
Report that the vulnerability is public
Change p to P in pxaState.
That is Public Awareness (CP).
Public awareness in a participant status
Announces, in the sender's own participant status, evidence that the vulnerability is known to the public.
- When… a Participant learns that the public knows of the vulnerability
- Send:
Add(ParticipantStatus)[target=CaseParticipant] - Send to: the case manager
- Sent by: the case manager or the case owner or the participant status's author
- Distinguished by:
caseStatus.pxaState=Pxa - Reference: Public awareness in a participant status
Example activity
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Add",
"id": "urn:uuid:9c290dfa-61bd-4f48-b5e2-735f331c4cac",
"name": "https://vultron.example/organizations/finder Add ACCEPTED NONE Pxa to https://vultron.example/cases/1/participants/finder",
"actor": "https://vultron.example/organizations/finder",
"target": "https://vultron.example/cases/1/participants/finder",
"object": {
"id": "https://vultron.example/cases/1/participants/finder/status/5",
"type": "ParticipantStatus",
"name": "ACCEPTED NONE Pxa",
"context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"attributedTo": "https://vultron.example/organizations/finder",
"rmState": "ACCEPTED",
"caseEngagement": true,
"cvdRole": [
"REPORTER"
],
"caseStatus": {
"id": "https://vultron.example/cases/1/status/5",
"type": "CaseStatus",
"name": "NONE Pxa",
"context": "https://vultron.example/cases/1",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"emState": "NONE",
"pxaState": "Pxa",
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
},
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
}
}
Report that an exploit is public
Change x to X.
That is Exploit Public (CX).
Exploit public in a participant status
Announces, in the sender's own participant status, evidence that an exploit is publicly available.
- When… a Participant learns that an exploit for the vulnerability is public
- Send:
Add(ParticipantStatus)[target=CaseParticipant] - Send to: the case manager
- Sent by: the case manager or the case owner or the participant status's author
- Distinguished by:
caseStatus.pxaState=PXa - Reference: Exploit public in a participant status
Example activity
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Add",
"id": "urn:uuid:5e0e2829-4ac7-4770-961c-121abe69c425",
"name": "https://vultron.example/organizations/finder Add ACCEPTED NONE PXa to https://vultron.example/cases/1/participants/finder",
"actor": "https://vultron.example/organizations/finder",
"target": "https://vultron.example/cases/1/participants/finder",
"object": {
"id": "https://vultron.example/cases/1/participants/finder/status/6",
"type": "ParticipantStatus",
"name": "ACCEPTED NONE PXa",
"context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"attributedTo": "https://vultron.example/organizations/finder",
"rmState": "ACCEPTED",
"caseEngagement": true,
"cvdRole": [
"REPORTER"
],
"caseStatus": {
"id": "https://vultron.example/cases/1/status/6",
"type": "CaseStatus",
"name": "NONE PXa",
"context": "https://vultron.example/cases/1",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"emState": "NONE",
"pxaState": "PXa",
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
},
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
}
}
Report that attacks are happening
Change a to A.
That is Attacks Observed (CA).
Attacks observed in a participant status
Announces, in the sender's own participant status, evidence that attackers are exploiting the vulnerability.
- When… a Participant observes attacks that exploit the vulnerability
- Send:
Add(ParticipantStatus)[target=CaseParticipant] - Send to: the case manager
- Sent by: the case manager or the case owner or the participant status's author
- Distinguished by:
caseStatus.pxaState=pxA - Reference: Attacks observed in a participant status
Example activity
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Add",
"id": "urn:uuid:f596b597-e43e-4d12-a5fa-ed3c75760bd8",
"name": "https://vultron.example/organizations/finder Add ACCEPTED NONE pxA to https://vultron.example/cases/1/participants/finder",
"actor": "https://vultron.example/organizations/finder",
"target": "https://vultron.example/cases/1/participants/finder",
"object": {
"id": "https://vultron.example/cases/1/participants/finder/status/7",
"type": "ParticipantStatus",
"name": "ACCEPTED NONE pxA",
"context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"attributedTo": "https://vultron.example/organizations/finder",
"rmState": "ACCEPTED",
"caseEngagement": true,
"cvdRole": [
"REPORTER"
],
"caseStatus": {
"id": "https://vultron.example/cases/1/status/7",
"type": "CaseStatus",
"name": "NONE pxA",
"context": "https://vultron.example/cases/1",
"published": "2026-06-01T19:12:00+00:00",
"updated": "2026-06-01T19:12:00+00:00",
"emState": "NONE",
"pxaState": "pxA",
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
},
"@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
}
}
What happens to your report
Your report is your view of the case status, not a change to it.
The CASE_MANAGER takes your participant status whole or refuses it whole: if one value cannot be accepted, nothing in the update is recorded, and its refusal notice names every value it refused and why (RSH-09-002).
The CASE_MANAGER records the status on your participant record and chooses whether to adopt the reported pxaState for the case, by default only with the Case Owner's authorization (RSH-07-001).
If it adopts the change, the CASE_MANAGER commits it as an Add(CaseStatus) entry to the case ledger.
While an embargo is active or proposed, it then ends or abandons the embargo (RSH-03-001).
The Reporter + Vendor (rv) demo and the status-updates demo report public awareness this way.
Post a note to the case
Use a note when the case needs narrative that no status field carries — a question, an answer, or a condition that needs human attention. A note goes to the case participants, not to the public.
To post a note, send one Add(Note) to the CASE_MANAGER, targeting the case, with the note carried inline as its object.
Set the note's context to the case as well: the CASE_MANAGER refuses a note whose context names another case, or names none (HP-08-007).
Give each note a new id: an Add(Note) introduces a note, so the CASE_MANAGER refuses one whose note id it already holds, whatever the note says (HP-08-006).
Changing a posted note would be an Update(Note), which this implementation does not handle yet.
A redelivery of the same Add(Note) changes nothing.
The CASE_MANAGER stores the note, attaches it to the case and commits an add_note_to_case entry to the case ledger.
The CASE_MANAGER accepts a note only from an active participant whose closure the case does not record, and refuses it from any other sender, including a closed participant (CM-23-018).
A refused note is not stored, attached, committed or sent on.
A participant's replica accepts a note only from the CASE_MANAGER.
Add(Note) is the one message that attaches a note (VAM-01-011).
Add note to case
Posts the note to the case named by the target, with the note carried inline as the object: the Case Manager stores the note, attaches it to the case and records the attachment in the case ledger. It is the one message that attaches a note: a received Create of a note is not a protocol message.
- When… a Participant posts a note to the case
- Send:
Add(Note)[target=VulnerabilityCase] - Send to: the case manager
- Sent by: an active participant
- Reference: Add note to case
Example activity
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Add",
"id": "urn:uuid:e3f25cb0-b638-4f66-9dd0-9c84bbcb6f58",
"name": "https://vultron.example/users/finndervul Add Note to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"actor": "https://vultron.example/users/finndervul",
"target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"object": {
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Note",
"id": "https://vultron.example/notes/1",
"name": "Note",
"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": "This is a note."
}
}
A received Create of a note is not a protocol message, and this implementation's inbox refuses it as an unrecognized activity (VAM-01-010).
To withdraw a note, send Remove(Note) to the CASE_MANAGER, targeting the case.
The CASE_MANAGER admits it from the note's author while that author is an active participant, or from the Case Owner, and refuses it from anyone else.
Remove note from case
Removes the note from the case named by the target.
- When… a note's author or the Case Owner withdraws a note from the case
- Send:
Remove(Note)[target=VulnerabilityCase] - Send to: the case manager
- Sent by: the case owner or the note's author
- Reference: Remove note from case
Example activity
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Remove",
"id": "urn:uuid:5b75af92-e182-4c8d-9f9b-a137483a6060",
"name": "https://vultron.example/users/finndervul Remove Note to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"actor": "https://vultron.example/users/finndervul",
"target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
"object": {
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Note",
"id": "https://vultron.example/notes/1",
"name": "Note",
"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": "This is a note."
}
}
The formal message set does not name this activity: it falls under the General Inquiry (GI) umbrella, which is a placeholder rather than a description — see Why GI expands.
If the note is a fault report rather than ordinary case discussion, see How to Report a Protocol Fault.
Verify
| What you sent | What to confirm |
|---|---|
Add(ParticipantStatus) |
Your participant record carries the new status, on every replica. |
Add(ParticipantStatus) carrying a pxaState |
Once the CASE_MANAGER adopts it, the case status carries the new pxaState, on every replica. |
Add(Note) |
The note appears on the case, on every replica. |
Each of these is committed by the CASE_MANAGER and fanned out, so checking your own store alone does not confirm the update landed.
See it end to end
Try it: vultron-demo status-updates
vultron-demo status-updates
Or with Docker Compose:
DEMO=status-updates docker compose -f docker/docker-compose.yml run --rm demo
The scenario adds and removes a note, then reports public awareness in a participant status and checks that the case status adopted it.
Further reading
- Case State (CS) Messages — the wire format and a rendered example for each status activity, and which dimensions are participant-scoped
- General Inquiry (GI) Messages — the wire format for the note lifecycle
- Vultron AS Objects — the ActivityStreams (AS)
CaseStatus,ParticipantStatus, andCaseParticipantobjects these activities carry - Activity Vocabulary Design — why the
CreateandAddsplit exists, and when an implementation may send only theAdd