"""Wire shapes for the system registry. Owner identity (name + work email) is included: unlike the bounty domain's researcher, a system owner is a colleague and the whole point of the row is being able to reach them. What is never included is anything about the owner beyond how to contact them. """ from __future__ import annotations from datetime import date, datetime from typing import Any from app.domains.system_registry.models import ( RegisteredSystem, RegisteredSystemEvent, ) def _iso(value: datetime | date | None) -> str | None: return None if value is None else value.isoformat() def _person(person: Any) -> dict[str, Any] | None: if person is None: return None return { "id": str(person.id), "name": person.display_name, "email": person.work_email, "department": person.department, "employment_status": person.employment_status, } def serialize_system( system: RegisteredSystem, *, include_notes: bool = True, ) -> dict[str, Any]: payload: dict[str, Any] = { "id": str(system.id), "slug": system.slug, "name": system.name, "kind": system.kind, "status": system.status, "exposure": system.exposure, "hostnames": list(system.hostnames or []), "description": system.description, "repo": system.repo, "owner": _person(system.owner), "backup_owner": _person(system.backup_owner), # Kept alongside ``owner`` because the owner's CURRENT department # can differ from the one recorded when they took the system on, # and an attribution report must not silently rewrite history. "owner_department": system.owner_department, "owner_assigned_at": _iso(system.owner_assigned_at), "budget_track": system.budget_track, "in_bounty_scope": system.in_bounty_scope, "source": system.source, "created_at": _iso(system.created_at), "updated_at": _iso(system.updated_at), } if include_notes: payload["notes"] = system.notes return payload def serialize_system_option(system: RegisteredSystem) -> dict[str, Any]: """The narrow shape the bounty console's picker needs: enough to choose correctly (name, hosts, owner, pot) and nothing else.""" return { "id": str(system.id), "slug": system.slug, "name": system.name, "kind": system.kind, "status": system.status, "exposure": system.exposure, "hostnames": list(system.hostnames or []), "budget_track": system.budget_track, "in_bounty_scope": system.in_bounty_scope, "owner": _person(system.owner), "backup_owner": _person(system.backup_owner), } def serialize_event(event: RegisteredSystemEvent) -> dict[str, Any]: return { "id": str(event.id), "system_id": str(event.system_id), "event_type": event.event_type, "actor_person_id": ( str(event.actor_person_id) if event.actor_person_id else None ), "actor_name": event.actor_name, "body": event.body, "meta": event.meta or {}, "created_at": _iso(event.created_at), }