From 43d4b27d9153e3b3e11597c317d07da6d75a2c8b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:15:25 +0000 Subject: [PATCH 1/5] Initial plan From 8f1e32c8b2c0f160e516a38a6727fe76fad25856 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:17:59 +0000 Subject: [PATCH 2/5] Address PR review comments: Add AnchorStatus enum, rename encrypted_blob, add validation and docs Co-authored-by: igor-holt <125706350+igor-holt@users.noreply.github.com> --- src/__pycache__/main.cpython-312.pyc | Bin 0 -> 2199 bytes src/a2a_ingest/__init__.py | 3 +- .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 517 bytes .../__pycache__/constellation.cpython-312.pyc | Bin 0 -> 8480 bytes src/a2a_ingest/constellation.py | 109 +++++++++++++++--- src/main.py | 40 +++++-- 6 files changed, 128 insertions(+), 24 deletions(-) create mode 100644 src/__pycache__/main.cpython-312.pyc create mode 100644 src/a2a_ingest/__pycache__/__init__.cpython-312.pyc create mode 100644 src/a2a_ingest/__pycache__/constellation.cpython-312.pyc diff --git a/src/__pycache__/main.cpython-312.pyc b/src/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..11658b793383f0dabd3205e9b07ba899ca698276 GIT binary patch literal 2199 zcmZ`)&2Jk;6rc6_W4-Z5+oWkjQgvuU6{}T1s1jgNiW5*3sz%U8NVr0)>F(Isc6Y~} z9XB{~5fl#n4>$l4N2>PFV~*s8)QhVi)vQ_x389LcML3}L!ke+ZiKBKbjo+Jn^FDv? z&4Ya2M6fR3`Nn;cM(9t;3|FF0XxlX)zC#YGB1dx)p5`a22~Ehv6#Uya6>g1R)pf^$UBYm_!92UQ0~EL;+d zQ#;kqmD(k(BcyFZ;E=a067b(&?c_b}?tr_QYNxJ(+}_nju|ygqc55Dpw$rghrmbJi z?A3r!JJZ(MiF=8=1O1oKaU_hP+$`b~Hw}>;@{Zm%zDGYMhFaUkt%Q@jX?$s{X+q&c zN{ZZ2zLpqh7#p5Ash4Y5Ltp5hp*5|PCU*f+E1U!&RMN);`y_B{kYNnfWx$V=v<087~6V1gp#H zyEcwL;5on!zCk?K0U$W|N(+$YhPc)YYzdE2tgF$y;<>hUjke18V?|@2F$qIvyXx+m zD^?XwW9{)}dpB~yncb{{8RRJx&;fL`6=DU~hWNEq2xa_YV2`S~LAhIVZPgmFCPiGN zkdA6ioTsf1IcFTat6@&BH(d_* zYA*Gh5ED+Z?}njl@ET{nQogrfpAxT0cXY_6-$7Ccv?uWeN?~5Ofht?<(n_nb>#DMf z1)TLwyMfI(w6jq1(CfuLDJ|(yQid31$*~8IiDPLf=$)VV1jA4Ewb0<$xHjcZLjWUCT za@o;5ugr~LkISZy%z8ZaA|v*su*bMYLpexf)2a1rEadjKjMk^`~TpM2J(;zFy zM)(tKU!mR`xl~1ad~j~#=x+y?ZkyflBag;UJ{&*!^SQ0@)3=T8)bU4CXCF?T{l(at zTDo267H1w6=N=a4y8DlICy#ayz1qv5eWh)b+-LSsGHd?#uZeOK{~#^(k@mPS*_k@C zK{hUR4pp`a3%_a|W9j+h+~g10&e$<21EvdyJJYA{e{z4ZGxhdX;hl}^9pnAyJzai# z7S4i`w<=mCi8hnjg@nGDFIHys&6xv|o-bC;=$mI!K&!BpOF2FP7uE~%UAYWz*eMLp z%;zf2kq*4dHJ9kdNB;;+E=%y`#lPSd0B z@e{zx2P?E;gS2Sc?`Y*ObnGdbd5RXEptpMIS*@aV^V2%p+fC_-kP2f4Y%xCjbBd literal 0 HcmV?d00001 diff --git a/src/a2a_ingest/__init__.py b/src/a2a_ingest/__init__.py index a05e6bb..1fff809 100644 --- a/src/a2a_ingest/__init__.py +++ b/src/a2a_ingest/__init__.py @@ -1,12 +1,13 @@ """A2A ingestion and interaction layer for moltbook.com.""" -from .constellation import ConstellationStore +from .constellation import AnchorStatus, ConstellationStore from .gatekeeper import IngestionGatekeeper from .schemas import AgentManifest, CelestialBody from .verification import InMemoryKnowledgeGraph __all__ = [ "AgentManifest", + "AnchorStatus", "CelestialBody", "ConstellationStore", "IngestionGatekeeper", diff --git a/src/a2a_ingest/__pycache__/__init__.cpython-312.pyc b/src/a2a_ingest/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86cff3343aeb29719acf589947ad23d7cdfd6759 GIT binary patch literal 517 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 a6yT?J?3`_A8(;r0Ali8ER~**NMfxvQ14IM> literal 0 HcmV?d00001 diff --git a/src/a2a_ingest/constellation.py b/src/a2a_ingest/constellation.py index 8327a0a..9dc9140 100644 --- a/src/a2a_ingest/constellation.py +++ b/src/a2a_ingest/constellation.py @@ -3,6 +3,7 @@ from __future__ import annotations from dataclasses import dataclass +from enum import Enum import hashlib import json from typing import Any, Dict, Optional @@ -10,21 +11,51 @@ from .schemas import AgentCapabilities, CelestialBody, MemoryState -CORRUPTION_MARKER = "[CORRUPTED/MUTATED]" +class AnchorStatus(str, Enum): + """Status of an anchored body in the Constellation.""" + ANCHOR_OK = "ANCHOR_OK" + CORRUPTED = "[CORRUPTED/MUTATED]" @dataclass(frozen=True) class ConstellationRecord: + """Record retrieved from the Constellation with integrity verification status.""" integrity_hash: str - encrypted_blob: Dict[str, Any] + record_data: Dict[str, Any] signature: str public_key: Optional[str] - status: str + status: AnchorStatus recalculated_hash: Optional[str] = None class ConstellationStore: - """In-memory DHT-like store for anchoring Celestial Body manifests.""" + """In-memory DHT-like store for anchoring Celestial Body manifests. + + Thread Safety: + This store is NOT thread-safe. Access from multiple threads requires + external synchronization (e.g., threading.Lock). + + Hash Collisions: + If two different bodies produce the same integrity hash, the second + anchor_body call will overwrite the first. While SHA-256 collisions + are extremely unlikely, callers should be aware of this behavior. + + Signature Verification: + This store accepts and stores signatures but does NOT perform + cryptographic validation. Signature verification is the caller's + responsibility before calling anchor_body. + + Integrity Hash: + The integrity hash covers mission-critical fields only: + - atmosphere: mission, constraints, interfaces + - capabilities: interfaces, skills, compute_profile + - memory_state: continuity_hash, summaries, attachments + + The following fields are intentionally excluded from integrity checks + as they are metadata that may change without affecting the agent's + core functionality: + - body_id, display_name, mass, gravity, trust + """ def __init__(self) -> None: self._dht: Dict[str, Dict[str, Any]] = {} @@ -35,37 +66,63 @@ def anchor_body( signature: str, public_key: Optional[str] = None, ) -> str: + """Anchor a CelestialBody to the Constellation. + + Args: + body: The CelestialBody to anchor + signature: Cryptographic signature (not validated by this method) + public_key: Optional public key associated with the signature + + Returns: + The integrity hash that can be used to retrieve the body + """ integrity_hash = self.compute_integrity_hash(body) - encrypted_blob = { + record_data = { "body": body.as_dict(), "signature": signature, "public_key": public_key, } - self._dht[integrity_hash] = encrypted_blob + self._dht[integrity_hash] = record_data return integrity_hash def retrieve_body(self, integrity_hash: str) -> Optional[ConstellationRecord]: - encrypted_blob = self._dht.get(integrity_hash) - if not encrypted_blob: + """Retrieve an anchored body and verify its integrity. + + Args: + integrity_hash: The hash returned by anchor_body + + Returns: + ConstellationRecord with verification status, or None if not found + """ + record_data = self._dht.get(integrity_hash) + if not record_data: return None - body = self._body_from_payload(encrypted_blob["body"]) + body = self._body_from_payload(record_data["body"]) recalculated_hash = self.compute_integrity_hash(body) - status = "ANCHOR_OK" + status = AnchorStatus.ANCHOR_OK if recalculated_hash != integrity_hash: - status = CORRUPTION_MARKER + status = AnchorStatus.CORRUPTED return ConstellationRecord( integrity_hash=integrity_hash, - encrypted_blob=encrypted_blob, - signature=encrypted_blob["signature"], - public_key=encrypted_blob.get("public_key"), + record_data=record_data, + signature=record_data["signature"], + public_key=record_data.get("public_key"), status=status, recalculated_hash=recalculated_hash, ) def compute_integrity_hash(self, body: CelestialBody) -> str: + """Compute SHA-256 integrity hash over mission-critical fields. + + The hash includes: + - atmosphere: mission, constraints, interfaces + - capabilities: interfaces, skills, compute_profile + - memory_state: continuity_hash, summaries, attachments + """ intent_payload = { "mission": body.atmosphere.get("mission"), "constraints": list(body.atmosphere.get("constraints", [])), + "interfaces": list(body.atmosphere.get("interfaces", [])), } capabilities_payload = { "interfaces": list(body.capabilities.interfaces), @@ -89,8 +146,32 @@ def compute_integrity_hash(self, body: CelestialBody) -> str: return hashlib.sha256(normalized.encode("utf-8")).hexdigest() def _body_from_payload(self, payload: Dict[str, Any]) -> CelestialBody: + """Reconstruct a CelestialBody from a stored payload. + + Args: + payload: Dictionary representation of a CelestialBody + + Returns: + Reconstructed CelestialBody instance + + Raises: + KeyError: If required fields are missing from the payload + TypeError: If field types are incorrect + """ + # Validate required top-level fields + required_fields = ["body_id", "display_name", "mass", "atmosphere", + "gravity", "memory_state", "capabilities"] + missing = [f for f in required_fields if f not in payload] + if missing: + raise KeyError(f"Missing required fields in payload: {missing}") + memory = payload["memory_state"] capabilities = payload["capabilities"] + + # Validate nested required fields + if "continuity_hash" not in memory: + raise KeyError("Missing 'continuity_hash' in memory_state") + return CelestialBody( body_id=payload["body_id"], display_name=payload["display_name"], diff --git a/src/main.py b/src/main.py index 7030368..7027968 100644 --- a/src/main.py +++ b/src/main.py @@ -13,16 +13,38 @@ def anchor_manifest( signature: str, public_key: str, constellation: ConstellationStore, + knowledge_graph: InMemoryKnowledgeGraph, ) -> str: - """Transform a manifest into a Celestial Body and anchor it to the Constellation.""" - gatekeeper = IngestionGatekeeper(knowledge_graph=InMemoryKnowledgeGraph()) - manifest = gatekeeper.load_manifest(payload) - celestial_body = gatekeeper.transform_to_celestial_body(manifest) - return constellation.anchor_body( - body=celestial_body, - signature=signature, - public_key=public_key, - ) + """Transform a manifest into a Celestial Body and anchor it to the Constellation. + + Args: + payload: Raw agent manifest payload + signature: Cryptographic signature (not validated by this function) + public_key: Public key associated with the signature + constellation: ConstellationStore instance for anchoring + knowledge_graph: InMemoryKnowledgeGraph instance for verification + + Returns: + The integrity hash of the anchored body + + Raises: + KeyError: If required fields are missing from the payload + ValueError: If the manifest is malformed or invalid + TypeError: If field types are incorrect + """ + try: + gatekeeper = IngestionGatekeeper(knowledge_graph=knowledge_graph) + manifest = gatekeeper.load_manifest(payload) + celestial_body = gatekeeper.transform_to_celestial_body(manifest) + return constellation.anchor_body( + body=celestial_body, + signature=signature, + public_key=public_key, + ) + except KeyError as e: + raise KeyError(f"Missing required field in manifest: {e}") from e + except (ValueError, TypeError) as e: + raise ValueError(f"Invalid manifest format: {e}") from e __all__ = ["anchor_manifest"] From a53b4b1a8fdb3c02b89eaf69e573f938d9784007 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:18:13 +0000 Subject: [PATCH 3/5] Remove __pycache__ files and add .gitignore Co-authored-by: igor-holt <125706350+igor-holt@users.noreply.github.com> --- .gitignore | 39 ++++++++++++++++++ src/__pycache__/main.cpython-312.pyc | Bin 2199 -> 0 bytes .../__pycache__/__init__.cpython-312.pyc | Bin 517 -> 0 bytes .../__pycache__/constellation.cpython-312.pyc | Bin 8480 -> 0 bytes 4 files changed, 39 insertions(+) create mode 100644 .gitignore delete mode 100644 src/__pycache__/main.cpython-312.pyc delete mode 100644 src/a2a_ingest/__pycache__/__init__.cpython-312.pyc delete mode 100644 src/a2a_ingest/__pycache__/constellation.cpython-312.pyc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..38f7f94 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Virtual environments +venv/ +ENV/ +env/ +.venv + +# IDEs +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db diff --git a/src/__pycache__/main.cpython-312.pyc b/src/__pycache__/main.cpython-312.pyc deleted file mode 100644 index 11658b793383f0dabd3205e9b07ba899ca698276..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2199 zcmZ`)&2Jk;6rc6_W4-Z5+oWkjQgvuU6{}T1s1jgNiW5*3sz%U8NVr0)>F(Isc6Y~} z9XB{~5fl#n4>$l4N2>PFV~*s8)QhVi)vQ_x389LcML3}L!ke+ZiKBKbjo+Jn^FDv? z&4Ya2M6fR3`Nn;cM(9t;3|FF0XxlX)zC#YGB1dx)p5`a22~Ehv6#Uya6>g1R)pf^$UBYm_!92UQ0~EL;+d zQ#;kqmD(k(BcyFZ;E=a067b(&?c_b}?tr_QYNxJ(+}_nju|ygqc55Dpw$rghrmbJi z?A3r!JJZ(MiF=8=1O1oKaU_hP+$`b~Hw}>;@{Zm%zDGYMhFaUkt%Q@jX?$s{X+q&c zN{ZZ2zLpqh7#p5Ash4Y5Ltp5hp*5|PCU*f+E1U!&RMN);`y_B{kYNnfWx$V=v<087~6V1gp#H zyEcwL;5on!zCk?K0U$W|N(+$YhPc)YYzdE2tgF$y;<>hUjke18V?|@2F$qIvyXx+m zD^?XwW9{)}dpB~yncb{{8RRJx&;fL`6=DU~hWNEq2xa_YV2`S~LAhIVZPgmFCPiGN zkdA6ioTsf1IcFTat6@&BH(d_* zYA*Gh5ED+Z?}njl@ET{nQogrfpAxT0cXY_6-$7Ccv?uWeN?~5Ofht?<(n_nb>#DMf z1)TLwyMfI(w6jq1(CfuLDJ|(yQid31$*~8IiDPLf=$)VV1jA4Ewb0<$xHjcZLjWUCT za@o;5ugr~LkISZy%z8ZaA|v*su*bMYLpexf)2a1rEadjKjMk^`~TpM2J(;zFy zM)(tKU!mR`xl~1ad~j~#=x+y?ZkyflBag;UJ{&*!^SQ0@)3=T8)bU4CXCF?T{l(at zTDo267H1w6=N=a4y8DlICy#ayz1qv5eWh)b+-LSsGHd?#uZeOK{~#^(k@mPS*_k@C zK{hUR4pp`a3%_a|W9j+h+~g10&e$<21EvdyJJYA{e{z4ZGxhdX;hl}^9pnAyJzai# z7S4i`w<=mCi8hnjg@nGDFIHys&6xv|o-bC;=$mI!K&!BpOF2FP7uE~%UAYWz*eMLp z%;zf2kq*4dHJ9kdNB;;+E=%y`#lPSd0B z@e{zx2P?E;gS2Sc?`Y*ObnGdbd5RXEptpMIS*@aV^V2%p+fC_-kP2f4Y%xCjbBd diff --git a/src/a2a_ingest/__pycache__/__init__.cpython-312.pyc b/src/a2a_ingest/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 86cff3343aeb29719acf589947ad23d7cdfd6759..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 517 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 a6yT?J?3`_A8(;r0Ali8ER~**NMfxvQ14IM> From 17a382f014d4c2d73e1fc689e51fe93e853a3cec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:19:18 +0000 Subject: [PATCH 4/5] Fix code style and complete security scan Co-authored-by: igor-holt <125706350+igor-holt@users.noreply.github.com> --- src/a2a_ingest/constellation.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/a2a_ingest/constellation.py b/src/a2a_ingest/constellation.py index 9dc9140..f10112f 100644 --- a/src/a2a_ingest/constellation.py +++ b/src/a2a_ingest/constellation.py @@ -159,8 +159,10 @@ def _body_from_payload(self, payload: Dict[str, Any]) -> CelestialBody: TypeError: If field types are incorrect """ # Validate required top-level fields - required_fields = ["body_id", "display_name", "mass", "atmosphere", - "gravity", "memory_state", "capabilities"] + required_fields = [ + "body_id", "display_name", "mass", "atmosphere", + "gravity", "memory_state", "capabilities" + ] missing = [f for f in required_fields if f not in payload] if missing: raise KeyError(f"Missing required fields in payload: {missing}") From 74d743c51b3fbc4cac072286d8430842e587abea Mon Sep 17 00:00:00 2001 From: Igor Holt Date: Sun, 17 May 2026 01:15:39 -0400 Subject: [PATCH 5/5] Update constellation.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Igor Holt --- src/a2a_ingest/constellation.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/a2a_ingest/constellation.py b/src/a2a_ingest/constellation.py index f10112f..9c802ed 100644 --- a/src/a2a_ingest/constellation.py +++ b/src/a2a_ingest/constellation.py @@ -173,6 +173,10 @@ def _body_from_payload(self, payload: Dict[str, Any]) -> CelestialBody: # Validate nested required fields if "continuity_hash" not in memory: raise KeyError("Missing 'continuity_hash' in memory_state") + if "interfaces" not in capabilities: + raise KeyError("Missing 'interfaces' in capabilities") + if "skills" not in capabilities: + raise KeyError("Missing 'skills' in capabilities") return CelestialBody( body_id=payload["body_id"],