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
ParticipantStatusis 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
CaseStatusis 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 withAcceptorReject.Offer, with aCaseParticipantas its object, is a participant recommending an actor. It is answered by the Case Owner, which may then cause anInviteto 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.
Announceof aCaseLedgerEntryis 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):
- 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_MANAGERrole. - 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
Addof aParticipantStatus. This is a claim. - The CASE_MANAGER, having adopted a claim, sends
Addof aCaseStatustargeting 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) |