@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,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system page-server
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* ORPC procedures for loading Puck pages. These replace the direct Prisma calls
|
|
7
|
+
* in load-puck-page-by-slug.ts with proper ORPC procedures that receive
|
|
8
|
+
* context.prisma from the router.
|
|
9
|
+
*/
|
|
10
|
+
import * as v from "valibot";
|
|
11
|
+
export declare const puckPagesRouter: {
|
|
12
|
+
loadFromWebsite: import("@orpc/server").DecoratedProcedure<Record<never, never>, Record<never, never>, v.ObjectSchema<{
|
|
13
|
+
readonly websiteSlug: v.StringSchema<undefined>;
|
|
14
|
+
readonly path: v.StringSchema<undefined>;
|
|
15
|
+
}, undefined>, v.NullableSchema<v.ObjectSchema<{
|
|
16
|
+
readonly id: v.StringSchema<undefined>;
|
|
17
|
+
readonly path: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
18
|
+
readonly puckData: v.UnknownSchema;
|
|
19
|
+
readonly mode: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
20
|
+
readonly render_mode: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
21
|
+
readonly website_slug: v.StringSchema<undefined>;
|
|
22
|
+
readonly organisation_id: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
23
|
+
readonly meta_title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
24
|
+
readonly meta_description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
25
|
+
readonly website: v.ObjectSchema<{
|
|
26
|
+
readonly slug: v.StringSchema<undefined>;
|
|
27
|
+
readonly name: v.StringSchema<undefined>;
|
|
28
|
+
readonly organisation_id: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
29
|
+
readonly website_type: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
30
|
+
readonly layout_settings: v.NullableSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
31
|
+
readonly header_settings: v.NullableSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
32
|
+
readonly footer_settings: v.NullableSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
33
|
+
}, undefined>;
|
|
34
|
+
}, undefined>, undefined>, Record<never, never>, Record<never, never>>;
|
|
35
|
+
loadById: import("@orpc/server").DecoratedProcedure<Record<never, never>, Record<never, never>, v.ObjectSchema<{
|
|
36
|
+
readonly pageId: v.StringSchema<undefined>;
|
|
37
|
+
}, undefined>, v.NullableSchema<v.ObjectSchema<{
|
|
38
|
+
readonly id: v.StringSchema<undefined>;
|
|
39
|
+
readonly path: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
40
|
+
readonly puckData: v.UnknownSchema;
|
|
41
|
+
readonly mode: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
42
|
+
readonly render_mode: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
43
|
+
readonly website_slug: v.StringSchema<undefined>;
|
|
44
|
+
readonly organisation_id: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
45
|
+
readonly meta_title: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
46
|
+
readonly meta_description: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
47
|
+
readonly website: v.ObjectSchema<{
|
|
48
|
+
readonly slug: v.StringSchema<undefined>;
|
|
49
|
+
readonly name: v.StringSchema<undefined>;
|
|
50
|
+
readonly organisation_id: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
51
|
+
readonly website_type: v.NullableSchema<v.StringSchema<undefined>, undefined>;
|
|
52
|
+
readonly layout_settings: v.NullableSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
53
|
+
readonly header_settings: v.NullableSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
54
|
+
readonly footer_settings: v.NullableSchema<v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>, undefined>;
|
|
55
|
+
}, undefined>;
|
|
56
|
+
}, undefined>, undefined>, Record<never, never>, Record<never, never>>;
|
|
57
|
+
};
|
|
58
|
+
export type PuckPagesRouter = typeof puckPagesRouter;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system page-server
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Server-side ORPC client for in-process direct invocation, per the canonical
|
|
7
|
+
* Vite/Next/Nuxt SSR pattern documented at https://orpc.dev/docs/best-practices/optimize-ssr
|
|
8
|
+
*
|
|
9
|
+
* The host service (scala-install) must call `setServerClient(client)` once
|
|
10
|
+
* at boot, after createRouterClient(appRouter, { context: { prisma } }).
|
|
11
|
+
* Then page-server's createPageHandler reads `getServerClient()` per request
|
|
12
|
+
* — no HTTP loopback, just a typed function call.
|
|
13
|
+
*/
|
|
14
|
+
import { createRouterClient } from "@orpc/server";
|
|
15
|
+
export declare function getServerClient(): ReturnType<typeof createRouterClient>;
|
|
16
|
+
export declare function setServerClient(client: ReturnType<typeof createRouterClient>): void;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system page-server
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* ORPC procedure: templates.getSettings(slug). Reads the registry_entries row
|
|
7
|
+
* of type='template_settings' for the requested slug, validates against the
|
|
8
|
+
* matching Valibot schema from db-validation, returns typed settings.
|
|
9
|
+
*
|
|
10
|
+
* Per data-access.md: every data read goes through ORPC. The Template
|
|
11
|
+
* components do not call Prisma or registry directly — they receive the
|
|
12
|
+
* typed result of this procedure as a prop.
|
|
13
|
+
*
|
|
14
|
+
* Server-side (SSR) calls land here in-process via createRouterClient.
|
|
15
|
+
* Client-side calls would land here over HTTP via createORPCClient.
|
|
16
|
+
*/
|
|
17
|
+
import * as v from "valibot";
|
|
18
|
+
export declare const templatesRouter: {
|
|
19
|
+
getSettings: import("@orpc/server").DecoratedProcedure<Record<never, never>, Record<never, never>, v.ObjectSchema<{
|
|
20
|
+
readonly slug: v.StringSchema<undefined>;
|
|
21
|
+
}, undefined>, import("@orpc/contract").Schema<unknown, unknown>, Record<never, never>, Record<never, never>>;
|
|
22
|
+
/**
|
|
23
|
+
* Patch a template's settings row. The patch is a deep partial applied
|
|
24
|
+
* over the existing config; the merged result is validated against the
|
|
25
|
+
* matching Valibot schema before write. Used by chrome layout (pane
|
|
26
|
+
* widths, toolbar height, etc.) so resizes persist server-side and the
|
|
27
|
+
* next SSR render picks them up directly — no localStorage, no flash.
|
|
28
|
+
*/
|
|
29
|
+
updateSettings: import("@orpc/server").DecoratedProcedure<Record<never, never>, Record<never, never>, v.ObjectSchema<{
|
|
30
|
+
readonly slug: v.StringSchema<undefined>;
|
|
31
|
+
readonly patch: v.RecordSchema<v.StringSchema<undefined>, v.UnknownSchema, undefined>;
|
|
32
|
+
}, undefined>, import("@orpc/contract").Schema<unknown, unknown>, Record<never, never>, Record<never, never>>;
|
|
33
|
+
};
|
|
34
|
+
export type TemplatesRouter = typeof templatesRouter;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system page-server
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* ORPC procedures for per-user portal UI preferences (sidebar collapse,
|
|
7
|
+
* panel sizes, active right panel, conversation ID, brand cache).
|
|
8
|
+
* Reads and writes the `portal` key inside `user.preferences` JSONB.
|
|
9
|
+
*
|
|
10
|
+
* The SSR page loads initial state via getPortalPreferences; mutations
|
|
11
|
+
* from usePortalActionHelpers call updatePortalPreferences. This replaces
|
|
12
|
+
* the injected localStorage pattern with DB-backed persistence.
|
|
13
|
+
*/
|
|
14
|
+
import * as v from "valibot";
|
|
15
|
+
export declare const userPreferencesRouter: {
|
|
16
|
+
/**
|
|
17
|
+
* Read the current user's portal preferences from user.preferences.portal.
|
|
18
|
+
* Returns null portal if no preferences exist yet.
|
|
19
|
+
*/
|
|
20
|
+
getPortalPreferences: import("@orpc/server").DecoratedProcedure<Record<never, never>, Record<never, never>, import("@orpc/contract").Schema<unknown, unknown>, import("@orpc/contract").Schema<{
|
|
21
|
+
portal: null;
|
|
22
|
+
} | {
|
|
23
|
+
portal: Record<string, unknown>;
|
|
24
|
+
}, {
|
|
25
|
+
portal: null;
|
|
26
|
+
} | {
|
|
27
|
+
portal: Record<string, unknown>;
|
|
28
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
29
|
+
/**
|
|
30
|
+
* Merge and persist a patch to the user's portal preferences.
|
|
31
|
+
* The patch is a deep partial of the portal object; missing keys
|
|
32
|
+
* are preserved from the existing value.
|
|
33
|
+
*/
|
|
34
|
+
updatePortalPreferences: import("@orpc/server").DecoratedProcedure<Record<never, never>, Record<never, never>, v.ObjectSchema<{
|
|
35
|
+
readonly patch: v.ObjectSchema<{
|
|
36
|
+
readonly theme: v.OptionalSchema<v.NullableSchema<v.PicklistSchema<["light", "dark"], undefined>, undefined>, undefined>;
|
|
37
|
+
readonly paneLeftWidth: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
38
|
+
readonly paneRightWidth: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
39
|
+
readonly sidebarCollapsed: v.OptionalSchema<v.BooleanSchema<undefined>, undefined>;
|
|
40
|
+
readonly activePanel: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
41
|
+
readonly panelSizes: v.OptionalSchema<v.ObjectSchema<{
|
|
42
|
+
readonly main: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
43
|
+
readonly right: v.OptionalSchema<v.NumberSchema<undefined>, undefined>;
|
|
44
|
+
}, undefined>, undefined>;
|
|
45
|
+
readonly conversationId: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
46
|
+
readonly brandCache: v.OptionalSchema<v.NullableSchema<v.ObjectSchema<{
|
|
47
|
+
readonly logo: v.ObjectSchema<{
|
|
48
|
+
readonly light: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
49
|
+
readonly dark: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
50
|
+
readonly brand: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
|
|
51
|
+
}, undefined>;
|
|
52
|
+
readonly primaryColor: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
53
|
+
}, undefined>, undefined>, undefined>;
|
|
54
|
+
}, undefined>;
|
|
55
|
+
}, undefined>, import("@orpc/contract").Schema<{
|
|
56
|
+
portal: {
|
|
57
|
+
theme?: "dark" | "light" | null | undefined;
|
|
58
|
+
paneLeftWidth?: number | undefined;
|
|
59
|
+
paneRightWidth?: number | undefined;
|
|
60
|
+
sidebarCollapsed?: boolean | undefined;
|
|
61
|
+
activePanel?: string | null | undefined;
|
|
62
|
+
conversationId?: string | null | undefined;
|
|
63
|
+
panelSizes: unknown;
|
|
64
|
+
brandCache: unknown;
|
|
65
|
+
};
|
|
66
|
+
}, {
|
|
67
|
+
portal: {
|
|
68
|
+
theme?: "dark" | "light" | null | undefined;
|
|
69
|
+
paneLeftWidth?: number | undefined;
|
|
70
|
+
paneRightWidth?: number | undefined;
|
|
71
|
+
sidebarCollapsed?: boolean | undefined;
|
|
72
|
+
activePanel?: string | null | undefined;
|
|
73
|
+
conversationId?: string | null | undefined;
|
|
74
|
+
panelSizes: unknown;
|
|
75
|
+
brandCache: unknown;
|
|
76
|
+
};
|
|
77
|
+
}>, Record<never, never>, Record<never, never>>;
|
|
78
|
+
};
|
|
79
|
+
export type UserPreferencesRouter = typeof userPreferencesRouter;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system server-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* The pg-boss scheduled-job handler registry — `handler_slug` → handler
|
|
7
|
+
* function. Built on `@teamscala/generic-registry` `createRegistry` (the mandated
|
|
8
|
+
* primitive per `generic-registry-is-the-only-registry-pattern`); a hand-rolled
|
|
9
|
+
* Map or a hardcoded switch in service-boot is the prohibited alternative.
|
|
10
|
+
*
|
|
11
|
+
* Handlers live in packages and self-register at boot (a boot hook / package
|
|
12
|
+
* subscriber shape) by calling `registerScheduledJobHandler`. `resolveHandler`
|
|
13
|
+
* in `pg-boss-mount.ts` reads this registry to dispatch a firing `scheduled_job`
|
|
14
|
+
* row to its registered function.
|
|
15
|
+
*/
|
|
16
|
+
import type { ScheduledJobConfig } from "@teamscala/db-validation/registry-schemas/scheduled-job";
|
|
17
|
+
export type PgBossJobHandler = (ctx: {
|
|
18
|
+
config: ScheduledJobConfig;
|
|
19
|
+
}) => Promise<void> | void;
|
|
20
|
+
export declare const pgBossHandlerRegistry: any;
|
|
21
|
+
/**
|
|
22
|
+
* Register a handler for a `scheduled_job.handler_slug`. Idempotent on re-import
|
|
23
|
+
* (createRegistry.register overwrites silently — last registration wins).
|
|
24
|
+
*/
|
|
25
|
+
export declare function registerScheduledJobHandler(slug: string, handler: PgBossJobHandler): void;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system server-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Mounts pg-boss for a backend service. Reads all scheduled_job registry
|
|
7
|
+
* entries scoped to the current service from the registry cache, registers
|
|
8
|
+
* pg-boss workers per queue_name, and schedules cron/interval jobs.
|
|
9
|
+
* Per Constitution Rule 6: pg-boss is the single mechanism for all
|
|
10
|
+
* application background work.
|
|
11
|
+
*/
|
|
12
|
+
import { PgBoss } from "pg-boss";
|
|
13
|
+
import "./handlers/prune-stale-data.ts";
|
|
14
|
+
import "./handlers/projects-digest.ts";
|
|
15
|
+
import "./handlers/sweep-event-log.ts";
|
|
16
|
+
import "./handlers/sweep-host-cache.ts";
|
|
17
|
+
import "./handlers/bun-stable-watch.ts";
|
|
18
|
+
import "./handlers/whatsapp-liveness.ts";
|
|
19
|
+
import "./handlers/upstream-issue-sync.ts";
|
|
20
|
+
import "./handlers/scheduled-browser-tests.ts";
|
|
21
|
+
import "./handlers/scala-tools-currency-watch.ts";
|
|
22
|
+
import "./handlers/registry-stale-inactive-sweep.ts";
|
|
23
|
+
export interface PgBossMountContext {
|
|
24
|
+
databaseUrl: string;
|
|
25
|
+
serviceSlug: string;
|
|
26
|
+
packages: string[];
|
|
27
|
+
}
|
|
28
|
+
export interface MountedJob {
|
|
29
|
+
queueName: string;
|
|
30
|
+
handlerSlug: string;
|
|
31
|
+
cron?: string;
|
|
32
|
+
intervalSeconds?: number;
|
|
33
|
+
}
|
|
34
|
+
export interface PgBossMountResult {
|
|
35
|
+
boss: PgBoss | null;
|
|
36
|
+
jobs: MountedJob[];
|
|
37
|
+
}
|
|
38
|
+
export declare function intervalToCron(intervalSeconds: number): string;
|
|
39
|
+
export declare function mountPgBoss(ctx: PgBossMountContext): Promise<PgBossMountResult>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Resolves the set of emails authorized to view a proposal. A proposal is
|
|
7
|
+
* gated (proposal-access) — only these emails can unlock it:
|
|
8
|
+
*
|
|
9
|
+
* - the issuing-org team: every member of the proposal's organisation
|
|
10
|
+
* (better_auth_member → user.email). Lets the agency team open any of their
|
|
11
|
+
* own proposals AND covers existing proposals whose created_by is
|
|
12
|
+
* "system"/null.
|
|
13
|
+
* - the recipient: the proposal's CRM contact (client_database.primary_email),
|
|
14
|
+
* when contact_id is set.
|
|
15
|
+
* - the partner team: every CRM contact belonging to the proposal's partner
|
|
16
|
+
* org (client_database.company_id = proposals.partner_id → primary_email),
|
|
17
|
+
* when partner_id is set. Lets the co-delivery partner's team open a
|
|
18
|
+
* co-branded proposal. The partner is still branding-first; this is the one
|
|
19
|
+
* access edge it carries.
|
|
20
|
+
*
|
|
21
|
+
* Uses $queryRaw (raw SQL) deliberately: the per-service Prisma client is scoped
|
|
22
|
+
* to that service's own models, so the proposals service's client has no
|
|
23
|
+
* `member`/`user` model methods — but $queryRaw runs against the shared DB
|
|
24
|
+
* regardless of the client's model scope. Returns a lowercased Set, checked
|
|
25
|
+
* server-side only (emails never sent to the client). Fail-closed: any error
|
|
26
|
+
* yields an empty set (no access).
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveProposalAuthorizedEmails(proposalId: string): Promise<Set<string>>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Injects the ProposalChatLauncher block into an AUTHORISED proposal page (called
|
|
7
|
+
* from proposalGateConfig.onAuthorized — so the bubble lives strictly behind the
|
|
8
|
+
* email gate, and every proposal gets it with no per-page Puck edit). It builds
|
|
9
|
+
* the proposal's full page content into a runtime-context string and passes it to
|
|
10
|
+
* the launcher, which forwards it to the chat as <runtime_context> — so ONE shared
|
|
11
|
+
* "Proposal Assistant" agent answers about whichever proposal is being viewed.
|
|
12
|
+
*
|
|
13
|
+
* The agent id is config, not code (registries-are-source-of-truth): the
|
|
14
|
+
* `config / proposal-assistant-agent` row carries { agentId }. No row (or no
|
|
15
|
+
* agent) → no injection, the page renders exactly as before (fail-soft).
|
|
16
|
+
*/
|
|
17
|
+
export declare function injectProposalChatLauncher(resolved: Record<string, unknown>, viewerEmail: string): Promise<void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* The PROPOSAL content gate, expressed as config for the content-gate primitive
|
|
7
|
+
* (content-gate/). No bespoke gate plumbing — just the proposal-specific bits:
|
|
8
|
+
* which resource (resolved.proposal.id), who's authorized (issuing-org team +
|
|
9
|
+
* recipient), what to seed (initialVisitor for the chat), and how to withhold
|
|
10
|
+
* (replace the proposal body with an injected SignIn gate block + neutralize the
|
|
11
|
+
* meta tags). The engine handles cookie/token/verify/orchestration.
|
|
12
|
+
*
|
|
13
|
+
* Universal: every proposal route exposes resolved.proposal, so this gates every
|
|
14
|
+
* proposal (existing + new) with no per-page block or migration.
|
|
15
|
+
*/
|
|
16
|
+
import type { AccessConfig, ContentGateConfig } from "./content-gate/config-types.ts";
|
|
17
|
+
export declare const proposalGateConfig: ContentGateConfig;
|
|
18
|
+
export declare const proposalAccessConfig: AccessConfig;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system ui-service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Reads the per-service HTML template (codegen'd from
|
|
7
|
+
* `@teamscala/scala-install/src/runtime/index.html`) and substitutes the
|
|
8
|
+
* `{{stylesPath}}` / `{{hydratePath}}` placeholders with the current
|
|
9
|
+
* content-hashed asset URLs from `dist/client/asset-manifest.json`.
|
|
10
|
+
*
|
|
11
|
+
* Build-time produces hashed filenames (e.g. `styles-abc123.css`); the
|
|
12
|
+
* static-asset handler serves them with `cache-control: immutable`. New
|
|
13
|
+
* deployments emit new hashes → new URLs → browsers refetch without ever
|
|
14
|
+
* holding a stale copy. Without the substitution, a fixed
|
|
15
|
+
* `/assets/styles.css` paired with `immutable` would pin every visitor to
|
|
16
|
+
* whatever version they first downloaded.
|
|
17
|
+
*
|
|
18
|
+
* Cached per service process, keyed on the manifest's mtime. The cache MUST
|
|
19
|
+
* invalidate when `asset-manifest.json` changes: `buildClientAssets` can
|
|
20
|
+
* rebuild the bundle AFTER the first request — producing a new content hash,
|
|
21
|
+
* rewriting the manifest, AND deleting the old hashed bundle
|
|
22
|
+
* (`removeStaleHashedFiles`). A lifetime-pinned HTML cache then keeps serving
|
|
23
|
+
* the OLD hash, which now 404s → hydration never runs → the page renders SSR
|
|
24
|
+
* HTML but is dead client-side (the doc-editor overlay never mounts; scala-docs
|
|
25
|
+
* 2026-06-13, exposed by the ui-foundation publish-storm's repeated rebuilds).
|
|
26
|
+
* Re-stat'ing the tiny manifest per request is negligible (OS-cached, no
|
|
27
|
+
* network); the substituted HTML is reused while the mtime is unchanged.
|
|
28
|
+
*
|
|
29
|
+
* NO-SILENT-REVERTS: when the manifest is a TOMBSTONE (the last client build
|
|
30
|
+
* failed), the served HTML is stamped with a `<meta name="x-client-build-status"
|
|
31
|
+
* content="failed">` tag in <head> so any operator / chrome-devtools / theme
|
|
32
|
+
* probe inspecting the page can see the served bundle is STALE (a published fix
|
|
33
|
+
* that reached node_modules but failed to bundle is silently served from the
|
|
34
|
+
* prior bundle otherwise — scala-agents 2026-07-18, the white-on-white toolbar
|
|
35
|
+
* regression that looked "not fixed" while the bundle kept serving pre-fix
|
|
36
|
+
* bytes across restarts).
|
|
37
|
+
*/
|
|
38
|
+
export declare function readHtmlTemplate(): Promise<string>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Server-side viewport detection from request headers. Two tiers:
|
|
7
|
+
* desktop (tablets, laptops, desktops) and mobile (phones).
|
|
8
|
+
*
|
|
9
|
+
* Tablets are NOT a separate tier — CSS handles responsive layout
|
|
10
|
+
* within the desktop tier via flex min/max and @container queries.
|
|
11
|
+
* Only phones (where the layout is fundamentally single-pane) get
|
|
12
|
+
* a different server-rendered page.
|
|
13
|
+
*
|
|
14
|
+
* Order of authority:
|
|
15
|
+
* cookie → Sec-CH-UA-Mobile client hint → User-Agent regex → desktop default.
|
|
16
|
+
*/
|
|
17
|
+
export type ViewportTier = "desktop" | "mobile";
|
|
18
|
+
export declare function readViewportFromRequest(request: Request): ViewportTier;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Readiness gate — returns 503 + Retry-After: 1 until the boot pipeline
|
|
7
|
+
* flips the ready flag true as its last step. Registered as the FIRST
|
|
8
|
+
* middleware in both UI and backend boot paths per readiness-gated-boot.
|
|
9
|
+
*
|
|
10
|
+
* The gate fails open: if it ever throws, the request passes through to
|
|
11
|
+
* the normal handler rather than producing a hard 500.
|
|
12
|
+
*/
|
|
13
|
+
import type { Context, Next } from "hono";
|
|
14
|
+
export declare function isReady(): boolean;
|
|
15
|
+
export declare function setReady(): void;
|
|
16
|
+
export declare function readinessGate(c: Context, next: Next): Promise<Response | void>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system server-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Walks `service_install.api_routes[]` and binds each entry to its
|
|
7
|
+
* registered handler (via mountRegistry.handlers, populated by server_packages
|
|
8
|
+
* during their mount phase). Unresolved handler_slug values are fatal — the
|
|
9
|
+
* service cannot boot with declared routes pointing at nothing.
|
|
10
|
+
*
|
|
11
|
+
* Injects x-remote-port header from Bun's getConnInfo so downstream
|
|
12
|
+
* handlers (MCP route) can resolve caller identity via process-tree
|
|
13
|
+
* walking when explicit caller headers are absent.
|
|
14
|
+
*/
|
|
15
|
+
import type { ServiceInstallConfig } from "@teamscala/db/registry/loader/load-service-install-row";
|
|
16
|
+
import type { MountRegistry } from "@teamscala/os/runtime-contracts/mount-context";
|
|
17
|
+
import type { Hono } from "hono";
|
|
18
|
+
export declare function registerApiRoutes(app: Hono, config: ServiceInstallConfig, mountRegistry: MountRegistry, serviceSlug: string): number;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system server-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Registers process-level crash handlers (unhandledRejection, uncaughtException)
|
|
7
|
+
* for a given service. Each handler logs the error with the service slug for
|
|
8
|
+
* identification. Per constitution crash-isolation.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerCrashHandlers(opts: {
|
|
11
|
+
serviceSlug: string;
|
|
12
|
+
}): {
|
|
13
|
+
unhandledRejection: boolean;
|
|
14
|
+
uncaughtException: boolean;
|
|
15
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system ui-service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit directly
|
|
5
|
+
*
|
|
6
|
+
* Page route registration — reads `page_route` registry rows for the
|
|
7
|
+
* current service and delegates to `registerRegistryPageRoute`.
|
|
8
|
+
*
|
|
9
|
+
* All routes are registry-driven (Phase 1): each `page_route` row pairs
|
|
10
|
+
* a URL pattern with a `resource_loader` graph that resolves data in
|
|
11
|
+
* wave-parallel via `resolveFromLoaderConfig`. No deploy-time shell
|
|
12
|
+
* variant routes — the old `service_install.page_routes[]` Phase 2 path
|
|
13
|
+
* was removed when every active service migrated to registry-driven
|
|
14
|
+
* `page_route` rows (all 9 services carry empty arrays).
|
|
15
|
+
*/
|
|
16
|
+
import type { Hono } from "hono";
|
|
17
|
+
import type { ServiceInstallConfig } from "./load-service-install-row.ts";
|
|
18
|
+
import type { RendererComponentEntry } from "./types.ts";
|
|
19
|
+
import type { CreatePageHandler } from "./types.ts";
|
|
20
|
+
export interface RegisterPageRoutesArgs {
|
|
21
|
+
app: Hono;
|
|
22
|
+
config: ServiceInstallConfig;
|
|
23
|
+
components: Record<string, RendererComponentEntry>;
|
|
24
|
+
serviceSlug: string;
|
|
25
|
+
createPageHandler: CreatePageHandler;
|
|
26
|
+
}
|
|
27
|
+
export declare function registerPageRoutes(args: RegisterPageRoutesArgs): Promise<string[]>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system ui-service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Registers the system server-client for page-server SSR rendering. Composes
|
|
7
|
+
* the platform-owned routers into the service's generated `appRouter` and
|
|
8
|
+
* stashes the resulting client via setServerClient. Called once at boot before
|
|
9
|
+
* any page route handler fires.
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerPageServerClient(serviceSlug: string): Promise<void>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSR-prefetch the signed-in user's AI-chat conversation so a CLICK-opened AI
|
|
3
|
+
* panel renders the real conversation on first paint — never a loading gate
|
|
4
|
+
* (ssr-then-live-handoff). The AiChat block lives on the /ai PANEL page, which
|
|
5
|
+
* isn't rendered when the panel is closed, so its block serverLoader can't run
|
|
6
|
+
* at page-load; this prefetches server-side (regardless of panel open-state) +
|
|
7
|
+
* stamps pageData.aiChatSession, which AiChat reads on mount. The agent is
|
|
8
|
+
* resolved from the /ai panel page's own AiChat block (single source of truth —
|
|
9
|
+
* no duplicate config to drift). Fired in parallel with the post-processors +
|
|
10
|
+
* bounded by their window; a failure degrades silently to the client-side
|
|
11
|
+
* createOrRestore fallback, never an error page.
|
|
12
|
+
*/
|
|
13
|
+
export declare function prefetchAiChatSession(resolved: Record<string, unknown>, sessionUserId: string | undefined, orgId: string | undefined): Promise<Record<string, unknown> | null>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type GraphCache = {
|
|
2
|
+
getWithMeta(key: string): {
|
|
3
|
+
value: unknown;
|
|
4
|
+
stale: boolean;
|
|
5
|
+
} | undefined;
|
|
6
|
+
refreshInBackground(key: string, compute: () => Promise<unknown>, opts?: {
|
|
7
|
+
ttlMs?: number;
|
|
8
|
+
}): void;
|
|
9
|
+
};
|
|
10
|
+
export declare const staticShellGraphCache: any;
|
|
11
|
+
export declare const paramRouteGraphCache: any;
|
|
12
|
+
/**
|
|
13
|
+
* Stale-while-revalidate read of a cached loader graph.
|
|
14
|
+
*
|
|
15
|
+
* - Fresh hit (within ttlMs): return the cached graph, no refresh.
|
|
16
|
+
* - Stale hit (within ttlMs + staleTtlMs): return the cached graph AND fire ONE
|
|
17
|
+
* background refresh via cache.refreshInBackground — single-flight (deduped
|
|
18
|
+
* against the cache's in-flight map), never rejects, leaves the stale entry in
|
|
19
|
+
* place on failure. The caller deep-clones the returned value before use.
|
|
20
|
+
* - Miss (past staleTtlMs, or never cached): return undefined — the caller
|
|
21
|
+
* resolves synchronously and cache.set()s the clone.
|
|
22
|
+
*
|
|
23
|
+
* The refresh callback must return a graph safe to store. To SKIP caching a
|
|
24
|
+
* refresh result (e.g. a primary-missing / dead-link graph that must stay
|
|
25
|
+
* per-request so a just-created record appears immediately), the callback THROWS
|
|
26
|
+
* — refreshInBackground catches it, leaves the stale entry, and logs one line
|
|
27
|
+
* (an observable dead-link signal, not a hard error).
|
|
28
|
+
*/
|
|
29
|
+
export declare function readCachedGraph(cache: GraphCache, key: string, refresh: () => Promise<unknown>): unknown | undefined;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare function buildMetaFromContext(metaContext: Record<string, Record<string, string>> | undefined, resolved: Record<string, unknown>): Record<string, unknown>;
|
|
2
|
+
export declare function resolveTemplateTitle(service: string, resolved: Record<string, unknown>): string | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the `{{approvalEmail}}` placeholder in a proposal page's button props
|
|
3
|
+
* (e.g. the Approve CTA) in place. Routing: the organisation's registered
|
|
4
|
+
* company email FIRST (organisation_profile.contact_email, already resolved
|
|
5
|
+
* into pageData.brand.contactEmail); the proposal creator's user email only as
|
|
6
|
+
* a fallback when the org has none — so a cloned proposal can never carry a
|
|
7
|
+
* stale hard-coded address. The creator lookup is null-safe and adds no user
|
|
8
|
+
* exposure: it resolves only where the in-process ORPC client exposes `user`
|
|
9
|
+
* (super-admin), degrading to the org email elsewhere. Called only for proposal
|
|
10
|
+
* pages; other registry pages are untouched.
|
|
11
|
+
*/
|
|
12
|
+
export declare function applyApprovalEmailToken(pageData: Record<string, unknown>, proposal: {
|
|
13
|
+
created_by?: string;
|
|
14
|
+
} | undefined): Promise<void>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stash a proposal's connected partner logo/colour on `pageData` from the
|
|
3
|
+
* `partnerOrg` loader source (`crm_organisations` loaded by the proposal's
|
|
4
|
+
* `partner_id`, via the SAME proven ORPC loader path that loads the proposal
|
|
5
|
+
* itself). resolve-page-brand (service-runtime) prefers `pageData.partnerLogo`
|
|
6
|
+
* over any inline body-Hero prop and fans it into the shared `/header` so a
|
|
7
|
+
* `source: "partner"` OrgLogo fills automatically — the partner logo lives on
|
|
8
|
+
* the CRM record, never duplicated per proposal. No partner → partnerOrg is
|
|
9
|
+
* null → nothing set → the partner logo block renders blank. Reading the
|
|
10
|
+
* already-resolved loader value (not a second hand-rolled getServerClient call)
|
|
11
|
+
* is what makes this reliable: the earlier direct `crm_organisations.findFirst`
|
|
12
|
+
* with a Prisma-style object `select` resolved intermittently/never against the
|
|
13
|
+
* generated ORPC, leaving the header partner blank (2026-06-12).
|
|
14
|
+
*/
|
|
15
|
+
export declare function applyPartnerBrand(pageData: Record<string, unknown>, partnerOrg: {
|
|
16
|
+
logo_url?: string | null;
|
|
17
|
+
brand_primary_color?: string | null;
|
|
18
|
+
} | undefined | null): void;
|
|
19
|
+
/**
|
|
20
|
+
* Auto-resolve the client's company logo from the `clientOrg` loader source
|
|
21
|
+
* (contact_id → company_id → crm_organisations.logo_url). Injects into the
|
|
22
|
+
* Hero block's clientLogo prop when it's empty — no manual logo URL needed
|
|
23
|
+
* per proposal when the contact's company profile has a logo.
|
|
24
|
+
*/
|
|
25
|
+
export declare function applyClientLogo(pageData: Record<string, unknown>, clientOrg: {
|
|
26
|
+
logo_url?: string | null;
|
|
27
|
+
name?: string | null;
|
|
28
|
+
} | undefined | null): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function resolvedToPageData(resolved: Record<string, unknown>, meta: Record<string, unknown>, request: Request, providers: string[] | undefined, regionSlots?: string[], themeOverride?: "light" | "dark"): Record<string, unknown>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system ui-service-boot
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Reads `page_route` registry rows for the current service slug and registers
|
|
7
|
+
* Hono routes that resolve data via `resource_loader` graph-based sources.
|
|
8
|
+
*
|
|
9
|
+
* Every page_route uses pattern `/:id` and every resource_loader uses a
|
|
10
|
+
* `sources[]` dependency graph. When header/footer sources are present in
|
|
11
|
+
* the resolved graph, the output includes a `regions` array for shell rendering.
|
|
12
|
+
* Otherwise it produces single-page puckData.
|
|
13
|
+
*/
|
|
14
|
+
import type { RenderModeLiteral } from "./page-route-shell-types.ts";
|
|
15
|
+
import type { Hono } from "hono";
|
|
16
|
+
import type { CreatePageHandler, RendererComponentEntry } from "./types.ts";
|
|
17
|
+
interface RegistryRouteArgs {
|
|
18
|
+
app: Hono;
|
|
19
|
+
serviceSlug: string;
|
|
20
|
+
components: Record<string, RendererComponentEntry>;
|
|
21
|
+
createPageHandler: CreatePageHandler;
|
|
22
|
+
authMode: string;
|
|
23
|
+
renderMode: RenderModeLiteral;
|
|
24
|
+
providers: string[];
|
|
25
|
+
}
|
|
26
|
+
export declare function registerRegistryPageRoute(args: RegistryRouteArgs): Promise<string[]>;
|
|
27
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @system server-handlers
|
|
3
|
+
* @status handwritten
|
|
4
|
+
* @edit edit directly
|
|
5
|
+
*
|
|
6
|
+
* Routes every service exposes regardless of registry config: /health
|
|
7
|
+
* (liveness probe), /favicon.svg (default brand mark), /api/assets/*
|
|
8
|
+
* (S3 asset proxy), and /assets/* (client bundle + stylesheet produced
|
|
9
|
+
* by build-client-assets.ts into dist/client/, served identically in
|
|
10
|
+
* dev and prod per scala-os/ui.md `bun-build-only`).
|
|
11
|
+
*/
|
|
12
|
+
import type { Hono } from "hono";
|
|
13
|
+
export declare function registerStaticAssets(app: Hono, serviceSlug: string, brandOrg?: string): Promise<void>;
|