stage-fed-b federation: dns record format

This commit is contained in:
m17hr1l
2026-06-06 16:08:31 +02:00
parent 4c35aad2bb
commit 50158f7fa8

View File

@@ -18,6 +18,7 @@ from typing import Tuple
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ed25519
from pydantic import BaseModel
from psyc import DATA_DIR, log
@@ -28,6 +29,10 @@ FED_DIR = DATA_DIR / "federation"
PRIVATE_KEY_PATH = FED_DIR / "node.key"
PUBLIC_KEY_PATH = FED_DIR / "node.pub"
FEED_VERSION = "psyc1"
FEED_ALG = "ed25519"
FEED_PATH = "/federation/feed"
# ---------- keypair persistence -----------------------------------------
@@ -93,3 +98,56 @@ def node_fingerprint() -> str:
_, pub = node_keypair()
digest = hashlib.sha256(_raw_pubkey_bytes(pub)).digest()
return digest[:16].hex()
def _fingerprint_for_pubkey_pem(pubkey_pem: str) -> str:
pub = serialization.load_pem_public_key(pubkey_pem.encode("ascii"))
if not isinstance(pub, ed25519.Ed25519PublicKey):
raise ValueError("not an Ed25519 public key")
return hashlib.sha256(_raw_pubkey_bytes(pub)).digest()[:16].hex()
# ---------- DNS record format -------------------------------------------
class DNSRecord(BaseModel):
"""The SRV + TXT pair an admin pastes into their zone file."""
srv_name: str
srv_target: str
srv_port: int
srv_priority: int = 10
srv_weight: int = 10
txt_name: str
txt_value: str
human_instructions: str
def dns_record(domain: str, port: int = 443) -> DNSRecord:
"""Build the DNS-SD-style records that advertise this node at `domain`."""
fp = node_fingerprint()
srv_name = f"_psyc._tcp.{domain}"
srv_target = f"{domain}."
txt_name = srv_name
txt_value = f"v={FEED_VERSION} fp={fp} alg={FEED_ALG} path={FEED_PATH}"
instructions = (
f"; psyc federation records for {domain}\n"
f"; ----------------------------------------------------------\n"
f"; 1) SRV record — locates this psyc node (host + port).\n"
f'{srv_name}. 3600 IN SRV 10 10 {port} {srv_target}\n'
f";\n"
f"; 2) TXT record — declares protocol version, key fingerprint,\n"
f"; signature algorithm, and the feed endpoint path.\n"
f'{txt_name}. 3600 IN TXT "{txt_value}"\n'
f"; ----------------------------------------------------------\n"
f"; Once these are live, federation peers can fetch:\n"
f"; https://{domain}{FEED_PATH} (signed feed JSON)\n"
f"; https://{domain}/federation/key (public key PEM)\n"
f"; https://{domain}/federation/info (capabilities)\n"
)
return DNSRecord(
srv_name=srv_name,
srv_target=srv_target,
srv_port=port,
txt_name=txt_name,
txt_value=txt_value,
human_instructions=instructions,
)