docs(identity): resolve merge revocability + SSE open questions

Open Question 1 (merge revocability): adopted. The clusterer will
clear merged_into_uuid on contradicting evidence and publish a new
identity.unmerged topic alongside the existing three identity.* topics
so subscribers on identity.> get it from day one.

Open Question 2 (AttackerDetail UX on identity_id change): adopted
SSE over refresh-on-focus. New endpoint will mirror the existing
topology mutator SSE (bus subscription on identity.>, JWT via ?token=,
snapshot-on-connect + live forward).

Risk 2 (API URL stability for soft-merged loser UUIDs): struck —
already shipped in commit dc3d08d (read-only API follows
merged_into_uuid and surfaces the canonical winner).
This commit is contained in:
2026-04-26 07:33:36 -04:00
parent f6b83755eb
commit 943bb3a39d

View File

@@ -234,11 +234,9 @@ badge linking to `/identities/<uuid>`. No change otherwise.
re-attributed; previous identity remains as a soft-merged
reference"). The `merged_into_uuid` chain is the audit trail.
2. **API URL stability.** Identity UUIDs that get soft-merged via
`merged_into_uuid` should still resolve at
`/api/v1/identities/{uuid}` — return 301 to the winner, or return
the loser row with a `merged_into` link. Decide before the
clusterer ships.
2. ~~**API URL stability.**~~ Resolved in commit `dc3d08d`: the
read-only API follows `merged_into_uuid` and surfaces the canonical
winner. Loser UUIDs resolve to the winner row.
3. **Schema-version lock-in for federation.** `schema_version=1` is
what we ship. Any fingerprint added to the identity row post-v1
@@ -263,19 +261,19 @@ badge linking to `/identities/<uuid>`. No change otherwise.
## Open Questions
1. **Revocability of identity merges.** When the clusterer merges
identities A and B into A (via `merged_into_uuid`), can a future
evidence update split them back apart? Leaning yes — clear
`B.merged_into_uuid`, re-link B's original observations. But that
leaks history (any subscriber that cached "B is gone" now sees B
alive again). May need an explicit `identity.unmerged` topic.
Decide before the clusterer ships.
1. ~~**Revocability of identity merges.**~~ **Resolved 2026-04-26:**
merges are revocable. `identity.unmerged` topic ships in
`decnet/bus/topics.py` alongside the existing three so subscribers
on `identity.>` get it from day one. Clusterer clears
`merged_into_uuid`, re-links observations, publishes
`identity.unmerged` + a fresh `identity.formed` for the
resurrected side.
2. **`AttackerDetail` UX when `identity_id` changes.** If an operator
has a tab open showing `attackers/X` with identity_id=A, and the
clusterer rewrites it to identity_id=B, the page goes stale.
Acceptable: stale tab, refresh on focus. Better: SSE channel
pushes the change. Decide alongside the clusterer.
2. ~~**`AttackerDetail` UX when `identity_id` changes.**~~ **Resolved
2026-04-26:** SSE channel modeled on the topology-mutator SSE.
New endpoint subscribes to `identity.>`, JWT via `?token=`,
snapshot-on-connect + live forward. `AttackerDetail` and
`IdentityDetail` consume it.
3. **`SessionProfile.identity_id` FK.** Does this PR sequence add it,
or does it wait for V2 keystroke dynamics? Leaning **wait** — the