Skip to content

Commit a5bbfe1

Browse files
committed
fix(federation): allow same-name pinned peer events
1 parent 2b47782 commit a5bbfe1

2 files changed

Lines changed: 53 additions & 15 deletions

File tree

internal/cortex/cortex.go

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,25 +1346,31 @@ func (c *Cortex) backfillTraceUsage() error {
13461346
return nil
13471347
}
13481348

1349-
// detectCopiedDirectory refuses to start when events this cortex *authored*
1350-
// (origin == its display name) are recorded under a cortex_id other than the
1351-
// one cortex.md now declares. That is the signature of a directory copied or
1352-
// re-identified from another instance: its own history lives under a stale
1353-
// identity, and running it would create two physical Cortexes claiming the same
1354-
// id in any federation they joined, silently merging vector clocks.
1349+
// detectCopiedDirectory refuses to start when events that appear locally
1350+
// authored are recorded under a cortex_id other than the one cortex.md now
1351+
// declares. That is the signature of a directory copied or re-identified from
1352+
// another instance: its own history lives under a stale identity, and running
1353+
// it would create two physical Cortexes claiming the same id in any federation
1354+
// they joined, silently merging vector clocks.
13551355
//
1356-
// Crucially, the check keys on origin, NOT on "any foreign cortex_id". Events
1357-
// replayed from peers via federation legitimately carry the originating
1358-
// cortex's id, so a receiver or subscribe cortex normally holds many
1359-
// foreign-id events with none of its own — that is expected, not a copy. The
1360-
// earlier id-only heuristic flagged exactly that case, making such a cortex
1361-
// unopenable (serve restart and every CLI command, including the reset-peer
1362-
// recovery) after its first sync. Scoping to origin matches precisely the rows
1363-
// `noema migrate cortex-id --reset` re-keys, so the guard and its remedy agree.
1356+
// The check cannot rely on origin alone. It is a display label, and real
1357+
// federations may contain multiple distinct cortex IDs with the same name. A
1358+
// peer event with origin == c.Name is legitimate when the foreign cortex_id is
1359+
// one of our pinned peers, so those IDs are excluded from the copy count.
13641360
func (c *Cortex) detectCopiedDirectory() error {
13651361
var ownUnderForeignID int
13661362
if err := c.DB.QueryRow(
1367-
`SELECT COUNT(*) FROM events WHERE origin = ? AND cortex_id != '' AND cortex_id != ?`,
1363+
`SELECT COUNT(*)
1364+
FROM events
1365+
WHERE origin = ?
1366+
AND cortex_id != ''
1367+
AND cortex_id != ?
1368+
AND cortex_id NOT IN (
1369+
SELECT value
1370+
FROM federation_state
1371+
WHERE key LIKE 'peer:%:cortex_id'
1372+
AND value != ''
1373+
)`,
13681374
c.Name, c.ID,
13691375
).Scan(&ownUnderForeignID); err != nil {
13701376
return nil // table missing or unreadable — treat as fresh, don't block

internal/cortex/cortex_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,38 @@ func TestOpen_AllowsFederatedReceiver(t *testing.T) {
280280
cx2.Close()
281281
}
282282

283+
func TestOpen_AllowsPinnedPeerWithSameDisplayName(t *testing.T) {
284+
dir := t.TempDir()
285+
if _, err := cortex.Create("agentbrain", dir); err != nil {
286+
t.Fatalf("Create: %v", err)
287+
}
288+
root := filepath.Join(dir, "agentbrain")
289+
290+
cx, err := cortex.Open("agentbrain", root)
291+
if err != nil {
292+
t.Fatalf("first Open: %v", err)
293+
}
294+
peerID := "01PEERCORTEX0000000000000A"
295+
if err := federation.NewState(cx.DB.DB).SetPeerCortexID("peer-a", peerID); err != nil {
296+
t.Fatalf("pin peer cortex id: %v", err)
297+
}
298+
// Multiple machines may intentionally use the same human-readable cortex
299+
// name. The authenticated cortex_id, not origin, is the peer identity.
300+
if _, err := cx.DB.Exec(
301+
`INSERT INTO events (id, action, trace_id, cortex_id, origin, timestamp) VALUES (?, ?, ?, ?, ?, ?)`,
302+
"01EVPEER0000000000000000B", "create", "20260610-peer-same-name", peerID, "agentbrain", "2026-06-10T00:00:00Z",
303+
); err != nil {
304+
t.Fatalf("seed same-name peer event: %v", err)
305+
}
306+
cx.Close()
307+
308+
cx2, err := cortex.Open("agentbrain", root)
309+
if err != nil {
310+
t.Fatalf("reopening with a pinned same-name peer event must succeed, got: %v", err)
311+
}
312+
cx2.Close()
313+
}
314+
283315
// TestOpen_RejectsReIdentifiedCopy keeps the real copy detection: when events
284316
// THIS cortex authored (origin == its name) are recorded under a cortex_id that
285317
// differs from the one cortex.md now declares, the directory was copied or

0 commit comments

Comments
 (0)