Skip to content
Reference

Protocol Layers

This page is normative

This page is considered a core part of the Vultron Protocol. This is a normative section of the documentation.

The whole specification on one page

The specification is also published as a single page that holds every section and annex in order, for printing or for searching the whole text at once.

This page holds sections 4 and 5 of the Vultron Protocol Specification: what each protocol message means, and how it is encoded on the wire, including the required Representational State Transfer (REST) transport profile. The case-state messages report the Vendor aware, Fix ready, fix Deployed (VFD) and Public aware, eXploit public, Attacks observed (PXA) dimensions of the Case State (CS).

4. Semantic Layer — Message Meanings [N]

This section defines what each protocol message means. It says nothing about how a message is encoded; §5 Syntactic Layer — Wire Format specifies that, and §5.7 Shorthand to Wire Form Mapping gives the mapping between the two.

Messages are named by two-letter shorthands, grouped by the state machine they concern: R* for report management, E* for embargo management, C* for case state. A shorthand names a meaning, not a wire format. Several shorthands share one wire form, so the mapping is not one-to-one in either direction.

Every message reports something that has already happened. A message does not instruct its recipient to make a transition; it tells the recipient that the sender has made one, or that the sender has observed something (§3.1 Coordination Model).

Six of the message types the formal protocol defines have no wire representation in this version. Each table below marks them, and §4.6 Error and Acknowledgment Messages explains why they are absent rather than merely unimplemented.

4.1 Report Management Messages

These eight messages concern one participant's handling of a report. Each reports a change to the sender's report management state (§6 Report Management (RM) State Machine).

Shorthand Name Meaning On the wire?
RS Report Submission The sender is sending a report to a new participant yes
RI Report Invalid The sender assessed the report as invalid yes
RV Report Valid The sender assessed the report as valid yes
RD Report/Case Deferred The sender is deferring further action; a case-participation decision yes
RA Report/Case Accepted The sender accepted the report/case for active work; a case-participation decision yes
RC Report Closed The sender closed the report yes
RK Report Acknowledgment The sender received the report submission yes
RE Report Error The sender received an unexpected report message no (§4.6 Error and Acknowledgment Messages)

Only RS drives a state change in its receiver: receiving a report moves the receiver to Received. The other seven tell the receiver something about the sender and leave the receiver's own state alone.

RK acknowledges the submission, not the reading

RK reports that the submission arrived. It does not report that the recipient has read the report, assessed it, or agreed to work on it — those are RV, RI, RA and RD.

The protocol defines no message meaning "I have read the report". An implementation MUST NOT infer from RK that the recipient has examined the content, and MUST NOT treat RK as a substitute for a report management state message.

4.2 Embargo Management Messages

These nine messages negotiate the case's embargo (§7 Embargo Management (EM) State Machine). They fall into three groups: proposing an embargo, revising one already in force, and ending one.

Shorthand Name Meaning On the wire?
EP Embargo Proposal The sender proposes embargo terms yes
ER Embargo Proposal Rejection The sender rejects a proposal yes
EA Embargo Proposal Acceptance The sender accepts a proposal yes
EV Embargo Revision Proposal The sender proposes changing terms already in force yes
EJ Embargo Revision Rejection The sender rejects a proposed revision yes
EC Embargo Revision Acceptance The sender accepts a proposed revision yes
ET Embargo Termination The sender ends the embargo, effective immediately yes
EK Embargo Acknowledgment The sender received an embargo message no (§4.6 Error and Acknowledgment Messages)
EE Embargo Error The sender received an unexpected embargo message no (§4.6 Error and Acknowledgment Messages)

The initial-proposal group (EP, ER, EA) and the revision group (EV, EJ, EC) are distinct meanings. The distinction matters because the outcome of a rejection differs: rejecting an initial proposal leaves the case with no embargo, while rejecting a revision leaves the previously agreed terms in force (§7.2 Transitions and Guards).

The revision shorthands are indistinguishable on the wire

EV, EJ and EC share their wire forms with EP, ER and EA respectively. The distinction is not encoded in the message.

An implementation MUST determine which it has received from its own embargo state. If the case embargo is Active or Revised, an arriving proposal is a revision. If it is None or Proposed, the same message is an initial proposal.

An implementation that treats the wire form as self-describing will mishandle every revision. Because a mishandled revision rejection returns the case to None, it will silently drop embargoes that every participant still believes are in force.

Choosing between EV and ET. ET takes effect immediately. A sender that wants the embargo to end at some future point SHOULD send EV proposing that end date rather than ET.

Tacit acceptance of a receiver's default embargo policy is specified at §7.2 Transitions and Guards: submitting a report without proposing terms accepts the receiver's default. Where the receiver has published no default, the same section specifies a short protocol default, so an embargo-eligible case never begins without an embargo.

4.3 Case State Messages

These messages report facts about the vulnerability (§8 Case State (CS) Dimensions). The first three concern what a specific participant has done; the next three concern the state of the world.

Shorthand Name Axis Meaning On the wire?
CV Vendor Awareness VFD A vendor has been made aware of the vulnerability yes
CF Fix Readiness VFD A vendor has a fix ready yes
CD Fix Deployment VFD A fix has been deployed yes
CP Public Awareness PXA The vulnerability is publicly known yes
CX Exploit Public PXA An exploit has been published yes
CA Attacks Observed PXA Attacks exploiting the vulnerability have been seen yes
CK Case State Acknowledgment — The sender received a case state message no (§4.6 Error and Acknowledgment Messages)
CE Case State Error — The sender received an unexpected case state message no (§4.6 Error and Acknowledgment Messages)

All six reporting shorthands share a single wire form. Which fact is being reported travels in the message's payload rather than in its type, so an implementation that dispatches on message type alone cannot tell CF from CA (§5.7 Shorthand to Wire Form Mapping).

The three VFD messages report the sender's own progress, so receiving one updates the receiver's model of the sender rather than the receiver's own state (§8.4 Receiving CS Messages: Own State vs. Model of Others). The three PXA messages report a claim about the world, which becomes canonical case state only if the CASE_MANAGER adopts it (§10.3 Status Adoption: The Two-Seam Model).

4.4 Case Coordination Operations

Alongside the state machine messages, the protocol defines the operations that create a case and manage who is in it. These have no two-letter shorthands, because they concern the case as an object rather than any machine's state.

Operation Meaning
Case creation An actor establishes a case for a vulnerability, and with it the case's authority chain (§4.5 Trust and Bootstrap Semantics)
Invitation The CASE_MANAGER invites an actor to join, on the Case Owner's behalf; the actor accepts or declines (§11.2 Invitation and Acceptance)
Actor suggestion A participant recommends that some actor be brought into the case; the Case Owner decides whether to invite it (§11.2 Invitation and Acceptance)
Role offer The Case Owner offers a role to an actor, which accepts or declines (§11.1 Role Assignment)
Ownership transfer The Case Owner offers ownership of the case to another actor (§11.3 Case Ownership Transfer)
Ledger replication The CASE_MANAGER sends each committed ledger entry to every participant. This is the only way a participant learns of an admitted change to shared case state
Case delivery The CASE_MANAGER sends a participant the full case, once that participant is admitted and its embargo consent is resolved (§9.7 Gating Full Case Delivery)
Case metadata update The CASE_MANAGER records a change to the case's own attributes

The wire form of each is given at §5.3 Activity Types and Canonical Message Forms.

4.5 Trust and Bootstrap Semantics

A case begins before there is a case. The reporter's first message goes to a vendor directly, because no case exists and so no CASE_MANAGER exists to route through. Every later message routes through the CASE_MANAGER (§5.4.2 Routing Topology). The transition between those two regimes is the bootstrap, and it is where a case's trust is established.

The case-creation message is the trust root. When a case is created for a report, the receiving party sends the reporter a case-creation message signed by the receiving party itself, the actor the reporter chose. That message introduces the actor holding the CASE_MANAGER role, which may be the receiving party or another actor it delegated case maintenance to. The reporter trusts the introduction because it came from the actor the reporter addressed, and never because a case snapshot names its own sender. Every participant's trust in the ledger derives from it: a participant accepts entries from the CASE_MANAGER because it accepts the message that established which actor holds the role.

A late joiner inherits that trust transitively. An actor invited after the case is under way never sees the original creation message. It receives the case snapshot and the prior ledger entries from the CASE_MANAGER (§10.1 Admitting a Participant), and it trusts them because it trusts the invitation that named the CASE_MANAGER. The hash-chaining of the ledger lets the joiner verify it received an unbroken history — a check against tampering and omission, not a second source of trust.

Messages that arrive before their case. A case-scoped message may reach a participant before the case it refers to has. A participant MUST NOT apply such a message to a case it has not yet received. It holds the message until the case arrives, and discards it if the case never does. Applying it early would create case state from a message whose context was never established.

The threat model, identity verification, and the limits of this trust chain are covered at §14.1 Trust Model.

4.6 Error and Acknowledgment Messages

The formal protocol defines an acknowledgment and an error message for each of the three state machines: RK, EK, CK and RE, EE, CE. Their status here is not uniform, and an implementation MUST NOT assume symmetry across the three.

Of the six, only RK exists on the wire. EK, CK, RE, EE and CE have no wire representation. An implementation MUST NOT expect to receive any of the five, and MUST NOT wait on one.

The two absences have different reasons.

EK and CK are redundant. Embargo and case state changes are replicated through the case ledger, and a participant establishes that it received them by holding an unbroken hash chain. A per-message acknowledgment would restate what the chain already shows. RK survives because report submission happens before the case exists, so there is no ledger to carry it.

RE, EE and CE are deliberately unmodeled, not merely unimplemented. The protocol does not model inbound error messages typed by the state machine that produced them, because that grouping tells a receiver nothing it can act on: knowing which machine was confused does not indicate what to do about it. Errors are grouped by failure mode instead, which is actionable:

Failure mode When it applies What the sender can do
Not understood The message could not be parsed, or its meaning is unrecognized Re-send, or send a simpler equivalent
Understood but declined The message was well-formed and meaningful, but the receiver will not act on it given the case's state Reconsider; the state, not the message, is the obstacle
Needs explanation The condition cannot be expressed as a structured message and requires prose Read the explanation; there is no automatic recovery

§5.3 Activity Types and Canonical Message Forms gives the wire form of each failure mode.

What is still missing. A message that cannot be processed is currently set aside for administrative attention, and its sender is not told. The three failure modes give a receiver a way to report a problem where it is implemented, but this version does not require it to.

Open question: negative-acknowledgment semantics are unspecified

Error message types (RE, EE, CE) are deliberately unmodeled (ADR-0049). Unprocessable inbound messages are dead-lettered with no sender notification. The three-way fault partition (§4.6 Error and Acknowledgment Messages, ADR-0083) provides structured error signaling where it is implemented, but whether the protocol needs a normative negative-acknowledgment facet — and if so, what the expected sender behavior (retry, suppress, escalate) should be — remains open.

4.7 Knowledge Model and Actor Isolation

Each participant knows only what it has been told. This subsection states what follows from that, including why a recipient must be able to obtain every object a message names (§5.5 Serialization).

What a participant knows versus what is true. A participant's replica reflects the messages it has received. Two participants in the same case may hold different views at the same moment, because a message is in transit or because a participant has not yet reported a change. The protocol does not require every participant to agree at every instant. It requires that each converge on the case's canonical state as ledger entries reach it.

No participant reads another's state. An implementation MUST NOT read or write another actor's state directly. Everything it knows about another participant MUST be derived from a message that participant sent, or from the canonical ledger. This is what makes a participant's knowledge independent of any other participant being reachable.

A recipient can obtain what a message names. A participant MUST NOT assume a recipient holds an object it was never sent (AKM-02-001). An object the recipient cannot be expected to hold is carried inline, or by a reference the recipient can dereference (AKM-02-002). Either form satisfies the protocol.


5. Syntactic Layer — Wire Format [N]

This section specifies how a Vultron message is encoded and delivered. Where §4 Semantic Layer — Message Meanings says what a message means, this section says what it looks like.

Vultron does not define its own message syntax. It uses ActivityStreams 2.0, a published World Wide Web Consortium (W3C) vocabulary for describing things that actors do, and extends it with the object types a vulnerability case needs. Reusing an existing vocabulary means the outer envelope is already specified, already tooled, and already understood by readers who have met it elsewhere.

The consequence for a reader is that Vultron messages look generic. There is no ProposeEmbargo verb; there is an Invite whose object happens to be an embargo event. Meaning comes from the combination of verb and object, not from the verb alone, which is why §5.7 Shorthand to Wire Form Mapping is needed to connect the two layers.

5.1 Base Vocabulary

Every Vultron message is an ActivityStreams 2.0 Activity: an object describing an action, with the actor who performed it and the thing it was performed on.

Four fields are required on every Activity:

Field Contains
type The Activity type — the verb, such as Offer or Announce
actor The Uniform Resource Identifier (URI) of the actor that performed the action
object The thing acted on, inline or by reference (§5.5 Serialization)
id A URI uniquely identifying this Activity, used for deduplication (§14.3 Replay and Idempotency)

Vultron's own types are declared in the vocabulary namespace https://certcc.github.io/Vultron/ns.

An implementation MUST use the Vultron ActivityStreams vocabulary for message structure.

This version does not require full ActivityPub server behavior. Inbox and outbox Hypertext Transfer Protocol (HTTP) delivery, WebFinger discovery and HTTP Signatures are not conformance requirements here.

Informative: ActivityPub conformance is not required by this version

A future version is expected to raise the floor to ActivityPub; §1.3 Relationship to Existing Standards states the roadmap.

5.2 Object Types

An Activity's meaning depends on what it acts on, so the object types matter as much as the verbs. Vultron defines eight, and they are not a flat set: a case contains participants, a report, status records, and an ordered ledger. That containment is the mental model the rest of this specification assumes.

---
title: Vultron object containment
---
classDiagram
    VulnerabilityCase "1" *-- "1..*" CaseParticipant
    VulnerabilityCase "1" *-- "0..*" VulnerabilityReport
    VulnerabilityCase "1" *-- "1" CaseStatus
    VulnerabilityCase "1" *-- "0..*" CaseLedgerEntry
    VulnerabilityCase "1" *-- "0..*" EmbargoEvent
    CaseParticipant "1" *-- "0..*" ParticipantStatus
    CaseParticipant "1" o-- "0..*" CaseParticipantRole
    CaseProposal ..> VulnerabilityCase : requests creation of
Object What it is
VulnerabilityCase The case itself: the container for everything below
VulnerabilityReport The report artifact that started the case
CaseParticipant An actor's membership in a case, carrying the roles it holds and the state it owns
CaseParticipantRole A role being offered to an actor in the context of a case. A distinct type so that offering a role is structurally different from offering ownership of the case
EmbargoEvent An embargo's terms — proposed, accepted, revised or terminated. A subtype of the ActivityStreams Event type, which is why embargo messages appear on the wire as invitations to an event rather than under an embargo-specific verb
CaseLedgerEntry One entry in the canonical case ledger (§2.3 Protocol Objects and Messages)
CaseProposal A request that some actor create and manage a case. Used when the requesting actor does not intend to manage the case itself; the actor that accepts becomes the case's creator
CaseStatus / ParticipantStatus Status records — see below

Status records: claim versus canonical. These two are the most easily confused types in the protocol, and the difference is one of authority rather than content.

  • A ParticipantStatus is a claim. It carries what one participant reports about its own state, or observes about the world. Any participant may write one, and writing one does not change what the case asserts.
  • A CaseStatus is canonical. It carries what the case asserts: its embargo state and what is publicly known. Only the CASE_MANAGER writes it (§5.4.1 Single-Writer Authority).

A claim becomes canonical only when the CASE_MANAGER adopts it, and adoption is an authorization decision with a named default rather than an automatic consequence of receipt (§10.3 Status Adoption: The Two-Seam Model). An implementation MUST NOT substitute one type for the other: a participant that emits CaseStatus is asserting authority it does not hold, and a CASE_MANAGER that treats an inbound ParticipantStatus as canonical has skipped the decision.

Informative: which types have core models

CaseProposal and the fault object of §5.3 Activity Types and Canonical Message Forms exist in the reference implementation only as wire types, with no separate internal model. Every other type above has both.

5.3 Activity Types and Canonical Message Forms

Vultron uses ActivityStreams verbs rather than defining its own. Thirteen are in use:

Create, Offer, Accept, Reject, TentativeReject, Announce, Update, Add, Remove, Invite, Read, Join, Ignore.

Because the verbs are generic, meaning often comes from nesting: an Activity whose object is itself an Activity. Accepting an embargo, for instance, is an Accept whose object is the Invite being accepted, which in turn carries the embargo event. The nesting is what distinguishes accepting an embargo from accepting a report.

{
  "@context": "https://certcc.github.io/Vultron/ns/context.jsonld",
  "id": "https://vendor.example/activities/8f2c",
  "type": "Accept",
  "actor": "https://vendor.example/actors/vendor",
  "object": {
    "id": "https://coord.example/activities/4a19",
    "type": "Invite",
    "actor": "https://coord.example/actors/case-manager",
    "context": { "type": "VulnerabilityCase", "id": "https://coord.example/cases/2026-0042" },
    "object": {
      "type": "EmbargoEvent",
      "endTime": "2026-11-01T00:00:00Z"
    }
  }
}

The two ways an actor joins a case are different messages. Conflating them loses a round-trip in which the Case Owner decides:

  • Invite, with the case stub as its target, is the CASE_MANAGER inviting an actor to join on the Case Owner's behalf. It is answered with Accept or Reject.
  • Offer, with a CaseParticipant as its object, is a participant recommending an actor. It is answered by the Case Owner, which may then cause an Invite to be sent. An implementation MUST NOT treat it as an invitation to the recommended actor.

Both paths end in an Accept of an Invite (§11.2 Invitation and Acceptance). That Accept joins the case; it is not RV. A participant that joined this way never saw the report offer, so it judges the case by answering a second Invite that has the case itself as its target, the full-case Invite, and that reply is RV, RI or RC (VAM-04-011, CM-11-020).

Fault reporting. The three failure modes of §4.6 Error and Acknowledgment Messages have these wire forms:

Failure mode Wire form
Not understood Create of a ProcessingFault object
Understood but declined Reject of the message being declined
Needs explanation Create of a Note, or Add of a Note to the case

5.4 Addressing and Channels

An actor is identified by a URI, and that URI is also where it receives messages. Each actor exposes an inbox to receive Activities and an outbox from which it sends them. An actor's URI is its identity for every purpose in the protocol: there is no separate registry, and no name or hosting location carries authority (§2.2 Roles).

Delivery is therefore inbox to inbox. Which inbox a message may go to, however, is constrained — and that constraint is the subject of the next two subsections.

5.4.1 Single-Writer Authority

The participant holding the CASE_MANAGER role is the only entity authorized to write the case's shared state: the PXA axis, the embargo state, the embargo record, and the case ledger. No participant and no handler may write shared case state directly; every such change MUST be made by the CASE_MANAGER.

The participant-specific axes — report management and VFD — are owned by each participant's own CaseParticipant record and are explicitly not subject to this restriction. A participant is the authority on its own report management and VFD state.

This rule exists to make concurrent claims resolvable. Two participants may report contradictory observations about the world at the same moment; with one writer, the case has one answer, and the decision about which claim becomes that answer is explicit (§10.3 Status Adoption: The Two-Seam Model) rather than a race. The routing rule below follows from it.

5.4.2 Routing Topology

Once a case exists, every case-scoped message follows this path:

Participant → CASE_MANAGER → CaseLedgerEntry → Announce(CaseLedgerEntry) → all Participants
  • A participant MUST address case-scoped Activities to the CASE_MANAGER.
  • The CASE_MANAGER MUST record a case-scoped message in the case ledger before sending it on to the other participants.
  • Announce of a CaseLedgerEntry is the only mechanism by which a participant learns of an admitted change to shared case state.

There are exactly two exceptions, both confined to case bootstrap, both occurring before a CASE_MANAGER exists to route through (§4.5 Trust and Bootstrap Semantics):

  1. Pre-case report submission — the reporter sends the report directly to the vendor. No case exists, and therefore no case actor service has provisioned an actor to hold the CASE_MANAGER role.
  2. Case creation handshake — the receiving party sends the case-creation message back to the reporter as itself, introducing the actor that holds the role. When that actor is not the receiving party, its first message to the reporter is a later sync, which the reporter holds if it arrives before the introduction.

This is a routing rule, not a prohibition on talking

The rule above scopes Vultron protocol messages about a case. It does not say that participants may not communicate with each other, and the protocol has no way to enforce such a thing. Participants routinely talk directly — by mail, by phone, in a shared channel — and that is outside the protocol's scope.

What the rule means is narrower: a case-scoped Vultron Activity delivered directly from one participant to another is not part of the protocol, and a receiving implementation has no obligation to apply it. Case state changes through the ledger or not at all.

Informative: why route through one writer

Routing through a single writer avoids the coordination cost of agreeing an order among peers, while still leaving each participant its own replica and its own view. The cost is that the CASE_MANAGER is a single point of coordination authority for the case, and its availability bounds how fast that case can progress.

This is scoped per case. The role is held for one case at a time, different cases may be managed by different actors, and the role is transferable (§11.3 Case Ownership Transfer). The current reference implementation goes further than the protocol requires and provisions a dedicated service actor per case.

The protocol deliberately leaves more decentralized realizations open — a ledger shared among peers, for instance, which would remove the single point of authority at the cost of needing agreement on ordering. This version does not specify one, and no implementation of one exists.

5.5 Serialization

Vultron messages are serialized as JavaScript Object Notation for Linked Data (JSON-LD). JSON-LD is JavaScript Object Notation (JSON) with a context that maps short names to full URIs, so a message is readable as ordinary JSON while remaining unambiguous about which vocabulary each term comes from.

An outbound message MUST set @context to the Vultron JSON-LD context document URI:

{
  "@context": "https://certcc.github.io/Vultron/ns/context.jsonld",
  "id": "https://coord.example/activities/1b7e",
  "type": "Announce",
  "actor": "https://coord.example/actors/case-manager",
  "object": {
    "type": "CaseLedgerEntry",
    "logIndex": 12,
    "contentHash": "sha256:9f2a...",
    "predecessorHash": "sha256:41c8..."
  }
}

That context document imports the ActivityStreams 2.0 namespace and declares every Vultron type name, so an implementation cites only the Vultron URI and does not need to declare the ActivityStreams namespace separately.

Objects travel inline or by reference. As ActivityStreams 2.0 allows, an Activity MAY carry an object inline or name it by URI, and a receiver MUST cope with either form (SE-01-002). An actor that names by reference an object its recipient cannot be expected to hold MUST use a reference the recipient can dereference (AKM-02-002, §4.7 Knowledge Model and Actor Isolation). A production implementation MUST be able to fetch an object named by a URI it holds no record of (AKM-05-004).

A case ledger entry records the asserted activity as it was sent. Its payload snapshot is the received body of an activity the Case Manager received, or the body it delivered for one it sent itself (CLP-07-011). Each nested object stays as the asserting activity carried it: inline where its sender inlined it, by reference where its sender named an object every replica already holds (CLP-07-006). The Case Manager never fills a reference in, because the entry hash covers the snapshot and nothing outside it, so a filled-in snapshot would record the Case Manager's reconstruction rather than what was sent.

The reference implementation inlines every object

The reference implementation does not yet dereference, so it carries every object inline and refuses a bare URI where it needs the object (AKM-03-003). That is a shortcut of the prototype, not a Vultron rule.

Provisional namespace URI

The namespace is currently hosted on GitHub Pages. A permanent URI may be registered in a future version (§13 IANA and Namespace Considerations).

5.6 Transport Layer [N/I]

The transport layer moves a serialized message from one actor to another. The message schema of §5.1 Base Vocabulary through §5.5 Serialization is transport-agnostic: the same JSON payload is deliverable over any conformant transport.

This version recognizes one required transport profile and describes a second that is anticipated.

REST (HTTP) profile [N]

This is the transport an implementation MUST provide.

  • Each actor exposes an inbox endpoint that accepts inbound Activities.
  • An outbound Activity is delivered by HTTP POST to the recipient's inbox.
  • Authentication and authorization requirements are at §14 Security Considerations.

Open question: which HTTP responses a receiving actor returns

This version does not say which HTTP status code a receiving actor returns when it refuses a message. For example, it does not say whether an invalid activity gets 422, an activity addressed only to other actors gets 400, or a message that cannot be decrypted gets 400.

One option is for the protocol to specify these responses, so that a sending actor can rely on them and act on them. The other is to leave them to each server implementation. A Vultron actor built on a stock ActivityPub server returns whatever that server returns, so a protocol rule could conflict with the server it runs on.

Until this is settled, these codes are recorded as the reference implementation's choices, not as protocol requirements. The codes that HTTP itself defines, such as 405 for an unsupported method and 413 for a body that is too large, are not part of this question.

ActivityPub federation profile [I]

Full ActivityPub conformance is not required by this version. The roadmap is at §1.3 Relationship to Existing Standards; Annex E Relationship to ActivityPub describes where Vultron follows ActivityPub conventions and where it diverges.

Participant discovery [I]

Before two actors can exchange messages they must locate each other. WebFinger is the anticipated mechanism, consistent with its use alongside ActivityPub in federated systems. This version does not specify participant discovery.

Transport is not routing

The routing rule of §5.4.2 Routing Topology is a protocol rule and applies regardless of which transport carries the messages. The transport is responsible for getting a message to an inbox. The protocol is responsible for which inbox it may go to.

5.7 Shorthand to Wire Form Mapping

This is the normative mapping from the protocol shorthands of §4 Semantic Layer — Message Meanings to their wire forms. It appears here rather than in §4 because it depends on both the shorthands and the object types of §5.2 Object Types.

Shorthand Wire form
RS Offer of a VulnerabilityReport
RI TentativeReject of the report offer, or of the full-case Invite (VAM-04-013)
RV Accept of the report offer, or of the full-case Invite (VAM-04-012)
RD Ignore of the VulnerabilityCase
RA Join of the VulnerabilityCase
RC Reject of the report offer, of the stub Invite (CM-11-007), or of the full-case Invite (VAM-04-014)
RK Read of the report offer
EP, EV Invite to an EmbargoEvent, in the context of the case
EA, EC Accept of that Invite
ER, EJ Reject of that Invite
ET Remove of the EmbargoEvent
CV–CA Add of a status record to the case — see below
RE, EE, CE, EK, CK none (§4.6 Error and Acknowledgment Messages)

The status messages depend on who is sending. The six case state shorthands do not have one wire form; they have two, and which applies is determined by the sender's authority:

  • A participant reporting its own VFD progress, or an observation about the world, sends Add of a ParticipantStatus. This is a claim.
  • The CASE_MANAGER, having adopted a claim, sends Add of a CaseStatus targeting the case. This is the canonical write.

A participant MUST NOT send Add of a CaseStatus (§5.4.1 Single-Writer Authority). An implementation that maps all six shorthands to CaseStatus regardless of sender will have participants asserting authority they do not hold.

Two collision classes exist. In both, the wire form alone is insufficient and an implementation MUST use additional information to disambiguate:

Collision Disambiguate by
The revision shorthands share wire forms with their initial-proposal counterparts The local embargo state (§4.2 Embargo Management Messages)
All six case state shorthands share one verb The status record's payload (§4.3 Case State Messages)