gabriel / muse public
records.py python
63 lines 2.3 KB
Raw
sha256:e8214e0062ef8ef0af999937df2731655b6082781fc22bc563f58db2f42b1de9 Merge 'bump/muse-v0.2.1' into 'dev' — proposal: chore: bump… Human 10 days ago
1 """Identity domain record types and path codec."""
2
3 import json
4 from typing import Literal, TypedDict
5
6 from muse.core.types import Metadata
7
8 class SignatureRecord(TypedDict):
9 signer: str
10 signature: str
11 signed_at: str
12
13 class IdentityRecord(TypedDict):
14 handle: str
15 type: Literal["human", "agent", "org"]
16 pubkey: str | None
17 quorum: int | None
18 registered_at: str
19 metadata: Metadata
20
21 class RelationshipRecord(TypedDict):
22 from_handle: str
23 to_handle: str
24 edge_type: Literal["spawns", "member_of"]
25 weight: str | None
26 authorized_by: list[SignatureRecord]
27
28 # ── path encoding ──────────────────────────────────────────────────────────────
29
30 def identity_path(handle: str) -> str:
31 return f"identities/{handle}.json"
32
33 def relationship_path(from_handle: str, edge_type: str, to_handle: str) -> str:
34 return f"relationships/{from_handle}--{edge_type}--{to_handle}.json"
35
36 def parse_identity_path(path: str) -> str | None:
37 """Return handle if path is an identity path, else None."""
38 if path.startswith("identities/") and path.endswith(".json"):
39 inner = path[len("identities/"):-len(".json")]
40 if "/" not in inner and inner:
41 return inner
42 return None
43
44 def parse_relationship_path(path: str) -> tuple[str, str, str] | None:
45 """Return (from, edge_type, to) if path is a relationship path, else None."""
46 if not (path.startswith("relationships/") and path.endswith(".json")):
47 return None
48 inner = path[len("relationships/"):-len(".json")]
49 parts = inner.split("--")
50 if len(parts) != 3:
51 return None
52 frm, edge, to = parts
53 if not frm or not edge or not to:
54 return None
55 return frm, edge, to
56
57 # ── serialisation ──────────────────────────────────────────────────────────────
58
59 def record_to_bytes(record: IdentityRecord | RelationshipRecord) -> bytes:
60 return json.dumps(record, sort_keys=True, ensure_ascii=False).encode()
61
62 def record_from_bytes(raw: bytes) -> IdentityRecord | RelationshipRecord:
63 return json.loads(raw)
File History 4 commits
sha256:e8214e0062ef8ef0af999937df2731655b6082781fc22bc563f58db2f42b1de9 Merge 'bump/muse-v0.2.1' into 'dev' — proposal: chore: bump… Human 10 days ago
sha256:8de4334a98c945aace420969d389ad678aa926d4ab4e886b2ac4c4241cb3bf2b revert: keep pyproject.toml in canonical PEP 440 form Sonnet 4.6 patch 68 days ago
sha256:a317886dc0496c4af7b285b3e41c86c4c34ea2e79afc63b8829aadb1ada7903f chore: bump version to 0.2.0rc15 to match musehub#113 fix release Sonnet 4.6 patch 68 days ago
sha256:f3b726b50f0aee3622bba751e0a67aa7ae4cf75a798477dbce581940b6a9cf70 feat: migrate invariants cache to .muse/cache/invariants.ms… Sonnet 4.6 patch 136 days ago