/**
 * Shared list-API URL builder — the single un-replicable piece of the
 * chat entity-card fetch path.
 *
 * ## Why this exists
 *
 * A fetch-mode entity card (`dispatch.tsx` → `useChatCardItem`) expands a
 * compact `[card://<type>:<id>]` marker by fetching the type's public list
 * endpoint with an `?ids=` (or `?task_ids=`) filter and matching the row
 * back by id. The per-type URL SHAPE is non-obvious — `task_ids` for the
 * ClickUp-backed types, `pageSize` for blog, `&limit=N&filter=all` for the
 * programs trio, a distinct `/customer-interviews` path, etc. — and lives in
 * the hub's 12 RAG mapper closures (`lib/config/rag-mappers/*.ts`). An
 * embedder can't reverse-engineer those shapes, so a wrong/missing builder
 * resolves a null URL ⇒ `enabled:false` ⇒ the card never fetches and renders
 * nothing.
 *
 * This builder is the ONE source for those shapes. The hub's 12 mappers
 * delegate their `listApi` here (a byte-parity test guards the migration),
 * and embedders wire it once:
 *
 *   endpoints.buildListUrl = (type, ids) => buildListUrl(type, ids, '/content')
 *
 * `base=''` (default) yields the hub-relative `/api/...`; `base='/content'`
 * (or any reverse-proxy prefix) yields `/content/api/...`.
 *
 * Pure + server-safe (no React, no browser APIs) so the hub's server-side
 * mappers can import it from `@flamingo-stack/openframe-frontend-core/utils`.
 */
/** Resolve a ContentRef rail-vocab type to its canonical `documentType`
 *  (registry vocabulary) — `blog_post_existing` → `blog_post`, everything
 *  else passes through. Exported so consumers comparing rail group keys to
 *  registry entityTypes (e.g. the related-content rail's same-type-first
 *  ordering) share THIS alias map instead of re-declaring it. */
export declare function canonicalContentRefType(contentRefType: string): string;
/**
 * Build a list-API URL that returns full rows for the given ids, or `null`
 * when the type has no list endpoint (the caller skips fetching rather than
 * fabricating a URL).
 *
 *   buildListUrl('roadmap_item', ['a','b'])             → '/api/roadmap?task_ids=a,b'
 *   buildListUrl('blog_post_existing', ['a','b'])       → '/api/blog/posts?ids=a,b&pageSize=2'  (alias)
 *   buildListUrl('roadmap_item', ['a','b'], '/content') → '/content/api/roadmap?task_ids=a,b'
 *   buildListUrl('github_pr', ['a'])                    → null  (absent key)
 *
 * `marketing_campaign` (admin-only, non-RAG) is a LITERAL case, NOT a
 * `BUILDERS` entry — a static branch keeps CodeQL able to prove no
 * user-controlled dynamic dispatch reaches the admin endpoint; embedders
 * can't hit `/api/admin` through their proxy anyway.
 */
export declare function buildListUrl(contentRefType: string, ids: string[], base?: string): string | null;
//# sourceMappingURL=list-url.d.ts.map