Sync / foldkit-sync/journal

DocumentHostOptions

interface · packages/sync/src/journal.ts:417

interface DocumentHostOptions<Message, Shared, Principal, RP = never> {
  readonly sync: Sync<Message, Shared>
  readonly journal: () => Promise<
    Journal<Operation, Shared, Principal, Operation>
  >
  readonly resolvePrincipal: (
    request: Request,
  ) => Effect.Effect<Principal, RemoteUnauthenticated, RP>
  readonly revalidate?:
    | {
        readonly every: Duration.Input
        readonly key?: ((principal: Principal) => unknown) | undefined
      }
    | undefined
  readonly settle?:
    | ((
        journal: Journal<Operation, Shared, Principal, Operation>,
      ) => Effect.Effect<void, unknown>)
    | undefined
  readonly opens?:
    ((principal: Principal) => Effect.Effect<boolean>) | undefined
  readonly admit?:
    | ((
        principal: Principal,
        operation: Operation,
      ) => AuthorizeDecision | Effect.Effect<AuthorizeDecision, unknown>)
    | undefined
}

What documentHost needs: one document, who may open it, and what they may do.

Members

DocumentHostOptions.sync

property · packages/sync/src/journal.ts:418

readonly sync: Sync<Message, Shared>

DocumentHostOptions.journal

property · packages/sync/src/journal.ts:423

readonly journal: () => Promise<
  Journal<Operation, Shared, Principal, Operation>
>

The document's journal, asked on each upgrade a principal passed; keep it open between calls. A rejection answers the upgrade with a 500.

DocumentHostOptions.resolvePrincipal

property · packages/sync/src/journal.ts:431

readonly resolvePrincipal: (
  request: Request,
) => Effect.Effect<Principal, RemoteUnauthenticated, RP>

Who is opening the socket, from the upgrade request. Fails with a RemoteUnauthenticated (RemoteServer.unauthenticated()) to refuse it: a 401 carrying its message. A defect is a 500 that says nothing of it. A browser's WebSocket sends no header of the page's: Origin and the cookie are what it has.

DocumentHostOptions.revalidate

property · packages/sync/src/journal.ts:442

readonly revalidate?:
  | {
      readonly every: Duration.Input
      readonly key?: ((principal: Principal) => unknown) | undefined
    }
  | undefined

Asks resolvePrincipal again, of the upgrade request, every every while the socket is open: a refusal closes it with 4401, and a principal whose key differs from the one it opened with (Policy.keyOf) closes it with 1012, which the replica reconnects after, as the new principal; without key only a refusal closes it. Without it a socket serves the principal it opened with until it closes, a revoked session included.

DocumentHostOptions.settle

property · packages/sync/src/journal.ts:449

readonly settle?:
  | ((
      journal: Journal<Operation, Shared, Principal, Operation>,
    ) => Effect.Effect<void, unknown>)
  | undefined

After each exchange's appends, given the journal. See journalExchange's settle.

DocumentHostOptions.opens

property · packages/sync/src/journal.ts:453

readonly opens?:
  ((principal: Principal) => Effect.Effect<boolean>) | undefined

Whether principal may open the document. See journalExchange's opens.

DocumentHostOptions.admit

property · packages/sync/src/journal.ts:455

readonly admit?:
  | ((
      principal: Principal,
      operation: Operation,
    ) => AuthorizeDecision | Effect.Effect<AuthorizeDecision, unknown>)
  | undefined

Whether an operation from principal may be appended. See journalExchange's admit.