···1import {useSignal} from '@preact/signals'
2import {useCallback} from 'preact/hooks'
34-import {useRealmIdentity} from '#client/realm/context-identity'
5import {useDatabase} from '#client/root/context-database'
6import {useSkypod} from '#client/skypod/context'
078export const Messenger: preact.FunctionComponent = () => {
9 const {useDbSignal} = useDatabase()
···1import {useSignal} from '@preact/signals'
2import {useCallback} from 'preact/hooks'
304import {useDatabase} from '#client/root/context-database'
5import {useSkypod} from '#client/skypod/context'
6+import {useRealmIdentity} from '#realm/client/context-identity'
78export const Messenger: preact.FunctionComponent = () => {
9 const {useDbSignal} = useDatabase()
+3-3
src/client/components/peer-list.tsx
···1import {useSignal, useSignalEffect} from '@preact/signals'
23-import {useRealmConnection} from '#client/realm/context-connection'
4-import {PeerState} from '#client/realm/types'
5-import {IdentID} from '#common/protocol'
67export const PeerList: preact.FunctionComponent = () => {
8 const connection = useRealmConnection()
···1import {useSignal, useSignalEffect} from '@preact/signals'
23+import {useRealmConnection} from '#realm/client/context-connection'
4+import {PeerState} from '#realm/client/types'
5+import {IdentID} from '#realm/protocol/index'
67export const PeerList: preact.FunctionComponent = () => {
8 const connection = useRealmConnection()
+5-5
src/client/page-app.tsx
···1-import {RealmConnectionManager} from '#client/realm/cmpnt-connection-manager'
002import {
3 RealmConnectionFallbackProps,
4 RealmConnectionProvider,
5-} from '#client/realm/context-connection'
6-import {RealmIdentityFallbackProps, RealmIdentityProvider} from '#client/realm/context-identity'
7-import {DatabaseProvider} from '#client/root/context-database'
8-import {SkypodProvider} from '#client/skypod/context'
910import {DebugNuke} from './components/debug-nuke'
11import {Messenger} from './components/messenger'
···1+import {DatabaseProvider} from '#client/root/context-database'
2+import {SkypodProvider} from '#client/skypod/context'
3+import {RealmConnectionManager} from '#realm/client/cmpnt-connection-manager'
4import {
5 RealmConnectionFallbackProps,
6 RealmConnectionProvider,
7+} from '#realm/client/context-connection'
8+import {RealmIdentityFallbackProps, RealmIdentityProvider} from '#realm/client/context-identity'
00910import {DebugNuke} from './components/debug-nuke'
11import {Messenger} from './components/messenger'
···45import {generateSignableJwt} from '#common/crypto/jwks'
6import {jwtSchema} from '#common/crypto/jwts'
7-import {RealmBrand} from '#common/protocol'
89import {useRealmConnection} from './context-connection'
10import {useRealmIdentity} from './context-identity'
···45import {generateSignableJwt} from '#common/crypto/jwks'
6import {jwtSchema} from '#common/crypto/jwts'
7+import {RealmBrand} from '#realm/protocol/index'
89import {useRealmConnection} from './context-connection'
10import {useRealmIdentity} from './context-identity'
···5import {useDatabase} from '#client/root/context-database'
6import {generateSigningJwkPair} from '#common/crypto/jwks'
7import {normalizeProtocolError, ProtocolError} from '#common/errors'
8-import {IdentBrand, IdentID} from '#common/protocol'
9-import {ClockState, ClockStorage, LogicalClock} from '#common/protocol/logical-clock'
1011import {RealmIdentity} from './service-identity'
12
···5import {useDatabase} from '#client/root/context-database'
6import {generateSigningJwkPair} from '#common/crypto/jwks'
7import {normalizeProtocolError, ProtocolError} from '#common/errors'
8+import {IdentBrand, IdentID} from '#realm/protocol/index'
9+import {ClockState, ClockStorage, LogicalClock} from '#realm/protocol/logical-clock'
1011import {RealmIdentity} from './service-identity'
12
···34import {BlockingQueue} from '#common/async/blocking-queue'
5import {sleep} from '#common/async/sleep'
6-import * as protocol from '#common/protocol'
7-import {IdentID} from '#common/protocol'
8-import {DeviceCaps, DeviceInfo} from '#common/protocol/device'
910import {RealmSyncManager} from './service-connection-sync'
11
···34import {BlockingQueue} from '#common/async/blocking-queue'
5import {sleep} from '#common/async/sleep'
6+import {DeviceCaps, DeviceInfo} from '#realm/protocol/device'
7+import * as protocol from '#realm/protocol/index'
8+import {IdentID} from '#realm/protocol/index'
910import {RealmSyncManager} from './service-connection-sync'
11
···1import {Database, StoredAction} from '#client/root/service-database'
2-import {IdentID} from '#common/protocol'
3-import {LCTimestamp, LogicalClock} from '#common/protocol/logical-clock'
4import {DeviceScanner} from './service-device'
56export class RealmSyncManager {
···1import {Database, StoredAction} from '#client/root/service-database'
2+import {IdentID} from '#realm/protocol/index'
3+import {LCTimestamp, LogicalClock} from '#realm/protocol/logical-clock'
4import {DeviceScanner} from './service-device'
56export class RealmSyncManager {
···7import {generateSignableJwt, jwkImport} from '#common/crypto/jwks'
8import {jwtPayload, verifyJwtToken} from '#common/crypto/jwts'
9import {normalizeError, normalizeProtocolError, ProtocolError} from '#common/errors'
10-import * as protocol from '#common/protocol'
11-import {IdentID, RealmID} from '#common/protocol'
12-import {LogicalClock} from '#common/protocol/logical-clock'
13import {streamSocketJson, takeSocketJson} from '#common/socket'
00001415import {Database} from '#client/root/service-database'
16
···7import {generateSignableJwt, jwkImport} from '#common/crypto/jwks'
8import {jwtPayload, verifyJwtToken} from '#common/crypto/jwts'
9import {normalizeError, normalizeProtocolError, ProtocolError} from '#common/errors'
00010import {streamSocketJson, takeSocketJson} from '#common/socket'
11+12+import {IdentID, RealmID} from '#realm/protocol/brands'
13+import * as protocol from '#realm/protocol/index'
14+import {LogicalClock} from '#realm/protocol/logical-clock'
1516import {Database} from '#client/root/service-database'
17
···1-import {IdentID, RealmID} from '#common/protocol'
23/** identity info for connecting to a realm */
4export interface ConnectionIdentity {
···1+import {IdentID, RealmID} from '#realm/protocol/index'
23/** identity info for connecting to a realm */
4export interface ConnectionIdentity {
+2-2
src/client/root/service-database.ts
···1import Dexie, {Collection, IndexableType, type Table} from 'dexie'
23import {JWK} from '#common/crypto/jwks'
4-import {IdentID, RealmID} from '#common/protocol'
5-import {LCTimestamp, LogicalClock} from '#common/protocol/logical-clock'
6import {Feed, FeedEntry, Lock} from '#skypod/schema'
78export interface LocalIdentity {
···1import Dexie, {Collection, IndexableType, type Table} from 'dexie'
23import {JWK} from '#common/crypto/jwks'
4+import {IdentID, RealmID} from '#realm/protocol/index'
5+import {LCTimestamp, LogicalClock} from '#realm/protocol/logical-clock'
6import {Feed, FeedEntry, Lock} from '#skypod/schema'
78export interface LocalIdentity {
+4-4
src/client/skypod/context.tsx
···2import {useContext, useEffect, useRef} from 'preact/hooks'
3import {z} from 'zod/v4'
45-import {IdentID} from '#common/protocol'
6import {Action, ActionMap, ActionOpts, actionSchema} from '#skypod/actions'
7import {feedSchema} from '#skypod/schema'
89-import {useRealmConnection} from '#client/realm/context-connection'
10-import {useRealmIdentity} from '#client/realm/context-identity'
11import {useDatabase} from '#client/root/context-database'
001213-import {LogicalClock} from '#common/protocol/logical-clock'
14import FeedFetchWorker from './feed-fetch.worker?worker'
1516export type MiddlewareFn = (
···2import {useContext, useEffect, useRef} from 'preact/hooks'
3import {z} from 'zod/v4'
45+import {IdentID} from '#realm/protocol/index'
6import {Action, ActionMap, ActionOpts, actionSchema} from '#skypod/actions'
7import {feedSchema} from '#skypod/schema'
8009import {useDatabase} from '#client/root/context-database'
10+import {useRealmConnection} from '#realm/client/context-connection'
11+import {useRealmIdentity} from '#realm/client/context-identity'
1213+import {LogicalClock} from '#realm/protocol/logical-clock'
14import FeedFetchWorker from './feed-fetch.worker?worker'
1516export type MiddlewareFn = (
+2-2
src/client/skypod/feed-fetch.worker.ts
···34import {Database} from '#client/root/service-database'
5import {normalizeProtocolError} from '#common/errors'
6-import {IdentBrand, IdentID} from '#common/protocol'
7-import {LCTimestamp, LogicalClock} from '#common/protocol/logical-clock'
89const msgStartSchema = z.object({
10 msg: z.literal('start'),
···34import {Database} from '#client/root/service-database'
5import {normalizeProtocolError} from '#common/errors'
6+import {IdentBrand, IdentID} from '#realm/protocol/index'
7+import {LCTimestamp, LogicalClock} from '#realm/protocol/logical-clock'
89const msgStartSchema = z.object({
10 msg: z.literal('start'),
+1-1
src/cmd/register-ident.ts
···1#!/usr/bin/env node
23import {generateSignableJwt, generateSigningJwkPair, jwkExport} from '#common/crypto/jwks'
4-import {IdentBrand, RealmBrand} from '#common/protocol'
56async function generateRegistrationJWT(realm?: string) {
7 const keypair = await generateSigningJwkPair()
···1#!/usr/bin/env node
23import {generateSignableJwt, generateSigningJwkPair, jwkExport} from '#common/crypto/jwks'
4+import {IdentBrand, RealmBrand} from '#realm/protocol/index'
56async function generateRegistrationJWT(realm?: string) {
7 const keypair = await generateSigningJwkPair()
+1-1
src/cmd/server.ts
···2import {fileURLToPath} from 'url'
3import {parseArgs} from 'util'
405import {buildServer} from '#server/index'
6-import {ensureRealmMap} from '#server/routes-socket/state'
78const __filename = fileURLToPath(import.meta.url)
9const __dirname = dirname(__filename)
···2import {fileURLToPath} from 'url'
3import {parseArgs} from 'util'
45+import {ensureRealmMap} from '#realm/server/state'
6import {buildServer} from '#server/index'
078const __filename = fileURLToPath(import.meta.url)
9const __dirname = dirname(__filename)
···1+import {z} from 'zod/v4'
2+3+import {ProtocolError} from '#common/errors'
4+5+import {errorMessageSchema} from './schema'
6+7+export * from './brands'
8+export * from './messages'
9+10+export function makeError(
11+ error: ProtocolError,
12+ detail: string,
13+ seq?: number,
14+): z.infer<typeof errorMessageSchema> {
15+ return {
16+ typ: 'err',
17+ msg: error.message,
18+ seq,
19+ dat: {
20+ code: error.status,
21+ detail,
22+ },
23+ }
24+}
+1-1
src/server/index.ts
···34import {WebSocketServer} from 'ws'
506import {apiRouter} from './routes-api/middleware'
7import {notFoundHandler} from './routes-error'
8-import {socketHandler} from './routes-socket/handler'
9import {makeSpaMiddleware, makeStaticMiddleware} from './routes-static'
1011/**
···34import {WebSocketServer} from 'ws'
56+import {socketHandler} from '#realm/server/handler'
7import {apiRouter} from './routes-api/middleware'
8import {notFoundHandler} from './routes-error'
09import {makeSpaMiddleware, makeStaticMiddleware} from './routes-static'
1011/**
···4import {z} from 'zod/v4'
56import {jwkExport, jwkImport, type JWK} from '#common/crypto/jwks'
7-import {IdentBrand, IdentID, RealmBrand, RealmID} from '#common/protocol'
8-import {LCTimestamp, LogicalClock} from '#common/protocol/logical-clock'
9-import {actionMessageSchema} from '#common/protocol/schema'
10import {StrictMap} from '#common/strict-map'
0001112export type IncomingAction = z.infer<typeof actionMessageSchema>
13export type StoredAction = z.infer<typeof storedActionSchema>
···4import {z} from 'zod/v4'
56import {jwkExport, jwkImport, type JWK} from '#common/crypto/jwks'
0007import {StrictMap} from '#common/strict-map'
8+import {IdentBrand, IdentID, RealmBrand, RealmID} from '#realm/protocol/index'
9+import {LCTimestamp, LogicalClock} from '#realm/protocol/logical-clock'
10+import {actionMessageSchema} from '#realm/protocol/schema'
1112export type IncomingAction = z.infer<typeof actionMessageSchema>
13export type StoredAction = z.infer<typeof storedActionSchema>
···34import {jwkExport} from '#common/crypto/jwks'
5import {normalizeProtocolError, ProtocolError} from '#common/errors'
6-import * as protocol from '#common/protocol'
7-import {actionMessageSchema} from '#common/protocol/schema'
8import {streamSocket} from '#common/socket'
910-import * as realm from '#server/routes-socket/state'
0001112// what can the server handle?
13const incomingMessageSchema = z.union([
···30 realmBroadcast(auth, await buildRtcPeerJoined(auth))
3132 try {
33- const incomingParser = protocol.parseJson.pipe(incomingMessageSchema)
34 for await (const msg of streamSocket(ws, {signal})) {
35 try {
36 const data = await incomingParser.parseAsync(msg)
···34import {jwkExport} from '#common/crypto/jwks'
5import {normalizeProtocolError, ProtocolError} from '#common/errors'
6+import {parseJson} from '#common/protocol'
07import {streamSocket} from '#common/socket'
89+import * as protocol from '#realm/protocol/index'
10+import {actionMessageSchema} from '#realm/protocol/schema'
11+12+import * as realm from '#realm/server/state'
1314// what can the server handle?
15const incomingMessageSchema = z.union([
···32 realmBroadcast(auth, await buildRtcPeerJoined(auth))
3334 try {
35+ const incomingParser = parseJson.pipe(incomingMessageSchema)
36 for await (const msg of streamSocket(ws, {signal})) {
37 try {
38 const data = await incomingParser.parseAsync(msg)
···1import WebSocket from 'isomorphic-ws'
23-import {IdentID, RealmID} from '#common/protocol'
4-import {DeviceCaps, DeviceInfo} from '#common/protocol/device'
5import {StrictMap} from '#common/strict-map'
0067-import {RealmStorage} from '#server/realm-storage'
89/** An authenticated identity; only handed out in response to successful authentication. */
10export interface AuthenticatedIdentity {
···1import WebSocket from 'isomorphic-ws'
2003import {StrictMap} from '#common/strict-map'
4+import {DeviceCaps, DeviceInfo} from '#realm/protocol/device'
5+import {IdentID, RealmID} from '#realm/protocol/index'
67+import {RealmStorage} from '#realm/realm-storage'
89/** An authenticated identity; only handed out in response to successful authentication. */
10export interface AuthenticatedIdentity {
+1-1
src/skypod/actions-feed.ts
···1-import {makeActionSchema} from '#common/protocol/schema'
2import {z} from 'zod/v4'
34import {feedSchema, lockSchema} from './schema'
···1+import {makeActionSchema} from '#realm/protocol/schema'
2import {z} from 'zod/v4'
34import {feedSchema, lockSchema} from './schema'
+1-1
src/skypod/actions-feedentry.ts
···1-import {makeActionSchema} from '#common/protocol/schema'
2import {z} from 'zod/v4'
34export const patchActionSchema = makeActionSchema(
···1+import {makeActionSchema} from '#realm/protocol/schema'
2import {z} from 'zod/v4'
34export const patchActionSchema = makeActionSchema(
+2-2
src/skypod/actions.ts
···1-import {LCTimestamp} from '#common/protocol/logical-clock'
2-import {actionOptionsSchema} from '#common/protocol/schema'
3import {z} from 'zod/v4'
45import {feedActionSchemas} from './actions-feed'
···1+import {LCTimestamp} from '#realm/protocol/logical-clock'
2+import {actionOptionsSchema} from '#realm/protocol/schema'
3import {z} from 'zod/v4'
45import {feedActionSchemas} from './actions-feed'
+2-2
src/skypod/schema.ts
···1-import {IdentBrand} from '#common/protocol/brands'
2-import {LogicalClock} from '#common/protocol/logical-clock'
3import {z} from 'zod/v4'
45// lock schema for distributed work coordination
···1+import {IdentBrand} from '#realm/protocol/brands'
2+import {LogicalClock} from '#realm/protocol/logical-clock'
3import {z} from 'zod/v4'
45// lock schema for distributed work coordination