Valider fase 22: STDB-migrering fullført, ingen rester i aktiv kode

Validering av fase 22 (SpacetimeDB-migrering) bekrefter:

1. WebSocket-sanntid fungerer:
   - maskinrommet lytter på PG NOTIFY-kanaler (node_changed, edge_changed,
     access_changed, mixer_channel_changed)
   - Enrichment av events med fulle rader fra PG
   - Broadcast via tokio::broadcast til WebSocket-klienter
   - Tilgangskontroll filtrerer events per bruker
   - Frontend kobler til /ws med JWT, mottar initial_sync + inkrementelle events

2. PG LISTEN/NOTIFY-triggere verifisert i database:
   - 4 notify-funksjoner: notify_node_change, notify_edge_change,
     notify_access_change, notify_mixer_channel_change
   - 4 triggere: nodes_notify, edges_notify, node_access_notify,
     mixer_channels_notify

3. Ingen STDB-rester i aktiv kode/konfig:
   - maskinrommet/src/: rent
   - Cargo.toml: ingen spacetimedb-avhengigheter
   - docker-compose.yml: ingen spacetimedb-tjeneste
   - Caddyfile: ingen spacetimedb-proxy
   - Eneste funn: frontend/src/lib/spacetime/ katalognavn —
     omdøpt til frontend/src/lib/realtime/ (32 filer oppdatert)
   - Historiske referanser i docs/arkiv og scripts/synops.md er OK
This commit is contained in:
vegard 2026-03-18 16:31:16 +00:00
parent 0dc014f4ab
commit e8a1a80652
34 changed files with 54 additions and 55 deletions

View file

@ -16,8 +16,8 @@
* Drop-sonen bruker presetets farge for visuell feedback. * Drop-sonen bruker presetets farge for visuell feedback.
* Inkompatible noder (lyd, bilde) får rød sone med forklaring. * Inkompatible noder (lyd, bilde) får rød sone med forklaring.
*/ */
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { nodeStore } from '$lib/spacetime'; import { nodeStore } from '$lib/realtime';
import { aiProcess, createAiPreset, updateNode, deleteNode, createEdge } from '$lib/api'; import { aiProcess, createAiPreset, updateNode, deleteNode, createEdge } from '$lib/api';
import { getDragPayload, checkAiToolCompat, setDragPayload } from '$lib/transfer'; import { getDragPayload, checkAiToolCompat, setDragPayload } from '$lib/transfer';

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { connectionState, nodeStore, edgeStore, nodeAccessStore, nodeVisibility } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore, nodeAccessStore, nodeVisibility } from '$lib/realtime';
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { getRankedNodeIds, recordVisit } from '$lib/workspace/recency.js'; import { getRankedNodeIds, recordVisit } from '$lib/workspace/recency.js';
import { TRAIT_PANEL_INFO, getPanelInfo } from '$lib/workspace/types.js'; import { TRAIT_PANEL_INFO, getPanelInfo } from '$lib/workspace/types.js';

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { nodeStore, edgeStore } from '$lib/spacetime'; import { nodeStore, edgeStore } from '$lib/realtime';
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
interface Props { interface Props {
currentUserId: string; currentUserId: string;

View file

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { createEdge } from '$lib/api'; import { createEdge } from '$lib/api';
import PresentationEditor from './PresentationEditor.svelte'; import PresentationEditor from './PresentationEditor.svelte';

View file

@ -15,8 +15,8 @@
* Oppgave 15.1 * Oppgave 15.1
*/ */
import { nodeStore, connectionState } from '$lib/spacetime'; import { nodeStore, connectionState } from '$lib/realtime';
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
const connected = $derived(connectionState.current === 'connected'); const connected = $derived(connectionState.current === 'connected');

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { Node, Edge } from '$lib/spacetime'; import type { Node, Edge } from '$lib/realtime';
import { edgeStore, nodeStore, nodeVisibility, connectionState } from '$lib/spacetime'; import { edgeStore, nodeStore, nodeVisibility, connectionState } from '$lib/realtime';
import { createNode, createEdge, updateEdge } from '$lib/api'; import { createNode, createEdge, updateEdge } from '$lib/api';
import { setDragPayload, checkCalendarCompat, type DragPayload } from '$lib/transfer'; import { setDragPayload, checkCalendarCompat, type DragPayload } from '$lib/transfer';
import type { BlockReceiver, PlacementIntent } from '$lib/components/blockshell/types'; import type { BlockReceiver, PlacementIntent } from '$lib/components/blockshell/types';

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { edgeStore, nodeStore, nodeVisibility } from '$lib/spacetime'; import { edgeStore, nodeStore, nodeVisibility } from '$lib/realtime';
import { createNode, casUrl } from '$lib/api'; import { createNode, casUrl } from '$lib/api';
import { setDragPayload, checkChatCompat, type DragPayload } from '$lib/transfer'; import { setDragPayload, checkChatCompat, type DragPayload } from '$lib/transfer';
import type { BlockReceiver, PlacementIntent } from '$lib/components/blockshell/types'; import type { BlockReceiver, PlacementIntent } from '$lib/components/blockshell/types';

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { Node, Edge } from '$lib/spacetime'; import type { Node, Edge } from '$lib/realtime';
import { edgeStore, nodeStore, nodeVisibility } from '$lib/spacetime'; import { edgeStore, nodeStore, nodeVisibility } from '$lib/realtime';
import { createNode, createEdge, updateNode, deleteEdge, aiProcess } from '$lib/api'; import { createNode, createEdge, updateNode, deleteEdge, aiProcess } from '$lib/api';
import PublishDialog from '$lib/components/PublishDialog.svelte'; import PublishDialog from '$lib/components/PublishDialog.svelte';
import { getDragPayload, setDragPayload, checkToolToNodeCompat, checkEditorCompat, type DragPayload } from '$lib/transfer'; import { getDragPayload, setDragPayload, checkToolToNodeCompat, checkEditorCompat, type DragPayload } from '$lib/transfer';

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { Node, Edge } from '$lib/spacetime'; import type { Node, Edge } from '$lib/realtime';
import { edgeStore, nodeStore, nodeVisibility } from '$lib/spacetime'; import { edgeStore, nodeStore, nodeVisibility } from '$lib/realtime';
import { createNode, createEdge, updateEdge } from '$lib/api'; import { createNode, createEdge, updateEdge } from '$lib/api';
import { setDragPayload, checkKanbanCompat, type DragPayload } from '$lib/transfer'; import { setDragPayload, checkKanbanCompat, type DragPayload } from '$lib/transfer';
import type { BlockReceiver, PlacementIntent } from '$lib/components/blockshell/types'; import type { BlockReceiver, PlacementIntent } from '$lib/components/blockshell/types';

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { Node, MixerChannel } from '$lib/spacetime'; import type { Node, MixerChannel } from '$lib/realtime';
import { edgeStore, nodeStore, mixerChannelStore } from '$lib/spacetime'; import { edgeStore, nodeStore, mixerChannelStore } from '$lib/realtime';
import { import {
createMixerChannel as apiCreateMixerChannel, createMixerChannel as apiCreateMixerChannel,
setMixerGain, setMixerGain,

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { edgeStore, nodeStore, nodeVisibility } from '$lib/spacetime'; import { edgeStore, nodeStore, nodeVisibility } from '$lib/realtime';
import { casUrl } from '$lib/api'; import { casUrl } from '$lib/api';
import AudioPlayer from '$lib/components/AudioPlayer.svelte'; import AudioPlayer from '$lib/components/AudioPlayer.svelte';
import TraitPanel from './TraitPanel.svelte'; import TraitPanel from './TraitPanel.svelte';

View file

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import TraitPanel from './TraitPanel.svelte'; import TraitPanel from './TraitPanel.svelte';
interface Props { interface Props {

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { edgeStore, nodeStore } from '$lib/spacetime'; import { edgeStore, nodeStore } from '$lib/realtime';
import TraitPanel from './TraitPanel.svelte'; import TraitPanel from './TraitPanel.svelte';
import { import {
joinCommunication, joinCommunication,

View file

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import TraitPanel from './TraitPanel.svelte'; import TraitPanel from './TraitPanel.svelte';
interface Props { interface Props {

View file

@ -8,7 +8,7 @@
* metadata.mixer.pads array and persisted via the API. * metadata.mixer.pads array and persisted via the API.
*/ */
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { casUrl, updateNode, uploadMedia } from '$lib/api'; import { casUrl, updateNode, uploadMedia } from '$lib/api';
import { import {
loadPadAudio, loadPadAudio,

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { edgeStore, nodeStore, nodeVisibility } from '$lib/spacetime'; import { edgeStore, nodeStore, nodeVisibility } from '$lib/realtime';
import { setDragPayload, checkStudioCompat, type DragPayload } from '$lib/transfer'; import { setDragPayload, checkStudioCompat, type DragPayload } from '$lib/transfer';
import type { BlockReceiver, PlacementIntent } from '$lib/components/blockshell/types'; import type { BlockReceiver, PlacementIntent } from '$lib/components/blockshell/types';

View file

@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import TraitPanel from './TraitPanel.svelte'; import TraitPanel from './TraitPanel.svelte';
interface Props { interface Props {

View file

@ -5,7 +5,7 @@
* mottar initial_sync og inkrementelle events, og oppdaterer reactive stores. * mottar initial_sync og inkrementelle events, og oppdaterer reactive stores.
* *
* Usage: * Usage:
* import { wsConnect, wsDisconnect, connectionState } from '$lib/spacetime/connection.svelte'; * import { wsConnect, wsDisconnect, connectionState } from '$lib/realtime/connection.svelte';
*/ */
import { page } from '$app/stores'; import { page } from '$app/stores';

View file

@ -2,7 +2,7 @@
* Re-exports for convenient imports. * Re-exports for convenient imports.
* *
* Usage: * Usage:
* import { wsConnect, connectionState, nodeStore, edgeStore } from '$lib/spacetime'; * import { wsConnect, connectionState, nodeStore, edgeStore } from '$lib/realtime';
*/ */
export { wsConnect, wsDisconnect, connectionState } from './connection.svelte'; export { wsConnect, wsDisconnect, connectionState } from './connection.svelte';

View file

@ -5,7 +5,7 @@
* Fylles fra portvokterens WebSocket (initial_sync + inkrementelle events). * Fylles fra portvokterens WebSocket (initial_sync + inkrementelle events).
* *
* Usage: * Usage:
* import { nodeStore, edgeStore } from '$lib/spacetime/stores.svelte'; * import { nodeStore, edgeStore } from '$lib/realtime/stores.svelte';
* *
* // I en .svelte-komponent: * // I en .svelte-komponent:
* const nodes = $derived(nodeStore.all); * const nodes = $derived(nodeStore.all);

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import '../app.css'; import '../app.css';
import { page } from '$app/stores'; import { page } from '$app/stores';
import { wsConnect, wsDisconnect } from '$lib/spacetime'; import { wsConnect, wsDisconnect } from '$lib/realtime';
import { browser } from '$app/environment'; import { browser } from '$app/environment';
import SystemAnnouncements from '$lib/components/SystemAnnouncements.svelte'; import SystemAnnouncements from '$lib/components/SystemAnnouncements.svelte';

View file

@ -1,8 +1,8 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { signOut } from '@auth/sveltekit/client'; import { signOut } from '@auth/sveltekit/client';
import { connectionState, nodeStore, edgeStore, nodeAccessStore, nodeVisibility } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore, nodeAccessStore, nodeVisibility } from '$lib/realtime';
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import NodeEditor from '$lib/components/NodeEditor.svelte'; import NodeEditor from '$lib/components/NodeEditor.svelte';
import NewChatDialog from '$lib/components/NewChatDialog.svelte'; import NewChatDialog from '$lib/components/NewChatDialog.svelte';
import AudioPlayer from '$lib/components/AudioPlayer.svelte'; import AudioPlayer from '$lib/components/AudioPlayer.svelte';

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/realtime';
import type { Node, Edge } from '$lib/spacetime'; import type { Node, Edge } from '$lib/realtime';
import { createNode, createEdge, updateEdge } from '$lib/api'; import { createNode, createEdge, updateEdge } from '$lib/api';
const session = $derived($page.data.session as Record<string, unknown> | undefined); const session = $derived($page.data.session as Record<string, unknown> | undefined);

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/realtime';
import type { Node, Edge } from '$lib/spacetime'; import type { Node, Edge } from '$lib/realtime';
import { createNode, createEdge, updateEdge } from '$lib/api'; import { createNode, createEdge, updateEdge } from '$lib/api';
const session = $derived($page.data.session as Record<string, unknown> | undefined); const session = $derived($page.data.session as Record<string, unknown> | undefined);

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/realtime';
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { createNode, casUrl } from '$lib/api'; import { createNode, casUrl } from '$lib/api';
import ChatInput from '$lib/components/ChatInput.svelte'; import ChatInput from '$lib/components/ChatInput.svelte';
import AudioPlayer from '$lib/components/AudioPlayer.svelte'; import AudioPlayer from '$lib/components/AudioPlayer.svelte';

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/realtime';
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { updateEdge } from '$lib/api'; import { updateEdge } from '$lib/api';
// Canvas + BlockShell // Canvas + BlockShell

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/realtime';
import type { Node, Edge } from '$lib/spacetime'; import type { Node, Edge } from '$lib/realtime';
import { setSlot } from '$lib/api'; import { setSlot } from '$lib/api';
const session = $derived($page.data.session as Record<string, unknown> | undefined); const session = $derived($page.data.session as Record<string, unknown> | undefined);

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { connectionState } from '$lib/spacetime'; import { connectionState } from '$lib/realtime';
import { createNode, createEdge } from '$lib/api'; import { createNode, createEdge } from '$lib/api';
import { traitCatalog, packages, type Package } from '$lib/traits'; import { traitCatalog, packages, type Package } from '$lib/traits';

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore, nodeVisibility } from '$lib/realtime';
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { createNode, createEdge } from '$lib/api'; import { createNode, createEdge } from '$lib/api';
const session = $derived($page.data.session as Record<string, unknown> | undefined); const session = $derived($page.data.session as Record<string, unknown> | undefined);

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { connectionState, nodeStore, edgeStore } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore } from '$lib/realtime';
import type { Edge } from '$lib/spacetime'; import type { Edge } from '$lib/realtime';
import { updateEdge, createCommunication } from '$lib/api'; import { updateEdge, createCommunication } from '$lib/api';
const session = $derived($page.data.session as Record<string, unknown> | undefined); const session = $derived($page.data.session as Record<string, unknown> | undefined);

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { connectionState, nodeStore, edgeStore } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore } from '$lib/realtime';
import { import {
casUrl, casUrl,
audioAnalyze, audioAnalyze,

View file

@ -1,8 +1,8 @@
<script lang="ts"> <script lang="ts">
import { page } from '$app/stores'; import { page } from '$app/stores';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { connectionState, nodeStore, edgeStore, nodeAccessStore, nodeVisibility } from '$lib/spacetime'; import { connectionState, nodeStore, edgeStore, nodeAccessStore, nodeVisibility } from '$lib/realtime';
import type { Node } from '$lib/spacetime'; import type { Node } from '$lib/realtime';
import { fetchMyWorkspace, updateNode } from '$lib/api'; import { fetchMyWorkspace, updateNode } from '$lib/api';
// Canvas + BlockShell // Canvas + BlockShell

View file

@ -308,8 +308,7 @@ med spesifikasjon for det som trenger en dedikert sesjon.
- [x] 23.8 Valider fase 1718 (lydstudio-utbedring + AI-verktøy): responsivt layout, FFmpeg-validering, fade/silence, AI-presets, direction-logikk, drag-and-drop integrasjon. - [x] 23.8 Valider fase 1718 (lydstudio-utbedring + AI-verktøy): responsivt layout, FFmpeg-validering, fade/silence, AI-presets, direction-logikk, drag-and-drop integrasjon.
- [x] 23.9 Valider fase 1920 (arbeidsflaten + universell overføring): canvas pan/zoom, BlockShell, layout-persistering, snarveier, transfer service, alle panelreworks (chat, kanban, kalender, editor, studio). - [x] 23.9 Valider fase 1920 (arbeidsflaten + universell overføring): canvas pan/zoom, BlockShell, layout-persistering, snarveier, transfer service, alle panelreworks (chat, kanban, kalender, editor, studio).
- [x] 23.10 Valider fase 21 (CLI-verktøy): kjør hvert synops-*-verktøy, verifiser --help, --payload-json, output-format, feilhåndtering, synops-common integrasjon. - [x] 23.10 Valider fase 21 (CLI-verktøy): kjør hvert synops-*-verktøy, verifiser --help, --payload-json, output-format, feilhåndtering, synops-common integrasjon.
- [~] 23.11 Valider fase 22 (STDB-migrering): WebSocket-sanntid fungerer, PG LISTEN/NOTIFY-triggere, ingen STDB-rester i aktiv kode/konfig. - [x] 23.11 Valider fase 22 (STDB-migrering): WebSocket-sanntid fungerer, PG LISTEN/NOTIFY-triggere, ingen STDB-rester i aktiv kode/konfig.
> Påbegynt: 2026-03-18T16:25
## Fase 24: Orkestrering — trigger-drevne automatiseringer ## Fase 24: Orkestrering — trigger-drevne automatiseringer