/** * Static-asset mount for the SPA bundle. * * The SPA bundle is produced by `6.5.2-cadre-host-local-ui-spa` into * `/dist/ui/`. When that directory exists we serve files from it * with an `index.html` SPA fallback. When it's missing (running from source * before the SPA ticket lands) we serve a placeholder page that explains * how to install/build the SPA. * * Hand-rolled rather than pulling in `@fastify/static` — the surface area we * need is tiny and the dep would only matter under tests that don't exercise * static serving anyway. */ import type { FastifyInstance } from 'fastify'; /** * Default location of the SPA bundle when `cadre-host` runs from its * installed package. * - dist/server/static.js → ../ui → packages/cadre-host/dist/ui */ export declare function defaultStaticRoot(): string; export interface StaticMountOptions { /** Absolute path to the SPA build output (defaults to `defaultStaticRoot()`). */ rootDir?: string; } export declare function registerStaticMount(app: FastifyInstance, opts?: StaticMountOptions): void; /** * Resolve a request path to an absolute file path inside `rootDir`, or `null` * if it would escape the root. * * Exported for direct unit testing. The containment check uses `path.relative` * rather than a bare `startsWith` prefix test: the latter is the classic * prefix-bypass anti-pattern, accepting sibling directories whose name shares * `rootDir`'s basename as a prefix (e.g. `dist/ui-private` vs `dist/ui`). * `relative` respects the path-separator boundary on both POSIX and Windows, * and surfaces cross-drive escapes on Windows as an absolute result. */ export declare function resolveSafe(rootDir: string, urlPath: string): string | null;