ConusAI vendor v0.1.0-beta.114
ci / gate (push) Waiting to run

This commit is contained in:
ConusAI vendor v0.1.0-beta.114
2026-11-14 09:56:45 +00:00
commit 1ce8d23c35
867 changed files with 122104 additions and 0 deletions
+190
View File
@@ -0,0 +1,190 @@
// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0
// The Convex profile's half of `POST /api/v1/orgs/{org}/live` (live.ts): the CLP/1 stream is served by
// @conusai-kit/live-server in this process, over the deployment's own functions (convex/live.ts):
//
// - the log: `live:head` and `live:changes` (internal queries) read with the admin key, and the wake-up
// is a reactive subscription to `live:head` per organization a stream reads (`convexLiveLog`
// refcounts it), over one websocket client opened by the first stream
// - who may stream what: `live:open`, a public query run under the caller's identity (the same claims
// every procedure call carries, convex-caller.ts), decides with the kernel's tenancy over the
// deployment's rows (`decideLiveGrants`); its refusal comes back as the live problem the Postgres
// profile answers (401 signed out, 404 not reached), and each heartbeat asks `live:recheck`
//
// The admin key stays in this process; the browser holds no Convex credential.
import {
type ConvexLiveHead,
type ConvexLiveRow,
type ConvexLiveSource,
type LiveAuthorization,
type LiveRecheck,
type OpenRequest,
problems,
type ResolvedTopic,
} from "@conusai-kit/live-server"
import { ConvexClient } from "convex/browser"
import { makeFunctionReference, type UserIdentityAttributes } from "convex/server"
import { ConvexError } from "convex/values"
import { asProblem, convexAdminClient } from "./convex-caller"
const OPEN = makeFunctionReference<"query">("live:open")
const RECHECK = makeFunctionReference<"query">("live:recheck")
const HEAD = makeFunctionReference<"query">("live:head")
const CHANGES = makeFunctionReference<"query">("live:changes")
/** What the source and the authorization ask of a one-shot client (`ConvexHttpClient`). */
export interface LiveQueryClient {
query(reference: never, args: never): Promise<unknown>
}
/** What the source asks of a subscribing client (`ConvexClient`, a websocket). */
export interface LiveWatchClient {
onUpdate(
reference: never,
args: never,
callback: (value: unknown) => unknown,
onError?: (error: Error) => unknown,
): () => void
close(): Promise<void>
}
type AdminAuthWatchClient = ConvexClient & {
/** Convex SDK 1.45.0 internal, as `ConvexHttpClient.setAdminAuth` (convex-caller.ts). */
setAdminAuth(token: string, identity?: UserIdentityAttributes): void
}
/**
* The log source over two clients: `admin` reads (it holds the admin key and no identity, so it may call
* the internal `live:head` and `live:changes`), and `watcher` opens the subscribing client on the first
* `watch`; `close` closes it.
*/
export function convexLiveSource(clients: {
readonly admin: LiveQueryClient
readonly watcher: () => LiveWatchClient
}): ConvexLiveSource {
let watcher: LiveWatchClient | undefined
return {
head: async (orgId) => (await clients.admin.query(HEAD as never, { orgId } as never)) as ConvexLiveHead,
changes: async (orgId, after, limit) =>
(await clients.admin.query(
CHANGES as never,
{ orgId, after: { txid: after.txid, seq: after.seq }, limit } as never,
)) as {
rows: readonly ConvexLiveRow[]
head: ConvexLiveHead
more: boolean
},
watch(orgId, onChange, onError) {
watcher ??= clients.watcher()
// Convex answers the current head first, then every new one: each is a wake-up, and a wake-up
// with nothing new is one empty read.
return watcher.onUpdate(HEAD as never, { orgId } as never, () => onChange(), onError)
},
async close() {
const open = watcher
watcher = undefined
await open?.close()
},
}
}
/** The log source over the linked deployment, with its admin key (env.convex). */
export function deploymentLiveSource(convex: { readonly url: string; readonly adminKey: string }): ConvexLiveSource {
return convexLiveSource({
admin: convexAdminClient(convex) as unknown as LiveQueryClient,
watcher: () => {
const client = new ConvexClient(convex.url, { unsavedChangesWarning: false })
;(client as AdminAuthWatchClient).setAdminAuth(convex.adminKey)
return client as unknown as LiveWatchClient
},
})
}
/** The verified caller of one stream, as live.ts resolves it from the request. */
export interface LiveCaller {
readonly userId: string
/** The session (or credential) key of the per-session stream limit. */
readonly session: string
/** The identity its Convex calls carry (convex-caller.ts `convexIdentity`). */
readonly identity: UserIdentityAttributes
}
export interface ConvexLiveAuthorizeOptions {
/** The request's caller: signed in (or the live 401) and its CSRF checked. */
caller(request: Request): Promise<LiveCaller>
/** A one-shot client that calls as `identity` (`convexAdminClient`). */
clientFor(identity: UserIdentityAttributes): LiveQueryClient
/** The org slug of `/api/v1/orgs/{org}/live`. */
orgSlugOf(request: Request): string
/** Where an unexpected re-check failure is reported (it does not end the stream). */
warn(message: string): void
}
/** The status of a refusal: a live problem's own, or the problem a Convex function threw. */
function statusOf(error: unknown): number | undefined {
if (error instanceof ConvexError) {
const status = (error.data as { status?: unknown } | null)?.status
return typeof status === "number" ? status : undefined
}
const status = (error as { status?: unknown } | null)?.status
return typeof status === "number" ? status : undefined
}
/** A refusal of `live:open` as the Postgres profile answers it; another Convex problem as the kernel's. */
function refusalOf(error: unknown): unknown {
if (!(error instanceof ConvexError)) return error
const status = statusOf(error)
if (status === 401) return problems.unauthenticated()
if (status === 404) return problems.notFound()
return asProblem(error)
}
interface OpenAnswer {
readonly org: string
readonly topics: readonly ResolvedTopic[]
readonly entities: readonly string[]
readonly denied: ReadonlyArray<{ readonly entity: string; readonly reason: string }>
}
/** The authorize function of `createLiveServer` on the Convex profile. */
export function convexLiveAuthorize(
options: ConvexLiveAuthorizeOptions,
): (request: Request, open: OpenRequest) => Promise<LiveAuthorization> {
return async (request, open) => {
const caller = await options.caller(request)
const slug = options.orgSlugOf(request)
// The validator of `live:open` takes these fields only.
const topics = open.topics.map((topic) => ({ ws: topic.ws, ...(topic.project ? { project: topic.project } : {}) }))
let answer: OpenAnswer
try {
answer = (await options
.clientFor(caller.identity)
.query(OPEN as never, { org: slug, topics, entities: [...open.entities] } as never)) as OpenAnswer
} catch (error) {
throw refusalOf(error)
}
return {
org: answer.org,
session: caller.session,
granted: { entities: answer.entities, topics: answer.topics },
denied: answer.denied,
// Every heartbeat and on a grant change: the credential is still valid, the caller still a member of
// every scope, and still holds the read permission of every entity the stream was granted.
recheck: async (): Promise<LiveRecheck> => {
try {
const again = await options.caller(new Request(request.url, { method: "GET", headers: request.headers }))
if (again.userId !== caller.userId) return "session"
return (await options
.clientFor(again.identity)
.query(RECHECK as never, { org: slug, topics, granted: [...answer.entities] } as never)) as LiveRecheck
} catch (error) {
const status = statusOf(error)
if (status === 401) return "session"
if (status === 403 || status === 404) return "membership"
options.warn(`live: the re-check failed: ${error instanceof Error ? error.name : "failed"}`)
return null
}
},
}
}
}