gabriel / muse public
records.py python
63 lines 2.3 KB
Raw
sha256:2eaa5d95f9d9383498e76947410a26e5a3ba23d182f339910c424cf88fad412b fix: try fetch/presign before fetch/mpack to avoid Cloudfla… Sonnet 4.6 patch 8 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 1 commit
sha256:2eaa5d95f9d9383498e76947410a26e5a3ba23d182f339910c424cf88fad412b fix: try fetch/presign before fetch/mpack to avoid Cloudfla… Sonnet 4.6 patch 8 days ago