Meshline
English translationDownload Markdown

The Simplified Chinese text is authoritative.

Group Core Objects

Group hosting protocol

Group ID

The creator generates a new 16-byte nonce, never reused by the same creator on the same relay; a cryptographically secure random source is recommended. Compute SHA-256 over the network-bound JSON input of this identity object:

{
  "$type": "meshline.group.identity",
  "creator": "neo:860833102:...",
  "nonce": "base64url...",
  "relay_id": "0x..."
}

creator is the initial owner and relay_id the selected host; both and nonce remain unchanged throughout the group lifecycle. The group ID is as follows, where group_identity_input means the group identity object above:

group_id = "grp_" + base64url(first_16_bytes(SHA-256(network_bound_json_bytes(group_identity_input))))

group_id MUST match ^grp_[A-Za-z0-9_-]{22}$. Name, description, members, capacity, invitation policy, event positions, and key epochs do not participate. The ID binds the host but does not reveal it by reverse derivation.

GroupState

GroupState is current group state maintained by the host:

Field Type Required Semantics and constraints
group_id string Yes Group described by this state
name string Yes Current name; MUST include a non-whitespace character; at most 256 UTF-8 bytes
description string No Current description; omission means no description; if nonempty, MUST NOT be solely whitespace; at most 4 KiB (4,096 UTF-8 bytes)
status string Yes active means existing; closed means permanently closed
owner string Yes Owner account, appearing exactly once in current membership with role owner
member_capacity integer Yes Positive member-count limit; may temporarily be below current count, retaining existing members but rejecting further admission
member_count integer Yes Positive current count, including owner and administrators
invite_policy string Yes Invitation policy; owner and administrators are not restricted by it

invite_policy means:

Value Invitations ordinary members may create
administrators None
members_targeted Only targeted invitations naming invitee
members_shareable Targeted and public invitations

Membership is indexed by group and account IDs and contains account, role, and member_encryption_public_key. Clients establish membership, roles, and keys from the verified administration chain.

While the group exists, the relay MUST retain current state and membership. State-changing methods MUST atomically update projections and append corresponding events.

GroupEvent

GroupEvent is an authoritative timeline entry appended by the host for administration, key rotation, and messages:

Field Type Required Semantics and constraints
sequence integer Yes Unique assigned position; creation is 0, later values strictly exceed the prior head without required continuity. Clients use it for ordering, pagination, and message references
epoch integer Yes Key epoch after the event; creation is 0, messages MUST match their envelope, and events not advancing keys retain the preceding event's epoch in the complete timeline
payload object Yes Complete event body identified by payload.$type; structure and handling follow its object/method definition
accepted_at integer Yes Relay acceptance UTC Unix seconds, used for retention, not as a substitute for sequence ordering
signer_device_id string Conditional Device verified at client-write acceptance; required for client events, referencing group.sync certificates, and omitted for relay-initiated rotation

Across the complete timeline, epoch is nondecreasing without required continuity.

Messages have payload.$type = meshline.group.message and may expire under Retention and access. Other events are administration events, permanently retained with verification certificates.

Message filtering/pruning or starting mid-history may make adjacent visible events nonadjacent in the full timeline. Administration events are unrestricted by message intervals and MUST NOT be pruned; complete synchronization from creation obtains all of them. Epoch handling follows group.sync.

Invitation creation/revocation, application submission/rejection, key-reset request submission/replacement/withdrawal/rejection, and client-secret rotation preparation do not enter the timeline. Approvers verify these pending records when acting. Join approval records authorized accounts and keys; reset approval records accounts and new keys. Banning and unbanning affect future permissions, so successful calls MUST write complete signed requests into the administration chain.

Relay Secret Rotation Events

Relay-initiated rotation generates this payload:

Field Type Required Semantics and constraints
$type string Yes Fixed as meshline.group.key.rotated

The new epoch is outer GroupEvent.epoch. This relay-generated body carries no device_signature, and outer signer_device_id MUST be omitted. Clients check the fixed type and epoch advancement. It is permanently retained but changes neither members, roles, bans, client-secret commitment, nor administration head.

Administration Chain

Participating Events and Predecessor References

The chain links only client-signed administration events actually written to the timeline. Messages and relay rotations do not advance it. Participating body types are:

Body $type Effect
meshline.group.create Establish group, initial owner, and client-secret commitment
meshline.group.application.approval Admit members
meshline.group.update Change properties
meshline.group.role.update Change administrative roles
meshline.group.owner.transfer Transfer ownership
meshline.group.member.leave Signing account leaves
meshline.group.member.removal Remove target members
meshline.group.member.recovery.approval Approve new member public keys
meshline.group.secret.rotation Update commitment and optional owner key
meshline.group.member.ban Ban targets and remove current members among them
meshline.group.member.unban Lift bans
meshline.group.close Permanently close

Creation starts the chain without prev_hash. Every other listed request's signed body MUST carry the previous locally verified administration digest as prev_hash, matching ^sha256:[A-Za-z0-9_-]{43}$, decoding to 32 bytes in canonical unpadded base64url. It is signed with all business fields and cannot be added or rewritten by the relay after verification. Requests not written do not advance the chain; message envelopes and relay-rotation bodies do not define this field.

Administration Digest Calculation

For administration event E, hash the network-bound input of complete payload, retaining root device_signature and all unknown properties:

management_hash(E) = network_bound_json_hash(E.payload)

Construction follows Network-bound JSON inputs. The digest includes the body signature; body signing excludes only root device_signature. signer_device_id locates the certificate; clients still MUST verify certificate, body signature, and account permission. Other outer fields retain ordering, time, and key checks. The next operation references management_hash(E).

Relay Commit and Concurrency Control

Relays MUST validate session, signature, and caller permissions. Creation establishes the starting point under group.create. Other requests MUST have prev_hash equal to the current head, with both permission and equality still holding at activation. Violating field constraints returns bad_request.

Success MUST append an administration event and update the head. Request evidence, state, event, timeline head, and administration head MUST commit atomically.

Of two requests citing one head, only one can succeed. To resubmit the other, synchronize new events, recheck permissions and operation content, and sign again. Clients MUST NOT replace only the digest while reusing the old signature.

Client Verification and Recovery

Chain Verification and State Reconstruction

Initially verify from creation: check expected ID derivation, creator account, certificate, and creation signature, establish state, and compute the head. Then verify each prev_hash, signature, and signer's membership, role, and ban state in the preceding state, apply the method's effects, and compute the new head.

Members are distinct by account, with no duplicates; roles are owner, administrator, or member. Creation establishes the owner; admission establishes ordinary members. Role changes, transfers, leaving, removal/banning, reset approval, and client rotation modify membership under their methods. Rejoining uses the newly approved key and cannot restore the old member record. Pending applications/resets do not change effective state.

Bans start empty. Clients obtain events through group.sync, adding and removing accounts according to verified ban/unban requests to reconstruct the set.

Applicants and resetting members sign complete requests containing their public keys. Approvers independently verify request signatures, certificates, and account binding, then sign those accounts and keys in approval objects. Other clients verify approval events and prior approver authority. Public-key sourcing and validation before secret wrapping MUST follow Client secret boxes.

Verification Interruption and Recovery

Missing intermediate administration events, invalid signatures, unauthorized operations, or uninterpretable administration extensions block later state verification; ordinary-message rejection rules MUST NOT be used to skip them. Unknown client administration body types MUST pause the projection until an extension defines hashing participation and state rules. Clients may retain them for reprocessing. Unknown properties still participate in hashes and signatures but affect state only as defined by known method fields.

On local reload, verified administration head, membership, bans, and synchronization position MUST remain consistent. Continue the verified chain rather than replacing it with a relay snapshot. On verification failure, stop applying later administration events and report an error. Missing records may be requested again through group.sync.