/** * Registrable domains the vendor controls. A URL on one of these fails both * checks. Adding a new vendor domain to the codebase without adding it here * does NOT make it invisible: check 1 is an allowlist, so an unlisted domain * fails as "unapproved" even if nobody has classified it as ours. */ export declare const VENDOR_CONTROLLED_DOMAINS: readonly string[]; /** * POLICY — third-party endpoint defaults vs vendor endpoint defaults. * * R1 bans defaulting to hosts *we operate*. It does not ban a bring-your-own-key * skill from naming the public API of the provider whose key the user supplies: * `api.openai.com` in a skill pointed at the user's own OpenAI account is the * provider's published address, not a service we run, and there is no other * value it could sensibly take. That is legitimate under R2's "third-party * provider the user configures directly (BYO key — documented, never proxied)". * * So the distinction is explicit rather than accidental: * * - a default endpoint on a host WE operate → forbidden, always; * - a default endpoint on an approved third-party host → allowed; * - a default endpoint on any other host → forbidden until * reviewed and listed here with a reason. * * Every entry is a registrable domain plus its justification. This list doubles * as the inventory of every host the published code is able to name. */ export declare const APPROVED_CODE_HOSTS: readonly { domain: string; reason: string; }[]; /** * The public fleet gateway's host. * * Every Hasna CLI reaches its service through one gateway origin, path-prefixed * by app, and since the credential-ladder ruling of 2026-09-04 (hasna/apps#1720, * #1668) that address is the DEFAULT authority in the shared @hasna/contracts * client — so the string ships inside the bundle, on a domain this policy calls * vendor-controlled. It is listed in VENDOR_HOST_URL_EXCEPTIONS below. * * R1 IS NOT WEAKENED BY THIS, because R1 was never about the hostname. It says * an UNCONFIGURED install must not produce a URL, and that still holds exactly: * the shared resolver composes the gateway only AFTER a credential has resolved * (an argument, an env pointer, the macOS Keychain, the credentials file, or * the API-key variable). With no credential there is no URL — which is what * `unconfigured-client-boundary.test.ts` asserts, against the resolvers rather * than against a hostname, so that test needed no weakening either. * * The exception is scoped to exact strings on this one host. Every other * endpoint on a vendor domain still fails, including other paths on this one. * * Typed as `string` rather than left to inference on purpose: a literal type * would print the host into the emitted `.d.ts`, which ships, and the packed * vendor-domain scan reads shipped bytes without caring that they are types. */ export declare const FLEET_GATEWAY_HOST: string; /** * Exact URLs that may appear despite being on a vendor domain. Matched on the * full URL, never on the domain, so a real endpoint on the same domain still * fails. Keep minimal and justified. * * An entry whose path is empty is allowed ONLY for {@link FLEET_GATEWAY_HOST}: * the shared client holds the gateway ORIGIN as a constant and appends the app * slug at runtime, so the origin and its one-slash folded form are the literals * that actually appear in the bundles. Every other vendor host must name an * exact endpoint, so a bare vendor origin can never be excepted. */ export declare const VENDOR_HOST_URL_EXCEPTIONS: readonly { url: string; reason: string; }[]; /** * The product default: the one vendor URL an UNCONFIGURED install may name. * * Owner rulings 2026-09-23 (Todos PLA8-00366) made the product the default place * to SIGN IN, superseding R1 for that one path: with no URL and no credential, * `skills login` targets this origin. Every data surface still fails closed with * no URL at all, and a credential that already resolves keeps its own instance * (see unconfigured-client-boundary.test.ts and skills-md-default.test.ts). * * Unlike {@link VENDOR_HOST_URL_EXCEPTIONS}, this exception is scoped to FILES as * well as to the exact URL. The origin is declared once, in `src/lib/product-default.ts`; * it may appear in the two bundles built from the CLI and MCP entry points that * import it, and in the README that documents it. The same URL anywhere else — * a server default, a skill, a split or folded literal — is still a finding, so * a second copy cannot quietly become another default. The URL is not repeated * in this file: it is the imported constant. */ export declare const PRODUCT_DEFAULT_URL_EXCEPTION: { url: string; files: readonly string[]; reason: string; }; /** Is this exact URL excepted in this exact file? Global exceptions, then the scoped product default. */ export declare function isExceptedVendorUrl(url: string, file: string): boolean; /** Every excepted URL for one file, for the value-independent token scan to strip. */ export declare function exceptedVendorUrlsFor(file: string | undefined): string[]; /** Reduce a hostname to its registrable domain (approximate eTLD+1). */ export declare function registrableDomain(host: string): string; export declare function isLoopbackHost(host: string): boolean; export declare function isVendorControlledHost(host: string): boolean; export declare function isApprovedCodeHost(host: string): boolean; /** * Packed files allowed to contain a host whose TLD is supplied by `{…}` template * syntax (`https://s3.{partitionResult#dnsSuffix}`). These are bundles of the * AWS SDK, whose endpoint-rule engine substitutes the DNS suffix per partition. * * File-scoped on purpose: the carve-out used to be package-wide, which meant any * file could park a partial authority next to a runtime value and be exempted. * A host completed from a *code* expression is never exempt, in any file. */ export declare const TEMPLATE_HOST_FILES: readonly { file: string; reason: string; }[]; export declare function allowsTemplateHost(file: string): boolean; /** * Sites that build a host out of a computed value. * * Building a host from configuration is exactly what R1 asks for, so these are * not defects — but they are also the shape an endpoint default hides in, so * each one is acknowledged here rather than exempted by a blanket rule. Matched * on file AND exact URL fragment, never on file alone, and never on line number * so that rebuilding a bundle does not churn the list. A new dynamic-host site * fails until someone reads it and adds it. */ export declare const DYNAMIC_HOST_SITES: readonly { file: string; path: string; expr: string; reason: string; }[]; /** * Path component of a URL, used as the annotation key. Deliberately not the full * URL: a dynamic-host URL renders as a bare scheme, and storing that literal * would both read as noise and trip the repo's own insecure-HTTP scanner. */ export declare function urlPath(url: string): string; /** * Is this specific site annotated? * * Matched on file AND url path AND a substring of the host-producing EXPRESSION. * The expression is what makes the annotation site-scoped: keying on * (file, path) alone degenerated to keying on the file, because every * computed host with no path renders to the same bare scheme — so one annotated * site silently pre-approved every future one in the same file. */ export declare function isAnnotatedDynamicHost(file: string, url: string, expressionText: string): boolean; /** * The policy module must name the vendor domains it declares. Exclude only this * file from the value-independent token check; URL-shaped checks still apply. */ export declare const VENDOR_DOMAIN_DECLARATION_FILE = "src/lib/vendor-host-policy.ts";