/**
 * Which site settings a member may change, and route-conflict checks.
 *
 * `site:settings` lets a site owner edit their own site — but a site's config
 * is not all equally harmless on a box shared with other tenants:
 *
 * - `build` and `start` are **shell commands run on the box at deploy time**,
 *   as root. A member who could set them would own the whole server, and every
 *   other tenant's site with it.
 * - `root` is a filesystem path. Pointed at another site's directory (or `/`),
 *   it serves someone else's files to the internet.
 * - `port`, `type` and `php` pick runtime and bind ports, which are the box's
 *   to allocate, not one tenant's.
 *
 * Those stay with the box owner. What is left is genuinely the tenant's own:
 * TLS, their app's env, their redirects, and their routing — and routing is
 * still checked against other tenants, since claiming `example.com` when
 * someone else already serves it is hijacking their traffic.
 *
 * An allowlist, not a blocklist: a site field added later is admin-only until
 * someone decides it is safe to hand over.
 */
/** Fields a member holding `site:settings` on the site may change. */
export declare const MEMBER_EDITABLE_SITE_FIELDS: ReadonlySet<string>;
/**
 * Fields only the box owner may change, with why — used to explain the refusal
 * rather than a bare 403.
 */
export declare const ADMIN_ONLY_SITE_FIELDS: Readonly<Record<string, string>>;
export interface FieldCheck {
    ok: boolean;
    error?: string;
}
/**
 * Whether a member may apply `body` to a site. Refuses the whole request if it
 * touches any admin-only field, rather than silently applying the safe subset —
 * a caller who asked to set `start` should be told it did not happen.
 */
export declare function checkMemberSiteFields(body: Record<string, any>): FieldCheck;
export interface RouteConflictInput {
    /** The site being edited. */
    siteName: string;
    /** The requested changes (domain / path / aliases). */
    body: Record<string, any>;
    /** All sites on the box, by name. */
    sites: Record<string, any>;
    /** Site names the editor holds a grant on — conflicts with these are theirs. */
    ownSites: string[];
}
/**
 * Refuse a routing change that would claim a host another tenant already
 * serves. Conflicts with the editor's own sites are allowed: moving a domain
 * between two sites you control is your business.
 */
export declare function checkRouteConflict({ siteName, body, sites, ownSites }: RouteConflictInput): FieldCheck;
