Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions internal/cortex/cortex.go
Original file line number Diff line number Diff line change
Expand Up @@ -1346,25 +1346,31 @@ func (c *Cortex) backfillTraceUsage() error {
return nil
}

// detectCopiedDirectory refuses to start when events this cortex *authored*
// (origin == its display name) are recorded under a cortex_id other than the
// one cortex.md now declares. That is the signature of a directory copied or
// re-identified from another instance: its own history lives under a stale
// identity, and running it would create two physical Cortexes claiming the same
// id in any federation they joined, silently merging vector clocks.
// detectCopiedDirectory refuses to start when events that appear locally
// authored are recorded under a cortex_id other than the one cortex.md now
// declares. That is the signature of a directory copied or re-identified from
// another instance: its own history lives under a stale identity, and running
// it would create two physical Cortexes claiming the same id in any federation
// they joined, silently merging vector clocks.
//
// Crucially, the check keys on origin, NOT on "any foreign cortex_id". Events
// replayed from peers via federation legitimately carry the originating
// cortex's id, so a receiver or subscribe cortex normally holds many
// foreign-id events with none of its own — that is expected, not a copy. The
// earlier id-only heuristic flagged exactly that case, making such a cortex
// unopenable (serve restart and every CLI command, including the reset-peer
// recovery) after its first sync. Scoping to origin matches precisely the rows
// `noema migrate cortex-id --reset` re-keys, so the guard and its remedy agree.
// The check cannot rely on origin alone. It is a display label, and real
// federations may contain multiple distinct cortex IDs with the same name. A
// peer event with origin == c.Name is legitimate when the foreign cortex_id is
// one of our pinned peers, so those IDs are excluded from the copy count.
func (c *Cortex) detectCopiedDirectory() error {
var ownUnderForeignID int
if err := c.DB.QueryRow(
`SELECT COUNT(*) FROM events WHERE origin = ? AND cortex_id != '' AND cortex_id != ?`,
`SELECT COUNT(*)
FROM events
WHERE origin = ?
AND cortex_id != ''
AND cortex_id != ?
AND cortex_id NOT IN (
SELECT value
FROM federation_state
WHERE key LIKE 'peer:%:cortex_id'
AND value != ''
)`,
c.Name, c.ID,
).Scan(&ownUnderForeignID); err != nil {
return nil // table missing or unreadable — treat as fresh, don't block
Expand Down
32 changes: 32 additions & 0 deletions internal/cortex/cortex_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,38 @@ func TestOpen_AllowsFederatedReceiver(t *testing.T) {
cx2.Close()
}

func TestOpen_AllowsPinnedPeerWithSameDisplayName(t *testing.T) {
dir := t.TempDir()
if _, err := cortex.Create("agentbrain", dir); err != nil {
t.Fatalf("Create: %v", err)
}
root := filepath.Join(dir, "agentbrain")

cx, err := cortex.Open("agentbrain", root)
if err != nil {
t.Fatalf("first Open: %v", err)
}
peerID := "01PEERCORTEX0000000000000A"
if err := federation.NewState(cx.DB.DB).SetPeerCortexID("peer-a", peerID); err != nil {
t.Fatalf("pin peer cortex id: %v", err)
}
// Multiple machines may intentionally use the same human-readable cortex
// name. The authenticated cortex_id, not origin, is the peer identity.
if _, err := cx.DB.Exec(
`INSERT INTO events (id, action, trace_id, cortex_id, origin, timestamp) VALUES (?, ?, ?, ?, ?, ?)`,
"01EVPEER0000000000000000B", "create", "20260610-peer-same-name", peerID, "agentbrain", "2026-06-10T00:00:00Z",
); err != nil {
t.Fatalf("seed same-name peer event: %v", err)
}
cx.Close()

cx2, err := cortex.Open("agentbrain", root)
if err != nil {
t.Fatalf("reopening with a pinned same-name peer event must succeed, got: %v", err)
}
cx2.Close()
}

// TestOpen_RejectsReIdentifiedCopy keeps the real copy detection: when events
// THIS cortex authored (origin == its name) are recorded under a cortex_id that
// differs from the one cortex.md now declares, the directory was copied or
Expand Down
Loading