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.

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.

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: String, aborted_at: PhysicalTime },
    Superseded { by: CeremonyId, reason: SupersessionReason },
}
}

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.

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