diff --git a/docs/erfaringer/access_propagering.md b/docs/erfaringer/access_propagering.md new file mode 100644 index 0000000..f4e5be8 --- /dev/null +++ b/docs/erfaringer/access_propagering.md @@ -0,0 +1,53 @@ +# Erfaring: Access-propagering for chat-meldinger (mars 2026) + +## Problemet + +Bot-svar i chatter var usynlige for brukere. Meldingene ble +skrevet til PG, men brukerne hadde ingen `node_access`-rad +for dem. Frontend filtrerte dem bort som "hidden". + +## Rotårsak + +`synops-respond` (og `chat-reply.sh`) opprettet svar-noder med +`visibility: 'hidden'` og `belongs_to`-edge til chatten, men +propagerte ikke `node_access` til chat-deltakerne. + +Maskinrommets intention-system (create_node med context_id) +propagerer access automatisk. Men verktøy som skriver direkte +til PG må gjøre det selv. + +## Fiks + +Etter INSERT av belongs_to-edge, propager access til alle +deltakere i chatten: + +```sql +INSERT INTO node_access (subject_id, object_id, access, via_edge) +SELECT e.source_id, $reply_id, 'reader', $edge_id +FROM edges e +WHERE e.target_id = $communication_id +AND e.edge_type IN ('owner', 'member_of') +ON CONFLICT DO NOTHING +``` + +## Lærdommer + +1. **Alle som skriver til PG direkte må propagere access.** + Maskinrommets intention-system gjør det automatisk, men + CLI-verktøy, scripts og direkte INSERT gjør det ikke. + Det er lett å glemme — og resultatet er usynlige noder. + +2. **Test med en annen bruker.** Utvikleren ser egne noder + uansett (created_by). Buggen er bare synlig for *andre* + deltakere i chatten. + +3. **WebSocket-filtrering forsterker problemet.** Selv om + noden er i PG, filtrerer portvokteren den bort for + brukere uten access. Dobbel usynlighet. + +## Påvirket kode + +- `tools/synops-respond/src/main.rs` — fikset +- `scripts/chat-reply.sh` — hadde allerede propagering +- Alle andre verktøy som skriver noder med belongs_to-edge + bør sjekkes diff --git a/tools/synops-respond/src/main.rs b/tools/synops-respond/src/main.rs index af8ff38..fc2a179 100644 --- a/tools/synops-respond/src/main.rs +++ b/tools/synops-respond/src/main.rs @@ -539,6 +539,24 @@ async fn write_to_db( .await .map_err(|e| format!("PG insert belongs_to-edge feilet: {e}"))?; + // Propager access: alle deltakere i chatten får lesetilgang til svaret + sqlx::query( + "INSERT INTO node_access (subject_id, object_id, access, via_edge) + SELECT e.source_id, $1, 'reader', $2 + FROM edges e + WHERE e.target_id = $3 + AND e.edge_type IN ('owner', 'member_of') + ON CONFLICT DO NOTHING" + ) + .bind(reply_id) + .bind(edge_id) + .bind(communication_id) + .execute(db) + .await + .map_err(|e| format!("PG access-propagering feilet: {e}"))?; + + tracing::info!(reply_node_id = %reply_id, "Access propagert til chat-deltakere"); + // ai_usage_log sqlx::query( "INSERT INTO ai_usage_log \