/** * `substrat hostnames` — the CLI half of surface hostname binding (K-26 multi-surface; * control-plane.md §4.7). One scope can front several apps; the hostname decides which * surface the vertical serves (`readRoutedNode(...).surface`). The dashboard's Domains * tab is the interactive path; this is CI-and-support parity over the same tenant- * narrowed control-plane routes (a builder session reaches only its own tenant's rows). * * A PLATFORM hostname is minted from the install's own default label — * `crm.global.substrat.run` + surface `eka` → `crm-eka.global.substrat.run` — and is * live immediately (it rides the wildcard cert). A CUSTOM domain lands `pending` and * walks the §4.2 DNS-validation lifecycle. */ /** A DNS record the tenant must publish (contracts' dnsRecord). */ export interface DnsRecordRow { type: 'hostname' | 'txt'; name: string; value: string; status: string | null; } /** One binding row as the control plane returns it (contracts' HostnameBinding). */ export interface HostnameRow { hostname: string; tenantId: string; scopeId: string; verticalSlug: string | null; surface: string; status: string; statusNote: string | null; canonical: boolean; createdAt: string; customHostnameId: string | null; validationRecords: DnsRecordRow[]; } /** The tenant's bindings for one vertical — matched bare or `/`-prefixed. */ export declare function listVerticalHostnames(controlPlaneUrl: string, header: Record, tenantId: string, slug: string): Promise; /** * Bind a hostname to one surface of an install. The install is addressed by its * vertical slug; the scope is found through the bindings that already exist (every * install got a default hostname at provisioning) — several installs of the same * vertical need an explicit `--scope`. */ export declare function bindSurfaceHostname(opts: { controlPlaneUrl: string; header: Record; tenantId: string; slug: string; surface: string; /** A custom domain to bind; omitted ⇒ mint a platform hostname for the surface. */ domain?: string; /** Disambiguates when the tenant runs several installs of the vertical. */ scope?: string; }): Promise<{ hostname: string; status: string; canonical: boolean; validationRecords?: DnsRecordRow[]; }>; /** * Bind a custom domain to a scope **by id** — the scope-addressed complement to * `bindSurfaceHostname` (which resolves a scope through a vertical slug's existing * bindings). Addressing the scope directly is what lets a bare **preview** or long-lived * **test** scope carry a custom domain: it has no install lineage to resolve through, and * the whole point is a stable address like `crm-test.ahero.se` on a scope whose binding * moves. The bind path is scope-generic (nothing checks prod/channel); the router resolves * `hostname → scope` and serves whatever version the scope is bound to. * * `canonical` defaults false — additive, never silently demoting the URL the surface * already serves on (the `--` hostname a preview minted). Pass it to make the custom * domain the surface's primary (the generated-URL / email address). */ export declare function bindScopeHostname(opts: { controlPlaneUrl: string; header: Record; tenantId: string; scopeId: string; surface: string; domain: string; canonical?: boolean; }): Promise; /** * Re-poll a custom hostname's Cloudflare-for-SaaS issuance ("check again") — CI/support * parity with the dashboard's button. Returns the row with its refreshed status + * records. Tenant-narrowed server-side: a foreign hostname is a 404. */ export declare function verifyHostname(controlPlaneUrl: string, header: Record, hostname: string): Promise; /** Unbind one hostname. Tenant-narrowed server-side: a foreign hostname is a 404. */ export declare function unbindHostname(controlPlaneUrl: string, header: Record, hostname: string): Promise; /** * Render the DNS records a tenant must publish for a custom domain to validate — * printed after a custom `bind` so the operator can copy them into their DNS provider. * Empty (a platform mint, or issuance not yet run) prints nothing. */ export declare function formatDnsRecords(records: DnsRecordRow[]): string; /** Render bindings as the aligned table `substrat hostnames ` prints. */ export declare function formatHostnames(rows: HostnameRow[]): string; //# sourceMappingURL=hostnames.d.ts.map