Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Ticket issuance

audience: contributors

A coalition may optionally publish a coalition-scoped ticket issuer — a mosaik ticket issuance root whose tickets components may choose to recognise. This page specifies the shape and the composition.

The primitive is deliberately thin. It is not a policy engine; it is not a state machine with Request/Grant semantics; it is not the former Passport spec. It is a mosaik ticket issuance root, folded into CoalitionConfig, with one composition discipline: components opt in.

Shape

#[non_exhaustive]
pub struct TicketIssuerConfig<'a> {
    /// Issuer role / name folded into the derivation.
    pub name: &'a str,
    /// The issuer's ACL composition — how committee
    /// members rotate, which operators run issuance, etc.
    pub acl: AclComposition<'a>,
}

pub const fn coalition_ticket_issuer_root(coalition_root: UniqueId) -> UniqueId {
    coalition_root.derive("tickets")
}

TICKETS_ROOT = COALITION_ROOT.derive("tickets"). The issuer’s TicketIssuerConfig is folded into COALITION_ROOT as an ordered element after confluences.

How components opt in

A confluence, module, or any organism that wants to recognise tickets issued by the coalition-scoped issuer includes TICKETS_ROOT in its own TicketValidator composition:

let validator = TicketValidator::new()
    .recognise_issuer(ETH_SUPERCHAIN.ticket_issuer_root()?)
    .require_ticket(Tdx::new().require_mrtd(confluence_mrtd));

No component is required to. A confluence designed to be referenced by many coalitions typically does not pin any coalition’s issuer, precisely because pinning a coalition would tie its identity to that coalition. A module shipped specifically for one coalition may pin it.

Trust shape

The trust shape is inherited from mosaik’s TicketValidator composition. This page introduces no new primitives:

  • Tickets issued under TICKETS_ROOT are ordinary mosaik tickets whose issuer identity happens to be coalition- scoped.
  • A component that pins the issuer trusts the coalition operator’s issuance discipline at least as far as they trust the ACL composition on that validator branch.
  • A component that does not pin the issuer ignores its tickets entirely.

Because recognition is per-component and voluntary, there is no protocol channel for the coalition to compel recognition. The coalition operator publishes the issuer root; components individually decide whether to trust it.

When to ship an issuer

  • Shared bonding. A coalition running several confluences whose committees cross-bond frequently benefits from a single issuance root rather than N per-confluence roots.
  • Multi-operator recognition. A coalition with multiple operators wanting a convenient common issuance root for ad-hoc identities.

When to skip

  • Single-operator coalitions. The coalition operator already issues their own tickets at the organism level; a separate coalition-scoped root is unnecessary indirection.
  • Open ecosystems. A coalition whose intended value is to stay out of bonding decisions ships no issuer.

Rotation

The coalition operator rotates the issuer ACL the same way any ticket-issuing organism rotates: publish a new TicketIssuerConfig (which bumps TICKETS_ROOT via COALITION_ROOT), update CoalitionConfig to the new issuer, announce through the change channel, and if the coalition ships a Chronicle, record the rotation as ChronicleKind::TicketIssuerRotated.

Components that pin the old root see new tickets fail validation; they pin the new root on their next upgrade. Components that don’t pin at all are unaffected.

Cross-references