starfish-spaces 3.0.0a42__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. starfish_spaces-3.0.0a42/PKG-INFO +19 -0
  2. starfish_spaces-3.0.0a42/README.md +53 -0
  3. starfish_spaces-3.0.0a42/pyproject.toml +40 -0
  4. starfish_spaces-3.0.0a42/setup.cfg +4 -0
  5. starfish_spaces-3.0.0a42/starfish_spaces/__init__.py +413 -0
  6. starfish_spaces-3.0.0a42/starfish_spaces/account_seal.py +231 -0
  7. starfish_spaces-3.0.0a42/starfish_spaces/cas_retry.py +43 -0
  8. starfish_spaces-3.0.0a42/starfish_spaces/client.py +533 -0
  9. starfish_spaces-3.0.0a42/starfish_spaces/config.py +299 -0
  10. starfish_spaces-3.0.0a42/starfish_spaces/identity_link.py +216 -0
  11. starfish_spaces-3.0.0a42/starfish_spaces/inbox.py +81 -0
  12. starfish_spaces-3.0.0a42/starfish_spaces/invite_helpers.py +243 -0
  13. starfish_spaces-3.0.0a42/starfish_spaces/keyed_store.py +110 -0
  14. starfish_spaces-3.0.0a42/starfish_spaces/layout.py +228 -0
  15. starfish_spaces-3.0.0a42/starfish_spaces/members.py +422 -0
  16. starfish_spaces-3.0.0a42/starfish_spaces/node_access_revoked_error.py +26 -0
  17. starfish_spaces-3.0.0a42/starfish_spaces/node_keyring.py +184 -0
  18. starfish_spaces-3.0.0a42/starfish_spaces/nodes.py +615 -0
  19. starfish_spaces-3.0.0a42/starfish_spaces/object_directory.py +104 -0
  20. starfish_spaces-3.0.0a42/starfish_spaces/object_index.py +159 -0
  21. starfish_spaces-3.0.0a42/starfish_spaces/objects.py +372 -0
  22. starfish_spaces-3.0.0a42/starfish_spaces/plugin.py +198 -0
  23. starfish_spaces-3.0.0a42/starfish_spaces/registry.py +558 -0
  24. starfish_spaces-3.0.0a42/starfish_spaces/request_verify.py +65 -0
  25. starfish_spaces-3.0.0a42/starfish_spaces/resource_requests.py +433 -0
  26. starfish_spaces-3.0.0a42/starfish_spaces/session.py +352 -0
  27. starfish_spaces-3.0.0a42/starfish_spaces/space_access.py +302 -0
  28. starfish_spaces-3.0.0a42/starfish_spaces/space_access_error.py +31 -0
  29. starfish_spaces-3.0.0a42/starfish_spaces/space_access_store.py +290 -0
  30. starfish_spaces-3.0.0a42/starfish_spaces/token_types.py +163 -0
  31. starfish_spaces-3.0.0a42/starfish_spaces.egg-info/PKG-INFO +19 -0
  32. starfish_spaces-3.0.0a42/starfish_spaces.egg-info/SOURCES.txt +42 -0
  33. starfish_spaces-3.0.0a42/starfish_spaces.egg-info/dependency_links.txt +1 -0
  34. starfish_spaces-3.0.0a42/starfish_spaces.egg-info/requires.txt +15 -0
  35. starfish_spaces-3.0.0a42/starfish_spaces.egg-info/top_level.txt +1 -0
  36. starfish_spaces-3.0.0a42/tests/test_cas_retry.py +47 -0
  37. starfish_spaces-3.0.0a42/tests/test_keyed_store.py +60 -0
  38. starfish_spaces-3.0.0a42/tests/test_layout.py +169 -0
  39. starfish_spaces-3.0.0a42/tests/test_layout_user_id.py +44 -0
  40. starfish_spaces-3.0.0a42/tests/test_objects.py +224 -0
  41. starfish_spaces-3.0.0a42/tests/test_request_verify.py +100 -0
  42. starfish_spaces-3.0.0a42/tests/test_space_access_error.py +24 -0
  43. starfish_spaces-3.0.0a42/tests/test_space_access_store.py +106 -0
  44. starfish_spaces-3.0.0a42/tests/test_trusted_adders.py +29 -0
@@ -0,0 +1,19 @@
1
+ Metadata-Version: 2.4
2
+ Name: starfish-spaces
3
+ Version: 3.0.0a42
4
+ Summary: Starfish multi-user spaces extension (registry, membership, object tree, E2EE keyrings, invite flows, resource-request inbox)
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: starfish-protocol
7
+ Requires-Dist: starfish-sdk
8
+ Requires-Dist: starfish-keyring
9
+ Requires-Dist: starfish-sharing
10
+ Requires-Dist: starfish-identities
11
+ Requires-Dist: cryptography>=41.0
12
+ Requires-Dist: mnemonic>=0.21
13
+ Provides-Extra: dev
14
+ Requires-Dist: pytest>=7.0; extra == "dev"
15
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
16
+ Requires-Dist: respx>=0.23.1; extra == "dev"
17
+ Requires-Dist: starfish-server; extra == "dev"
18
+ Requires-Dist: fastapi>=0.100; extra == "dev"
19
+ Requires-Dist: httpx>=0.25.0; extra == "dev"
@@ -0,0 +1,53 @@
1
+ # starfish-spaces
2
+
3
+ Starfish extension for **multi-user spaces**: a roster of members, a shared object
4
+ tree with per-node access control and optional E2EE, invite / link join flows,
5
+ revocation, and a sealed request/grant inbox round-trip.
6
+
7
+ Mirrors [`@drakkar.software/starfish-spaces`](../ts/spaces) (TypeScript).
8
+
9
+ ## Install
10
+
11
+ ```bash
12
+ pip install starfish-spaces
13
+ ```
14
+
15
+ ## Concepts
16
+
17
+ | Concept | Description |
18
+ |---|---|
19
+ | **Space** | Named container with owner + member roster at `spaces/{spaceId}/_access`. |
20
+ | **Node** | Entry in a space's object tree with `access` (`"public"` \| `"space"` \| `"invite"`) and `enc` (bool). |
21
+ | **SpaceLayout** | Protocol that produces all storage paths and cap scopes. Inject a custom layout or use `default_space_layout()`. |
22
+ | **Session** | Central runtime object: identity keys + Starfish clients + resolved layout. |
23
+ | **Space keyring** | One AES-256-GCM keyring per space encrypts all `enc` nodes. |
24
+ | **Inbox** | Monthly-sharded public-write ring buffer for sealed resource requests. |
25
+
26
+ ## Quick start
27
+
28
+ ```python
29
+ from starfish_spaces import build_session, make_space_client, default_space_layout
30
+
31
+ session = await build_session(
32
+ passphrase="…",
33
+ server_url="https://sync.example.com",
34
+ layout=default_space_layout(),
35
+ )
36
+
37
+ client = make_space_client(session)
38
+
39
+ # Create a space
40
+ space_id = await client.registry.create_space(name="My Space")
41
+
42
+ # Invite a member
43
+ await client.members.invite(space_id, user_id=recipient_id, write=True)
44
+ ```
45
+
46
+ ## API surface
47
+
48
+ - **`build_session` / `derive_session`** — construct the runtime session from passphrase or device keys
49
+ - **`make_space_client`** — unified client covering registry, members, nodes, objects, inbox, identity links
50
+ - **`configure_spaces` / `default_space_layout`** — layout injection
51
+ - **`generate_seed_words` / `is_valid_seed`** — BIP-39 mnemonic helpers
52
+
53
+ See the [full guide](/extensions/spaces) for detailed documentation on all subsystems.
@@ -0,0 +1,40 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "starfish-spaces"
7
+ version = "3.0.0a42"
8
+ description = "Starfish multi-user spaces extension (registry, membership, object tree, E2EE keyrings, invite flows, resource-request inbox)"
9
+ requires-python = ">=3.11"
10
+ dependencies = [
11
+ "starfish-protocol",
12
+ "starfish-sdk",
13
+ "starfish-keyring",
14
+ "starfish-sharing",
15
+ "starfish-identities",
16
+ "cryptography>=41.0",
17
+ "mnemonic>=0.21",
18
+ ]
19
+
20
+ [project.optional-dependencies]
21
+ dev = [
22
+ "pytest>=7.0",
23
+ "pytest-asyncio>=0.21",
24
+ "respx>=0.23.1",
25
+ "starfish-server",
26
+ "fastapi>=0.100",
27
+ "httpx>=0.25.0",
28
+ ]
29
+
30
+ [tool.uv.sources]
31
+ starfish-protocol = { path = "../protocol", editable = true }
32
+ starfish-sdk = { path = "../client", editable = true }
33
+ starfish-keyring = { path = "../keyring", editable = true }
34
+ starfish-sharing = { path = "../sharing", editable = true }
35
+ starfish-identities = { path = "../identities", editable = true }
36
+ starfish-server = { path = "../server", editable = true }
37
+
38
+ [tool.pytest.ini_options]
39
+ asyncio_mode = "auto"
40
+ testpaths = ["tests"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,413 @@
1
+ """starfish-spaces — space + node management for Starfish.
2
+
3
+ Public surface (mirrors ``@drakkar.software/starfish-spaces``):
4
+
5
+ - **Config & layout**: :func:`configure_spaces`, :func:`get_spaces_config`,
6
+ :class:`SpaceLayout`, :data:`default_space_layout`, :func:`default_user_id_from_ed_pub`
7
+ - **Session**: :class:`Session`, :func:`build_session`, :func:`derive_session`
8
+ - **Registry**: :func:`create_space`, :func:`read_spaces`, :func:`build_space`, ...
9
+ - **Members**: :func:`invite_to_space`, :func:`accept_space_invite`,
10
+ :func:`create_space_invite_link`, :func:`join_space_by_link`, ...
11
+ - **Nodes**: :func:`create_node`, :func:`invite_to_node`, :func:`accept_node_invite`, ...
12
+ - **Resource requests**: :func:`submit_resource_request`, :func:`scan_resource_requests`, ...
13
+ - **Identity link**: :class:`IdentityLink`, :func:`decode_identity_link`, ...
14
+ - **Server plugin**: :func:`create_spaces_role_enricher` (pass ``allow_tofu=True``
15
+ for first-create provisioning; default is fail-closed),
16
+ :func:`create_spaces_directory_server_plugin` (lazy-imported to avoid pulling
17
+ in ``starfish_server`` for client-only users).
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ # ── Config & layout ───────────────────────────────────────────────────────────
23
+ from starfish_spaces.config import (
24
+ KvAdapter,
25
+ NodeAccess,
26
+ ObjectNode,
27
+ ObjectsIndex,
28
+ ObjectType,
29
+ SealedBlob,
30
+ Space,
31
+ SpaceLayout,
32
+ SpacesConfig,
33
+ configure_spaces,
34
+ get_spaces_config,
35
+ )
36
+ from starfish_spaces.layout import (
37
+ OBJECT_COLLECTIONS,
38
+ RECIPIENT_LABEL_LEN,
39
+ USER_ID_HEX_LENGTH,
40
+ default_space_layout,
41
+ default_user_id_from_ed_pub,
42
+ )
43
+
44
+ # ── Session ────────────────────────────────────────────────────────────────────
45
+ from starfish_spaces.session import (
46
+ BuildLinkedSessionOpts,
47
+ BuildSessionOpts,
48
+ LinkedIdentity,
49
+ Session,
50
+ build_linked_session,
51
+ build_session,
52
+ derive_session,
53
+ fingerprint_from_user_id,
54
+ generate_seed_words,
55
+ is_valid_seed,
56
+ owner_trusted_adders,
57
+ )
58
+
59
+ # ── Client helpers ─────────────────────────────────────────────────────────────
60
+ from starfish_spaces.client import (
61
+ ClientOpts,
62
+ DeviceKeys,
63
+ PublicProfile,
64
+ add_keyring_recipient_core,
65
+ add_space_keyring_recipient,
66
+ build_auth_headers,
67
+ build_encryptor,
68
+ cap_provider_for,
69
+ ensure_profile_keys,
70
+ ensure_pseudo,
71
+ ensure_space_keyring_recipient,
72
+ is_already_present_recipient,
73
+ is_keyring_missing,
74
+ make_anon_space_client,
75
+ make_space_client,
76
+ open_encryptor,
77
+ owner_ensure_keyring,
78
+ owner_ensure_space_keyring,
79
+ read_profile,
80
+ read_profiles,
81
+ write_profile,
82
+ )
83
+
84
+ # ── Keyed store ────────────────────────────────────────────────────────────────
85
+ from starfish_spaces.keyed_store import (
86
+ ComposedStore,
87
+ KeyedStore,
88
+ create_composed_store,
89
+ create_keyed_store,
90
+ )
91
+
92
+ # ── Space access error ─────────────────────────────────────────────────────────
93
+ from starfish_spaces.space_access_error import SpaceAccessError
94
+ from starfish_spaces.node_access_revoked_error import NodeAccessRevokedError
95
+
96
+ # ── Space access store ─────────────────────────────────────────────────────────
97
+ from starfish_spaces.space_access_store import (
98
+ SpaceAccessEntry,
99
+ clear_persisted_space_access,
100
+ clear_space_access_store,
101
+ configure_space_access_store,
102
+ get_node_access_entry,
103
+ get_node_keyring_access_entry,
104
+ get_node_stream_access_entry,
105
+ get_space_access_entry,
106
+ hydrate_space_access_store,
107
+ link_access_from_store,
108
+ local_space_access_entries,
109
+ member_caps_from_store,
110
+ remove_node_access_entry,
111
+ remove_node_keyring_access_entry,
112
+ remove_node_stream_access_entry,
113
+ remove_space_access_entry,
114
+ save_node_access_entry,
115
+ save_node_keyring_access_entry,
116
+ save_node_stream_access_entry,
117
+ save_space_access_entry,
118
+ )
119
+
120
+ # ── Account seal ──────────────────────────────────────────────────────────────
121
+ from starfish_spaces.account_seal import (
122
+ seal_to_recipient,
123
+ seal_to_self,
124
+ unseal_from_recipient,
125
+ unseal_from_self,
126
+ )
127
+
128
+ # ── Request verify ─────────────────────────────────────────────────────────────
129
+ from starfish_spaces.request_verify import sign_kem_sig, verify_kem_sig
130
+
131
+ # ── CAS retry ─────────────────────────────────────────────────────────────────
132
+ from starfish_spaces.cas_retry import run_cas
133
+
134
+ # ── Objects (pure tree algorithms) ────────────────────────────────────────────
135
+ from starfish_spaces.objects import add_object, build_tree
136
+
137
+ # ── Node keyring ──────────────────────────────────────────────────────────────
138
+ from starfish_spaces.node_keyring import (
139
+ NodeKeyringRecipient,
140
+ add_node_keyring_recipient,
141
+ build_node_encryptor,
142
+ ensure_node_keyring_recipient,
143
+ open_node_encryptor,
144
+ owner_ensure_node_keyring,
145
+ remove_node_keyring_recipient,
146
+ )
147
+
148
+ # ── Space access resolver ──────────────────────────────────────────────────────
149
+ from starfish_spaces.space_access import (
150
+ NodeAccessHandle,
151
+ build_node_access,
152
+ clear_node_access_cache,
153
+ get_node_access,
154
+ get_node_stream_client,
155
+ get_space_client,
156
+ )
157
+
158
+ # ── Token types ────────────────────────────────────────────────────────────────
159
+ from starfish_spaces.token_types import (
160
+ JoinRequest,
161
+ NodeInviteBundle,
162
+ NodeInviteKind,
163
+ NodeInviteLinkToken,
164
+ ResourceGrant,
165
+ ResourceReject,
166
+ ResourceRequest,
167
+ SpaceInviteLinkToken,
168
+ StoredNodeInvite,
169
+ )
170
+
171
+ # ── Invite helpers ─────────────────────────────────────────────────────────────
172
+ from starfish_spaces.invite_helpers import (
173
+ CapSubject,
174
+ adder_of,
175
+ assert_cap_for_me,
176
+ cap_nonce,
177
+ ephemeral_subject_async,
178
+ evict_keyring_member,
179
+ mint_cap,
180
+ parse_join_request,
181
+ )
182
+
183
+ # ── Registry ───────────────────────────────────────────────────────────────────
184
+ from starfish_spaces.registry import (
185
+ SpaceEntry,
186
+ SpacesDoc,
187
+ add_joined_space,
188
+ add_joined_space_with_cap,
189
+ add_joined_space_with_link_access,
190
+ add_space_member,
191
+ broadcast_space_meta,
192
+ build_space,
193
+ create_space,
194
+ move_space,
195
+ on_space_meta,
196
+ read_space_access,
197
+ read_space_access_batch,
198
+ read_spaces,
199
+ reconcile_space_meta,
200
+ remove_joined_space,
201
+ remove_space_member,
202
+ reorder_spaces,
203
+ update_spaces_doc,
204
+ update_spaces_extra_field,
205
+ write_space_access,
206
+ write_spaces,
207
+ )
208
+
209
+ # ── Object index ───────────────────────────────────────────────────────────────
210
+ from starfish_spaces.object_index import (
211
+ push_index_seed,
212
+ read_object_tree,
213
+ seed_space_object_index,
214
+ update_object_index,
215
+ )
216
+
217
+ # ── Members ────────────────────────────────────────────────────────────────────
218
+ from starfish_spaces.members import (
219
+ StoredSpaceInvite,
220
+ accept_space_invite,
221
+ add_device_to_space_keyring,
222
+ clear_space_invite_store,
223
+ create_space_invite_link,
224
+ decode_space_invite_link,
225
+ encode_space_invite_link,
226
+ get_space_invite_entry,
227
+ hydrate_space_invite_store,
228
+ invite_to_space,
229
+ join_space_by_link,
230
+ make_join_request,
231
+ recover_space_access,
232
+ revoke_space_access,
233
+ save_space_invite_entry,
234
+ serialize_space_invite_store,
235
+ )
236
+
237
+ # ── Nodes ──────────────────────────────────────────────────────────────────────
238
+ from starfish_spaces.nodes import (
239
+ CreateNodeInput,
240
+ accept_node_invite,
241
+ clear_node_invite_store,
242
+ create_node,
243
+ create_node_invite_link,
244
+ decode_node_invite_link,
245
+ encode_node_invite_link,
246
+ get_node_invite_entry,
247
+ hydrate_node_invite_store,
248
+ invite_to_node,
249
+ join_node_by_link,
250
+ read_node_with_link_cap,
251
+ revoke_node_access,
252
+ save_node_invite_entry,
253
+ serialize_node_invite_store,
254
+ set_node_access,
255
+ write_node_with_link_cap,
256
+ )
257
+
258
+ # ── Inbox ──────────────────────────────────────────────────────────────────────
259
+ from starfish_spaces.inbox import InboxElement, inbox_shard, inbox_shards, pull_inbox
260
+
261
+ # ── Identity link ──────────────────────────────────────────────────────────────
262
+ from starfish_spaces.identity_link import (
263
+ IdentityLink,
264
+ decode_identity_link,
265
+ encode_identity_link,
266
+ my_identity_link,
267
+ verify_identity_link_binding,
268
+ verify_identity_link_keys,
269
+ )
270
+
271
+ # ── Resource requests ──────────────────────────────────────────────────────────
272
+ from starfish_spaces.resource_requests import (
273
+ PendingRequest,
274
+ accept_resource_grant,
275
+ accept_resource_request,
276
+ clear_req_id_owner_store,
277
+ hydrate_req_id_owner_store,
278
+ reject_resource_request,
279
+ scan_resource_grants,
280
+ scan_resource_rejects,
281
+ scan_resource_requests,
282
+ save_req_id_owner,
283
+ serialize_req_id_owner_store,
284
+ submit_resource_request,
285
+ )
286
+
287
+ # ── Object directory ───────────────────────────────────────────────────────────
288
+ from starfish_spaces.object_directory import (
289
+ ObjectDirectoryEntry,
290
+ parse_object_directory_doc,
291
+ read_object_directory,
292
+ )
293
+
294
+ # ── Lazy plugin imports (avoids pulling starfish_server into client contexts) ──
295
+
296
+ _LAZY_PLUGIN = {
297
+ "create_spaces_role_enricher",
298
+ "create_spaces_directory_server_plugin",
299
+ "spaces_collections",
300
+ }
301
+
302
+
303
+ def __getattr__(name: str) -> object:
304
+ if name in _LAZY_PLUGIN:
305
+ from starfish_spaces import plugin as _plugin
306
+ return getattr(_plugin, name)
307
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
308
+
309
+
310
+ # ── __all__ ────────────────────────────────────────────────────────────────────
311
+
312
+ __all__ = [
313
+ # config & layout
314
+ "SpaceLayout", "SpacesConfig", "KvAdapter", "Space", "ObjectType", "NodeAccess",
315
+ "ObjectNode", "ObjectsIndex", "SealedBlob", "configure_spaces", "get_spaces_config",
316
+ "default_space_layout", "default_user_id_from_ed_pub",
317
+ "OBJECT_COLLECTIONS", "USER_ID_HEX_LENGTH", "RECIPIENT_LABEL_LEN",
318
+ # session
319
+ "Session", "BuildSessionOpts", "BuildLinkedSessionOpts", "LinkedIdentity",
320
+ "build_session", "build_linked_session", "derive_session",
321
+ "fingerprint_from_user_id", "generate_seed_words", "is_valid_seed", "owner_trusted_adders",
322
+ # client helpers
323
+ "DeviceKeys", "ClientOpts", "PublicProfile",
324
+ "make_space_client", "make_anon_space_client", "cap_provider_for",
325
+ "open_encryptor", "build_encryptor",
326
+ "owner_ensure_keyring", "add_keyring_recipient_core",
327
+ "add_space_keyring_recipient", "owner_ensure_space_keyring",
328
+ "ensure_space_keyring_recipient",
329
+ "is_already_present_recipient", "is_keyring_missing",
330
+ "read_profile", "read_profiles", "write_profile", "ensure_pseudo", "ensure_profile_keys",
331
+ "build_auth_headers",
332
+ # keyed store
333
+ "KeyedStore", "ComposedStore", "create_keyed_store", "create_composed_store",
334
+ # space access error
335
+ "SpaceAccessError",
336
+ "NodeAccessRevokedError",
337
+ # space access store
338
+ "SpaceAccessEntry",
339
+ "configure_space_access_store", "hydrate_space_access_store",
340
+ "get_space_access_entry", "save_space_access_entry", "remove_space_access_entry",
341
+ "get_node_access_entry", "save_node_access_entry", "remove_node_access_entry",
342
+ "get_node_stream_access_entry", "save_node_stream_access_entry", "remove_node_stream_access_entry",
343
+ "get_node_keyring_access_entry", "save_node_keyring_access_entry", "remove_node_keyring_access_entry",
344
+ "local_space_access_entries", "member_caps_from_store", "link_access_from_store",
345
+ "clear_space_access_store", "clear_persisted_space_access",
346
+ # account seal
347
+ "seal_to_self", "unseal_from_self", "seal_to_recipient", "unseal_from_recipient",
348
+ # request verify
349
+ "sign_kem_sig", "verify_kem_sig",
350
+ # CAS retry
351
+ "run_cas",
352
+ # objects
353
+ "build_tree", "add_object",
354
+ # node keyring
355
+ "NodeKeyringRecipient",
356
+ "owner_ensure_node_keyring", "open_node_encryptor", "build_node_encryptor",
357
+ "add_node_keyring_recipient", "ensure_node_keyring_recipient", "remove_node_keyring_recipient",
358
+ # space access resolver
359
+ "NodeAccessHandle",
360
+ "get_space_client", "get_node_stream_client", "get_node_access", "build_node_access",
361
+ "clear_node_access_cache",
362
+ # token types
363
+ "JoinRequest", "SpaceInviteLinkToken", "NodeInviteBundle", "NodeInviteKind",
364
+ "NodeInviteLinkToken", "ResourceRequest", "ResourceGrant", "ResourceReject",
365
+ "StoredNodeInvite",
366
+ # invite helpers
367
+ "CapSubject", "adder_of", "mint_cap", "cap_nonce", "parse_join_request",
368
+ "ephemeral_subject_async", "assert_cap_for_me", "evict_keyring_member",
369
+ # registry
370
+ "SpacesDoc", "SpaceEntry",
371
+ "build_space", "on_space_meta", "broadcast_space_meta",
372
+ "read_spaces", "update_spaces_doc", "update_spaces_extra_field", "write_spaces",
373
+ "reorder_spaces", "read_space_access", "read_space_access_batch", "write_space_access",
374
+ "add_space_member", "remove_space_member",
375
+ "remove_joined_space", "move_space",
376
+ "add_joined_space", "add_joined_space_with_cap", "add_joined_space_with_link_access",
377
+ "create_space", "reconcile_space_meta",
378
+ # object index
379
+ "push_index_seed", "seed_space_object_index", "update_object_index", "read_object_tree",
380
+ # members
381
+ "StoredSpaceInvite",
382
+ "make_join_request", "save_space_invite_entry", "get_space_invite_entry",
383
+ "clear_space_invite_store", "serialize_space_invite_store", "hydrate_space_invite_store",
384
+ "invite_to_space", "accept_space_invite",
385
+ "encode_space_invite_link", "decode_space_invite_link", "create_space_invite_link",
386
+ "join_space_by_link", "add_device_to_space_keyring",
387
+ "recover_space_access", "revoke_space_access",
388
+ # nodes
389
+ "CreateNodeInput",
390
+ "save_node_invite_entry", "get_node_invite_entry",
391
+ "clear_node_invite_store", "serialize_node_invite_store", "hydrate_node_invite_store",
392
+ "create_node", "set_node_access",
393
+ "invite_to_node", "accept_node_invite", "revoke_node_access",
394
+ "encode_node_invite_link", "decode_node_invite_link", "create_node_invite_link",
395
+ "join_node_by_link", "read_node_with_link_cap", "write_node_with_link_cap",
396
+ # inbox
397
+ "InboxElement", "inbox_shard", "inbox_shards", "pull_inbox",
398
+ # identity link
399
+ "IdentityLink",
400
+ "verify_identity_link_binding", "encode_identity_link", "decode_identity_link",
401
+ "my_identity_link", "verify_identity_link_keys",
402
+ # resource requests
403
+ "PendingRequest",
404
+ "save_req_id_owner", "serialize_req_id_owner_store",
405
+ "hydrate_req_id_owner_store", "clear_req_id_owner_store",
406
+ "submit_resource_request", "scan_resource_requests",
407
+ "accept_resource_request", "reject_resource_request",
408
+ "scan_resource_grants", "scan_resource_rejects", "accept_resource_grant",
409
+ # object directory
410
+ "ObjectDirectoryEntry", "parse_object_directory_doc", "read_object_directory",
411
+ # lazy plugin exports
412
+ "create_spaces_role_enricher", "create_spaces_directory_server_plugin",
413
+ ]