# Feature: Kunnskaps-Bridge (Cross-Context Discovery)
**Filsti:** `docs/features/kunnskaps_bridge.md`

> **NB:** Dette dokumentet er en skisse fra v1 og må oppdateres til node/edge-modellen ved implementering.

## 1. Konsept
En valgfri, opt-in feature som lar brukere oppdage semantisk beslektet kunnskap på tvers av samlings-noder de har tilgang til. Bryter ikke tilgangsstyringen — resultatet er en *peker* ("dette finnes i Podcast B"), ikke selve innholdet. Brukeren må ha tilgang til begge samlings-nodene via `node_access` for å se treffet.

## 2. Avgrensning: Hva dette IKKE er
- **Ikke datadeling.** Ingen data kopieres mellom samlings-noder. Bridge viser kun at en relevant node *finnes*.
- **Ikke automatisk.** Begge samlings-noder må ha Bridge eksplisitt aktivert av en admin.
- **Ikke synlig for gjester.** Kun for brukere med tilgang til begge samlings-nodene.
- **Ikke et søk i andres data.** Du ser bare treff i samlings-noder du allerede har tilgang til.

## 3. Teknisk arkitektur

### 3.1 Vector Embeddings (pgvector)
Krever `pgvector`-extension i PostgreSQL:

```sql
CREATE EXTENSION IF NOT EXISTS vector;

ALTER TABLE actors ADD COLUMN embedding vector(768);
ALTER TABLE topics ADD COLUMN embedding vector(768);
ALTER TABLE factoids ADD COLUMN embedding vector(768);

CREATE INDEX idx_actors_embedding ON actors USING ivfflat (embedding vector_cosine_ops);
CREATE INDEX idx_topics_embedding ON topics USING ivfflat (embedding vector_cosine_ops);
CREATE INDEX idx_factoids_embedding ON factoids USING ivfflat (embedding vector_cosine_ops);
```

### 3.2 Embedding-generering (`generate_embeddings`)
En jobbkø-jobb som genererer embeddings for nye/endrede noder:
1. Rust-worker plukker opp jobben fra jobbkøen.
2. Bygger en tekst-representasjon av noden (navn, body, tilknyttede faktoider).
3. Sender til AI Gateway (`sidelinja/rutine`) for embedding-generering.
4. Lagrer vektoren i pgvector-kolonnen.
5. Re-genereres ved vesentlige endringer av noden.

### 3.3 Cross-context søk
Når en bruker utforsker en node (f.eks. Tema "Skolepolitikk"):
1. SvelteKit server-side henter brukerens tilgjengelige samlings-noder fra `node_access`-matrisen.
2. Kjører et similarity-søk med `<=>` (cosine distance), filtrert mot brukerens tilgjengelige noder:
   ```sql
   SELECT na.node_id, e.name, e.embedding <=> $target_embedding AS distance
   FROM entities e
   JOIN nodes n ON e.id = n.id
   JOIN node_access na ON n.id = na.node_id
   WHERE na.user_id = $current_user
     AND n.id != $current_node_id
     AND e.embedding <=> $target_embedding < 0.3
   ORDER BY distance
   LIMIT 10;
   ```
3. Resultatet vises som en diskret "Finnes også i..."-seksjon i UI-et.

### 3.4 Samlings-node config
Bridge aktiveres per samlings-node i nodens metadata (JSONB):
```json
{
  "bridge_enabled": true,
  "bridge_discoverable": true
}
```
- `bridge_enabled` — samlings-noden kan søke i andre samlings-noder
- `bridge_discoverable` — andre samlings-noder kan finne noder under denne

Begge må være `true` for at en kobling skal vises.

## 4. Dataklassifisering

| Data | Kategori | Detaljer |
|---|---|---|
| Embedding-vektorer | Avledet (PG) | Kan regenereres fra nodeinnhold |

## 5. Instruks for Claude Code
* pgvector er en ny avhengighet — dokumenter i docker-compose og setup-guides.
* Cross-context søk bruker `node_access`-matrisen for tilgangsstyring. Isolér denne koden grundig — egen funksjon, aldri gjenbruk i andre kontekster.
* Embedding-dimensjon (768) bør matche modellen som brukes. Konfigurér som konstant, ikke hardkod overalt.
* Jobbtype `generate_embeddings` bruker `sidelinja/rutine` som modellalias.
* Bridge er **Lag 4+** — krever fylt kunnskapsgraf i minst to samlings-noder.
