records.py
python
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