trust-protocol

RLTP Membership Tasks

Real Life Trust Protocol — task types: Membership

Abstract

This document registers the task types with which membership changes of an RLTP group travel between people: the invitation and its explicit acceptance, and the carrier that delivers the admitting operation and its welcome to a new member across the replica boundary. (The removal notice a removed member is owed travels as the Access layer’s own compact task, removal-notice/0.1 — Access §10.2; transition-bearing operation envelopes never cross the replica boundary at all, Access §5.3.)

The dividing line is the replica boundary: inside a group, the authority log replicates as shared state, and exactly one operation crosses the boundary as a task — the admitting member.add delivered to its own subject, the invitee who is not yet a member and holds no replica to receive it from. The removed member, whom the capability gate has just shut out, is owed a signed claim rather than an operation (Access removal-notice/0.1, its §10.2). The log is canonical; a task is a feeder, never a second truth. Authority never comes from a task: every operation carries its own signatures, and its validity is judged by the Access layer’s materialization rules alone — issuance counts, arrival never.

Membership is entered only by explicit, cryptographically bound consent, and the consent evidence travels inside the admitting operation: the invitation and acceptance documents themselves, verifiable by every replica. That makes admission verifiable without private knowledge, lets any authorized member complete an admission, and makes invitation provenance provable — who invited whom is read from signatures in the log, never asserted by a field.

Status of This Document

This is an Editor’s Draft with no standing beyond its own argument, the sixteenth casting of this document. It is developed through the same adversarial convergence process as its companions (casting, independent adversarial review, full recast — never a patch). The tenth and eleventh castings closed the joint seam with Access 0.24/0.25 on both sides.

The twelfth through fifteenth castings are this document’s half of the M-DID loop (design/mdid-loop-zerlegung-2026-08.md, design/mdid-guss-plan-2026-08.md), recast against Access 0.26: every anchor of this document’s flow — invite.inviter, invite.invitee, accept.subject, the enclosed cards’ anchors, and thereby member.add’s body.subject — is a member anchor (Access §5.1: the per-group context anchor; DTGWG: M-DID), never a cross-group coordinate. Three consequences are this casting’s substance: the prelude — the inviter cannot derive the invitee’s member anchor, so the invitee’s app supplies it over the existing relationship channel before the formal invite (3.1), an application exchange like the human decision itself, stated honestly rather than hidden; the enclosed cards are member-anchor cards and MUST carry no deliveryHints (Section 2 — the log’s permanence now prices in group-scoped identifiers only); and the candidacy of the vouched admission path SHOULD be surfaced into the group space as Layer-4 content (3.4 — Access §5.3 owns the flow’s authority rules; this document owns only the travel and the surfacing duty). The transcribed Access schemas stand byte-identically (wire 0.24 unchanged — the coupling of Section 10 holds without a break); the Access section references of this document cite Access 0.26 as of that casting — this is genealogy, not the current companion pin; §10 carries that. This casting begins a fresh convergence loop; the eleventh casting’s seam-closure applies to it, not to this draft.

The thirteenth casting answers the loop’s joint round 1 (design/mdid-joint-review1-2026-08.md): the prelude is closed at its consumer — the invitee MUST verify, on invite receipt, that invite.invitee equals its own derivation from invite.genesisDigest, so no substitution or mis-binding survives to an accept (M6); and the candidacy becomes explicit consent — the accept (type bumped to membership-accept/0.2) carries a signed candidacy boolean, the pre-admission surfacing of 3.4 is gated on it, and the candidacy content has a stated lifecycle with the honest one-way-door sentence (M10 — the opt-in exists precisely because group-space publication cannot be recalled). Companion pins moved with the joint castings (then Delivery 0.21 and Access 0.29 — this is genealogy, not the current pin; §10 carries that). The fourteenth casting answers joint round 2: the candidacy lifecycle names only observable triggers — completed admission and invite expiry — and states that a group’s refusal is deliberately NOT an observable event (refusal privacy: no artifact announces “we decided against”), so earlier removal stays at the surfacing member’s discretion; and the normative references pin the joint castings consistently (M4/M5). The sixteenth casting is the DTG adoption cast (design/dtg-credential-adoption-2026-08.md): the invitation becomes membership-invite/0.2, a conformant DTG InvitationCredential — issuer = the inviting member’s anchor, credentialSubject.id = the invitee’s member anchor, validUntil native, taskContext = the membership thread (the WD01 binding, adopted), and every RLTP field (group, genesisDigest, card) a WD01-legal additional subject property. The invite’s proof is the VC’s own DataIntegrityProof (one carrier — the document-level task proof falls away for the invite; the accept keeps its task proof). Every consumer check maps one-to-one onto the new paths; nothing weakens. Feedback is welcome via the issues of the publication repository (github.com/real-life-org/trust-protocol).

1. Introduction (informative)

1.1 What this fixes

The deployed app enforces membership on two disconnected planes: a membership document that only clients check, and a relay registry that only the relay checks. The seams show — a promoted admin passes every client check and still cannot enforce a removal; a removed member never canonically learns of the removal, because the same capability gate that enforces it also cuts off the replica that would tell them; an invitation hands the full key history to someone who never consented to join. This specification is one half of the repair: consent, the admitting operation, and the keys it commits to travel as first-class, acknowledged task documents to exactly the one party the replica cannot reach — the invitee — while the removed member is owed a compact signed notice of their own (Access §10.2); and keys travel only after consent. The other half — one authority plane, the operation log, with services fed by chain-proven epoch updates instead of their own registries — belongs to the Access layer and its service ports.

1.2 The flow at a glance

  1. The prelude (application-level, over the existing relationship channel): the inviter asks, the invitee’s app derives the invitee’s member anchor for the offered group from the genesis digest (Access §5.1, Identity §6’s group/<digest> context) and answers with it — the inviter cannot derive another person’s context anchor, so the formal invite can name it only after this exchange.
  2. A member sends an invite — no key material, but the inviter’s contact card at the inviter’s own member anchor (so the answer has a key to travel under) and the group’s genesis digest (so the invitee can later verify the bootstrap against what was offered). It names the invitee’s member anchor from the prelude.
  3. The invitee decides, humanly, and sends an accept: signed by themselves, bound to that exact invite, carrying their own contact card (so the welcome has a key to travel under).
  4. Any authorized member — not only the inviter — completes the admission: a member.add operation that carries the invite and the accept inside its signed body, travelling together with the welcome (the current epoch’s keys, sealed to the invitee, digest-committed by the operation’s signatures). The full history opens from the replica afterwards, epoch by epoch, through the key lineage the log itself carries (1.3). Until the welcome arrives, the invitee’s state is honest and visible: accepted — waiting for a group member to come online and hand over the keys (Section 7).

The flow, as a picture (informative):

sequenceDiagram
    participant I as Invitee
    participant V as Inviter
    participant M as Any authorized member
    participant L as Group log
    V->>I: membership-invite, carries no keys
    Note over I: human decision
    I->>V: membership-accept, signed consent, own live-keyed card
    Note over I: accepted, waiting for a member to hand over the keys
    V-->>M: membership-evidence, the complete pair relayed
    M->>L: member.add, body encloses invite and accept
    M->>I: access-operation with welcome, sealed to the accept's card
    Note over I: unseal, fetch log, verify own genesis digest, materialize
    I->>L: full history opens via the epoch-key lineage

1.3 History through lineage, not through the welcome

The welcome carries only the current epoch. The group’s history is opened by the epoch-key lineage that the Access layer records in the replicated log itself: at each epoch transition, the previous epoch key travels encrypted under the new one. A new member holding the current key therefore unlocks the entire readable history from the replica, epoch by epoch — the group’s shared world whole (calendar, board, map), which is this profile’s default. The visibility policy narrows history exactly by omitting lineage entries; nothing about history size ever burdens the welcome, and nothing can be withheld from a new member that is not equally withheld from the replica. The lineage is Access-layer property and, since Access 0.24, a normative fact rather than a dependency this document must demand: Access §7.1 requires every transition to carry its lineage state explicitly (MO-6 discharged). The full-history default of this profile is delivered exactly as far as unbroken lineage reaches; across a narrowed or damaged span, a bootstrap degrades honestly to current-epoch access. This document transports no history either way.

1.4 The three principles inherited

2. Conventions and Terminology

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals.

The interim securing profile of Encounter 2.3 (Encounter 0.29) applies. The document profile, sealed envelope, staged dispositions, and acknowledgement rules of the Delivery Contract (Sections 3–6) apply to every type registered here. Task proofs of this document (on the accept) MUST verify under the key bound to the document issuer anchor (Encounter 2.3), and the proof’s verificationMethod DID MUST equal that issuer; the invite carries its authenticity inside — its payload is a DTG InvitationCredential whose DataIntegrityProof verifies under its issuer (one carrier; the invite document itself carries no proof, like the operation carrier of 3.3). Stated honestly, that carrier covers payload.invite and nothing else: the invite document’s own id, issuedAt, and ceremony are unauthenticated transport metadata and MUST carry no authority at any consumer (a present ceremony.enactment MUST still recompute per Delivery §3 — a validity gate that can reject the document, never a source of authority). The invitation’s identity — for consent, consumption, and idempotency — is the digest of the complete credential (the multibase multihash over the JCS of payload.invite including its proof), never the enclosing document’s digest: a mutated wrapper around the same credential is the same invitation, and every alias collapses onto it.

Group — an Access-layer group. Its identity is the genesis digest (Access §3.2 — the multibase multihash over the genesis operation’s proof-free signature input); the group DID is its address, never its identity, and implementations key all group state — pending stores, evidence authorization, bootstrap verification — by genesis digest. Operation — an Access-layer operation envelope (its §3.3): self-addressing (oid:), causally referenced (prev), individually signed (proof.signatures). Materialization — the Access layer’s deterministic derivation of group state from the operation DAG; an operation is canonical per Access §3.5/§3.6 — judged at its causal position, with merge outcomes governed by Access’s closed exception list. Replica boundary — the set of parties holding (and entitled to hold) the group’s replicated log at a given materialized state. Admission chain — invite → accept → member.add, carried in full inside the admitting operation (Section 3.3). Boundary-crossing member.add — the access-operation document that delivers an admitting member.add to its own subject.

The membership size budget: a membership-invite and a membership-accept document MUST NOT exceed 16 384 bytes in their JCS serialization. An oversized document is non-conformant at issuance and failed(validation-failed) at receipt. The budget exists so that complete enclosure (3.3) fits the Delivery Contract’s envelope bound in every normal construction, and it doubles as the log-growth cap per admission. It is not a proof of fit: even with Access §5.3’s transported-variant caps on the enclosed proof (at most 64 signatures and 16 credentials of at most 2048 bytes JCS each), adversarially maximized documents can exhaust the budget, so the sender MUST verify the complete serialized task against the Contract’s plaintext limit before sealing (the Contract’s stage-1 bound remains the authoritative gate; where the admission cannot fit, the re-welcome fallback of 3.3 travels instead), and a welcome plaintext MUST NOT exceed 16 384 bytes in its JCS serialization either.

Enclosed cards are key transport, not enactment material: the contact cards inside invite and accept follow Encounter §6’s displayed form — their proof MUST verify under their anchor, which is the party’s member anchor (Access §5.1), and they MUST carry neither sentTo nor boundTo and no challenge obligation applies (they enter no enactment). They MUST carry no deliveryHints (hardened from the earlier SHOULD): the log replicates every enclosed card forever, and a member-anchor card carries a group-scoped identity and a seal key — never routing material. No freshness is claimed or needed — a seal needs a live key, not a fresh one; creating the card for this thread is RECOMMENDED, required is only the retention of Section 5.

3. Registered Task Types

3.1 membership-invite/0.2

The invitation: one member proposes membership to a person outside the group. It carries no key material and no operation — nothing a non-accepting recipient could hold against the group.

3.2 membership-accept/0.2

The explicit acceptance — the consent artifact. Membership is entered only through it: a member.add admitting a subject across the replica boundary MUST enclose a valid accept (3.3); without one, issuing such a member.add is non-conformant, and a welcome MUST NOT be sent.

3.3 access-operation/0.1

The carrier for the one operation that genuinely crosses the replica boundary: the admitting member.add delivered to its own subject, the bootstrap. Round 8 narrowed this type to exactly that: replication owns the inside (MO-1), so members already hold operations; a removed member’s notice is Access’s own removal-notice/0.1 (its §10.2); transition key material travels per recipient via key-delivery/0.1 (Access §10.1); and transition-bearing envelopes never leave the replica at all (Access §5.3). A conformant access-operation/0.1 payload therefore carries an admitting member.add and its welcome, and nothing else — the schema requires op = member.add, a member.add body, and the welcome (there is no non-admitting use). Leave and dissolve notices, if they are ever wanted, need their own compact task types (MO-3), not this generic hole.

3.4 membership-evidence/0.1

The evidence relay’s wire form: any holder of the consent pair MAY hand it to any authorized member, so that any member can complete an admission (the availability property of 1.2). The original documents cannot simply be re-sealed — their signed recipient fields name the invitee and the inviter, and the Contract’s receiver principle would rightly reject them — so they travel enclosed, exactly as they later travel inside the admitting operation.

4. The Welcome Seal

The welcome carries what the current epoch requires and nothing more; history opens through the lineage in the replica (1.3).

5. Timing

Parameter Default Meaning
invite-validity P90D default for validUntil when the inviter names none
membership-skew PT5M clock-skew allowance of this profile; widens every comparison of Section 3 toward acceptance (registered here — Encounter’s skew-tolerance is pinned to its ceremony and not borrowed)
bootstrap-retention P90D minimum retention of an incomplete(missing: group-state) document, from first receipt; redelivery never resets it

Delivery time is unbounded (Contract §7); no rule of this document references arrival time for validity. The one issuance-time window — accept against validUntil — is an honest-clock bound (3.1), widened by membership-skew; clock tolerance never rejects.

6. What is deliberately absent

7. State Machines (informative)

Invitee: invited (human decision pending) → accepted — waiting for a group member to come online and hand over the keys → welcome arrived → bootstrapping (provisional under Access §10.1: fetch log scoped by the own pinned genesis digest, materialize, check the own admission against the current state) → member — the waiting state MUST be user-visible as such; decline or expiry ends the thread with local state only. The bootstrapping state is provisional and time-bounded: it ends in member only on current membership with a current-epoch commitment match. A single candidate’s failure wipes that candidate and checks the buffered alternate at once (Access §10.1’s fallback); only when every held candidate has failed, or the provisional-window expires with no log arrival, is the bootstrap wiped completely. The diagram below depicts §3.3 and Access §10.1; where it and they could be read apart, they govern.

stateDiagram-v2
    [*] --> invited: membership-invite arrives
    invited --> accepted: human accepts (signs membership-accept)
    invited --> [*]: decline / validUntil expiry
    accepted --> welcomeArrived: member.add + welcome delivered
    note right of accepted
        user-visible! waiting for a group
        member to come online and
        hand over the keys
    end note
    welcomeArrived --> bootstrapping: all case-1 pre-checks pass, incl. seal opens under own accept card and material well-formed for the adapter — adopted PROVISIONALLY, one window per genesisDigest+invitee
    welcomeArrived --> [*]: any pre-check fails — nothing adopted, no state written
    bootstrapping --> member: own admission canonical AND invitee a CURRENT member AND unsealed content key matches the CURRENT epoch commitment
    bootstrapping --> bootstrapping: single candidate fails (stale epoch after rotation/removal) — wipe THAT candidate, check the buffered alternate at once (Access 10.1 fallback)
    bootstrapping --> bootstrapping: log not yet resolvable — waiting INSIDE the window, at most one buffered alternate
    bootstrapping --> wiped: every held candidate has failed — OR the provisional-window expires with no log arrival
    wiped --> [*]: provisional keys and replica wiped completely, unique data preserved

Admitting member (any authorized member): admission evidence at hand → verify chain → issue member.add enclosing invite + accept, with welcome → done. The evidence reaches non-inviter members via membership-evidence (3.4) — that wire form is what makes “any authorized member can admit” operationally true rather than merely possible.

Removed member: removal-notice arrives (Access §10.2) → surfaced as a signed claim → verification attempt (replication) → hygiene only on the member's own canonical application of the removal — the notice itself changes no state; a forged notice is a surfaced, attributable lie with no mechanical effect.

8. Security Considerations

9. Open Issues

10. Conformance

References

[RFC2119] · [RFC8174] BCP 14 · [RFC8785] JCS · [TT] ToIP DTGWG Trust Tasks framework 0.4 · RLTP Delivery Contract 0.79 (normative; §4.4 registry) · RLTP Encounter Layer 0.29, wire 0.25 (securing profile 2.3, principles 1.3, contact card §6) · RLTP Access Layer 0.53, wire 0.24 (normative: operation envelope §3.3, group identity §3.2, member identity §5.1, admission, candidacy and key service duty §5.3, member-mapping §5.5, material §9.5, key-delivery/0.1 §10.1, removal-notice/0.1 §10.2, authorization views §7.3, epoch-key lineage §7.1).