Server runtime + native renderer (napi-rs) for aihu SSR.
_buildStateScriptfunction _buildStateScript(root: unknown, opts: SsrOptions | undefined): stringBuild the `__aihu_state__` script for one finished render, or `''` when there is no state to ship (so a state-free page's HTML is byte-identical to today and the client's no-script hydration path is exercised).
_getNativeStateKindfunction _getNativeStateKind(): NativeState['kind']Returns the resolved native loader state kind.
_resetNativeStatefunction _resetNativeState(): voidReset the cached native state.
_setContextFnsfunction _setContextFns(set: (map: Map<symbol, unknown>) => void, clear: () => void): voidInject context activation/deactivation functions from
_setStoreSerializerfunction _setStoreSerializer(fn: (() => Record<string, unknown>) | undefined): voidInject the store snapshot function from
attachSsrStringfunction attachSsrString<T extends () => unknown>( component: T, ssrString: unknown, props: unknown, ): TCarry a compiled string renderer across a props-binding wrapper.
badRequestfunction badRequest(message?: string): ResponsecheckEntitlementfunction checkEntitlement( registry: EntitlementsHandle, principal: EntitledPrincipal, scope: string, memo?: EntitlementMemo, url?: URL, ): Promise<EntitlementVerdict>THE single live check, both axes (§4.6) — a named alias over the registry's `check` so call sites read as the spec does.
composeMiddlewarefunction composeMiddleware(middlewares: ReadonlyArray<Middleware>): MiddlewareCompose middleware in array order (index 0 = outermost).
createGovernedRegistryfunction createGovernedRegistry(): GovernedRegistryCreate the governed registry (§2.2).
createRequestRouterfunction createRequestRouter( manifest: RouteManifest, options?: RouterOptions, ): (req: Request) => Promise<Response>Create a fetch-API compatible request handler.
defineAihuConfigfunction defineAihuConfig(config: AihuConfig): AihuConfigDefine the aihu application configuration.
defineApiRoutefunction defineApiRoute(method: HttpMethod, pattern: string, handler: ApiHandler): RouteThe router enforces the method: a request to the matching pattern with a non-matching method receives `405 Method Not Allowed` with an `Allow` header listing all registered methods for that pattern.
defineGovernedFetchfunction defineGovernedFetch<T>(p: DataProvider<T>): DefinedGovernedFetch<T>The escape hatch (§4.7): hand-written data logic on a governed route.
defineLoaderfunction defineLoader<T>(fn: LoaderFn<T>): DefinedLoader<T>Loaders run before the route handler.
defineMiddlewarefunction defineMiddleware(handler: Middleware): MiddlewaredefineRoutefunction defineRoute<T = never>( pattern: string, handlerOrSubroutes: | RouteHandler | ((req: Request, ctx: LoadedRouteContext<T>) => Response | Promise<Response>) | ReadonlyArray<SubrouteTuple>, options?: RouteOptions<T>, ): Route | Route[]defineRoutesfunction defineRoutes(inputs: ReadonlyArray<RouteInput>): Route[]Register multiple routes in a single call.
defineStreamRoutefunction defineStreamRoute(handler: StreamRouteHandler): RouteDefine a route that streams text/plain chunks to the client.
deriveReadPolicyfunction deriveReadPolicy(read: unknown): ReadDerivationDerive every compliance-tier output signal from one `read` value.
extractReadValuefunction extractReadValue(extract: unknown): unknownPull the `read` member off a compiled `extract` object without trusting its shape.
governedHttpStatusfunction governedHttpStatus<T>(emission: GovernedEmission<T>): 200 | 401 | 403 | 500 | 503The HTTP status a governed emission serves with (read axis, §4.3 ladder).
isCallAdvertisedfunction isCallAdvertised(extract: unknown): booleanIs this surface's agent surface advertisable at all — i.e.
isGovernedFetchfunction isGovernedFetch(x: unknown): x is DefinedGovernedFetch<unknown>Is this module export the branded governed-fetch escape hatch?
jsonfunction json(data: unknown, status?: number): ResponsematerializeGeneratedLoaderfunction materializeGeneratedLoader<T>( registry: GovernedRegistry, decl: GovernedRouteDataDecl, readValue: unknown, override?: DataProvider<T>, ): GeneratedLoader<T>Materialize the generated loader for one governed route (§3, §4.7): `data:` present and no sibling loader → registry provider; the `defineGovernedFetch` escape hatch supplies `override` — replacing step 4 ONLY.
methodNotAllowedfunction methodNotAllowed(allowed: ReadonlyArray<HttpMethod>): ResponsenormalizeGovernedDatafunction normalizeGovernedData(data: unknown): GovernedRouteDataDecl | 'malformed' | nullNormalize a `.route.json` `data` field fail-closed: `null` when absent, `'malformed'` when present but unparseable (a corrupted declaration is refused at boot, never rounded to ungoverned — the same posture as `deriveReadPolicy`'s `'malformed'`).
notFoundfunction notFound(): ResponsepassesRouteReadfunction passesRouteRead(principal: Principal, readValue: unknown): booleanRoute-level read decision for the T4 fallback path (a hard-`read` route with a plain `defineLoader` and no `data:`): may this principal receive the route's loader output at all?
renderToStreamfunction renderToStream( component: ComponentDescription, opts?: StreamOptions, ): ReadableStream<string>renderToStringasync function renderToString( component: ComponentDescription, opts?: SsrOptions, ): Promise<string>Render a component to an HTML string.
renderToStringNativeasync function renderToStringNative( component: ComponentDescription, opts?: SsrOptions, ): Promise<string>Render via the native (Rust) renderer when available, falling back to the TS implementation for edge / unsupported platforms.
resolveNativeStatefunction resolveNativeState(): NativeStateResolve (and cache) the native loader state.
resolveRequestPrincipalasync function resolveRequestPrincipal( req: Request, auth?: GovernedRequestAuth, ): Promise<Principal>Step 1 for the SSR/E3 transports: settle THE principal for one request from its credential material (Authorization bearer, User-Agent, host-verified session).
routeHeadToSsrHeadfunction routeHeadToSsrHead( head: RouteHead | undefined, opts: RouteHeadLowerOptions = {}, ): HeadConfigLower a route's head metadata into a renderable `HeadConfig`, merged with an optional global head.
serverErrorfunction serverError(err?: unknown): ResponseSECURITY: In production (`__DEV__ === false`), the error message MUST NOT appear in the response body.
throwIfNativeFailedfunction throwIfNativeFailed(state: NativeState): voidConvert a `native-failed-loud` state into the formatted AihuNativeError and throw it.
validateGovernedBootfunction validateGovernedBoot( registry: GovernedRegistry | undefined, routes: readonly GovernedRouteCensusEntry[], opts?: { strict?: boolean }, ): voidValidate the registry against the compiled route census at `createServerRouter` construction (§2.3).
DEFAULT_ENTITLEMENT_TIMEOUT_MSconst DEFAULT_ENTITLEMENT_TIMEOUT_MSDefault live-resolver deadline (ms) — ratified Q1 (§7).
GOVERNED_RETRY_AFTER_SECONDSconst GOVERNED_RETRY_AFTER_SECONDS`Retry-After` seconds on `'unavailable'` responses (503).
AihuNativeErrorclass AihuNativeError extends ErrorAgentReadinessConfiginterface AgentReadinessConfig {
// ── Identity ─────────────────────────────────────────────────────────
readonly name: string
readonly version?: string
readonly summary?: string
// ── MCP endpoint ─────────────────────────────────────────────────────
/** When present: MCP card generated at `/.well-known/mcp/server-card.json`. */
readonly endpoint?: string
// ── Auth (opt-in, default: no-auth) ──────────────────────────────────
readonly auth?: {
readonly type: 'oauth2'
readonly authorizationUrl: string
readonly tokenUrl: string
readonly scopes?: ReadonlyArray<string>
readonly resourceUri?: string
}
// ── llms.txt ─────────────────────────────────────────────────────────
readonly llmsSections?: ReadonlyArray<{
readonly title: string
readonly links: ReadonlyArray<{
readonly title: string
readonly url: string
readonly description?: string
}>
}>
readonly llmsOptional?: ReadonlyArray<{
readonly title: string
readonly url: string
readonly description?: string
}>
// ── robots.txt ───────────────────────────────────────────────────────
/**
* AI-agent crawl policy. Default: `'allow-agents'` (tiered, since
* @aihu-plugin/agent-readiness 2.1.0 / #430) — user-delegated fetchers
* (ChatGPT-User, OAI-SearchBot, DuckAssistBot, Applebot) are allowed;
* training/scraping crawlers (GPTBot, CCBot, Bytespider, …) are disallowed
* and must be opted in explicitly via `'allow-all'` or rules.
* Any other string value throws at robots.txt generation time.
*/
readonly aiAgents?:
| 'allow-agents'
| 'allow-all'
| 'deny-all'
| ReadonlyArray<{
readonly userAgent: string | ReadonlyArray<string>
readonly allow?: ReadonlyArray<string>
readonly disallow?: ReadonlyArray<string>
readonly crawlDelay?: number
}>
readonly standardBots?: ReadonlyArray<{
readonly userAgent: string | ReadonlyArray<string>
readonly allow?: ReadonlyArray<string>
readonly disallow?: ReadonlyArray<string>
readonly crawlDelay?: number
}>
/**
* GX Phase 3 (#437-GX): the COMPILED route table — structurally,
* `@aihu/router`'s `RouteDefinition[]` (e.g. `import routes from
* 'virtual:aihu-routes'`, the same array handed to `createServerRouter`).
* Each route's compiled `extract` declaration derives its robots.txt
* per-path directives and its presence in the agent-facing discovery
* documents (llms.txt). This is a conduit for compiled output, never a
* place to hand-author policy — the `.aihu` `extract:` declaration is the
* one source (spec §8). Omitted → global-policy-only robots.txt and no
* derived route listing, byte-identical to pre-GX output.
*/
readonly routes?: ReadonlyArray<{
readonly pattern: string
readonly extract?: { readonly read?: unknown; readonly call?: unknown }
}>
readonly sitemap?: string
/**
* robots.txt always ends with a `User-agent: * / Allow: /` block for
* predictable output. Set `false` to suppress it. (It is also skipped
* automatically when one of your own rules already targets `*`.)
*/
readonly wildcard?: boolean
// ── Skills ───────────────────────────────────────────────────────────
/** Manually declared MCP skills, merged with auto-derived from AgentMetadata.actions. */
readonly skills?: ReadonlyArray<{
readonly id: string
readonly name: string
readonly description: string
readonly inputSchema?: Record<string, unknown>
}>
// ── Site identity ─────────────────────────────────────────────────────
/** Canonical base URL (e.g. 'https://aihu.dev'). Used by A2A card, MCP discovery, and JSON-LD. */
readonly siteUrl?: string
// ── A2A Agent Card ────────────────────────────────────────────────────
/**
* Generate /.well-known/agent.json (Google A2A protocol).
* `true` derives name/description/url/version from top-level config fields.
* Object form overrides streaming/pushNotifications capabilities.
*/
readonly a2aCard?:
| true
| {
readonly capabilities?: {
readonly streaming?: boolean
readonly pushNotifications?: boolean
}
readonly skills?: ReadonlyArray<{
readonly id: string
readonly name: string
readonly description?: string
}>
}
// ── MCP Discovery ─────────────────────────────────────────────────────
/**
* Generate /.well-known/mcp.json.
* When true and `endpoint` is set, points to the endpoint URL.
* When true and `endpoint` is absent, falls back to /.well-known/mcp/server-card.json.
*/
readonly mcpDiscovery?: boolean
// ── Sitemap pages ─────────────────────────────────────────────────────
/**
* Pages to include in /sitemap.xml.
* When provided, the Vite plugin emits sitemap.xml at build time.
* The existing `sitemap` field (URL string) is used for robots.txt Sitemap: reference.
*/
readonly sitemapPages?: ReadonlyArray<{
readonly url: string
readonly lastmod?: string
readonly changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'
readonly priority?: number
}>
// ── JSON-LD structured data ───────────────────────────────────────────
/**
* JSON-LD objects injected into <head> via <script type="application/ld+json">.
* If absent but `siteUrl` is set, a SoftwareApplication schema is auto-generated.
* Set `false` to disable auto-generation.
*/
readonly jsonLd?: ReadonlyArray<Record<string, unknown>> | false
}Canonical `AgentReadinessConfig` — the type of `AihuConfig.agent`.
AihuConfiginterface AihuConfig {
readonly server?: ServerConfig
readonly agent?: import('./agent-readiness-config.ts').AgentReadinessConfig
readonly routes?: RouteConfig
/**
* Plugins registered in this aihu project.
*
* Per Plugin Contract Spec §7.1-§7.2: plugins MUST be explicitly imported
* and registered here. Auto-discovery is forbidden.
*
* v0.2.1: type contract + registration plumbing only. The compiler
* dispatcher is a no-op until v0.3+ wires block parsers, macro lowerings,
* and hook execution. Admitting the field now lets plugin authors begin
* shaping `definePlugin({...})` calls against a stable type surface.
*/
readonly plugins?: ReadonlyArray<Plugin>
/**
* v0.6.5: Build target configuration.
* Controls whether aihu emits a client bundle, server bundle, or both.
* This field is read by the compiler/build tooling; it has no runtime effect.
*/
readonly build?: BuildConfig
/**
* Runtime rendering strategy. Defaults to SSR with hydration enabled —
* the agent-ready posture that gives LLMs, crawlers, and the aihu MCP
* server access to content without JavaScript execution.
*/
readonly rendering?: RenderingConfig
/**
* v1: `@aihu/ui` styled-recipe registry configuration.
* BUILD-TIME ONLY — consumed by the `aihu add` CLI and the css-engine
* scanner; it has no runtime/edge effect (matching the `build`/`plugins`
* field posture). Defaults are resolved by the CLI at read-time, so omitting
* `ui` entirely is valid.
*/
readonly ui?: UiConfig
}BuildConfiginterface BuildConfig {
/** Build target. Default: 'universal' */
target?: BuildTarget
}CorsConfiginterface CorsConfig {
readonly origin: string | ReadonlyArray<string> | '*'
readonly methods?: ReadonlyArray<import('./types.ts').HttpMethod>
readonly headers?: ReadonlyArray<string>
readonly credentials?: boolean
readonly maxAge?: number
}DataProviderinterface DataProvider<T> {
/** The one data-source access. Runs ONLY after grant. Server-only, never bundled. */
fetch(ctx: GovernedFetchContext): Promise<T>
/** Optional: data for the declared `preview:` fields of the withheld state. */
preview?(ctx: GovernedFetchContext): Promise<Partial<T>>
}WHERE a governed type's data comes from.
DataSourceinterface DataSource<T> {
/** Current resolution state. */
readonly status: 'pending' | 'ready' | 'error'
/** The resolved value. Defined only when status === 'ready'. */
readonly value?: T
/** The rejection reason. Defined only when status === 'error'. */
readonly error?: unknown
/**
* Register a callback to be invoked exactly once when status transitions
* to 'ready' or 'error'. Returns a dispose function that cancels the
* registration if called before the transition fires.
*/
onReady(cb: () => void): () => void
}Describes an async data boundary that renderToStream can suspend on.
DefinedGovernedFetchinterface DefinedGovernedFetch<T> extends DataProvider<T> {
readonly _brand: 'DefinedGovernedFetch'
}The branded route-local provider — replaces step 4 ONLY, never the gate.
DefinedLoaderinterface DefinedLoader<T> {
readonly _brand: 'DefinedLoader'
/** @internal */
readonly fn: LoaderFn<T>
}EntitlementContextinterface EntitlementContext {
/** Static meet already passed — never anonymous (§4.2). */
readonly principal: EntitledPrincipal
readonly scope: string
/** Never the raw credential. */
readonly request: { readonly url: URL }
/**
* Aborted when the registered `timeoutMs` (default 2000) elapses (§4.3).
* Deadline exhaustion is indistinguishable from a throw: `'unavailable'`.
*/
readonly signal: AbortSignal
}The live per-request entitlement check's context (§3.1, §4.3).
EntitlementRegistrationinterface EntitlementRegistration {
/** The LIVE per-request check. `true` = entitled now. Throw/timeout ⇒ withhold. */
resolve(ctx: EntitlementContext): Promise<boolean>
/** Resolver deadline in ms; default {@link DEFAULT_ENTITLEMENT_TIMEOUT_MS}. */
timeoutMs?: number
/** Positive-verdict TTL cache, per (scope, principal.sub). Negatives are NEVER cached (Q2). */
cache?: { ttlMs: number }
}Whether a principal may have the scope's authority RIGHT NOW.
ExtractDeclarationLikeinterface ExtractDeclarationLike {
readonly read?: unknown
readonly call?: unknown
}A compiled `extract` declaration as it appears on `.route.json` / agent-meta artifacts.
GovernedFetchContextinterface GovernedFetchContext {
readonly params: Record<string, string>
readonly url: URL
/**
* The SETTLED principal (§4.7): a hand-written fetch may further narrow on
* it, never widen. On the granted path this is always a verified principal;
* on the `preview` path it may be anonymous.
*/
readonly principal: Principal
}The context a provider's `fetch`/`preview` receives.
GovernedLoadContextinterface GovernedLoadContext {
readonly params: Record<string, string>
readonly url: URL
/** Settled by `resolvePrincipal` in `handle` — step 1, once per request. */
readonly principal: Principal
/** The per-request memo (§4.4 layer 1). */
readonly entitlements: EntitlementMemo
}The context the generated loader runs in (principal settled by `handle`).
GovernedRegistryinterface GovernedRegistry extends EntitlementsHandle {
/** Register the data-source provider for a governed resource type. */
provider<T>(type: string, p: DataProvider<T>): GovernedRegistry
/**
* Register the live entitlement resolver for a scope — or declare the scope
* explicitly static with `'token-only'` (required in strict mode, §2.3).
* Registering a resolver makes EVERY use of the scope — both axes — live.
*/
entitlement(scope: string, r: EntitlementRegistration | 'token-only'): GovernedRegistry
/**
* Revocation composition hook (§4.4.3): purge every cached entitlement
* entry for `sub`, so "revoke this delegation" also drops cached
* entitlement warmth immediately (in-process; a shared cache store is an
* operator upgrade, not a framework default).
*/
onRevoke(sub: string): void
/** @internal Provider lookup for the generated loader / boot validation. */
providerFor(type: string): DataProvider<unknown> | undefined
/** @internal How a scope is registered — drives strict-mode boot validation. */
entitlementKind(scope: string): 'live' | 'token-only' | 'unregistered'
/** @internal Telemetry counters (G7d/G7e assertions). */
stats(): GovernedRegistryStats
}The single server-init registration surface (§4.1): a builder passed to `createServerRouter(routes, { governed })` and (same instance) to `AgentServiceOptions.entitlements`.
GovernedRegistryStatsinterface GovernedRegistryStats {
/** Live resolver invocations (post-memo, post-cache). */
readonly resolves: number
/** Cross-request TTL cache consults. */
readonly cacheReads: number
/** Cross-request TTL cache hits (positive, unexpired). */
readonly cacheHits: number
}GovernedRequestAuthinterface GovernedRequestAuth extends PrincipalGateDeps {
/**
* Resolve a HOST-VERIFIED session from the request (e.g. `getAuthState`
* over the cookie). Same injection posture as `PrincipalSource.session`:
* never pass unverified cookie contents.
*/
readonly resolveSession?: (
req: Request,
) =>
| { readonly sub: string; readonly scopes: readonly string[] }
| null
| undefined
| Promise<{ readonly sub: string; readonly scopes: readonly string[] } | null | undefined>
}The host-injected auth material for principal resolution on the SSR path.
GovernedRouteCensusEntryinterface GovernedRouteCensusEntry {
readonly pattern: string
readonly data?: unknown
readonly extract?: { readonly read?: unknown; readonly call?: unknown } | undefined
}One row of the compiled route census the boot check reads.
GovernedRouteDataDeclinterface GovernedRouteDataDecl {
/** Names the governed resource type — the provider key. */
readonly type: string
/** Fields renderable in the locked state (declared public-tier, §4.5). */
readonly preview?: readonly string[]
}The normalized `data:` route declaration.
HeadConfiginterface HeadConfig {
readonly title?: string
readonly meta?: ReadonlyArray<MetaTag>
readonly links?: ReadonlyArray<LinkTag>
readonly lang?: string
/**
* Inline `<script>` elements (e.g. JSON-LD structured data). Backward
* compatible: omitted means no script tags are emitted, matching prior
* `buildHead` behavior.
*/
readonly scripts?: ReadonlyArray<ScriptTag>
}LinkTaginterface LinkTag {
readonly rel: string
readonly href: string
readonly [attr: string]: string | undefined
}LoadedRouteContextinterface LoadedRouteContext<T> extends RouteContext {
readonly loaderData: LoaderResult<T>
}LoaderResultinterface LoaderResult<T> {
readonly data: T
readonly error?: Error
readonly status: number
}MetaTaginterface MetaTag {
readonly name?: string
readonly property?: string
readonly content: string
readonly [attr: string]: string | undefined
}NativeAddoninterface NativeAddon {
renderTree(treeJson: string, hydratable: boolean): string
renderDocument(treeJson: string, headJson: string, hydratable: boolean): string
}PlatformDescriptorinterface PlatformDescriptor {
readonly platformId: string
readonly packageName: string
readonly nodeFile: string
}ReadDerivationinterface ReadDerivation {
readonly value: NormalizedReadValue
/**
* `'compliance'` for the anonymous values (`'all'`/`'agents'`/`'search'`/
* `'none'`), `'hard'` for the verified values — the spec §2.1 tier break.
* NOTE: the tier names what full enforcement WOULD be; this module only
* emits the compliance-tier signals either way (see module docblock).
*/
readonly tier: 'compliance' | 'hard'
/**
* Which declared crawler tiers the value admits. Meaningful for compliance
* values; all-false for hard values (no anonymous crawl access at all).
*/
readonly crawl: CrawlerTierAccess
/**
* Should robots.txt carry per-path directives for this surface?
* Compliance values: yes (`read:'none'` routes are served to humans, so
* their existence is not a secret — they DO get Disallow lines, spec §8).
* Hard values: NO — the path is simply absent from robots.txt. A Disallow
* line naming a governed path would advertise its existence (spec §8
* existence-advertising; the A-5 self-contradiction).
*/
readonly advertiseInRobots: boolean
/**
* Should the served response carry a noindex signal (`X-Robots-Tag:
* noindex`)? True for `read:'none'` and every hard/malformed value.
*/
readonly noindex: boolean
/**
* Listed in agent-facing discovery (llms.txt, MCP server-card tools)?
* Requires user-fetcher access: a surface that refuses user-directed AI
* fetchers must not be advertised to them.
*/
readonly agentDiscovery: boolean
/** Listed in search-facing surfaces (sitemap)? Requires searcher access. */
readonly searchDiscovery: boolean
}Everything the derived surfaces need to know about one `read` value.
RenderingConfiginterface RenderingConfig {
/**
* Default rendering mode for all routes.
* Default: 'ssr' — server-renders every page with hydration markers enabled.
*/
readonly mode?: RenderingMode
/**
* Emit `data-aihu-path` hydration markers on SSR output by default.
* Only applies when mode is 'ssr' or 'hybrid'.
* Default: true — enabling client-side takeover after first paint.
*/
readonly hydratable?: boolean
}Routeinterface Route {
readonly pattern: string
readonly handler: RouteHandler
readonly middleware?: ReadonlyArray<Middleware>
}RouteConfiginterface RouteConfig {
/** Default: `./routes.gen.ts`. */
readonly manifestPath?: string
}RouteContextinterface RouteContext {
readonly params: Record<string, string>
readonly url: URL
readonly env?: unknown
}RouteHeadinterface RouteHead {
readonly title?: string
readonly description?: string
readonly canonical?: string
readonly og?: {
readonly title?: string
readonly description?: string
readonly image?: string
readonly type?: string
readonly url?: string
}
readonly twitter?: {
readonly card?: string
readonly title?: string
readonly description?: string
readonly image?: string
readonly site?: string
}
/**
* JSON-LD structured data. The compiler captures the `@route` `jsonld` block
* VERBATIM as a raw JSON string, so this is typically a `string`. A
* pre-parsed object/value is also accepted and will be `JSON.stringify`'d.
*/
readonly jsonld?: unknown
}Per-route head metadata, as emitted by the compiler into `.route.json` and (post-B2) re-exported from `@aihu/router`.
RouteHeadLowerOptionsinterface RouteHeadLowerOptions {
/**
* Absolute site base URL (e.g. `https://example.com`) used to resolve
* relative `canonical` / `og.image` / `og.url` values into absolute URLs.
* Supplied by the wiring Builder (from `AihuConfig.site.url`). When absent,
* relative values are emitted as-is (documented, non-throwing).
*/
readonly siteUrl?: string
/**
* Global head defaults (typically from `app.head`). Route fields override
* global per field; `meta`/`links`/`scripts` arrays are key-merged with the
* route winning on conflicts.
*/
readonly globalHead?: HeadConfig
}RouteInputinterface RouteInput {
readonly pattern: string
readonly handler: RouteHandler
readonly options?: RouteOptions<never>
}A route config object for use with `defineRoutes`.
RouteManifestinterface RouteManifest {
readonly routes: ReadonlyArray<Route | ReadonlyArray<Route>>
readonly layouts?: Readonly<Record<string, ReadonlyArray<string>>>
}Route manifest produced by the file-based routing Vite plugin at build time.
RouteOptionsinterface RouteOptions<T = never> {
readonly loader?: DefinedLoader<T>
readonly middleware?: ReadonlyArray<Middleware>
}RouterOptionsinterface RouterOptions {
readonly middleware?: ReadonlyArray<Middleware>
readonly notFound?: RouteHandler
readonly env?: unknown
}ScriptTaginterface ScriptTag {
readonly type: string
readonly content: string
}A `<script>` element in the document head.
ServerConfiginterface ServerConfig {
readonly basePath?: string
readonly cors?: CorsConfig
/** Default: 1_048_576 (1 MB). */
readonly maxBodySize?: number
}SsrOptionsinterface SsrOptions {
/**
* When provided: output is a full HTML document.
* When absent: output is the component's inner HTML fragment only.
*/
readonly head?: HeadConfig
/**
* When true: rendered HTML includes hydration markers as data attributes.
* Default: false.
*/
readonly hydratable?: boolean
/**
* Injected signal serializer (an arbor `MountScope.serialize`-shaped
* snapshot: path key → value). When provided it REPLACES the default
* post-render signal collection and its result rides the `signals` key of
* the `__aihu_state__` envelope. When it throws, the error is swallowed
* and the `signals` channel is omitted.
*/
readonly serializer?: () => Record<string, unknown>
/**
* Optional per-render context setup hook. When provided alongside a prior call
* to _setContextFns, ssr.ts will:
* 1. Call contextSetup(activateFn, deactivateFn) so the caller can do
* per-request setup (e.g. pre-populate the context map).
* 2. Activate a fresh context Map before the tree walk.
* 3. Clear it in a finally block after the walk.
*
* ssr.ts never imports @aihu/context — the hard boundary is preserved.
* The activate/deactivate functions are wired via _setContextFns at startup.
*
* Minimal usage:
* import { setSsrContextMap, clearSsrContextMap } from '@aihu/context/ssr'
* import { _setContextFns, renderToString } from '@aihu/server'
* _setContextFns(setSsrContextMap, clearSsrContextMap)
* await renderToString(component, { contextSetup: () => {} })
*/
readonly contextSetup?: (
activate: (map: Map<symbol, unknown>) => void,
deactivate: () => void,
) => void
/**
* GX Phase 4 (#466) — the P5/I2s guard: mark this render as a GOVERNED
* tree. Governed trees are never streamed — encountering a `pending`
* `dataSource` boundary in a governed render is refused fail-closed
* (`GOVERNED_UNGATED` posture, 40-spec §10) rather than suspended, because
* a streamed governed subtree would be an emission path the generated
* loader never gated. Set by the router's governed `handle` path.
*/
readonly governed?: boolean
}StreamOptionsinterface StreamOptions extends SsrOptions {}Options for renderToStream.
UiConfiginterface UiConfig {
/** Source registry to pull recipes from. v1: the '@aihu/ui' package specifier. Default: '@aihu/ui'. */
readonly registry?: string
/** Directory `aihu add` copies recipe sources into. Default: './src/components/ui'. */
readonly target?: string
/** Active style pack name. Default: 'aihu-default'. */
readonly style?: string
/** Custom-element tag prefix for copied recipes. Default: 'aihu'. */
readonly prefix?: string
/** RESERVED for v2 multi-registry support — schema slot only, unimplemented. */
readonly registries?: Readonly<Record<string, string>>
}Configuration for the `@aihu/ui` styled-recipe registry, consumed by the `aihu add` / `aihu list` CLI subcommands and the css-engine scanner.
ApiHandlertype ApiHandler = (
req: Request,
ctx: import('./types.ts').RouteContext,
) => Response | Promise<Response>BuildTargettype BuildTarget = 'client' | 'server' | 'universal'Build target for the aihu application.
ComponentDescriptiontype ComponentDescription = (() => unknown) | { toHtml(): string }Accepts: 1.
CrawlerTiertype CrawlerTier = 'searcher' | 'user-fetcher' | 'training-crawler'The three declared-crawler tiers of the unified bot registry.
CrawlerTierAccesstype CrawlerTierAccess = Readonly<Record<CrawlerTier, boolean>>Per-tier crawl access derived from a `read` value.
Entitledtype Entitled<T> = T & { readonly $gx: { readonly entitled: true } }The granted shape: the declared type plus the reserved `$gx` discriminant.
EntitledPrincipaltype EntitledPrincipalEntitlementMemotype EntitlementMemoEntitlementsHandletype EntitlementsHandleEntitlementVerdicttype EntitlementVerdictGeneratedLoadertype GeneratedLoader<T> = (ctx: GovernedLoadContext) => Promise<GovernedEmission<T>>The generated loader — what the framework materializes per governed route.
GovernedEmissiontype GovernedEmission<T> =
| { readonly kind: 'granted'; readonly data: Entitled<T> }
| {
readonly kind: 'withheld'
readonly data: Withheld<T>
readonly decision: EmissionDecision
}
/** Provider failed AFTER grant (§4.3): an error state, never a locked state. */
| { readonly kind: 'error'; readonly status: 500 }What the generated loader emits (§3.1).
HttpMethodtype HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'LoaderFntype LoaderFn<T> = (ctx: RouteContext) => Promise<T>Middlewaretype Middleware = (req: Request, next: Next) => Response | Promise<Response>NativeStatetype NativeState =
| { kind: 'native-loaded'; addon: NativeAddon; descriptor: PlatformDescriptor }
| { kind: 'edge-skipped' }
| { kind: 'native-failed-loud'; descriptor: PlatformDescriptor; error: Error }
| { kind: 'unsupported-platform' }Nexttype Next = () => Promise<Response>NormalizedReadValuetype NormalizedReadValue =
| 'all'
| 'agents'
| 'search'
| 'none'
| 'verified'
| 'human'
| { readonly scope: string }
| 'malformed'The normalized `read` value.
Principaltype PrincipalPrincipalGateDepstype PrincipalGateDepsPrincipalSourcetype PrincipalSourceRenderingModetype RenderingMode = 'ssr' | 'spa' | 'hybrid'Runtime rendering strategy for the application.
RouteHandlertype RouteHandler = (req: Request, ctx: RouteContext) => Response | Promise<Response>StreamRouteHandlertype StreamRouteHandler = (req: Request) => Promise<ReadableStream<string>>SubrouteTupletype SubrouteTuple =
| readonly [string, RouteHandler]
| readonly [string, RouteHandler, RouteOptions<never>]A subroute tuple for use with the prefix-group overload of `defineRoute`.
Withheldtype Withheld<T> = {
readonly $gx: {
readonly entitled: false
readonly reason: WithheldReason
}
readonly preview?: Partial<T>
}The withheld shape: NO field of `T` beyond the declared `preview:` subset.
WithheldReasontype WithheldReason = 'auth' | 'scope' | 'entitlement' | 'unavailable'Why a withheld response is withheld — the template's "sign in" vs "upgrade" vs "try later".