import { type OrganizationsClient } from "@aws-sdk/client-organizations"; import { type Result } from "@fjall/generator"; import { type OUMap, type OUTree, type AccountInfo, type AccountPlacementResult } from "./types.js"; /** * Ensure the specified organisational units exist. Accepts either: * - `string[]` (flat): creates OUs directly under root (original behaviour) * - `OUTree` (nested): creates a recursive OU hierarchy * * Returns a map of OU key (lowercase) to OU ID. For nested trees, keys * use dot notation (e.g., "workloads.production") with shorthand aliases * for leaf names that don't collide with top-level keys. * * Idempotent — existing OUs are adopted, not duplicated. * * AWS cannot move OUs between parents. Migrating from flat to nested * creates new OUs under new parents; old empty OUs remain at root. */ export declare function ensureOrganisationalUnitsExist(client: OrganizationsClient, rootId: string, ouConfig: string[] | OUTree, abortSignal?: AbortSignal): Promise>; /** * Build a flat map of accountName (lowercase) to OU ID from an OUTree * and its resolved OUMap. * * Walks the tree recursively. For each leaf (string[]), maps each account * name to the parent OU's ID using the dotted OUMap key. * * Callers must pass account names that match the tree leaf values. */ export declare function buildAccountToOUMap(tree: OUTree, ouMap: OUMap, prefix?: string): Record; /** * Place accounts into the correct organisational units. * Skips organisation-tier accounts (via accountTier) and accounts already in the target OU. * * When `accountToOU` is provided, looks up the target OU by account name * (lowercase) instead of by environment. This supports tree-based placement * where the OU is determined by which leaf the account appears in. * * Idempotent — accounts already in the correct OU are counted but not moved. */ export declare function placeAccountsInOUs(client: OrganizationsClient, ouMap: OUMap, accounts: AccountInfo[], accountToOU?: Record, abortSignal?: AbortSignal): Promise>; /** * Find the id of the organisational unit named "development" (case-insensitive), * searching breadth-first from the root up to DEV_OU_SEARCH_MAX_DEPTH levels. * Supports both OU shapes ensureOrganisationalUnitsExist creates: flat * (development at root) and nested (workloads.development). * * Collects EVERY match rather than returning the shallowest one: a flat→nested * migration leaves a stray empty "development" OU at the root alongside the * real nested one, and silently attaching the dev-isolation SCP to the stray * would isolate nothing. Exactly one match → its id; zero → `undefined` (the * org has no development OU — the caller treats that as "nothing to isolate", * not an error); two or more → a loud failure naming the ids so the operator * disambiguates, because a security backstop must never attach to the wrong OU. */ export declare function findDevelopmentOuId(client: OrganizationsClient, rootId: string, abortSignal?: AbortSignal): Promise>;