@teamscala/service-boot 0.23.284 → 0.23.286
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1006 -1014
- package/src/agreement-gate.d.ts +19 -0
- package/src/asset-cache-key.d.ts +11 -0
- package/src/asset-optimize.d.ts +17 -0
- package/src/asset-proxy.d.ts +11 -0
- package/src/asset-social-card.d.ts +17 -0
- package/src/attach-agreement-magic.d.ts +20 -0
- package/src/attach-portal-members.d.ts +23 -0
- package/src/attach-proposal-accept.d.ts +26 -0
- package/src/attach-proposal-magic.d.ts +18 -0
- package/src/attach-transfers-upload.d.ts +27 -0
- package/src/auth-gate.d.ts +28 -0
- package/src/bind-page-handler.d.ts +18 -0
- package/src/build-client-assets/input-hashing.d.ts +25 -0
- package/src/build-client-assets/source-candidates.d.ts +27 -0
- package/src/build-client-assets.d.ts +50 -0
- package/src/compose-page-title.d.ts +41 -0
- package/src/content-gate/access.d.ts +15 -0
- package/src/content-gate/config-types.d.ts +99 -0
- package/src/content-gate/gate.d.ts +13 -0
- package/src/content-gate/parse-cookie.d.ts +9 -0
- package/src/content-gate/token.d.ts +48 -0
- package/src/content-page-floor.d.ts +39 -0
- package/src/discover-blocks.d.ts +28 -0
- package/src/expand-roster.d.ts +34 -0
- package/src/fn-routers/agreement-completion-email.d.ts +14 -0
- package/src/fn-routers/agreement-send-router.d.ts +82 -0
- package/src/fn-routers/ai-health-router.d.ts +35 -0
- package/src/fn-routers/auth-router.d.ts +47 -0
- package/src/fn-routers/cache-admin-router.d.ts +57 -0
- package/src/fn-routers/chat-session-router.d.ts +219 -0
- package/src/fn-routers/email-defaults.d.ts +1 -0
- package/src/fn-routers/email-link-ttl.d.ts +1 -0
- package/src/fn-routers/index.d.ts +18 -0
- package/src/fn-routers/panel-data-router.d.ts +19 -0
- package/src/fn-routers/persist-chat-messages.d.ts +36 -0
- package/src/fn-routers/plans-router.d.ts +25 -0
- package/src/fn-routers/proposal-send-router.d.ts +58 -0
- package/src/fn-routers/public-agreement-router.d.ts +281 -0
- package/src/fn-routers/public-assessment-router.d.ts +68 -0
- package/src/fn-routers/public-gpt-session-router.d.ts +125 -0
- package/src/fn-routers/sign-in-flow-router.d.ts +75 -0
- package/src/fn-routers/task-sync-dispatch.d.ts +61 -0
- package/src/fn-routers/task-sync-router.d.ts +376 -0
- package/src/fn-routers/task-sync-router.test.ts +32 -0
- package/src/fn-routers/task-sync-router.ts +27 -1
- package/src/fn-routers/tasks-router.d.ts +25 -0
- package/src/fn-routers/user-preferences-router.d.ts +77 -0
- package/src/fn-routers/work-items-router.d.ts +102 -0
- package/src/gate-ttls.d.ts +6 -0
- package/src/gpt-gate.d.ts +25 -0
- package/src/handlers/bun-stable-watch.d.ts +1 -0
- package/src/handlers/projects-digest.d.ts +26 -0
- package/src/handlers/prune-stale-data.d.ts +30 -0
- package/src/handlers/registry-stale-inactive-sweep.d.ts +1 -0
- package/src/handlers/scala-tools-currency-watch.d.ts +1 -0
- package/src/handlers/scheduled-browser-tests.d.ts +1 -0
- package/src/handlers/sweep-event-log.d.ts +1 -0
- package/src/handlers/sweep-host-cache.d.ts +1 -0
- package/src/handlers/upstream-issue-sync.d.ts +1 -0
- package/src/handlers/whatsapp-liveness-logic.d.ts +34 -0
- package/src/handlers/whatsapp-liveness.d.ts +4 -0
- package/src/hono-error-handler.d.ts +25 -0
- package/src/install-harness.d.ts +45 -0
- package/src/install-logging.d.ts +34 -0
- package/src/load-service-install-row.d.ts +24 -0
- package/src/load-service-prisma-client.d.ts +18 -0
- package/src/mount-orpc-router.d.ts +15 -0
- package/src/mount-server-packages.d.ts +29 -0
- package/src/mount.d.ts +9 -0
- package/src/mutable-app-ref.d.ts +38 -0
- package/src/page-route-shell-types.d.ts +12 -0
- package/src/page-server-orpc/audit-revert-router.d.ts +37 -0
- package/src/page-server-orpc/hub-mcp-client.d.ts +12 -0
- package/src/page-server-orpc/portal-diagnostics-router.d.ts +49 -0
- package/src/page-server-orpc/puck-pages-router.d.ts +58 -0
- package/src/page-server-orpc/server-client.d.ts +16 -0
- package/src/page-server-orpc/templates-router.d.ts +34 -0
- package/src/page-server-orpc/user-preferences-router.d.ts +79 -0
- package/src/pg-boss-handler-registry.d.ts +25 -0
- package/src/pg-boss-mount.d.ts +39 -0
- package/src/proposal-authorized-emails.d.ts +28 -0
- package/src/proposal-chat-inject.d.ts +17 -0
- package/src/proposal-gate.d.ts +18 -0
- package/src/read-html-template.d.ts +38 -0
- package/src/read-viewport-from-request.d.ts +18 -0
- package/src/readiness-gate.d.ts +16 -0
- package/src/register-api-routes.d.ts +18 -0
- package/src/register-crash-handlers.d.ts +15 -0
- package/src/register-page-routes.d.ts +27 -0
- package/src/register-page-server-client.d.ts +11 -0
- package/src/register-registry-page-route/ai-chat-prefetch.d.ts +13 -0
- package/src/register-registry-page-route/graph-cache.d.ts +30 -0
- package/src/register-registry-page-route/meta-title.d.ts +2 -0
- package/src/register-registry-page-route/proposal-approval-email-token.d.ts +14 -0
- package/src/register-registry-page-route/proposal-brand-stamping.d.ts +28 -0
- package/src/register-registry-page-route/resolve-page-data.d.ts +1 -0
- package/src/register-registry-page-route.d.ts +27 -0
- package/src/register-static-assets.d.ts +13 -0
- package/src/register-ws-routes.d.ts +28 -0
- package/src/resolve-app-base-url.d.ts +13 -0
- package/src/resolve-brand-favicon.d.ts +28 -0
- package/src/resolve-from-loader-config.d.ts +32 -0
- package/src/resolve-service-context.d.ts +17 -0
- package/src/resolve-theme-mode.d.ts +42 -0
- package/src/resolvers/fetch-org-brand.d.ts +2 -0
- package/src/resolvers/portal-route-paths.d.ts +39 -0
- package/src/resolvers/website-by-host-map.d.ts +12 -0
- package/src/resource-chat-inject.d.ts +46 -0
- package/src/resource-not-found.d.ts +60 -0
- package/src/run-boot-hook-list.d.ts +19 -0
- package/src/run-boot-hooks.d.ts +31 -0
- package/src/scala-tools-currency-watchdog.d.ts +10 -0
- package/src/security-headers.d.ts +12 -0
- package/src/serve/serve.d.ts +46 -0
- package/src/server-error-page.d.ts +29 -0
- package/src/start-scheduled-jobs.d.ts +18 -0
- package/src/two-phase-boot.d.ts +93 -0
- package/src/two-phase-boot.ts +3 -0
- package/src/types.d.ts +46 -0
- package/src/ui-service.d.ts +46 -0
- package/src/ui-service.ts +10 -1
- package/src/ws-boot-self-test.d.ts +19 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system ui-service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Surgical block discovery: at boot, queries every block_schema row in the
|
|
7
|
+
* registry whose componentPath starts with one of the service's declared
|
|
8
|
+
* block_packages, then dynamic-imports each one. Per-block try/catch — one
|
|
9
|
+
* dead componentPath logs and skips, the rest still register and the page
|
|
10
|
+
* renders the surviving blocks. This replaces the static
|
|
11
|
+
* `.scala-install/page-manifest.ts` codegen output, which had the failure
|
|
12
|
+
* mode of a single dead block_schema row crashing the whole manifest at
|
|
13
|
+
* compile time.
|
|
14
|
+
*
|
|
15
|
+
* Empty block_packages is NOT fatal here: it falls back to scanning all
|
|
16
|
+
* active block_schema (uninstalled packages skip via the per-block try/catch),
|
|
17
|
+
* so a service whose row is unpopulated but whose blocks are installed still
|
|
18
|
+
* renders. The real "booted with zero blocks" fail-closed is at the call site
|
|
19
|
+
* (loaded.length === 0 → BootFatalError). A DB-unreachable error still throws —
|
|
20
|
+
* no fallback to a package-side puckBlocks scan, which masked blockless boots.
|
|
21
|
+
*/
|
|
22
|
+
import type { RendererComponentEntry } from "./types.ts";
|
|
23
|
+
export interface DiscoveredBlocks {
|
|
24
|
+
components: Record<string, RendererComponentEntry>;
|
|
25
|
+
loaded: string[];
|
|
26
|
+
skipped: string[];
|
|
27
|
+
}
|
|
28
|
+
export declare function discoverBlocks(blockPackages: string[]): Promise<DiscoveredBlocks>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system server-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Server-side roster expansion — the executor that handles "render N of block X
|
|
7
|
+
* per data row" so the page never needs a domain-specific panel/list block. A
|
|
8
|
+
* block authored with `props.dataRepeat: "parties"` is a TEMPLATE; before SSR
|
|
9
|
+
* this clones it once per roster item into its parent slot (top-level content or
|
|
10
|
+
* any Container's `content` slot), then drops the marker. Each clone:
|
|
11
|
+
* - sets `role` + `dataKey` to the item's key, so a prop-driven block (the
|
|
12
|
+
* SignatureField cell) finds its own party with no per-clone wiring;
|
|
13
|
+
* - substitutes `{{name}}` / `{{role}}` / `{{company}}` / `{{date}}` /
|
|
14
|
+
* `{{status}}` placeholders in any string prop (so a recipient row is plain
|
|
15
|
+
* `Container` + `Text` primitives — the copy lives on the page, not here).
|
|
16
|
+
* `{{status}}` resolves from the template's own `signedLabel` /
|
|
17
|
+
* `awaitingLabel` props (DB-driven copy), never hardcoded.
|
|
18
|
+
* Generic over any roster; the agreement page passes its parties.
|
|
19
|
+
*/
|
|
20
|
+
export interface RosterItem {
|
|
21
|
+
key: string;
|
|
22
|
+
role: string;
|
|
23
|
+
name: string;
|
|
24
|
+
title: string | null;
|
|
25
|
+
company: string | null;
|
|
26
|
+
signedAt: string | null;
|
|
27
|
+
signature: string | null;
|
|
28
|
+
}
|
|
29
|
+
/** Agreement-level tokens (one substitution, not per-party). */
|
|
30
|
+
export interface RosterMeta {
|
|
31
|
+
[token: string]: string;
|
|
32
|
+
}
|
|
33
|
+
/** Expand roster templates + bind agreement-meta placeholders across regions. */
|
|
34
|
+
export declare function expandRosterTemplates(resolved: Record<string, unknown>, parties: RosterItem[], meta?: RosterMeta): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Completion delivery. When an agreement is fully EXECUTED (every party has
|
|
7
|
+
* signed), email each party their executed copy + a note to download the
|
|
8
|
+
* Certificate of Completion. Each link is a per-party magic-link (no email gate,
|
|
9
|
+
* no OTP — see attach-agreement-magic.ts). Best-effort and self-contained: it
|
|
10
|
+
* loads its own data and swallows every error, so a send failure is logged and
|
|
11
|
+
* NEVER undoes the signature (the payment-setup non-fatal rule, applied to mail).
|
|
12
|
+
* Fire-and-forget from the sign handler: `void sendAgreementCompletionEmails(...)`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function sendAgreementCompletionEmails(agreementId: string, baseUrl: string): Promise<void>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* fn.agreementSend.send — authenticated "send for signature" procedure. Emails
|
|
7
|
+
* each party of an agreement a link to its signing page, stamps the lifecycle
|
|
8
|
+
* (sent_to / sent_at, status draft→sent), and returns a per-recipient result.
|
|
9
|
+
*
|
|
10
|
+
* Off-the-shelf path per building-applications: this is server logic beyond
|
|
11
|
+
* CRUD, so it is a typed ORPC procedure (not a bespoke endpoint), and it sends
|
|
12
|
+
* through the shared Resend adapter (@teamscala/api-resend) — the same surface
|
|
13
|
+
* @teamscala/auth uses for OTP — never a new email integration.
|
|
14
|
+
*
|
|
15
|
+
* Per-org sender: emails go FROM the org's display name on the platform's
|
|
16
|
+
* verified Resend domain ("<Org> via Sign <verified-addr>"), with reply_to set
|
|
17
|
+
* to the org's contact_email, so replies reach the org without each org needing
|
|
18
|
+
* its own verified domain. When an org later verifies its own sending domain,
|
|
19
|
+
* resolveSender is the single place to switch the FROM address.
|
|
20
|
+
*
|
|
21
|
+
* Sending is privileged (it reaches real inboxes), so the procedure requires an
|
|
22
|
+
* authenticated caller — the localhost super-admin bypass authorises operator /
|
|
23
|
+
* portal-SSR callers; the public signing page cannot invoke it.
|
|
24
|
+
*/
|
|
25
|
+
import * as v from "valibot";
|
|
26
|
+
interface User {
|
|
27
|
+
id: string;
|
|
28
|
+
organisationId: string | null;
|
|
29
|
+
}
|
|
30
|
+
interface Context {
|
|
31
|
+
user: User | null | undefined;
|
|
32
|
+
headers: Headers;
|
|
33
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<User | null>;
|
|
34
|
+
prisma: any;
|
|
35
|
+
}
|
|
36
|
+
export declare const agreementSendRouter: {
|
|
37
|
+
send: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
38
|
+
headers: Headers;
|
|
39
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<User | null>;
|
|
40
|
+
prisma: any;
|
|
41
|
+
user: User;
|
|
42
|
+
}>, v.ObjectSchema<{
|
|
43
|
+
readonly agreementId: v.StringSchema<undefined>;
|
|
44
|
+
/** Public base URL of the signing site, e.g. https://sign-dev.scala.business (no trailing slash). */
|
|
45
|
+
readonly baseUrl: v.StringSchema<undefined>;
|
|
46
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
47
|
+
ok: false;
|
|
48
|
+
error: string;
|
|
49
|
+
sentAt?: undefined;
|
|
50
|
+
url?: undefined;
|
|
51
|
+
sent?: undefined;
|
|
52
|
+
} | {
|
|
53
|
+
error?: undefined;
|
|
54
|
+
ok: boolean;
|
|
55
|
+
sentAt: string | null;
|
|
56
|
+
url: string;
|
|
57
|
+
sent: {
|
|
58
|
+
email: string;
|
|
59
|
+
ok: boolean;
|
|
60
|
+
id?: string;
|
|
61
|
+
error?: string;
|
|
62
|
+
}[];
|
|
63
|
+
}, {
|
|
64
|
+
ok: false;
|
|
65
|
+
error: string;
|
|
66
|
+
sentAt?: undefined;
|
|
67
|
+
url?: undefined;
|
|
68
|
+
sent?: undefined;
|
|
69
|
+
} | {
|
|
70
|
+
error?: undefined;
|
|
71
|
+
ok: boolean;
|
|
72
|
+
sentAt: string | null;
|
|
73
|
+
url: string;
|
|
74
|
+
sent: {
|
|
75
|
+
email: string;
|
|
76
|
+
ok: boolean;
|
|
77
|
+
id?: string;
|
|
78
|
+
error?: string;
|
|
79
|
+
}[];
|
|
80
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
81
|
+
};
|
|
82
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* `fn.aiHealth` — the AI-availability probe the shared chat hook
|
|
7
|
+
* (`useAIHealthCheck`) polls before showing the chat's health dot. It resolves
|
|
8
|
+
* the same DB-driven default model the chat engine uses (`ai-default-model`
|
|
9
|
+
* config → an active `llm_model` row) and reports `{status, mcp, gateway}`;
|
|
10
|
+
* `status:"ok"` means the chat has a usable model configured.
|
|
11
|
+
*
|
|
12
|
+
* Unauthed (a public GPT surface polls it too) and a LIGHTWEIGHT registry read
|
|
13
|
+
* via the request `prisma` — deliberately NO `@teamscala/chat-completion` import,
|
|
14
|
+
* so wiring this universal procedure never pulls the AI stack into every
|
|
15
|
+
* service. Registered into the `fn` namespace by registerFnRouters, so any
|
|
16
|
+
* chat-capable service answers it instead of 404-ing.
|
|
17
|
+
*/
|
|
18
|
+
interface Context {
|
|
19
|
+
prisma: {
|
|
20
|
+
registry_entries: {
|
|
21
|
+
findFirst: (args: unknown) => Promise<{
|
|
22
|
+
config?: unknown;
|
|
23
|
+
id?: string;
|
|
24
|
+
} | null>;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface AiHealthResponse {
|
|
29
|
+
status: "ok" | "error";
|
|
30
|
+
mcp: boolean;
|
|
31
|
+
gateway: boolean;
|
|
32
|
+
error?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare const aiHealthHandler: import("@orpc/server").DecoratedProcedure<Context & Record<never, never>, Context, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<AiHealthResponse, AiHealthResponse>, Record<never, never>, Record<never, never>>;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* ORPC procedures for auth checks (isOrgAdmin, resolveAdminOverride).
|
|
7
|
+
* Extracted from @teamscala/orpc/fn-router — primitives tier must not
|
|
8
|
+
* contain application-specific auth logic.
|
|
9
|
+
*/
|
|
10
|
+
interface User {
|
|
11
|
+
id: string;
|
|
12
|
+
name?: string | null;
|
|
13
|
+
email?: string;
|
|
14
|
+
organisationId: string | null;
|
|
15
|
+
}
|
|
16
|
+
interface Context {
|
|
17
|
+
user: User | null | undefined;
|
|
18
|
+
headers: Headers;
|
|
19
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<User | null>;
|
|
20
|
+
prisma: any;
|
|
21
|
+
orgId?: string | null;
|
|
22
|
+
}
|
|
23
|
+
declare const authed: import("@orpc/server").BuilderWithMiddlewares<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
24
|
+
headers: Headers;
|
|
25
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<User | null>;
|
|
26
|
+
prisma: any;
|
|
27
|
+
user: User;
|
|
28
|
+
orgId: string | null | undefined;
|
|
29
|
+
}>, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<unknown, unknown>, Record<never, never>, Record<never, never>>;
|
|
30
|
+
export declare const authRouter: {
|
|
31
|
+
isOrgAdmin: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
32
|
+
headers: Headers;
|
|
33
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<User | null>;
|
|
34
|
+
prisma: any;
|
|
35
|
+
user: User;
|
|
36
|
+
orgId: string | null | undefined;
|
|
37
|
+
}>, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<boolean, boolean>, Record<never, never>, Record<never, never>>;
|
|
38
|
+
resolveAdminOverride: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
39
|
+
headers: Headers;
|
|
40
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<User | null>;
|
|
41
|
+
prisma: any;
|
|
42
|
+
user: User;
|
|
43
|
+
orgId: string | null | undefined;
|
|
44
|
+
}>, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<string | null, string | null>, Record<never, never>, Record<never, never>>;
|
|
45
|
+
};
|
|
46
|
+
export type { Context, User };
|
|
47
|
+
export { authed };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* `fn.cacheAdmin` — ORPC procedures for in-process cache enable/disable/flush.
|
|
7
|
+
* Replaces the former `/api/data/cache-monitor/*` HANDLER_MAP entries
|
|
8
|
+
* (orpc-is-the-only-api: every API surface is a typed ORPC procedure, never a
|
|
9
|
+
* hand-written Hono route). Calls through @teamscala/cache/registry — the
|
|
10
|
+
* platform-singleton cache surface (cache-is-the-only-cache).
|
|
11
|
+
*/
|
|
12
|
+
import * as v from "valibot";
|
|
13
|
+
export declare const cacheAdminRouter: {
|
|
14
|
+
enable: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<import("./auth-router.ts").Context & Record<never, never>, import("./auth-router.ts").Context, import("./auth-router.ts").Context>, import("@orpc/server").MergedCurrentContext<import("./auth-router.ts").Context, {
|
|
15
|
+
headers: Headers;
|
|
16
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
|
|
17
|
+
prisma: any;
|
|
18
|
+
user: import("./auth-router.ts").User;
|
|
19
|
+
orgId: string | null | undefined;
|
|
20
|
+
}>, v.ObjectSchema<{
|
|
21
|
+
readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
|
|
22
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
23
|
+
ok: boolean;
|
|
24
|
+
name: string;
|
|
25
|
+
}, {
|
|
26
|
+
ok: boolean;
|
|
27
|
+
name: string;
|
|
28
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
29
|
+
disable: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<import("./auth-router.ts").Context & Record<never, never>, import("./auth-router.ts").Context, import("./auth-router.ts").Context>, import("@orpc/server").MergedCurrentContext<import("./auth-router.ts").Context, {
|
|
30
|
+
headers: Headers;
|
|
31
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
|
|
32
|
+
prisma: any;
|
|
33
|
+
user: import("./auth-router.ts").User;
|
|
34
|
+
orgId: string | null | undefined;
|
|
35
|
+
}>, v.ObjectSchema<{
|
|
36
|
+
readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
|
|
37
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
38
|
+
ok: boolean;
|
|
39
|
+
name: string;
|
|
40
|
+
}, {
|
|
41
|
+
ok: boolean;
|
|
42
|
+
name: string;
|
|
43
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
44
|
+
flush: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<import("./auth-router.ts").Context & Record<never, never>, import("./auth-router.ts").Context, import("./auth-router.ts").Context>, import("@orpc/server").MergedCurrentContext<import("./auth-router.ts").Context, {
|
|
45
|
+
headers: Headers;
|
|
46
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
|
|
47
|
+
prisma: any;
|
|
48
|
+
user: import("./auth-router.ts").User;
|
|
49
|
+
orgId: string | null | undefined;
|
|
50
|
+
}>, v.ObjectSchema<{
|
|
51
|
+
readonly name: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
52
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
53
|
+
flushed: any;
|
|
54
|
+
}, {
|
|
55
|
+
flushed: any;
|
|
56
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
57
|
+
};
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* ORPC procedures for the AUTHENTICATED AI-chat conversation lifecycle —
|
|
7
|
+
* the org+user-keyed sibling of publicGptSessionRouter (which is contact-
|
|
8
|
+
* linked for anonymous public GPT visitors). One signed-in user chatting
|
|
9
|
+
* with one agent in one org owns a thread of `conversations` rows; this
|
|
10
|
+
* router createOrRestore-s the active one, saves turns, archives+news on
|
|
11
|
+
* clear, lists past threads, and loads a specific thread.
|
|
12
|
+
*
|
|
13
|
+
* Identity: the USER is resolved from the ORPC session context (`authed`
|
|
14
|
+
* middleware → `context.user.id`); the ORGANISATION is supplied by the
|
|
15
|
+
* client (it is the URL :orgId for org-scoped apps like scala-projects —
|
|
16
|
+
* the session does not carry it) and VERIFIED — the caller must be a
|
|
17
|
+
* member of that organisation, else FORBIDDEN. A caller cannot read or
|
|
18
|
+
* write another user's threads (ownership is user_id) or another org's
|
|
19
|
+
* (createOrRestore/list are membership-scoped to the supplied org).
|
|
20
|
+
*
|
|
21
|
+
* This restores the capability the portal AI chat lost when the June
|
|
22
|
+
* chat-engine migration severed `usePortalConversationId` + the
|
|
23
|
+
* `portalConversation` router (capability-named `chatSession` here per
|
|
24
|
+
* name-by-capability; the host-named orphan was deleted in the same change).
|
|
25
|
+
*
|
|
26
|
+
* Persistence model: the chat client owns writes via onMessagesPersist →
|
|
27
|
+
* saveMessages, and sends clientPersists:true so handle-chat-stream skips its
|
|
28
|
+
* own persistChatRun (single writer, no double-persist). Verbatim UIMessage
|
|
29
|
+
* parts are stored in messages.channel_data.parts so multi-step (tool-using)
|
|
30
|
+
* turns round-trip losslessly (apps/chat.md messages-stored-as-uimessage-verbatim).
|
|
31
|
+
*/
|
|
32
|
+
import * as v from "valibot";
|
|
33
|
+
import { type Context } from "./auth-router.ts";
|
|
34
|
+
export declare const chatSessionRouter: {
|
|
35
|
+
createOrRestore: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
36
|
+
headers: Headers;
|
|
37
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
|
|
38
|
+
prisma: any;
|
|
39
|
+
user: import("./auth-router.ts").User;
|
|
40
|
+
orgId: string | null | undefined;
|
|
41
|
+
}>, v.ObjectSchema<{
|
|
42
|
+
readonly agentId: v.StringSchema<undefined>;
|
|
43
|
+
readonly organisationId: v.StringSchema<undefined>;
|
|
44
|
+
/**
|
|
45
|
+
* SSR-only: the real user's id, passed by the AiChat serverLoader. The
|
|
46
|
+
* in-process server client is system-authed (context.user.id === "system"),
|
|
47
|
+
* so without this the conversation is created under user_id="system" and
|
|
48
|
+
* the real user's saveMessages hits assertOwns → FORBIDDEN. Only honoured
|
|
49
|
+
* when the caller is the system user (server-side SSR), never from a
|
|
50
|
+
* client-side ORPC call.
|
|
51
|
+
*/
|
|
52
|
+
readonly userId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
53
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
54
|
+
conversationId: any;
|
|
55
|
+
model: any;
|
|
56
|
+
messages: {
|
|
57
|
+
id: any;
|
|
58
|
+
role: any;
|
|
59
|
+
content: any;
|
|
60
|
+
parts: unknown[] | undefined;
|
|
61
|
+
metadata: Record<string, unknown> | undefined;
|
|
62
|
+
created_at: any;
|
|
63
|
+
occurred_at: any;
|
|
64
|
+
}[];
|
|
65
|
+
tokenTotals: {
|
|
66
|
+
inputTokens: number;
|
|
67
|
+
outputTokens: number;
|
|
68
|
+
};
|
|
69
|
+
hasMore: boolean;
|
|
70
|
+
}, {
|
|
71
|
+
conversationId: any;
|
|
72
|
+
model: any;
|
|
73
|
+
messages: {
|
|
74
|
+
id: any;
|
|
75
|
+
role: any;
|
|
76
|
+
content: any;
|
|
77
|
+
parts: unknown[] | undefined;
|
|
78
|
+
metadata: Record<string, unknown> | undefined;
|
|
79
|
+
created_at: any;
|
|
80
|
+
occurred_at: any;
|
|
81
|
+
}[];
|
|
82
|
+
tokenTotals: {
|
|
83
|
+
inputTokens: number;
|
|
84
|
+
outputTokens: number;
|
|
85
|
+
};
|
|
86
|
+
hasMore: boolean;
|
|
87
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
88
|
+
loadEarlier: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
89
|
+
headers: Headers;
|
|
90
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
|
|
91
|
+
prisma: any;
|
|
92
|
+
user: import("./auth-router.ts").User;
|
|
93
|
+
orgId: string | null | undefined;
|
|
94
|
+
}>, v.ObjectSchema<{
|
|
95
|
+
readonly conversationId: v.StringSchema<undefined>;
|
|
96
|
+
/** Cursor: the occurred_at (ISO) of the oldest currently-loaded message. */
|
|
97
|
+
readonly before: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.IsoTimestampAction<string, undefined>]>;
|
|
98
|
+
/** Cap; defaults to RECENT_MESSAGE_LIMIT, clamped to it. */
|
|
99
|
+
readonly limit: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
100
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
101
|
+
messages: {
|
|
102
|
+
id: any;
|
|
103
|
+
role: any;
|
|
104
|
+
content: any;
|
|
105
|
+
parts: unknown[] | undefined;
|
|
106
|
+
metadata: Record<string, unknown> | undefined;
|
|
107
|
+
created_at: any;
|
|
108
|
+
occurred_at: any;
|
|
109
|
+
}[];
|
|
110
|
+
hasMore: boolean;
|
|
111
|
+
}, {
|
|
112
|
+
messages: {
|
|
113
|
+
id: any;
|
|
114
|
+
role: any;
|
|
115
|
+
content: any;
|
|
116
|
+
parts: unknown[] | undefined;
|
|
117
|
+
metadata: Record<string, unknown> | undefined;
|
|
118
|
+
created_at: any;
|
|
119
|
+
occurred_at: any;
|
|
120
|
+
}[];
|
|
121
|
+
hasMore: boolean;
|
|
122
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
123
|
+
saveMessages: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
124
|
+
headers: Headers;
|
|
125
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
|
|
126
|
+
prisma: any;
|
|
127
|
+
user: import("./auth-router.ts").User;
|
|
128
|
+
orgId: string | null | undefined;
|
|
129
|
+
}>, v.ObjectSchema<{
|
|
130
|
+
readonly conversationId: v.StringSchema<undefined>;
|
|
131
|
+
readonly messages: v.ArraySchema<v.ObjectSchema<{
|
|
132
|
+
readonly id: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
133
|
+
readonly role: v.StringSchema<undefined>;
|
|
134
|
+
readonly content: v.StringSchema<undefined>;
|
|
135
|
+
readonly parts: v.OptionalSchema<v.ArraySchema<v.AnySchema, undefined>, undefined>;
|
|
136
|
+
readonly metadata: v.OptionalSchema<v.RecordSchema<v.StringSchema<undefined>, v.AnySchema, undefined>, undefined>;
|
|
137
|
+
}, undefined>, undefined>;
|
|
138
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
139
|
+
success: boolean;
|
|
140
|
+
}, {
|
|
141
|
+
success: boolean;
|
|
142
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
143
|
+
clear: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
144
|
+
headers: Headers;
|
|
145
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
|
|
146
|
+
prisma: any;
|
|
147
|
+
user: import("./auth-router.ts").User;
|
|
148
|
+
orgId: string | null | undefined;
|
|
149
|
+
}>, v.ObjectSchema<{
|
|
150
|
+
readonly conversationId: v.StringSchema<undefined>;
|
|
151
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
152
|
+
conversationId: any;
|
|
153
|
+
messages: never[];
|
|
154
|
+
tokenTotals: {
|
|
155
|
+
inputTokens: number;
|
|
156
|
+
outputTokens: number;
|
|
157
|
+
};
|
|
158
|
+
}, {
|
|
159
|
+
conversationId: any;
|
|
160
|
+
messages: never[];
|
|
161
|
+
tokenTotals: {
|
|
162
|
+
inputTokens: number;
|
|
163
|
+
outputTokens: number;
|
|
164
|
+
};
|
|
165
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
166
|
+
list: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
167
|
+
headers: Headers;
|
|
168
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
|
|
169
|
+
prisma: any;
|
|
170
|
+
user: import("./auth-router.ts").User;
|
|
171
|
+
orgId: string | null | undefined;
|
|
172
|
+
}>, v.ObjectSchema<{
|
|
173
|
+
readonly agentId: v.StringSchema<undefined>;
|
|
174
|
+
readonly organisationId: v.StringSchema<undefined>;
|
|
175
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
176
|
+
conversations: any;
|
|
177
|
+
}, {
|
|
178
|
+
conversations: any;
|
|
179
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
180
|
+
load: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
181
|
+
headers: Headers;
|
|
182
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
|
|
183
|
+
prisma: any;
|
|
184
|
+
user: import("./auth-router.ts").User;
|
|
185
|
+
orgId: string | null | undefined;
|
|
186
|
+
}>, v.ObjectSchema<{
|
|
187
|
+
readonly conversationId: v.StringSchema<undefined>;
|
|
188
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
189
|
+
conversationId: any;
|
|
190
|
+
messages: {
|
|
191
|
+
id: any;
|
|
192
|
+
role: any;
|
|
193
|
+
content: any;
|
|
194
|
+
parts: unknown[] | undefined;
|
|
195
|
+
metadata: Record<string, unknown> | undefined;
|
|
196
|
+
created_at: any;
|
|
197
|
+
occurred_at: any;
|
|
198
|
+
}[];
|
|
199
|
+
tokenTotals: {
|
|
200
|
+
inputTokens: number;
|
|
201
|
+
outputTokens: number;
|
|
202
|
+
};
|
|
203
|
+
}, {
|
|
204
|
+
conversationId: any;
|
|
205
|
+
messages: {
|
|
206
|
+
id: any;
|
|
207
|
+
role: any;
|
|
208
|
+
content: any;
|
|
209
|
+
parts: unknown[] | undefined;
|
|
210
|
+
metadata: Record<string, unknown> | undefined;
|
|
211
|
+
created_at: any;
|
|
212
|
+
occurred_at: any;
|
|
213
|
+
}[];
|
|
214
|
+
tokenTotals: {
|
|
215
|
+
inputTokens: number;
|
|
216
|
+
outputTokens: number;
|
|
217
|
+
};
|
|
218
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
219
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getDefaultEmailSender(): Promise<string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getEmailLinkTtlMs(): Promise<number>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Composes auth, tasks, work-items, plans, chat-session, public-gpt-session,
|
|
7
|
+
* public-agreement, and user-preferences routers into the `fn` namespace and
|
|
8
|
+
* registers it via registerCustomRouter.
|
|
9
|
+
* Called at boot by registerFnRouters() — invoked before any ORPC dispatch.
|
|
10
|
+
*
|
|
11
|
+
* Also exposes the `regions` namespace on the client /api/rpc mount: a single
|
|
12
|
+
* `loadPage` procedure (reusing puckPagesRouter.loadFromWebsite) so a client
|
|
13
|
+
* RegionPageSwap can fetch a region's Puck page on demand and render it into a
|
|
14
|
+
* slot — the no-reload half of `region-views-are-pages` (every region is a Puck
|
|
15
|
+
* page; switching a view loads a different page's content). loadById is NOT
|
|
16
|
+
* exposed (website+path is the client-facing contract, not raw page ids).
|
|
17
|
+
*/
|
|
18
|
+
export declare function registerFnRouters(): void;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as v from "valibot";
|
|
2
|
+
interface Context {
|
|
3
|
+
prisma: {
|
|
4
|
+
builda_websites: {
|
|
5
|
+
findFirst: (args: unknown) => Promise<{
|
|
6
|
+
organisation_id?: string | null;
|
|
7
|
+
} | null>;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export declare const resolvePanelDataHandler: import("@orpc/server").DecoratedProcedure<Context & Record<never, never>, Context, v.ObjectSchema<{
|
|
12
|
+
readonly panelSlug: v.StringSchema<undefined>;
|
|
13
|
+
readonly websiteSlug: v.StringSchema<undefined>;
|
|
14
|
+
/** Tenant orgId (preferred over the website's organisation_id, which is
|
|
15
|
+
* the platform org on a multi-tenant portal — not the tenant). The
|
|
16
|
+
* caller (RegionPageSwap) threads this from __PAGE_DATA__.orgId. */
|
|
17
|
+
readonly orgId: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
18
|
+
}, undefined>, import("@orpc/contract").Schema<Record<string, unknown> | null, Record<string, unknown> | null>, Record<never, never>, Record<never, never>>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* The ONE chat-message write surface for the session routers. Both the authed
|
|
7
|
+
* (chatSession) and public (publicGptSession) saveMessages procedures persist
|
|
8
|
+
* turns through here — they differ only in IDENTITY/ownership (user_id vs
|
|
9
|
+
* contact_email, resolved in the router before calling this), never in the
|
|
10
|
+
* write itself. Keeping the write in two routers was literal duplication
|
|
11
|
+
* (no-duplicate-canonical-units) and is why the stable-id fix had to be applied
|
|
12
|
+
* twice.
|
|
13
|
+
*
|
|
14
|
+
* Upserts each message on its SDK UIMessage id so a re-save of a turn (a retry,
|
|
15
|
+
* a reconnect after a network drop, or a stray dual-write) updates the one row
|
|
16
|
+
* in place instead of inserting a duplicate (chat-message-ids-server-stable);
|
|
17
|
+
* falls back to create only for legacy id-less callers. occurred_at is stamped
|
|
18
|
+
* with a 1ms step preserving array order so same-second saves restore in order.
|
|
19
|
+
*/
|
|
20
|
+
export interface ChatMessageInput {
|
|
21
|
+
id?: string;
|
|
22
|
+
role: string;
|
|
23
|
+
content: string;
|
|
24
|
+
parts?: unknown[];
|
|
25
|
+
/** The SDK UIMessage `metadata` — carries per-message token usage
|
|
26
|
+
* (`inputTokens`/`outputTokens`/`contextWindow`/`model`) the stream attaches
|
|
27
|
+
* via `messageMetadata`. Persisted so the context-usage gauge can rehydrate
|
|
28
|
+
* on reload and budget-enforcement can read per-message token counts; without
|
|
29
|
+
* it the save dropped the usage and the gauge came back blank on refresh. */
|
|
30
|
+
metadata?: Record<string, unknown> | null;
|
|
31
|
+
}
|
|
32
|
+
export declare function persistChatMessages(prisma: any, opts: {
|
|
33
|
+
conversationId: string;
|
|
34
|
+
organisationId: string | null;
|
|
35
|
+
messages: ChatMessageInput[];
|
|
36
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* ORPC procedures for plan creation with tasks and subtasks.
|
|
7
|
+
* Extracted from @teamscala/orpc/fn-router — primitives tier must not
|
|
8
|
+
* contain application-specific work_items logic.
|
|
9
|
+
*/
|
|
10
|
+
import { type Context } from "./auth-router.ts";
|
|
11
|
+
export declare const plansRouter: {
|
|
12
|
+
save: import("@orpc/server").DecoratedProcedure<import("@orpc/server").MergedInitialContext<Context & Record<never, never>, Context, Context>, import("@orpc/server").MergedCurrentContext<Context, {
|
|
13
|
+
headers: Headers;
|
|
14
|
+
resolveUser?: (headers: Headers, prisma: any) => Promise<import("./auth-router.ts").User | null>;
|
|
15
|
+
prisma: any;
|
|
16
|
+
user: import("./auth-router.ts").User;
|
|
17
|
+
orgId: string | null | undefined;
|
|
18
|
+
}>, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<{
|
|
19
|
+
success: boolean;
|
|
20
|
+
data: any;
|
|
21
|
+
}, {
|
|
22
|
+
success: boolean;
|
|
23
|
+
data: any;
|
|
24
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
25
|
+
};
|