Skip to content
Reference

Embargo Management (EM) Messages

The EM process is global to the case. A Participant emits an EM message when the case's EM state changes. The AS2 wire vocabulary collapses the revision-negotiation shorthands onto their initial-negotiation counterparts: EV is sent as EP, EJ as ER, and EC as EA, discriminated by EM state context rather than by a payload field (MSM-02).

An embargo proposal carries its EmbargoEvent inline on the Invite that proposes it. The protocol names Invite(Event) as the one form; a received Create(Event) is not a protocol message, and its receiver must not change the case file because of it (ADR-0137, VAM-01-011). This implementation's inbox refuses one as an unrecognized activity and changes nothing (VAM-01-010).

Occasions

When… Send Send to Sent by Distinguished by Details
the Case Owner terminates the active embargo Remove(Event) the case manager the case manager or the case owner — Embargo Termination (ET)
the Case Manager ends the active embargo, on its own decision or on the Case Owner's Remove(Event) a participant the case manager — Tell a participant the embargo has ended
the Case Manager states the terms of the embargo in force Announce(Event)[context=VulnerabilityCase] a participant the case manager register status of the named embargo ACTIVE Announce embargo
the Case Manager has applied an Embargo Termination a Case Owner sent before the end time Announce(Event)[context=VulnerabilityCase] a participant the case manager register status of the named embargo TERMINATED Announce embargo termination
a Participant proposes embargo terms for a case with no active embargo Invite(Event)[context=VulnerabilityCase] the case manager the case manager or an active participant EM state NONE or PROPOSED Embargo Proposal (EP)
a Participant proposes revised terms for the active embargo Invite(Event)[context=VulnerabilityCase] the case manager the case manager or an active participant EM state ACTIVE or REVISE Embargo Revision Proposal (EV)
the Case Manager asks a Participant to answer embargo terms another Participant proposed Invite(Event)[context=VulnerabilityCase] a participant the case manager — Ask a participant about proposed embargo terms
a Participant agrees to proposed embargo terms Accept(Invite(Event)[context=VulnerabilityCase]) the case manager the invitee EM state PROPOSED Embargo Proposal Acceptance (EA)
a Participant agrees to a proposed embargo revision Accept(Invite(Event)[context=VulnerabilityCase]) the case manager the invitee EM state REVISE Embargo Revision Acceptance (EC)
a Participant refuses proposed embargo terms Reject(Invite(Event)[context=VulnerabilityCase]) the case manager the invitee EM state PROPOSED Embargo Proposal Rejection (ER)
a Participant refuses a proposed embargo revision Reject(Invite(Event)[context=VulnerabilityCase]) the case manager the invitee EM state REVISE Embargo Revision Rejection (EJ)
the Case Manager abandons an open embargo proposal once the case is public, an exploit is public or attacks are observed Undo(Invite(Event)[context=VulnerabilityCase]) a participant not handled — Withdraw an embargo invitation
the Case Owner decides to activate a proposed embargo Accept(Event)[target=VulnerabilityCase] the case manager the case owner — Activate embargo
the Case Owner decides to reject a proposed embargo Reject(Event)[target=VulnerabilityCase] the case manager the case owner — Reject embargo proposal
a Participant bound by the active embargo stops complying with it Leave(Event)[context=VulnerabilityCase] the case manager a participant — Withdraw from embargo
the Case Manager has created a case and, with it, an embargo such as the default embargo Create(EmbargoEvent) a participant not handled — Create embargo event
the Case Manager creates a participant's consent row for an embargo, such as the UNINVITED row a proposal writes Create(EmbargoConsent) a participant not handled — Create embargo consent
the Case Manager changes a participant's consent row, such as an invitation timing out, the rows carried over at activation or a change of its own consent Update(EmbargoConsent) a participant not handled — Update embargo consent

Embargo Proposal (EP)

Proposes embargo terms, such as an end date and time.

  • When… a Participant proposes embargo terms for a case with no active embargo
  • Send: Invite(Event)[context=VulnerabilityCase]
  • Send to: the case manager
  • Sent by: the case manager or an active participant
  • Distinguished by: EM state NONE or PROPOSED
  • Seen in: How to Establish an Embargo
  • Formal definition: Embargo Proposal (EP)
  • Mapping status: collapse
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Invite",
  "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_proposals/1",
  "name": "https://vultron.example/organizations/vendorco Invite Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "summary": "We propose to embargo case 1 for 90 days.",
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-08-30T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Triggering transition: None or Proposed → Proposed ({N,P} → P).
  • Wire form: Invite(Event)[context=VulnerabilityCase], and no other (MSM-02-001).

Ask a participant about proposed embargo terms

Asks one participant to accept or reject proposed embargo terms, or a proposed revision. The Case Manager sends one to each participant other than the proposer, naming the proposer in attributedTo, and the participant's answer names this Invite.

  • When… the Case Manager asks a Participant to answer embargo terms another Participant proposed
  • Send: Invite(Event)[context=VulnerabilityCase]
  • Send to: a participant
  • Sent by: the case manager
  • Seen in: How to Establish an Embargo
  • Mapping status: collapse

The wire form is the Embargo Proposal (EP) or Embargo Revision Proposal (EV) a participant sends; only its sender and addressee differ.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Invite",
  "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_proposals/1/invites/coordinator",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Invite Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "endTime": "2026-06-08T19:12:00+00:00",
  "summary": "The vendor proposes to embargo case 1 for 90 days.",
  "to": [
    "https://vultron.example/organizations/coordinator"
  ],
  "attributedTo": "https://vultron.example/organizations/vendorco",
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-08-30T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Recipient: one Invite per participant other than the proposer, each addressed to that participant alone, so its answer names the Invite it received (EP-09-002, EP-09-010).

Announce embargo

Tells participants the terms of the active embargo. It proposes nothing.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Announce",
  "id": "urn:uuid:29ec26a4-140e-43f8-9032-6e49242ce15a",
  "name": "https://vultron.example/organizations/vendorco Announce Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "to": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/participants",
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-08-30T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}

When the CASE_MANAGER activates a revision that ends no later than the embargo it replaces, it sends Announce(Event) with the new terms directly to each bound signatory that no longer receives ledger entries (removed, or at Report Management (RM) CLOSED). That participant applies the new terms only when the CASE_MANAGER sent them. A revision that ends later sends no such notice, because those participants never agreed to it.

Announce embargo termination

Tells the active participants other than the Case Manager and any Closed Participant that the embargo it names is terminated. It proposes nothing.

  • When… the Case Manager has applied an Embargo Termination a Case Owner sent before the end time
  • Send: Announce(Event)[context=VulnerabilityCase]
  • Send to: a participant
  • Sent by: the case manager
  • Distinguished by: register status of the named embargo TERMINATED
  • Seen in: How to Revise or Terminate an Embargo
  • Mapping status: none

A termination the Case Manager starts itself, or one at the end time, sends no announcement: after the end time, the Case Manager's own end-time check ends the embargo before it applies a Case Owner's termination.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Announce",
  "id": "urn:uuid:969493d4-039c-47c9-9a4f-b26df5470f59",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Announce Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "to": [
    "https://vultron.example/organizations/vendorco",
    "https://vultron.example/organizations/coordinator",
    "https://vultron.example/users/finndervul"
  ],
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-08-30T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Recipient: every active participant other than the CASE_MANAGER and any Closed Participant, after the CASE_MANAGER applies a Case Owner's Remove(Event) that arrives before the end time (EMB-19-001, CM-10-004, CM-23-004). A termination the CASE_MANAGER starts itself, or one at the end time, sends no Announce(Event). A bound signatory that no longer receives ledger entries gets the CASE_MANAGER's own Remove(Event) instead (CM-31-009).

Embargo Proposal Rejection (ER)

Records the sender's own refusal of the proposed terms. The proposal is rejected for the case only when the Case Owner sends its decision.

The Case Manager sends the same activity when it abandons an open proposal once the case is public, an exploit is public or attacks are observed. Its Reject cancels the proposal, and each Invite it relayed for the proposal is then withdrawn.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Reject",
  "id": "urn:uuid:de0715d2-8afa-4d91-88a7-da27c7a39e56",
  "name": "https://vultron.example/organizations/vendorco Reject https://vultron.example/organizations/vendorco Invite Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "to": "https://vultron.example/cases/1/participants",
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Invite",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_proposals/1",
    "name": "https://vultron.example/organizations/vendorco Invite Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:37+00:00",
    "updated": "2026-10-23T20:17:37+00:00",
    "summary": "We propose to embargo case 1 for 90 days.",
    "actor": "https://vultron.example/organizations/vendorco",
    "object": {
      "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
      "type": "EmbargoEvent",
      "name": "Embargo for VendorCo Case #70930046",
      "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
      "startTime": "2026-06-01T19:12:00+00:00",
      "endTime": "2026-08-30T00:00:00+00:00",
      "published": "2026-06-01T19:12:00+00:00",
      "updated": "2026-06-01T19:12:00+00:00",
      "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
    }
  }
}
  • Triggering transition: Proposed → None (P → N), or Proposed → Proposed (P → P) while another proposal is open (EMB-18-005).
  • Who decides: a participant's Reject of the Invite is its own refusal of those terms, the Case Owner's included. It changes no embargo on the case (see The Case Owner's Decision).
  • The Case Manager's Reject: when the case becomes public, an exploit is public or attacks are observed while a proposal is open, the Case Manager rejects each proposal it received. That Reject cancels the proposal (EMB-16-001). A replica tells it from a participant's Reject by its actor. The Case Manager never sends a Reject of an Invite as its own consent: a Case Manager with a stake in the embargo records its answer as its own update of its consent row.
  • Refusal on a public case: a receiver answers an EP with ER when the case is public, an exploit is public, or attacks are observed. The ER names the Invite by id, so it is sent even when the Invite named its terms only by URI. A receiver sends one ER per Invite: a re-delivered Invite is skipped.
  • Malformed Invite: an EP that names no to recipient or several is not answered with ER. It is received but not understood, so the receiver sends Create(ProcessingFault) to the sender.

Withdraw an embargo invitation

Withdraws an Invite the Case Manager sent for the abandoned proposal. The Case Manager first rejects the proposal it received, which cancels it, then withdraws each Invite it relayed for it. When the Case Manager made the proposal itself, withdrawing that proposal is the cancel.

  • When… the Case Manager abandons an open embargo proposal once the case is public, an exploit is public or attacks are observed
  • Send: Undo(Invite(Event)[context=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": "Undo",
  "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_proposals/1/invites/coordinator/undo",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Undo https://vultron.example/case-actors/vendorco-case-actor Invite Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Invite",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_proposals/1/invites/coordinator",
    "name": "https://vultron.example/case-actors/vendorco-case-actor Invite Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "endTime": "2026-06-08T19:12:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-10-23T20:17:37+00:00",
    "summary": "The vendor proposes to embargo case 1 for 90 days.",
    "to": [
      "https://vultron.example/organizations/coordinator"
    ],
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "actor": "https://vultron.example/case-actors/vendorco-case-actor",
    "object": {
      "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
      "type": "EmbargoEvent",
      "name": "Embargo for VendorCo Case #70930046",
      "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
      "startTime": "2026-06-01T19:12:00+00:00",
      "endTime": "2026-08-30T00:00:00+00:00",
      "published": "2026-06-01T19:12:00+00:00",
      "updated": "2026-06-01T19:12:00+00:00",
      "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
    }
  }
}
  • Triggering transition: Proposed → None (P → N) with the last open proposal, when the Undo withdraws the Case Manager's own proposal; otherwise none.
  • Order: for each abandoned proposal, the cancel comes first: the Case Manager's Reject of a proposal it received, or its Undo of one it made itself. An Undo of each invitation it relayed for the proposal follows, and changes nothing more. All of them are committed together, or none is.
  • Who sends it: only the Case Manager, which undoes only invitations it sent. No use case handles it on receipt.

Create embargo event

Carries the new embargo in full, its start and end times included. It follows the case's genesis entry.

  • When… the Case Manager has created a case and, with it, an embargo such as the default embargo
  • Send: Create(EmbargoEvent)
  • 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:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00/create",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Create Embargo for 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/embargo_events/2026-08-30T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-08-30T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Protocol role: each embargo a case's creation writes, such as the default embargo, is its own ledger entry, right after the case's genesis entry, carrying the embargo in full (CLP-07-013). A replica built from the ledger alone reads the embargo's start and end times from it.
  • Who commits it: only the Case Manager, as a ledger entry. No use case handles it on receipt: each replica stores the embargo from the ledger entry.

Carries the new consent row in full: the embargo it answers, the participant it belongs to and its state.

  • When… the Case Manager creates a participant's consent row for an embargo, such as the UNINVITED row a proposal writes
  • Send: Create(EmbargoConsent)
  • 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:357c22ba-e7ca-5bd7-9ce0-b608143c7def/create",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Create urn:uuid:357c22ba-e7ca-5bd7-9ce0-b608143c7def",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "object": {
    "id": "urn:uuid:357c22ba-e7ca-5bd7-9ce0-b608143c7def",
    "type": "EmbargoConsent",
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "embargoId": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "state": "UNINVITED",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Protocol role: each consent row the Case Manager brings into existence is its own ledger entry, after the act that caused it, carrying the row in full (CLP-07-013). A proposal writes an UNINVITED row for each participant this way.
  • Who sends it: only the Case Manager. No use case handles it on receipt: each replica writes the row from the ledger entry.

Carries the changed consent row in full. A Case Manager with an embargo stake of its own records a change of its own consent this way, never as a Reject of the Invite.

  • When… the Case Manager changes a participant's consent row, such as an invitation timing out, the rows carried over at activation or a change of its own consent
  • Send: Update(EmbargoConsent)
  • 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:357c22ba-e7ca-5bd7-9ce0-b608143c7def/update",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Update urn:uuid:357c22ba-e7ca-5bd7-9ce0-b608143c7def",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "object": {
    "id": "urn:uuid:357c22ba-e7ca-5bd7-9ce0-b608143c7def",
    "type": "EmbargoConsent",
    "attributedTo": "https://vultron.example/organizations/vendorco",
    "embargoId": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "state": "TIMED_OUT",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Protocol role: each consent row the Case Manager changes is its own ledger entry, carrying the changed row in full (CLP-07-013). An invitation whose deadline passes unanswered moves to TIMED_OUT this way, and the rows carried over at activation are written the same way.
  • The Case Manager's own consent: a Case Manager with a stake in the embargo records a change of its own consent as this Update, never as a Reject of the Invite (MSM-07-004).
  • Who sends it: only the Case Manager. No use case handles it on receipt: each replica writes the row from the ledger entry.

Embargo Proposal Acceptance (EA)

Records the sender's own consent to the proposed terms. The embargo becomes active only when the Case Owner sends its decision.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Accept",
  "id": "urn:uuid:f3c7d997-70d0-41f5-b5a5-3b4269831524",
  "name": "https://vultron.example/organizations/vendorco Accept https://vultron.example/organizations/vendorco Invite Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "to": "https://vultron.example/cases/1/participants",
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Invite",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_proposals/1",
    "name": "https://vultron.example/organizations/vendorco Invite Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:37+00:00",
    "updated": "2026-10-23T20:17:37+00:00",
    "summary": "We propose to embargo case 1 for 90 days.",
    "actor": "https://vultron.example/organizations/vendorco",
    "object": {
      "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
      "type": "EmbargoEvent",
      "name": "Embargo for VendorCo Case #70930046",
      "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
      "startTime": "2026-06-01T19:12:00+00:00",
      "endTime": "2026-08-30T00:00:00+00:00",
      "published": "2026-06-01T19:12:00+00:00",
      "updated": "2026-06-01T19:12:00+00:00",
      "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
    }
  }
}
  • Triggering transition: Proposed → Active (P → A), or Proposed → Revise (P → R) while another proposal stays open as a revision (EMB-18-005).
  • Who decides: an Accept of the Invite is always the sender's own consent to those terms, the Case Owner's included. It moves the sender's consent to that embargo to AGREED and changes no embargo on the case (see The Case Owner's Decision, MSM-07-003).
  • The embargo in force: an Accept or Reject may answer an Invite for the embargo already in force, such as a proposal that was activated before the sender answered it, an invitation whose deadline has passed, or a re-invitation after a lapse, while the sender's consent to it is INVITED or TIMED_OUT (EP-09-012). The answer names that Invite by id.

Embargo Revision Proposal (EV)

Proposes a revision to the terms of the active embargo. The wire form is the same as a first proposal; the receiver's EM state makes it a revision.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Invite",
  "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_proposals/2",
  "name": "https://vultron.example/organizations/vendorco Invite Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "summary": "We propose to extend the embargo on case 1 to 120 days.",
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-09-29T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-09-29T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 120 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Triggering transition: Active → Revise (A → R).

Embargo Revision Rejection (EJ)

Records the sender's own refusal of the revision. The Case Owner keeps the prior terms by sending its decision.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Reject",
  "id": "urn:uuid:a17bca64-7de5-4c3b-bd4f-3e957eede6fe",
  "name": "https://vultron.example/organizations/vendorco Reject https://vultron.example/organizations/vendorco Invite Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "to": "https://vultron.example/cases/1/participants",
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Invite",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_proposals/2",
    "name": "https://vultron.example/organizations/vendorco Invite Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:37+00:00",
    "updated": "2026-10-23T20:17:37+00:00",
    "summary": "We propose to extend the embargo on case 1 to 120 days.",
    "actor": "https://vultron.example/organizations/vendorco",
    "object": {
      "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-09-29T00:00:00+00:00",
      "type": "EmbargoEvent",
      "name": "Embargo for VendorCo Case #70930046",
      "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
      "startTime": "2026-06-01T19:12:00+00:00",
      "endTime": "2026-09-29T00:00:00+00:00",
      "published": "2026-06-01T19:12:00+00:00",
      "updated": "2026-06-01T19:12:00+00:00",
      "content": "We propose to embargo VendorCo Case #70930046 for 120 days.",
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
    }
  }
}
  • Triggering transition: Revise → Active (R → A), or Revise → Revise (R → R) while another proposal is open (EMB-18-005).
  • Who decides: as for ER, the Reject is the sender's own refusal (see The Case Owner's Decision).

Embargo Revision Acceptance (EC)

Records the sender's own consent to the revision. The revision replaces the active embargo only when the Case Owner sends its decision.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Accept",
  "id": "urn:uuid:60db7a2f-35e4-4716-8d7c-780ce6bc994b",
  "name": "https://vultron.example/organizations/vendorco Accept https://vultron.example/organizations/vendorco Invite Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "to": "https://vultron.example/cases/1/participants",
  "actor": "https://vultron.example/organizations/vendorco",
  "object": {
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Invite",
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_proposals/2",
    "name": "https://vultron.example/organizations/vendorco Invite Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "published": "2026-10-23T20:17:37+00:00",
    "updated": "2026-10-23T20:17:37+00:00",
    "summary": "We propose to extend the embargo on case 1 to 120 days.",
    "actor": "https://vultron.example/organizations/vendorco",
    "object": {
      "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-09-29T00:00:00+00:00",
      "type": "EmbargoEvent",
      "name": "Embargo for VendorCo Case #70930046",
      "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
      "startTime": "2026-06-01T19:12:00+00:00",
      "endTime": "2026-09-29T00:00:00+00:00",
      "published": "2026-06-01T19:12:00+00:00",
      "updated": "2026-06-01T19:12:00+00:00",
      "content": "We propose to embargo VendorCo Case #70930046 for 120 days.",
      "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
    }
  }
}
  • Triggering transition: Revise → Active (R → A), or Revise → Revise (R → R) while another proposal is open (EMB-18-005).
  • Who decides: as for EA, the Accept is the sender's own consent (see The Case Owner's Decision).

The Case Owner's Decision

The Case Owner decides each embargo proposal for the case with an activity of its own. Its object is the proposed Event itself, not the Invite that proposed it, and its target is the case. Only the Case Owner may send either activity, and it sends them to the Case Manager. Any other sender is refused. The Case Manager records the decision in the case ledger, and every participant learns it from there.

These two activities carry no shorthand of their own. They are how the case takes the EA, EC, ER, and EJ transitions above, while the Accept and Reject of each Invite record each participant's consent.

Activate embargo

Activates the proposal for the case. If an embargo is already active, the proposal replaces it.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Accept",
  "id": "urn:uuid:4d2cba97-1f1d-4672-b50a-a39eac8abfd5",
  "name": "https://vultron.example/organizations/vendorco Accept Embargo for VendorCo Case #70930046 to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "actor": "https://vultron.example/organizations/vendorco",
  "target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-08-30T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}

The activation supersedes the embargo in force, if there is one, in the same register step, and any other open proposal stays open as a revision. The Case Owner's own consent to the activated terms is recorded with it, as AGREED. A Case Owner that had declined those terms may still activate them: activating is the Case Owner changing its answer, so its consent moves straight to AGREED (MSM-07-008). When the new terms end no later than the ones they replace, every participant that agreed to the old terms is carried over to the new ones; when they end later, a participant that has not agreed to them is no longer bound (MSM-07-005). The Case Manager refuses an activation once the case is public, an exploit is public, or attacks are observed, and refuses one whose Event is not an open proposal of the case.

Reject embargo proposal

Rejects the proposal for the case. An active embargo stays in force on its current terms.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Reject",
  "id": "urn:uuid:e3c6af72-4ff9-49f7-94db-ee9c7dae1439",
  "name": "https://vultron.example/organizations/vendorco Reject Embargo for VendorCo Case #70930046 to urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "actor": "https://vultron.example/organizations/vendorco",
  "target": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-08-30T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}

If an embargo is active, it stays in force on its current terms (EJ); otherwise the case has no embargo (ER). While another proposal is still open, the case stays in negotiation. No participant's consent changes, the Case Owner's included. If the case is public, an exploit is public, or attacks are observed when the Case Owner rejects the last open revision, the Case Manager also ends the embargo in the same act (ET). The ledger then holds two entries: the Reject, which leaves the revision rejected, and the Case Manager's own Remove, which leaves the embargo terminated. If the termination is refused, neither entry is committed.

Embargo Termination (ET)

Terminates the embargo with immediate effect.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Remove",
  "id": "urn:uuid:c8cbd807-6f8d-4236-88c6-dd2135b15a83",
  "name": "https://vultron.example/organizations/vendorco Remove Embargo for VendorCo Case #70930046 from urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "content": "EARLY",
  "summary": "The embargo ended before its end time.",
  "actor": "https://vultron.example/organizations/vendorco",
  "origin": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-08-30T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  },
  "terminationCause": {
    "kind": "FIX_DEPLOYED"
  }
}
  • Triggering transition: Active or Revise → eXited ({A,R} → X). The same register step cancels every open proposal, and no participant's consent is written (EP-08-004, MSM-07-006).
  • Reason: content says what ended the embargo, exactly END_TIME_REACHED or EARLY. A receiver refuses a Remove whose content is anything else. summary is a human-readable account that the protocol does not read.
  • Why it ended: terminationCause gives the cause, when the sender names one, and the Case Manager's embargo register records it beside the reason (EMB-13-004, EMB-13-005). Its kind is THREAT_SIGNAL (with the signals P, X or A), FIX_READY (with the vendors whose readiness made the quorum), FIX_DEPLOYED, or OTHER (whose account is the summary). Every cause goes with EARLY; a Remove that carries END_TIME_REACHED names no cause. A receiver refuses a Remove with an unknown kind, a missing or malformed detail, or a cause on END_TIME_REACHED. The Case Owner's Remove may name FIX_READY, FIX_DEPLOYED or OTHER, and the Case Manager records the cause as given. Only the Case Manager's own Remove may name THREAT_SIGNAL. A Case Owner reports public awareness, a public exploit or observed attacks as a case status update setting P, X or A; the Case Manager then ends the embargo with the signals the case carries. Each replica copies the cause from the ledger entry onto its own register, and never works a cause out from its own case state.
  • At the end time: when the end time of the embargo in force has passed, the Case Manager ends it with END_TIME_REACHED. It does so the next time it handles the case, or when an outside service such as a Sentinel asks it to. Whichever comes second finds the embargo already ended and sends nothing. A Remove that claims END_TIME_REACHED before the embargo's end time is refused.
  • Bound participants that are no longer active: a signatory that was removed from the case, or that left it and is at RM CLOSED, stays bound by the embargo but no longer receives ledger entries. The CASE_MANAGER sends each such participant ET directly, one activity per participant, outside the ledger stream. The notice carries the embargo, the reason and the cause the Case Manager recorded, and nothing else. It is not a ledger entry. The participant applies it only when the CASE_MANAGER sent it. A termination on or after the embargo's agreed end date is expiry, and sends no notice.

Tell a participant the embargo has ended

Tells one participant that the embargo has ended, with immediate effect. The Case Manager sends one to each participant other than itself, naming the Case Owner in attributedTo when the Case Owner asked for the termination.

  • When… the Case Manager ends the active embargo, on its own decision or on the Case Owner's
  • Send: Remove(Event)
  • Send to: a participant
  • Sent by: the case manager
  • Seen in: How to Revise or Terminate an Embargo
  • Mapping status: direct

The wire form is the Embargo Termination (ET) a Case Owner sends; only its sender and addressee differ.

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Remove",
  "id": "urn:uuid:0dd76d92-de1a-4c57-81df-47f4b672aba9",
  "name": "https://vultron.example/case-actors/vendorco-case-actor Remove Embargo for VendorCo Case #70930046 from urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "content": "EARLY",
  "summary": "The embargo ended before its end time.",
  "to": [
    "https://vultron.example/organizations/coordinator"
  ],
  "attributedTo": "https://vultron.example/organizations/vendorco",
  "actor": "https://vultron.example/case-actors/vendorco-case-actor",
  "origin": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-08-30T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Recipient: one Remove(Event) per participant other than the CASE_MANAGER, never the CASE_MANAGER itself (EMB-19-001).

Withdraw from embargo

Ends the sender's own consent to the embargo in force, and to any revision it had agreed to. The embargo stays in force for every other participant.

  • When… a Participant bound by the active embargo stops complying with it
  • Send: Leave(Event)[context=VulnerabilityCase]
  • Send to: the case manager
  • Sent by: a participant
  • Seen in: How to Revise or Terminate an Embargo
  • Mapping status: none
{
  "@context": "https://www.w3.org/ns/activitystreams",
  "type": "Leave",
  "id": "urn:uuid:29d56b61-6baa-4d88-a579-b34798b4abfc",
  "name": "https://vultron.example/users/finndervul Leave Embargo for VendorCo Case #70930046",
  "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
  "to": "https://vultron.example/case-actors/vendorco-case-actor",
  "actor": "https://vultron.example/users/finndervul",
  "object": {
    "id": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0/embargo_events/2026-08-30T00:00:00+00:00",
    "type": "EmbargoEvent",
    "name": "Embargo for VendorCo Case #70930046",
    "context": "urn:uuid:d483d06d-400e-47fd-9b8a-9a2643e3a4b0",
    "startTime": "2026-06-01T19:12:00+00:00",
    "endTime": "2026-08-30T00:00:00+00:00",
    "published": "2026-06-01T19:12:00+00:00",
    "updated": "2026-06-01T19:12:00+00:00",
    "content": "We propose to embargo VendorCo Case #70930046 for 90 days.",
    "@context": "https://certcc.github.io/Vultron/ns/context.jsonld"
  }
}
  • Triggering transition: none; the case's EM state does not move. The sender's consent to the embargo in force moves from AGREED to DECLINED (MSM-07-010).
  • Who sends it: a participant that agreed to the embargo in force, sent to the Case Manager. It answers no Invite, so a participant whose consent was recorded when the case was created, or when it joined, can send it too.
  • Open revisions: every open revision the sender had agreed to is declined with it, because each one would replace the embargo it left.
  • Refused: a Leave of an embargo that is not in force, from a sender whose consent to it is not AGREED, or from the Case Owner, which ends an embargo by terminating it (ET).
  • Not a Reject: a Reject of the Invite for the embargo in force, sent by a participant that agreed to it, is refused; withdrawal is this activity (MSM-07-004).

When the Case Manager Refuses a Message

When the Case Manager refuses an embargo message because the case cannot take it, nothing is committed. The Case Manager tells the sender why with the refusal notice (CLP-02-005, CLP-05-001). The notice is a Reject whose object is the refused activity, inline, whose inReplyTo names that activity's id, and whose summary gives the reason. It goes to the sender alone, and the sender closes its pending request when the notice arrives.

Message Refused, with the notice, when
Invite(Event) (EP, EV) the embargo has ended (EM EXITED), which admits no proposal. The notice is a Reject of the Invite, the same shape as a decline, and the proposer reads it as one (EP-09-008).
Accept(Invite(Event)) (EA, EC) the Event is neither the embargo in force nor an open proposal: the register does not hold it, or the proposal was already decided, replaced or ended (CM-18-003).
Reject(Invite(Event)) (ER, EJ) the Event is neither the embargo in force nor an open proposal, or the sender agreed to the embargo in force, since withdrawal is Leave(Event) (MSM-07-004).
Accept(Event)[target=VulnerabilityCase] the Event is not an open proposal of the case, or the case is public, an exploit is public, or attacks are observed (MSM-07-008, EMB-02-002).
Reject(Event)[target=VulnerabilityCase] the Event is not an open proposal of the case, or the termination the rejection would cause is refused (MSM-07-009).
Remove(Event) (ET) it claims END_TIME_REACHED before the embargo's end time, or a Case Owner's Remove names a THREAT_SIGNAL cause (EMB-13-005).
Leave(Event) no embargo is in force, the Event is not the embargo in force, the sender's consent to it is not AGREED, or the sender is the Case Owner (MSM-07-010).

Some deliveries get no notice:

  • A message the sender has no standing to send is refused with no answer (HP-01-006).
  • A repeat of an answer already recorded, under a new id or the same one, is skipped and gets no notice (CM-13-005).
  • An Invite or Accept that arrives once the case is public, an exploit is public, or attacks are observed is answered with ER instead (EMB-01-002, EMB-02-002). The Case Manager's ER to an Accept reaches the participant, which closes its pending Accept.
  • A late Accept of the embargo in force is recorded as an on-time Accept is, and a late Accept of replaced terms is answered with a relayed invitation to the current ones (EMB-17). A late Accept of an embargo the case no longer has changes nothing, so the Case Manager records and sends nothing for it (EMB-17-004).
  • A failure inside the Case Manager is not a refusal, and is never answered with a notice.

Formal messages with no dedicated wire activity

EK — Embargo Acknowledgment

  • Protocol role: Acknowledges receipt of an EM message.
  • Triggering transition: any valid EM message.
  • Wire activity: none dedicated. Acknowledgment of ledger-replicated state is cumulative and implicit through hash-chain continuity; a per-message EK would be redundant (ADR-0083).
  • Formal definition: Message Types.

EE — Embargo Error

  • Protocol role: Indicates a Participant received an unexpected EM message.
  • Triggering transition: any unexpected EM message.
  • Wire activity: none dedicated. Faults are conveyed by Create(ProcessingFault), as:Reject, or Add(Note), partitioned by failure mode (ADR-0083).
  • Formal definition: Message Types.