hivemind-http-protocol 0.0.7a3__tar.gz → 0.0.8a2__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 (19) hide show
  1. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/PKG-INFO +1 -1
  2. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/hivemind_http_protocol/__init__.py +9 -0
  3. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/hivemind_http_protocol/version.py +2 -2
  4. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/hivemind_http_protocol.egg-info/PKG-INFO +1 -1
  5. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/hivemind_http_protocol.egg-info/SOURCES.txt +1 -0
  6. hivemind_http_protocol-0.0.8a2/tests/test_acl_parity.py +47 -0
  7. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/tests/test_client_lifecycle.py +1 -0
  8. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/LICENSE.md +0 -0
  9. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/README.md +0 -0
  10. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/hivemind_http_protocol.egg-info/dependency_links.txt +0 -0
  11. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/hivemind_http_protocol.egg-info/entry_points.txt +0 -0
  12. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/hivemind_http_protocol.egg-info/requires.txt +0 -0
  13. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/hivemind_http_protocol.egg-info/top_level.txt +0 -0
  14. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/pyproject.toml +0 -0
  15. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/setup.cfg +0 -0
  16. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/tests/test_decode_auth.py +0 -0
  17. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/tests/test_handlers.py +0 -0
  18. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/tests/test_protocol_unit.py +0 -0
  19. {hivemind_http_protocol-0.0.7a3 → hivemind_http_protocol-0.0.8a2}/tests/test_retention_bound.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hivemind-http-protocol
3
- Version: 0.0.7a3
3
+ Version: 0.0.8a2
4
4
  Summary: http network protocol for hivemind-core
5
5
  Author-email: jarbasAi <jarbasai@mailfence.com>
6
6
  License-Expression: Apache-2.0
@@ -582,6 +582,15 @@ class HiveMindHttpHandler(web.RequestHandler):
582
582
  client.name = f"{useragent}::{user.client_id}::{user.name}"
583
583
  client.crypto_key = user.crypto_key
584
584
  client.allowed_types = user.allowed_types
585
+ # The WebSocket transport copies this too. Leaving it out let the
586
+ # dataclass default (True) stand, so `hivemind-core blacklist-broadcast`
587
+ # — a command whose only purpose is to set it False — was silently a
588
+ # no-op over HTTP while being enforced over WebSocket. Two transports
589
+ # into one node must reach the same admission decision for the same
590
+ # database row.
591
+ client.can_broadcast = user.can_broadcast
592
+ client.intent_blacklist = user.intent_blacklist
593
+ client.skill_blacklist = user.skill_blacklist
585
594
  client.can_propagate = user.can_propagate
586
595
  client.can_escalate = user.can_escalate
587
596
  client.is_admin = user.is_admin
@@ -1,8 +1,8 @@
1
1
  # START_VERSION_BLOCK
2
2
  VERSION_MAJOR = 0
3
3
  VERSION_MINOR = 0
4
- VERSION_BUILD = 7
5
- VERSION_ALPHA = 3
4
+ VERSION_BUILD = 8
5
+ VERSION_ALPHA = 2
6
6
  # END_VERSION_BLOCK
7
7
 
8
8
  __version__ = f"{VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_BUILD}" + (f"a{VERSION_ALPHA}" if VERSION_ALPHA else "")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hivemind-http-protocol
3
- Version: 0.0.7a3
3
+ Version: 0.0.8a2
4
4
  Summary: http network protocol for hivemind-core
5
5
  Author-email: jarbasAi <jarbasai@mailfence.com>
6
6
  License-Expression: Apache-2.0
@@ -9,6 +9,7 @@ hivemind_http_protocol.egg-info/dependency_links.txt
9
9
  hivemind_http_protocol.egg-info/entry_points.txt
10
10
  hivemind_http_protocol.egg-info/requires.txt
11
11
  hivemind_http_protocol.egg-info/top_level.txt
12
+ tests/test_acl_parity.py
12
13
  tests/test_client_lifecycle.py
13
14
  tests/test_decode_auth.py
14
15
  tests/test_handlers.py
@@ -0,0 +1,47 @@
1
+ """Both transports must reach the same admission decision for one DB row.
2
+
3
+ A node accepts clients over WebSocket and over HTTP, and each builds its
4
+ connection object from the same database record. Any ACL field one transport
5
+ copies and the other does not is a weaker door into the same node: the
6
+ `hivemind-core` command that sets it appears to work and is enforced on one
7
+ transport only.
8
+ """
9
+ import inspect
10
+ import re
11
+
12
+ import hivemind_http_protocol
13
+
14
+ #: Every ACL field a transport must carry from the database row onto the
15
+ #: connection. Listed explicitly rather than derived from the other transport
16
+ #: at runtime, so the check does not depend on which version happens to be
17
+ #: installed. When a new ACL field is added, add it here.
18
+ REQUIRED_ACL_FIELDS = {
19
+ "crypto_key",
20
+ "allowed_types",
21
+ "can_broadcast",
22
+ "can_propagate",
23
+ "can_escalate",
24
+ "is_admin",
25
+ "intent_blacklist",
26
+ "skill_blacklist",
27
+ }
28
+
29
+
30
+ def _copied_fields() -> set:
31
+ src = inspect.getsource(hivemind_http_protocol)
32
+ return {m.group(1)
33
+ for m in re.finditer(r"client\.(\w+)\s*=\s*user\.(\w+)", src)}
34
+
35
+
36
+ def test_every_acl_field_is_carried_from_the_database():
37
+ missing = REQUIRED_ACL_FIELDS - _copied_fields()
38
+
39
+ assert not missing, (
40
+ f"HTTP clients silently keep the permissive dataclass default for: "
41
+ f"{sorted(missing)}")
42
+
43
+
44
+ def test_broadcast_permission_is_among_them():
45
+ """`hivemind-core blacklist-broadcast` exists to set this False; without
46
+ the copy it was a no-op over HTTP while being enforced over WebSocket."""
47
+ assert "can_broadcast" in _copied_fields()
@@ -36,6 +36,7 @@ class _DB:
36
36
  client_id=1, name="node", crypto_key=None, password=None,
37
37
  skill_blacklist=[], intent_blacklist=[], allowed_types=["speak"],
38
38
  can_propagate=True, can_escalate=True, is_admin=False,
39
+ can_broadcast=True,
39
40
  )
40
41
 
41
42