diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-23 17:31:06 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-23 17:31:06 +0200 |
| commit | d30e95b2ce1ffe9dc4655855406f2784b5f7af34 (patch) | |
| tree | 91d86ffd59eb3593a76139ab264e1eb5da1ae687 /packages/meshbay-common/src | |
| parent | 339cb427f886a0177014126bb684335837eff067 (diff) | |
| download | meshbay-d30e95b2ce1ffe9dc4655855406f2784b5f7af34.tar.gz | |
feat(node): invitation links — a code bound to no account until redeemed
New invite kind "link": member of one group, once, never operator, not
spendable by an active member, capped at 20 per group, cancellable by
handle. Signed ops invite_link_create / invite_cancel, loopback routes,
and the known-device join path now accepts a link code. Adds the plan,
docs/invite-links.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-common/src')
| -rw-r--r-- | packages/meshbay-common/src/meshbay_common/__init__.py | 5 | ||||
| -rw-r--r-- | packages/meshbay-common/src/meshbay_common/adminop.py | 7 | ||||
| -rw-r--r-- | packages/meshbay-common/src/meshbay_common/protocol.py | 3 |
3 files changed, 15 insertions, 0 deletions
diff --git a/packages/meshbay-common/src/meshbay_common/__init__.py b/packages/meshbay-common/src/meshbay_common/__init__.py index 1271c4e..77e6fac 100644 --- a/packages/meshbay-common/src/meshbay_common/__init__.py +++ b/packages/meshbay-common/src/meshbay_common/__init__.py @@ -236,5 +236,10 @@ __version__ = "0.15.0" # *wrong* one outright and treats an absent one as "this node cannot prove # itself early", which it discovers from the node's answer and never from the # version number. `MNP_MIN_SUPPORTED` does not move. +# +# The same version adds invitation links: `invite_link_create` / +# `invite_link_result` and `invite_cancel`, a code bound to no account until it +# is redeemed. Additive in the same way — a 3.3 node answers `unknown message +# type`, and no client can hold a link code for a node that could not issue one. MNP_VERSION = "3.4" MHP_VERSION = "0.1" diff --git a/packages/meshbay-common/src/meshbay_common/adminop.py b/packages/meshbay-common/src/meshbay_common/adminop.py index 20b5080..23040be 100644 --- a/packages/meshbay-common/src/meshbay_common/adminop.py +++ b/packages/meshbay-common/src/meshbay_common/adminop.py @@ -36,6 +36,13 @@ ADMIN_TRANSCRIPT_PREFIX = b"meshbay:admin:v1" OP_FILE_DELETE = "file_delete" OP_DIR_DELETE = "dir_delete" OP_INVITE_CREATE = "invite_create" +# An invitation bound to no account (docs/invite-links.md). Its own op rather +# than `invite_create` with an empty subject: that subject is the invitee, and +# what the operator is shown before signing has to name the outcome (H5) — here +# "a link into this group", `link:<group_id>`. +OP_INVITE_LINK_CREATE = "invite_link_create" +# Taking back an unredeemed link, by the handle it was issued with. +OP_INVITE_CANCEL = "invite_cancel" OP_MEMBER_REVOKE = "member_revoke" # Rotating the group key is what actually takes it away from a revoked member: # revocation stops the node serving the *next* key, and they still hold the diff --git a/packages/meshbay-common/src/meshbay_common/protocol.py b/packages/meshbay-common/src/meshbay_common/protocol.py index 5374742..4df06bf 100644 --- a/packages/meshbay-common/src/meshbay_common/protocol.py +++ b/packages/meshbay-common/src/meshbay_common/protocol.py @@ -153,6 +153,8 @@ class MNP: JOIN_REQUEST = "join_request" # client → node: pair/recognise this identity JOIN_RESULT = "join_result" # node → client: outcome + wrapped GEK INVITE_CREATE = "invite_create" # operator → node: issue a pairing code + INVITE_LINK_CREATE = "invite_link_create" # operator → node: a code bound to no account + INVITE_CANCEL = "invite_cancel" # operator → node: take back an unredeemed link MEMBER_REVOKE = "member_revoke" # operator → node: stop serving the key MEMBER_REVOKE_ACK = "member_revoke_ack" MEMBER_UNPIN = "member_unpin" # operator → node: forget an identity @@ -222,6 +224,7 @@ class MNP: GEK_ROTATE = "gek_rotate" # operator → node: new group key GEK_ROTATE_ACK = "gek_rotate_ack" INVITE_RESULT = "invite_result" # node → operator: the code, once + INVITE_LINK_RESULT = "invite_link_result" # node → operator: link code + handle, once NODE_STATUS = "node_status" # operator → node: list all groups + roots NODE_STATUS_ACK = "node_status_ack" # node → operator: full status ROOT_ADD = "root_add" # operator → node: add a directory to a group |