A participant in Condensation — a user, service, or other entity — is an actor group encompassing one or more devices:
An actor group behaves like a single, consistent entity. Actors within the same group unconditionally trust each other, share (synchronize) their private data, and read each other's messages. Each actor thereby uses its own key pair.
A group may evolve over time. New actors may be added, obsolete members removed, and stolen keys revoked.
All actors in the group are equal. There is no group leader or main actor — unless the application designates such roles.
Group members may use different stores.
Every actor publishes a list of group members on its public card. Conceptually, these cards form a directed graph of actors and their relationships:
If two actors mutually claim to belong together, they are in the same group. In the above example, A, B, and C form a group.
A group's active members should be fully connected. However, when joining an actor, some links may be missing temporarily. A, for example, may just have joined the group through B, and C does not yet know about it.
Unidirectional links may also exist while a new actor (D) is joining the group.
Group members have one of the following status:
- Active members regularly read their messages.
- Idle members just belong to the group, but are not active. They typically correspond to old devices that are not in use any more.
- Revoked members do not belong to the group any more because their private key got exposed.
Note that the distinction between active and idle is based on the member's intent, and not on its actual behavior. An active member may be sleeping for days (or even disappear), and an idle member may suddenly become active again.
Every actor publishes the status of each group member on its public card. This information may not be consistent, and is therefore most-recent merged on a revision timestamp:
In the above example, B set the status of C to idle, and thereby overwrote C's own status declaration.
Note that public cards of idle and revoked members may not be read during group discovery. As a consequence, an active member may switch itself to idle, but an idle member cannot reactivate itself.
Given an actor, its group can be discovered by reading its public card, and that of all associated group members. Often, only the subgroup of active members is of interest.
Starting with A, the above group is discovered as follows:
The resulting active subgroup is [A, B]. Since C is marked idle by B, its public card is ignored.
The origin actor is always considered active to start with, but may may switch to idle (or revoked) throughout the discovery process. This occurs, for instance, when starting the discovery process with C:
Adding a new member
To attach a new actor D to the group, D sends a join request message to the group, and announces its (one-sided) membership on the public card:
An active member of the group (B) validates the request. If approved, it announces D on its public card, and discloses the current private data to the new member.
The content of a join request is specific to the application and its validation procedure. New actors may be validated through a shared group secret, a temporary pin code, or through any other appropriate means.
Removing a member
A member is removed by changing its status to idle (or revoked). This may be done by any active member of the group, including the member to be removed itself.
To send a message to a group, an actor discovers the group, encrypts the message for all active group members, and places the envelope into the in-queue of an active member. Usually, the most recent active member is chosen.
Messages specific to an actor can still be sent to the specific actor rather than to its group.