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

Operation Categories

This document defines the three-tier classification system for distributed operations in Aura. It specifies the ceremony contract for Category C operations, the consistency metadata types for each category, and the decision framework for categorizing new operations. The core insight is that not all operations require consensus. Many can proceed optimistically with background reconciliation.

1. Overview

Operations in Aura fall into three categories based on their effect timing and security requirements.

CategoryNameEffect TimingWhen Used
AOptimisticImmediate local effectLow-risk operations within established contexts
BDeferredPending until confirmedMedium-risk policy/membership changes
CConsensus-GatedBlocked until ceremony completesCryptographic context establishment

Agreement modes are orthogonal to categories. Operations can use provisional or soft-safe fast paths, but any durable shared state must be consensus-finalized (A3). See Consensus for the fast-path and finalization taxonomy.

1.1 Key Generation Methods

Aura separates key generation from agreement:

CodeMethodDescription
K1Single-signerNo DKG required. Local key generation.
K2Dealer-based DKGTrusted coordinator distributes shares.
K3Consensus-finalized DKGBFT-DKG with transcript commit.
DKDDistributed key derivationMulti-party derivation without DKG.

1.2 Agreement Levels

CodeLevelDescription
A1ProvisionalUsable immediately but not final.
A2Coordinator Soft-SafeBounded divergence with convergence certificate.
A3Consensus-FinalizedUnique, durable, non-forkable.

Fast paths (A1/A2) are provisional. Durable shared state must be finalized by A3.

1.3 The Key Architectural Insight

Ceremonies establish shared cryptographic context. Operations within that context are cheap.

Ceremony (Category C)                    Optimistic Operations (Category A)
─────────────────────                    ─────────────────────────────────
• Runs once per relationship             • Within established context
• Establishes ContextId + shared roots   • Derive keys from context
• Creates relational context journal     • Just emit CRDT facts
• All future encryption derives here     • No new agreement needed

2. Category A: Optimistic Operations

Category A operations have immediate local effect via CRDT fact emission. Background sync via anti-entropy propagates facts to peers. Failure shows a status indicator but does not block functionality. Partial success is acceptable.

2.1 Examples

OperationImmediate ActionBackground SyncOn Failure
Create channelShow channel, enable messagingFact syncs to membersShow "unsynced" badge
Send messageDisplay in chat immediatelyDelivery receiptsShow "undelivered" indicator
Add contact (within context)Show in listMutual acknowledgmentShow "pending" status
Block contactHide from view immediatelyPropagate to contextAlready effective locally
Update profileShow changes immediatelyPropagate to contactsShow sync indicator
React to messageShow reactionFact syncsShow "pending"

2.2 Implementation Pattern

#![allow(unused)]
fn main() {
async fn create_channel_optimistic(&mut self, config: ChannelConfig) -> ChannelId {
    let channel_id = ChannelId::derive(&config);

    self.emit_fact(ChatFact::ChannelCheckpoint {
        channel_id,
        epoch: 0,
        base_gen: 0,
        window: 1024,
    }).await;

    channel_id
}
}

This pattern emits a fact into the existing relational context journal. The channel is immediately usable. Key derivation uses KDF(ContextRoot, ChannelId, epoch).

2.3 Why This Works

Category A operations work because encryption keys already exist (derived from established context), facts are CRDTs (eventual consistency is sufficient), no coordination is needed (shared state already agreed upon), and the worst case is delay rather than a security issue.

The CRDT property is a contract on the fact family, not on transport. Each family is reduced by a pure, order-independent function of its fact set: reversible state uses the observed-remove set, multi-value register and episode patterns, writers stamp causal metadata with a logical clock, and physical time is display-only. See the canonical domain fact model in docs/105_journal.md §4.2.1.

3. Category B: Deferred Operations

Category B operations have local effect pending until agreement is reached. The UI shows intent immediately with a "pending" indicator. Operations may require approval from capability holders. Automatic rollback occurs on rejection.

3.1 Examples

OperationImmediate ActionAgreement RequiredOn Rejection
Change channel permissionsShow "pending"Moderator approvalRevert, notify
Remove channel memberShow "pending removal"Moderator consensusKeep member
Transfer ownershipShow "pending transfer"Recipient acceptanceCancel transfer
Rename channelShow "pending rename"Member acknowledgmentKeep old name
Archive channelShow "pending archive"Moderator approvalStay active

3.2 Implementation Pattern

#![allow(unused)]
fn main() {
async fn change_permissions_deferred(
    &mut self,
    channel_id: ChannelId,
    changes: PermissionChanges,
) -> ProposalId {
    let proposal = Proposal {
        operation: Operation::ChangePermissions { channel_id, changes },
        requires_approval_from: vec![CapabilityRequirement::Role("moderator")],
        threshold: ApprovalThreshold::Any,
        timeout_ms: 24 * 60 * 60 * 1000,
    };

    let proposal_id = self.emit_proposal(proposal).await;
    proposal_id
}
}

This pattern creates a proposal that does not apply the effect yet. The UI shows "pending" state. The effect applies when threshold approvals are received. Auto-revert occurs on timeout or rejection.

3.3 Approval Thresholds

#![allow(unused)]
fn main() {
pub enum ApprovalThreshold {
    Any,
    Unanimous,
    Threshold { required: u32 },
    Percentage { percent: u8 },
}
}

Any requires any single holder of the required capability. Unanimous requires all holders to approve. Threshold requires k-of-n approval. Percentage requires a percentage of holders.

4. Category C: Consensus-Gated Operations

Category C operations do NOT proceed until a ceremony completes. Partial state would be dangerous or irrecoverable. The user must wait for confirmation. These operations use choreographic protocols with session types, executed through Aura’s Telltale runtime.

4.1 Examples

OperationWhy Blocking RequiredRisk if Optimistic
Add contact (new relationship)Creates cryptographic contextNo shared keys possible
Create groupMulti-party key agreementInconsistent member views
Add member to groupChanges group keysForward secrecy violation
Device enrollmentKey shares distributed atomicallyPartial enrollment unusable
Guardian rotationKey shares distributed atomicallyPartial rotation unusable
Recovery executionAccount state replacementPartial recovery corruption
OTA hard forkScope-bound breaking protocol changeExplicit partition or rejected incompatible sessions outside the cutover scope
Device revocationSecurity-critical removalAttacker acts first

4.2 Implementation Pattern

#![allow(unused)]
fn main() {
async fn add_contact(&mut self, invitation: Invitation) -> Result<ContactId> {
    let ceremony_id = self.ceremony_executor
        .initiate_invitation_ceremony(invitation)
        .await?;

    loop {
        match self.ceremony_executor.get_status(&ceremony_id)? {
            CeremonyStatus::Committed => {
                return Ok(ContactId::from_ceremony(&ceremony_id));
            }
            CeremonyStatus::Aborted { reason } => {
                return Err(AuraError::ceremony_failed(reason));
            }
            _ => {
                tokio::time::sleep(POLL_INTERVAL).await;
            }
        }
    }
}
}

This pattern blocks until the ceremony completes. The user sees progress UI during execution. Context is established only on successful commit.

5. Ceremony Contract

All Category C ceremonies follow a shared contract that ensures atomic commit/abort semantics.

5.1 Ceremony Phases

  1. Compute prestate: Derive a stable prestate hash from the authority/context state being modified. Include the current epoch and effective participant set.

  2. Propose operation: Define the operation being performed. Compute an operation hash bound to the proposal parameters.

  3. Enter pending epoch: Generate new key material at a pending epoch without invalidating the old epoch. Store metadata for commit or rollback.

  4. Collect responses: Send invitations/requests to participants. Participants respond using their full runtimes. Responses must be authenticated and recorded as facts.

  5. Commit or abort: If acceptance/threshold conditions are met, commit the pending epoch and emit resulting facts. Otherwise abort, emit an abort fact with a reason, and leave the prior epoch active.

5.2 Ceremony Properties

All Category C ceremonies implement:

  1. Prestate Binding: CeremonyId = H(prestate_hash, operation_hash, nonce) prevents concurrent ceremonies on same state and ensures exactly-once semantics.

  2. Atomic Commit/Abort: Either fully committed or no effect. No partial state possible.

  3. Epoch Isolation: Uncommitted key packages are inert. No explicit rollback needed on abort.

  4. Session Types: Protocol compliance enforced at compile time via choreographic projection and enforced at runtime via Telltale adapter/VM execution.

5.3 Per-Ceremony Policy Matrix

Authority and Device Ceremonies

CeremonyKey GenAgreementFallbackNotes
Authority bootstrapK1A3NoneLocal, immediate
Device enrollmentK2A1→A2→A3A1/A2Provisional → soft-safe → finalize
Device MFA rotationK3A2→A3A2Consensus-finalized keys
Device removalK3A2→A3A2Remove via rotation

Guardian Ceremonies

CeremonyKey GenAgreementFallbackNotes
Guardian setup/rotationK3A2→A3A2Consensus-finalized for durability
Recovery approvalA2→A3A2Soft-safe approvals → consensus
Recovery executionA2→A3A2Consensus-finalized commit

Channel and Group Ceremonies

CeremonyKey GenAgreementFallbackNotes
AMP channel epoch bumpA1→A2→A3A1/A2Proposed → cert → commit
AMP channel bootstrapA1→A2→A3A1/A2Provisional → group key rotation
Group/Block creationK3A1→A2→A3A1/A2Provisional bootstrap → consensus
Rendezvous secure-channelA1→A2→A3A1/A2Provisional → consensus

Other Ceremonies

CeremonyKey GenAgreementFallbackNotes
Invitation (contact/channel/guardian)A3NoneConsensus-finalized only
OTA activationA2→A3A2Threshold-signed → consensus
DKD ceremonyDKDA2→A3A2Multi-party derivation → commit

5.4 Bootstrap Exception

When creating a new group/channel before the group key ceremony completes, Aura allows a bootstrap epoch using a trusted-dealer key (K2/A1). The dealer distributes a bootstrap key with the channel invite, enabling immediate encrypted messaging. This is explicitly provisional and superseded by the consensus-finalized group key (K3/A3) once the ceremony completes.

5.5 AMP Channel Epoch Transition Refinement

AMP channel epoch transitions use the existing A1 -> A2 -> A3 agreement ladder with an AMP-specific live-state rule. This rule applies only to AMP channel epoch and membership state inside a relational context. It does not weaken authority-root membership, account commitment trees, guardian rotation, or recovery execution.

For a channel transition:

  • A1 observed means a syntactically valid successor proposal exists as a journal fact, but it has no live operational authority.
  • A2Live means exactly one unsuppressed AMP-certified successor exists for the parent epoch and deterministic reduction exposes that successor as the live epoch for AMP send and receive policy.
  • A3Finalized means consensus-backed commit facts durably finalize a successor. The normal path finalizes the same transition_id previously exposed as A2Live.

A2Live is operationally authoritative but non-durable. It may drive live AMP traffic before full A3 finalization, but durable shared state still requires the A3 consensus boundary described in Consensus.

Every AMP transition fact binds a canonical transition_id, a typed digest over:

  • context_id
  • channel_id
  • parent_epoch
  • parent_commitment
  • successor_epoch
  • successor_commitment
  • membership_commitment
  • transition_policy

Proposals, A2 certificates, A3 commits, aborts, conflicts, and supersessions refer to the same transition only when this full identity matches. A different successor for the same parent is a conflicting transition.

The reducer states for a parent transition group are:

StateMeaning
ObservedProposal facts exist, but no live certificate is valid.
A2LiveExactly one valid unsuppressed AMP certificate selects a successor.
A2ConflictConflicting valid certificates or unresolved equivocation evidence suppress live exposure.
A3FinalizedConsensus-backed commit finalizes one successor.
A3ConflictConflicting durable commit evidence suppresses live exposure.
AbortedExplicit abort evidence invalidates the proposal for live use.
SupersededAuthorized supersession replaces an earlier transition path.

The reducer must never choose between conflicting valid A2 certificates by arrival order, local preference, wall-clock time, or deterministic tie-breaking. If facts do not prove a single winner, no live successor is exposed.

AMP transition policies distinguish additive and non-removal transitions from subtractive, removal, revocation, and emergency transitions. Additive transitions may permit bounded dual-epoch receive overlap. Subtractive and emergency transitions require stricter old-epoch acceptance so removed or suspected participants do not retain indefinite send authority.

Emergency AMP transitions are channel-scoped control-plane transitions:

  • EmergencyQuarantineTransition excludes a suspect from the successor epoch, cuts new sends over immediately, minimizes old-epoch receive grace, and rotates or erases old secret material aggressively.
  • EmergencyCryptoshredTransition uses the strongest channel-scoped bar and destroys ordinary pre-emergency readable state at the A2Live cutover boundary.

Emergency channel facts do not automatically remove authority-root membership or suspend recovery/governance rights. Those require separate authority-scoped governance facts and their own thresholds.

6. Consistency Metadata

Each operation category has a purpose-built status type for tracking consistency.

6.1 Core Types

#![allow(unused)]
fn main() {
pub enum Agreement {
    Provisional,
    SoftSafe { cert: Option<ConvergenceCert> },
    Finalized { consensus_id: ConsensusId },
}

pub enum Propagation {
    Local,
    Syncing { peers_reached: u16, peers_known: u16 },
    Complete,
    Failed { retry_at: PhysicalTime, retry_count: u32, error: String },
}

pub struct Acknowledgment {
    pub acked_by: Vec<AckRecord>,
}
}

Agreement indicates the finalization level (A1/A2/A3). Propagation tracks anti-entropy sync status. Acknowledgment tracks explicit per-peer delivery confirmation.

6.2 Category A: OptimisticStatus

#![allow(unused)]
fn main() {
pub struct OptimisticStatus {
    pub agreement: Agreement,
    pub propagation: Propagation,
    pub acknowledgment: Option<Acknowledgment>,
}
}

Use cases include send message, create channel, update profile, and react to message.

UI patterns:

  • ◐ Sending: propagation == Local
  • ✓ Sent: propagation == Complete
  • ✓✓ Delivered: acknowledgment.count() >= expected.len()
  • ◆ Finalized: agreement == Finalized

6.3 Category B: DeferredStatus

#![allow(unused)]
fn main() {
pub struct DeferredStatus {
    pub proposal_id: ProposalId,
    pub state: ProposalState,
    pub approvals: ApprovalProgress,
    pub applied_agreement: Option<Agreement>,
    pub expires_at: PhysicalTime,
}

pub enum ProposalState {
    Pending,
    Approved,
    Rejected { reason: String, by: AuthorityId },
    Expired,
    Superseded { by: ProposalId },
}
}

Use cases include change permissions, remove member, transfer ownership, and archive channel.

6.4 Category C: CeremonyStatus

#![allow(unused)]
fn main() {
pub struct CeremonyStatus {
    pub ceremony_id: CeremonyId,
    pub state: CeremonyState,
    pub responses: Vec<ParticipantResponse>,
    pub prestate_hash: Hash32,
    pub committed_agreement: Option<Agreement>,
}

pub enum CeremonyState {
    Preparing,
    PendingEpoch { pending_epoch: Epoch, required_responses: u16, received_responses: u16 },
    Committing,
    Committed { consensus_id: ConsensusId, committed_at: PhysicalTime },
    Aborted { reason: CeremonyFailureReason, aborted_at: PhysicalTime },
    Superseded { by: CeremonyId, reason: SupersessionReason },
}

pub enum CeremonyFailureReason {
    Rejected,
    Cancelled,
    TimedOut,
    ChoreographyFailed,
    RuntimeFailed,
    Superseded,
}
}

Use cases include add contact, create group, guardian rotation, device enrollment, and recovery.

When a ceremony commits successfully, committed_agreement is set to Agreement::Finalized with the consensus ID, indicating A3 durability.

An issued invitation or enrollment code is the terminal result of code issuance, not the terminal result of the ceremony it starts. Enrollment completion has a separate operation instance linked to the ceremony ID. The initiator and invitee derive completion from the same authoritative ceremony outcome. A completion instance has exactly one terminal result: committed, cancelled, rejected, or timed out. The first terminal result is stable under duplicate, late, and replayed messages; a conflicting later result cannot replace it. Failure and cancellation carry stable, typed reasons independently of display text. An unauthenticated response cannot terminate a valid ceremony.

An enrollment request must match the issued invitation's subject authority, invitation, ceremony, target device and pending epoch. Successful confirmation must identify that same invitation and ceremony, explicitly establish enrollment, and carry the expected resulting epoch. A mismatch is a typed failure rather than an observation of completion. Matching message contents alone does not establish authentication or commit provenance.

Enrollment setup statements bind the exporting authority, physical device, request nonce, bounded validity interval, signing epoch, signing mode, threshold policy and public key package in a dedicated canonical signing transcript. Possession verification requires the proof's epoch and package to match that statement and produces sealed, non-deserializable evidence. This evidence certifies possession of the embedded key only. Association with the intended physical device requires explicit user transfer or an independently authenticated binding; decoding or self-certification cannot establish that association.

The initiator retains the selected setup statement and digest with its subject, ceremony, pending epoch and physical initiator before admitting response owners. Enrollment acceptance requires proof under that retained provisional package, epoch, mode and signer policy. A missing verifier record, unknown record version, corrupt binding or response-supplied substitute key cannot count a participant. The setup expiry gates issuance; an admitted response remains subject to the invitation and ceremony deadline. Persisted verifier selection alone does not prove baseline authentication, authenticated refusal, nonce consumption, first-decision persistence or atomic activation.

Issuance reserves its invitation identity before fact preparation or delivery. The reservation has one physical issuer and is consumed by the preparation owner. The complete signed payload binds that identity before publication; later payload repair cannot change an already committed invitation. Invalid or overflowing expiration fails before preparation mutates authoritative state.

A signed setup admission includes the setup nonce/digest, both device identities, subject and provisional authority, invitation/ceremony, pending epoch, manifest digest and exact-parent verifier inventory digest. Its expected verification key comes from the independently pinned manifest inventory at the exact prestate; the pending enrollment package and the receipt's embedded key are insufficient. Signature-only evidence remains separate from authenticated admission provenance. An invitee response owner requires that provenance and locally owned admission and revocation state before selecting a retained historical signing share.

6.5 Unified Consistency Type

For cross-category queries and generic handling:

#![allow(unused)]
fn main() {
pub struct Consistency {
    pub category: OperationCategory,
    pub agreement: Agreement,
    pub propagation: Propagation,
    pub acknowledgment: Option<Acknowledgment>,
}

pub enum OperationCategory {
    Optimistic,
    Deferred { proposal_id: ProposalId },
    Ceremony { ceremony_id: CeremonyId },
}
}

7. Ceremony Supersession

When a new ceremony replaces an old one, Aura emits explicit supersession facts that propagate via anti-entropy.

7.1 Supersession Reasons

#![allow(unused)]
fn main() {
pub enum SupersessionReason {
    PrestateStale,
    NewerRequest,
    ExplicitCancel,
    Timeout,
    Precedence,
}
}

PrestateStale indicates the prestate changed while the ceremony was pending. NewerRequest indicates an explicit newer request from the same initiator. ExplicitCancel indicates manual cancellation by an authorized participant. Timeout indicates the ceremony exceeded its validity window. Precedence indicates a concurrent ceremony won via conflict resolution.

7.2 Supersession Facts

Each ceremony fact enum includes a CeremonySuperseded variant:

#![allow(unused)]
fn main() {
CeremonySuperseded {
    superseded_ceremony_id: String,
    superseding_ceremony_id: String,
    reason: String,
    trace_id: Option<String>,
    timestamp_ms: u64,
}
}

7.3 CeremonyTracker API

The CeremonyTracker in aura-agent maintains supersession records for auditability:

MethodPurpose
supersede(old_id, new_id, reason)Record a supersession event
check_supersession_candidates(prestate_hash, op_type)Find stale ceremonies
get_supersession_chain(ceremony_id)Get full supersession history
is_superseded(ceremony_id)Check if ceremony was replaced

Supersession facts propagate via the existing anti-entropy mechanism. Peers receiving a CeremonySuperseded fact update their local ceremony state accordingly.

8. Decision Tree

Use this tree to categorize new operations:

Does this operation establish or modify cryptographic relationships?
│
├─ YES: Does the user need to wait for completion?
│       │
│       ├─ YES (new context, key changes) → Category C (Blocking Ceremony)
│       │   Examples: add contact, create group, guardian rotation
│       │
│       └─ NO (removal from existing context) → Category B (Deferred)
│           Examples: remove from group (epoch rotation in background)
│
└─ NO: Does this affect other users' access or policies?
       │
       ├─ YES: Is this high-security or irreversible?
       │       │
       │       ├─ YES → Category B (Deferred)
       │       │   Examples: transfer ownership, delete channel, kick member
       │       │
       │       └─ NO → Category A (Optimistic)
       │           Examples: pin message, update topic
       │
       └─ NO → Category A (Optimistic)
           Examples: send message, create channel, block contact

9. UI Feedback Patterns

9.1 Category A: Instant Result with Sync Indicator

┌───────────────────────────────────┐
│ You: Hello everyone!         ◆ ✓✓ │  ← Finalized + Delivered
│ You: Check this out            ✓✓ │  ← Delivered (not yet finalized)
│ You: Another thought           ✓  │  ← Sent
│ You: New idea                  ◐  │  ← Sending
└───────────────────────────────────┘

Effect already applied. Indicators show delivery status (◐ → ✓ → ✓✓ → ✓✓ blue) and finalization (◆ appears when A3 consensus achieved).

9.2 Category B: Pending Indicator

┌─────────────────────────────────────────────────────────────────────┐
│ Channel: #project                                                   │
├─────────────────────────────────────────────────────────────────────┤
│ Pending: Remove Carol (waiting for Bob to confirm)                  │
├─────────────────────────────────────────────────────────────────────┤
│ Members:                                                            │
│   Alice (moderator)    ✓                                            │
│   Bob (moderator)      ✓                                            │
│   Carol                ✓  ← Still has access until confirmed        │
└─────────────────────────────────────────────────────────────────────┘

Proposal shown. Effect NOT applied yet.

9.3 Category C: Blocking Wait

┌─────────────────────────────────────────────────────────────────────┐
│                    Adding Bob to group...                           │
│                                                                     │
│    ✓ Invitation sent                                                │
│    ✓ Bob accepted                                                   │
│    ◐ Deriving group keys...                                         │
│    ○ Ready                                                          │
│                                                                     │
│                      [Cancel]                                       │
└─────────────────────────────────────────────────────────────────────┘

User waits. Cannot proceed until ceremony completes.

10. Effect Policy Configuration

Operations use configurable policies that reference the capability system:

#![allow(unused)]
fn main() {
pub struct EffectPolicy {
    pub operation: OperationType,
    pub timing: EffectTiming,
    pub security_level: SecurityLevel,
}

pub enum EffectTiming {
    Immediate,
    Deferred {
        requires_approval_from: Vec<CapabilityRequirement>,
        timeout_ms: u64,
        threshold: ApprovalThreshold,
    },
    Blocking {
        ceremony: CeremonyType,
    },
}
}

10.1 Context-Specific Overrides

Contexts can override default policies:

#![allow(unused)]
fn main() {
// Strict security channel: unanimous moderator approval for kicks
channel.set_effect_policy(RemoveFromChannel, EffectTiming::Deferred {
    requires_approval_from: vec![CapabilityRequirement::Role("moderator")],
    timeout_ms: 48 * 60 * 60 * 1000,
    threshold: ApprovalThreshold::Unanimous,
});

// Casual channel: any moderator can kick immediately
channel.set_effect_policy(RemoveFromChannel, EffectTiming::Immediate);
}

11. Full Operation Matrix

OperationCategoryEffect TimingSecurityNotes
Within Established Context
Send messageAImmediateLowKeys already derived
Create channelAImmediateLowJust facts into context
Update topicAImmediateLowCRDT, last-write-wins
React to messageAImmediateLowLocal expression
Local Authority
Block contactAImmediateLowYour decision
Mute channelAImmediateLowLocal preference
Policy Changes
Change permissionsBDeferredMediumOthers affected
Kick from channelBDeferredMediumAffects access
Archive channelBDeferredLow-MedReversible
High Risk
Transfer ownershipBDeferredHighIrreversible
Delete channelBDeferredHighData loss
Remove from contextBDeferredHighAffects encryption
Cryptographic
Add contactCBlockingCriticalCreates context
Create groupCBlockingCriticalMulti-party keys
Add group memberCBlockingCriticalChanges group keys
Device enrollmentCBlockingCriticalDeviceEnrollment choreography
Guardian rotationCBlockingCriticalKey shares
Recovery executionCBlockingCriticalAccount state
Device revocationCBlockingCriticalSecurity response

12. Common Mistakes to Avoid

Mistake 1: Making Everything Category C

Wrong: "Adding a channel member requires ceremony"

Right: If the member is already in the relational context, it is Category A. Just emit a fact. Only if they need to join the context first is it Category C.

Mistake 2: Forgetting Context Existence

Wrong: Trying to create a channel before establishing relationship

Right: Contact invitation (Category C) must complete before any channel operations (Category A) are possible.

Mistake 3: Optimistic Key Operations

Wrong: "User can start using new guardians while ceremony runs"

Right: Guardian changes affect key shares. Partial state means unusable keys. Must be Category C.

Mistake 4: Blocking on Low-Risk Operations

Wrong: "Wait for all members to confirm before showing channel"

Right: Channel creation is optimistic. Show immediately, sync status later.

See Also

Enrollment manifest ownership

Exporting setup or manifest transfer material is read-only with respect to enrollment business state. Invitation reservation and pending generation ownership precede key writes; signed manifest retention precedes invitation publication. Import admission requires the app-issued explicit transfer selection and produces a runtime-private, non-deserializable witness. The bootstrap session consumes that witness without changing global transport identity or durable membership. Enrollment acceptance and activation require their separate verified response and registered generation permissions.

The app owns the complete manifest-pin, import, acceptance, and convergence lifecycle under one ImportDeviceEnrollmentCode operation. Frontends transfer submission ownership before the first awaited workflow step. Missing transfer input is a typed terminal failure before import mutation. Browser persistence consumes only the app-issued completed enrollment result after acceptance and adoption; received authority/device identifiers cannot stage that result.

Enrollment invitee adoption is the application of an authenticated committed ceremony result. Its local persistence and signing-context activation consume runtime-owned durable confirmation evidence for the exact imported generation. They are not independent agreement operations, and local accepted status or receipt locator fields do not authorize adoption. Generic key-rotation commit is not an alternate enrollment activation path.

Enrollment initiation under an active quorum

Preparing an enrollment signing intent retains the original issuer allocation and establishes neither enrollment success nor local signing consent. Each active physical participant independently approves the exact manifest, public transport commitment, initial Request, issuer return mailbox statement and finite negative terminal policy under its current authenticated policy. Resuming that allocation may produce a pending enrollment code only after the four initiation signatures verify. The policy is conditional consent, not a fifth initiation signature. A later Failed control also requires the original protected first negative decision and retained participant custody. Committed control, durable membership and invitee activation retain their separate agreement and evidence requirements.