{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://schemas.synq.io/synq-recon/v1/config.schema.json",
  "$defs": {
    "AggregateConfig": {
      "properties": {
        "measures": {
          "items": {
            "$ref": "#/$defs/MeasureConfig"
          },
          "type": "array",
          "minItems": 1
        },
        "group_columns": {
          "$ref": "#/$defs/GroupColumns",
          "description": "Column(s) defining the drill-down hierarchy."
        },
        "thresholds": {
          "$ref": "#/$defs/ThresholdConfig"
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "measures"
      ],
      "description": "AggregateConfig defines aggregate comparison settings."
    },
    "Annotations": {
      "oneOf": [
        {
          "items": {
            "properties": {
              "name": {
                "type": "string",
                "maxLength": 50,
                "minLength": 1
              },
              "values": {
                "items": {
                  "type": "string",
                  "maxLength": 50,
                  "minLength": 1
                },
                "type": "array",
                "maxItems": 20
              }
            },
            "type": "object",
            "required": [
              "name"
            ]
          },
          "type": "array",
          "description": "Canonical list form. Each entry has a name and optional values."
        },
        {
          "additionalProperties": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "type": "string",
                "maxLength": 50,
                "minLength": 1
              },
              {
                "items": {
                  "type": "string",
                  "maxLength": 50,
                  "minLength": 1
                },
                "type": "array",
                "maxItems": 20
              }
            ]
          },
          "type": "object",
          "description": "Map shorthand: key is annotation name; value is null (name-only), a single string, or an array of strings."
        }
      ]
    },
    "AthenaConf": {
      "properties": {
        "region": {
          "type": "string",
          "description": "AWS region hosting the Athena service and Glue Data Catalog."
        },
        "workgroup": {
          "type": "string",
          "description": "Athena workgroup. Defaults to \"primary\" when empty. Must have a\nResultConfiguration.OutputLocation configured."
        },
        "catalog": {
          "type": "string",
          "description": "Glue Data Catalog name. Defaults to \"AwsDataCatalog\" when empty."
        },
        "access_key_id": {
          "type": "string",
          "description": "Static AWS credentials. Pair access_key_id with secret_access_key."
        },
        "secret_access_key": {
          "type": "string"
        },
        "session_token": {
          "type": "string",
          "description": "Optional STS session token, when access_key_id+secret_access_key are\nshort-lived STS credentials."
        },
        "aws_profile": {
          "type": "string",
          "description": "Named AWS shared-config profile (from ~/.aws/credentials or\n~/.aws/config). Used only when static credentials are absent."
        },
        "role_arn": {
          "type": "string",
          "description": "IAM role ARN to assume via STS. Wraps whichever base credentials\nresolved above (or the host's default chain when no other auth is set)."
        },
        "external_id": {
          "type": "string",
          "description": "External ID required by the role's trust policy. Pair with role_arn."
        },
        "role_session_name": {
          "type": "string",
          "description": "Optional STS session name. Defaults to \"synq-athena\"."
        },
        "scope": {
          "$ref": "#/$defs/ScopeConf",
          "description": "Scope filter for include/exclude filtering by Glue catalog, Glue\ndatabase, and table. Mapping: ScopeRule.database = Glue catalog,\nScopeRule.schema = Glue database, ScopeRule.table = Glue table/view."
        },
        "use_show_create_table": {
          "type": "boolean",
          "description": "Use SHOW CREATE TABLE to retrieve full table DDL (CTAS bodies, Iceberg\nTBLPROPERTIES, Hive external LOCATION/SerDe). One Athena query per\ntable — billed at the 10MB scan minimum each."
        },
        "use_show_create_view": {
          "type": "boolean",
          "description": "Use SHOW CREATE VIEW to retrieve full view DDL instead of the\nrewritten body from information_schema.views.view_definition."
        },
        "use_iceberg_metrics_scan": {
          "type": "boolean",
          "description": "For Iceberg tables, fan out one Athena query per table to read row\ncount, total file size, snapshot commit timestamp, and partition\ncolumns from the table's $files / $snapshots / $partitions metadata\ntables. Hive externals are unaffected."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "region"
      ],
      "description": "AthenaConf contains Amazon Athena connection parameters."
    },
    "BigQueryConf": {
      "properties": {
        "project_id": {
          "type": "string",
          "description": "GCP project ID."
        },
        "region": {
          "type": "string",
          "description": "Region for BigQuery resources."
        },
        "service_account_key": {
          "type": "string",
          "description": "Inline JSON content of the service account key."
        },
        "service_account_key_file": {
          "type": "string",
          "description": "Path to the service account key JSON file."
        },
        "datasets": {
          "items": {
            "type": "string"
          },
          "type": "array",
          "description": "Explicit list of dataset names to scrape. When set, only these datasets are queried\nand project-level bigquery.datasets.list permission is not required."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "project_id",
        "region"
      ],
      "description": "BigQueryConf contains BigQuery connection parameters."
    },
    "BisectionConfig": {
      "properties": {
        "enabled": {
          "type": "boolean"
        },
        "factor": {
          "type": "integer",
          "maximum": 1024,
          "minimum": 2,
          "description": "Number of segments per bisection level."
        },
        "threshold": {
          "type": "integer",
          "minimum": 1,
          "description": "Stop drilling when segment row count falls below this."
        },
        "strategy": {
          "$ref": "#/$defs/SegmentationStrategy",
          "description": "Segmentation strategy."
        },
        "time_column": {
          "type": "string",
          "description": "Column for time-based partitioning (required when strategy is 'time')."
        },
        "time_granularity": {
          "$ref": "#/$defs/TimeGranularity",
          "description": "Time truncation granularity."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "BisectionConfig controls the bisection drill-down behavior."
    },
    "ClickhouseConf": {
      "properties": {
        "host": {
          "type": "string"
        },
        "port": {
          "type": "integer",
          "maximum": 65535,
          "minimum": 1
        },
        "database": {
          "type": "string",
          "description": "Database to connect to. If empty, all databases are scraped."
        },
        "username": {
          "type": "string"
        },
        "password": {
          "type": "string"
        },
        "allow_insecure": {
          "type": "boolean",
          "description": "Disable SSL certificate verification."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "host",
        "username",
        "password"
      ],
      "description": "ClickhouseConf contains ClickHouse connection parameters."
    },
    "ColumnMapping": {
      "oneOf": [
        {
          "additionalProperties": {
            "type": "string"
          },
          "type": "object",
          "description": "Map source column names to target column names (object format)"
        },
        {
          "items": {
            "properties": {
              "source": {
                "type": "string",
                "minLength": 1
              },
              "target": {
                "type": "string",
                "minLength": 1
              }
            },
            "type": "object",
            "required": [
              "source",
              "target"
            ]
          },
          "type": "array",
          "description": "Map source column names to target column names (array format)"
        }
      ]
    },
    "Connection": {
      "properties": {
        "name": {
          "type": "string",
          "description": "Display name for this connection. Defaults to the connection ID (map key)."
        },
        "disabled": {
          "type": "boolean",
          "description": "When true, the connection is skipped during execution."
        },
        "parallelism": {
          "type": "integer",
          "maximum": 256,
          "minimum": 1,
          "description": "Maximum number of parallel queries. Range: 1-256. Defaults to 8."
        },
        "postgres": {
          "$ref": "#/$defs/PostgresConf"
        },
        "snowflake": {
          "$ref": "#/$defs/SnowflakeConf"
        },
        "bigquery": {
          "$ref": "#/$defs/BigQueryConf"
        },
        "redshift": {
          "$ref": "#/$defs/RedshiftConf"
        },
        "mysql": {
          "$ref": "#/$defs/MySQLConf"
        },
        "clickhouse": {
          "$ref": "#/$defs/ClickhouseConf"
        },
        "trino": {
          "$ref": "#/$defs/TrinoConf"
        },
        "databricks": {
          "$ref": "#/$defs/DatabricksConf"
        },
        "mssql": {
          "$ref": "#/$defs/MSSQLConf"
        },
        "oracle": {
          "$ref": "#/$defs/OracleConf"
        },
        "duckdb": {
          "$ref": "#/$defs/DuckDBConf"
        },
        "athena": {
          "$ref": "#/$defs/AthenaConf"
        },
        "fabric": {
          "$ref": "#/$defs/FabricConf"
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "Connection is a single database connection entry in a connections map."
    },
    "CutoffAggregate": {
      "type": "string",
      "enum": [
        "MAX",
        "MIN"
      ]
    },
    "CutoffApply": {
      "properties": {
        "source": {
          "$ref": "#/$defs/CutoffApplySide"
        },
        "target": {
          "$ref": "#/$defs/CutoffApplySide"
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "CutoffApply configures custom WHERE clause generation for cutoff."
    },
    "CutoffApplySide": {
      "properties": {
        "column": {
          "type": "string",
          "description": "Column to filter on. When not set, uses the derivation column."
        },
        "operator": {
          "type": "string",
          "description": "Comparison operator. Default: \"\u003c=\"."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "CutoffApplySide configures WHERE clause generation for one side."
    },
    "CutoffCombine": {
      "type": "string",
      "enum": [
        "min",
        "max",
        "source",
        "target"
      ]
    },
    "CutoffConfig": {
      "properties": {
        "column": {
          "type": "string",
          "description": "Simple: same column for both source and target watermark derivation."
        },
        "source_column": {
          "type": "string",
          "description": "Medium: different columns per side."
        },
        "target_column": {
          "type": "string"
        },
        "source": {
          "$ref": "#/$defs/CutoffSideConfig",
          "description": "Advanced: full per-side watermark derivation config."
        },
        "target": {
          "$ref": "#/$defs/CutoffSideConfig",
          "description": "Advanced: full per-side watermark derivation config."
        },
        "combine": {
          "$ref": "#/$defs/CutoffCombine",
          "description": "How to combine watermarks when both sides are configured: min, max, source, target."
        },
        "truncate": {
          "$ref": "#/$defs/CutoffTruncate",
          "description": "Truncate the combined watermark to a time boundary before applying."
        },
        "offset": {
          "type": "string",
          "description": "Time offset applied after truncation. Negative durations create a safety buffer (e.g., '-30m')."
        },
        "apply": {
          "$ref": "#/$defs/CutoffApply",
          "description": "Advanced: custom apply config for WHERE clause generation."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "CutoffConfig defines a dynamic cutoff filter for sync reconciliation."
    },
    "CutoffSideConfig": {
      "properties": {
        "column": {
          "type": "string",
          "description": "Column to derive the watermark from (e.g., \"created_at\", \"synced_at\").\nRequired when query is not set."
        },
        "aggregate": {
          "$ref": "#/$defs/CutoffAggregate",
          "description": "Aggregate function for watermark derivation: MAX (default) or MIN."
        },
        "query": {
          "type": "string",
          "description": "Custom SQL query for watermark derivation. Must return a single row with a \"watermark\" column.\nWhen not set, auto-generated from the dataset at runtime."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "CutoffSideConfig configures watermark derivation for one side (source or target)."
    },
    "CutoffTruncate": {
      "type": "string",
      "enum": [
        "HOUR",
        "DAY",
        "WEEK",
        "MONTH",
        "QUARTER",
        "YEAR"
      ]
    },
    "DatabricksConf": {
      "properties": {
        "workspace_url": {
          "type": "string",
          "description": "Databricks workspace URL."
        },
        "auth_token": {
          "type": "string",
          "description": "Personal access token for authentication."
        },
        "auth_client": {
          "type": "string",
          "description": "OAuth client ID (M2M authentication)."
        },
        "auth_secret": {
          "type": "string",
          "description": "OAuth client secret (M2M authentication)."
        },
        "warehouse": {
          "type": "string",
          "description": "SQL warehouse ID to use for queries."
        },
        "refresh_table_metrics": {
          "type": "boolean"
        },
        "refresh_table_metrics_use_scan": {
          "type": "boolean"
        },
        "fetch_table_tags": {
          "type": "boolean"
        },
        "use_show_create_table": {
          "type": "boolean"
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "workspace_url"
      ],
      "description": "DatabricksConf contains Databricks connection parameters."
    },
    "Dataset": {
      "properties": {
        "connection": {
          "type": "string",
          "description": "Connection name (must exist in connections map)."
        },
        "query": {
          "type": "string",
          "description": "Base SQL query (mutually exclusive with 'table'). Supports {{variable_name}} interpolation."
        },
        "table": {
          "$ref": "#/$defs/TableReference",
          "description": "Table reference (mutually exclusive with 'query'). Accepts \"db.schema.table\" string or structured object."
        },
        "columns": {
          "items": {
            "type": "string"
          },
          "type": "array",
          "description": "Explicit column list (only with 'table'). Mutually exclusive with 'exclude_columns'."
        },
        "exclude_columns": {
          "items": {
            "type": "string"
          },
          "type": "array",
          "description": "Columns to exclude (only with 'table', resolved at runtime). Mutually exclusive with 'columns'."
        },
        "where": {
          "type": "string",
          "description": "SQL WHERE clause filter (only with 'table'). Applied as WHERE (condition). Supports {{variable_name}} interpolation."
        },
        "as_of": {
          "type": "string",
          "description": "Time-travel timestamp. Wraps query with database-specific time-travel syntax."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "connection"
      ],
      "description": "Dataset defines a data source for reconciliation."
    },
    "DuckDBConf": {
      "properties": {
        "database": {
          "type": "string",
          "description": "File path, ':memory:' for in-memory, or MotherDuck database name."
        },
        "motherduck_account": {
          "type": "string",
          "description": "MotherDuck organization/account name (for cloud mode)."
        },
        "motherduck_token": {
          "type": "string",
          "description": "MotherDuck authentication token (required for cloud MotherDuck)."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "DuckDBConf contains DuckDB / MotherDuck connection parameters."
    },
    "ErrorHandlingConfig": {
      "properties": {
        "query_timeout": {
          "type": "string",
          "description": "Per-query timeout as a Go duration string (e.g., '30s', '5m')."
        },
        "max_retries": {
          "type": "integer",
          "maximum": 10,
          "minimum": 0,
          "description": "Maximum retry attempts for transient query failures."
        },
        "retry_initial_delay": {
          "type": "string",
          "description": "Initial backoff delay before the first retry."
        },
        "retry_backoff_factor": {
          "type": "number",
          "minimum": 1,
          "description": "Backoff multiplier applied after each retry."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "ErrorHandlingConfig controls retry behavior for query failures."
    },
    "FabricConf": {
      "properties": {
        "host": {
          "type": "string",
          "description": "Hostname of the workspace's SQL analytics endpoint. Copy it from the\nFabric portal: open your Warehouse or Lakehouse, then Settings → SQL\nconnection string.",
          "examples": [
            "my-workspace.datawarehouse.fabric.microsoft.com"
          ]
        },
        "database": {
          "type": "string",
          "description": "Default database for queries that don't name one explicitly. Optional —\ndefaults to \"master\". Because metadata and metric queries are always\nfully qualified, this only affects ad-hoc SQL that omits the database.",
          "examples": [
            "my_warehouse"
          ]
        },
        "auth_type": {
          "type": "string",
          "description": "How to authenticate to Fabric. Optional — defaults to a service principal\n(client_id + client_secret). Values are matched case-insensitively, and\nthe equivalent dbt-fabric and Microsoft ODBC spellings are also accepted:\n  - \"service_principal\" (default): Entra ID service principal. Set\n    client_id, client_secret and, if needed, tenant_id.\n  - \"azure_cli\": reuse the machine's `az login` session. On-prem agent only.\n  - \"default\": try Azure's default credential chain (environment, managed\n    identity, CLI, ...). On-prem agent only.\n  - \"managed_identity\": use an Azure managed identity; set client_id to\n    select a user-assigned identity. On-prem agent only.",
          "examples": [
            "service_principal",
            "azure_cli",
            "default",
            "managed_identity"
          ]
        },
        "client_id": {
          "type": "string",
          "description": "Application (client) ID of the Entra ID service principal. When auth_type\nis \"managed_identity\", this instead selects a user-assigned identity.",
          "examples": [
            "00000000-0000-0000-0000-000000000000"
          ]
        },
        "client_secret": {
          "type": "string",
          "description": "Client secret for the service principal. Supply it through an environment\nvariable (e.g. ${FABRIC_CLIENT_SECRET}) rather than committing it in plain\ntext.",
          "examples": [
            "${FABRIC_CLIENT_SECRET}"
          ]
        },
        "tenant_id": {
          "type": "string",
          "description": "Entra ID tenant (directory) ID. Optional — inferred from the endpoint\nhostname when omitted. Set it only when the service principal lives in a\ndifferent tenant than the workspace.",
          "examples": [
            "00000000-0000-0000-0000-000000000000"
          ]
        },
        "access_token": {
          "type": "string",
          "description": "A pre-acquired Entra ID OAuth access token for the SQL scope\n(https://database.windows.net/.default). Optional — when set it overrides\nevery other authentication method. Mainly for hosted deployments that mint\ntheir own token.",
          "examples": [
            "${FABRIC_ACCESS_TOKEN}"
          ]
        },
        "scope": {
          "$ref": "#/$defs/ScopeConf",
          "description": "Optional include/exclude filter that limits which databases, schemas and\ntables are scanned. When omitted, the whole workspace is scanned."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "host"
      ],
      "description": "FabricConf contains the connection settings for a Microsoft Fabric Warehouse or Lakehouse SQL analytics endpoint."
    },
    "GroupColumns": {
      "oneOf": [
        {
          "type": "string",
          "description": "Single group column"
        },
        {
          "items": {
            "type": "string"
          },
          "type": "array",
          "minItems": 1,
          "description": "Hierarchical group columns for drill-down"
        }
      ]
    },
    "HashAlgorithm": {
      "type": "string",
      "enum": [
        "auto",
        "md5",
        "farm_fingerprint",
        "xxhash64"
      ]
    },
    "MSSQLConf": {
      "properties": {
        "host": {
          "type": "string"
        },
        "port": {
          "type": "integer",
          "maximum": 65535,
          "minimum": 1
        },
        "database": {
          "type": "string"
        },
        "username": {
          "type": "string"
        },
        "password": {
          "type": "string"
        },
        "trust_cert": {
          "type": "boolean",
          "description": "Trust the server certificate without validation."
        },
        "encrypt": {
          "type": "string",
          "description": "Encryption mode (e.g. \"true\", \"false\", \"strict\")."
        },
        "fed_auth": {
          "type": "string",
          "description": "Federated authentication method (e.g. \"ActiveDirectoryDefault\")."
        },
        "access_token": {
          "type": "string",
          "description": "Pre-acquired access token for Azure AD authentication."
        },
        "application_client_id": {
          "type": "string",
          "description": "Azure AD application client ID for service principal auth."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "host",
        "database"
      ],
      "description": "MSSQLConf contains Microsoft SQL Server / Azure SQL Database connection parameters."
    },
    "MeasureConfig": {
      "properties": {
        "column": {
          "type": "string",
          "minLength": 1
        },
        "function": {
          "$ref": "#/$defs/MeasureFunction"
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "column",
        "function"
      ],
      "description": "MeasureConfig defines a column + aggregation function pair."
    },
    "MeasureFunction": {
      "oneOf": [
        {
          "type": "string",
          "enum": [
            "SUM",
            "COUNT",
            "AVG",
            "MIN",
            "MAX"
          ],
          "description": "Single aggregation function"
        },
        {
          "items": {
            "type": "string",
            "enum": [
              "SUM",
              "COUNT",
              "AVG",
              "MIN",
              "MAX"
            ]
          },
          "type": "array",
          "minItems": 1,
          "description": "Multiple aggregation functions"
        }
      ]
    },
    "MySQLConf": {
      "properties": {
        "host": {
          "type": "string"
        },
        "port": {
          "type": "integer",
          "maximum": 65535,
          "minimum": 1
        },
        "database": {
          "type": "string"
        },
        "username": {
          "type": "string"
        },
        "password": {
          "type": "string"
        },
        "allow_insecure": {
          "type": "boolean",
          "description": "Disable SSL certificate verification."
        },
        "params": {
          "additionalProperties": {
            "type": "string"
          },
          "type": "object",
          "description": "Additional DSN parameters passed to the driver."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "host",
        "port",
        "username",
        "password"
      ],
      "description": "MySQLConf contains MySQL connection parameters."
    },
    "OracleConf": {
      "properties": {
        "host": {
          "type": "string"
        },
        "port": {
          "type": "integer",
          "maximum": 65535,
          "minimum": 1
        },
        "service_name": {
          "type": "string",
          "description": "Oracle service name."
        },
        "username": {
          "type": "string"
        },
        "password": {
          "type": "string"
        },
        "ssl": {
          "type": "boolean",
          "description": "Enable SSL/TLS for the connection."
        },
        "ssl_verify": {
          "type": "boolean",
          "description": "Verify the server's SSL certificate."
        },
        "wallet_path": {
          "type": "string",
          "description": "Path to Oracle Wallet directory for authentication."
        },
        "use_diagnostics_pack": {
          "type": "boolean",
          "description": "Enable Oracle Diagnostics Pack features (AWR, ASH)."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "host",
        "service_name"
      ],
      "description": "OracleConf contains Oracle Database connection parameters."
    },
    "PercentageMode": {
      "type": "string",
      "enum": [
        "source",
        "target",
        "symmetric"
      ]
    },
    "PostgresConf": {
      "properties": {
        "host": {
          "type": "string"
        },
        "port": {
          "type": "integer",
          "maximum": 65535,
          "minimum": 1
        },
        "database": {
          "type": "string"
        },
        "username": {
          "type": "string"
        },
        "password": {
          "type": "string"
        },
        "allow_insecure": {
          "type": "boolean",
          "description": "Disable SSL certificate verification."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "host",
        "database",
        "username",
        "password"
      ],
      "description": "PostgresConf contains PostgreSQL connection parameters."
    },
    "Reconciliation": {
      "properties": {
        "title": {
          "type": "string",
          "description": "Human-readable title."
        },
        "description": {
          "type": "string",
          "description": "Human-readable description."
        },
        "source": {
          "$ref": "#/$defs/Dataset",
          "description": "Source dataset."
        },
        "target": {
          "$ref": "#/$defs/Dataset",
          "description": "Target dataset."
        },
        "key_column": {
          "$ref": "#/$defs/StringOrStrings",
          "description": "Single key column for bisection split points and aggregate grouping.\nDeprecated in favor of key_columns; accepts a string or a one-element list.\nSet either key_column or key_columns, not both."
        },
        "key_columns": {
          "$ref": "#/$defs/StringOrStrings",
          "description": "Ordered key columns for bisection split points and aggregate grouping.\nSupports composite (multi-column) keys; the bisection orders and\nrange-filters on the column tuple. Accepts a string or a list of strings."
        },
        "mode": {
          "$ref": "#/$defs/ReconciliationMode",
          "description": "Reconciliation mode."
        },
        "hash_algorithm": {
          "$ref": "#/$defs/HashAlgorithm",
          "description": "Hash algorithm for row checksums."
        },
        "case_insensitive": {
          "type": "boolean",
          "description": "Automatically match columns case-insensitively."
        },
        "column_mapping": {
          "$ref": "#/$defs/ColumnMapping",
          "description": "Column name mapping between source and target."
        },
        "bisection": {
          "$ref": "#/$defs/BisectionConfig"
        },
        "reporting": {
          "$ref": "#/$defs/ReportingConfig"
        },
        "aggregate": {
          "$ref": "#/$defs/AggregateConfig"
        },
        "error_handling": {
          "$ref": "#/$defs/ErrorHandlingConfig"
        },
        "window": {
          "$ref": "#/$defs/WindowConfig"
        },
        "cutoff": {
          "$ref": "#/$defs/CutoffConfig",
          "description": "Dynamic cutoff filter. Derives a watermark value from actual data to exclude rows not yet synced."
        },
        "annotations": {
          "$ref": "#/$defs/Annotations",
          "description": "Annotations attached to this reconciliation case. Merged with suite-level annotations."
        },
        "setup": {
          "additionalProperties": {
            "$ref": "#/$defs/StringOrStrings"
          },
          "type": "object",
          "description": "Per-reconciliation setup/teardown."
        },
        "teardown": {
          "additionalProperties": {
            "$ref": "#/$defs/StringOrStrings"
          },
          "type": "object"
        },
        "setup_file": {
          "additionalProperties": {
            "$ref": "#/$defs/StringOrStrings"
          },
          "type": "object"
        },
        "teardown_file": {
          "additionalProperties": {
            "$ref": "#/$defs/StringOrStrings"
          },
          "type": "object"
        },
        "teardown_on_failure": {
          "type": "boolean",
          "description": "Whether teardown runs on failure. Inherits from suite level when not set."
        },
        "ignore_setup_errors": {
          "type": "boolean",
          "description": "When true, logs setup errors as warnings. Inherits from suite level when not set."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "source",
        "target"
      ],
      "description": "Reconciliation defines a single reconciliation scenario."
    },
    "ReconciliationMode": {
      "type": "string",
      "enum": [
        "row_count",
        "full",
        "row_checksum",
        "aggregate"
      ]
    },
    "RedshiftConf": {
      "properties": {
        "host": {
          "type": "string"
        },
        "port": {
          "type": "integer",
          "maximum": 65535,
          "minimum": 1
        },
        "database": {
          "type": "string"
        },
        "username": {
          "type": "string"
        },
        "password": {
          "type": "string"
        },
        "freshness_from_query_logs": {
          "type": "boolean",
          "description": "Estimate table freshness from Redshift query logs instead of metadata."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "host",
        "port",
        "database",
        "username",
        "password"
      ],
      "description": "RedshiftConf contains Amazon Redshift connection parameters."
    },
    "ReportingConfig": {
      "properties": {
        "level": {
          "$ref": "#/$defs/ReportingLevel"
        },
        "sample_limit": {
          "type": "integer",
          "minimum": 1
        },
        "consent_acknowledged": {
          "type": "boolean"
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "ReportingConfig controls what level of detail is reported."
    },
    "ReportingLevel": {
      "type": "string",
      "enum": [
        "count_only",
        "with_keys",
        "detailed"
      ]
    },
    "SYNQConfig": {
      "properties": {
        "client_id": {
          "type": "string",
          "description": "OAuth client ID for authenticating with the SYNQ platform."
        },
        "client_secret": {
          "type": "string",
          "description": "OAuth client secret for authenticating with the SYNQ platform."
        },
        "endpoint": {
          "type": "string",
          "description": "gRPC endpoint for the SYNQ API (e.g. \"developer.synq.io:443\")."
        },
        "ingest_endpoint": {
          "type": "string",
          "description": "gRPC endpoint for the SYNQ ingest API. Defaults to Endpoint if empty."
        },
        "oauth_url": {
          "type": "string",
          "description": "OAuth token URL. Derived from Endpoint if empty."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "SYNQConfig holds SYNQ platform connection settings."
    },
    "ScopeConf": {
      "properties": {
        "include": {
          "items": {
            "$ref": "#/$defs/ScopeRuleConf"
          },
          "type": "array",
          "description": "Include rules. If non-empty, only matching objects are accepted."
        },
        "exclude": {
          "items": {
            "$ref": "#/$defs/ScopeRuleConf"
          },
          "type": "array",
          "description": "Exclude rules. Matching objects are rejected, even if they match an include rule."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "ScopeConf is the YAML representation of synq.common.v1.ScopeFilter — the shared include/exclude filter used by warehouses with hierarchical catalogs."
    },
    "ScopeRuleConf": {
      "properties": {
        "database": {
          "type": "string",
          "description": "Database-level pattern (catalog for Athena/Trino/Databricks, project for BigQuery)."
        },
        "schema": {
          "type": "string",
          "description": "Schema-level pattern (Glue database for Athena, dataset for BigQuery)."
        },
        "table": {
          "type": "string",
          "description": "Table or view name pattern."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "ScopeRuleConf is a single include/exclude rule."
    },
    "SegmentationStrategy": {
      "type": "string",
      "enum": [
        "auto",
        "quantile",
        "hash",
        "time"
      ]
    },
    "SnowflakeConf": {
      "properties": {
        "account": {
          "type": "string",
          "description": "Snowflake account identifier."
        },
        "warehouse": {
          "type": "string",
          "description": "Virtual warehouse to use for queries."
        },
        "role": {
          "type": "string",
          "description": "Role to assume after connecting."
        },
        "username": {
          "type": "string"
        },
        "password": {
          "type": "string"
        },
        "private_key": {
          "type": "string",
          "description": "PEM-encoded private key content for key-pair authentication."
        },
        "private_key_file": {
          "type": "string",
          "description": "Path to a PEM-encoded private key file."
        },
        "private_key_passphrase": {
          "type": "string",
          "description": "Passphrase to decrypt the private key."
        },
        "databases": {
          "items": {
            "type": "string"
          },
          "type": "array",
          "description": "Databases to include. If empty, all accessible databases are scraped."
        },
        "use_get_ddl": {
          "type": "boolean",
          "description": "Use GET_DDL() to retrieve DDL for tables and views."
        },
        "account_usage_db": {
          "type": "string",
          "description": "Database containing the ACCOUNT_USAGE schema. Defaults to SNOWFLAKE."
        },
        "auth_type": {
          "type": "string",
          "description": "Set to \"externalbrowser\" to use SSO browser-based authentication."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "account",
        "warehouse",
        "role",
        "username"
      ],
      "description": "SnowflakeConf contains Snowflake connection parameters."
    },
    "StringOrStrings": {
      "oneOf": [
        {
          "type": "string"
        },
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        }
      ]
    },
    "TableReference": {
      "oneOf": [
        {
          "type": "string",
          "description": "Table in dotted format: 'table', 'schema.table', or 'database.schema.table'"
        },
        {
          "properties": {
            "database": {
              "type": "string",
              "description": "Database/catalog name"
            },
            "schema": {
              "type": "string",
              "description": "Schema/dataset name"
            },
            "name": {
              "type": "string",
              "minLength": 1,
              "description": "Table or view name"
            }
          },
          "type": "object",
          "required": [
            "name"
          ],
          "description": "Structured table reference"
        }
      ]
    },
    "ThresholdConfig": {
      "properties": {
        "absolute": {
          "type": "number",
          "minimum": 0,
          "description": "Maximum absolute difference."
        },
        "percentage": {
          "type": "number",
          "minimum": 0,
          "description": "Maximum percentage difference (0.1 = 10%)."
        },
        "percentage_mode": {
          "$ref": "#/$defs/PercentageMode",
          "description": "Percentage formula: source, target, or symmetric."
        },
        "per_column": {
          "additionalProperties": {
            "$ref": "#/$defs/ThresholdConfig"
          },
          "type": "object",
          "description": "Per group_column threshold overrides."
        },
        "per_measure": {
          "additionalProperties": {
            "$ref": "#/$defs/ThresholdConfig"
          },
          "type": "object",
          "description": "Per measure threshold overrides, keyed by FUNC(column)."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "description": "ThresholdConfig defines tolerance for aggregate differences."
    },
    "TimeGranularity": {
      "type": "string",
      "enum": [
        "hour",
        "day",
        "week",
        "month",
        "quarter",
        "year"
      ]
    },
    "TrinoConf": {
      "properties": {
        "host": {
          "type": "string"
        },
        "port": {
          "type": "integer",
          "maximum": 65535,
          "minimum": 1
        },
        "use_plaintext": {
          "type": "boolean",
          "description": "Use a plain HTTP connection instead of HTTPS."
        },
        "username": {
          "type": "string"
        },
        "password": {
          "type": "string"
        },
        "catalogs": {
          "items": {
            "type": "string"
          },
          "type": "array",
          "description": "Catalogs to include. Required for most Trino deployments."
        },
        "no_show_create_view": {
          "type": "boolean"
        },
        "no_show_create_table": {
          "type": "boolean"
        },
        "no_materialized_views": {
          "type": "boolean"
        },
        "fetch_table_comments": {
          "type": "boolean"
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "host"
      ],
      "description": "TrinoConf contains Trino / Starburst connection parameters."
    },
    "WindowConfig": {
      "properties": {
        "column": {
          "type": "string",
          "description": "Column being windowed."
        },
        "lookback": {
          "type": "string",
          "description": "How far back to look from the current time (e.g., '14d', '2h')."
        },
        "strategy": {
          "$ref": "#/$defs/WindowStrategy",
          "description": "Windowing strategy: 'sliding' or 'fixed'."
        }
      },
      "additionalProperties": false,
      "type": "object",
      "required": [
        "lookback"
      ],
      "description": "WindowConfig defines time-windowed reconciliation settings."
    },
    "WindowStrategy": {
      "type": "string",
      "enum": [
        "sliding",
        "fixed"
      ]
    }
  },
  "properties": {
    "name": {
      "type": "string",
      "maxLength": 255,
      "minLength": 1,
      "pattern": "^[a-zA-Z0-9][a-zA-Z0-9_-]*$",
      "description": "Short machine identifier for the suite."
    },
    "title": {
      "type": "string",
      "description": "Human-readable title for the suite."
    },
    "description": {
      "type": "string",
      "description": "Human-readable description."
    },
    "connections": {
      "additionalProperties": {
        "$ref": "#/$defs/Connection"
      },
      "type": "object",
      "description": "Database connection definitions."
    },
    "reconciliations": {
      "additionalProperties": {
        "$ref": "#/$defs/Reconciliation"
      },
      "type": "object",
      "description": "Reconciliation scenario definitions."
    },
    "variables": {
      "additionalProperties": {
        "type": "string"
      },
      "type": "object",
      "description": "Template variables for query interpolation via {{variable_name}} syntax."
    },
    "setup": {
      "additionalProperties": {
        "$ref": "#/$defs/StringOrStrings"
      },
      "type": "object",
      "description": "Setup queries run once before all reconciliations begin."
    },
    "teardown": {
      "additionalProperties": {
        "$ref": "#/$defs/StringOrStrings"
      },
      "type": "object",
      "description": "Teardown queries run once after all reconciliations complete."
    },
    "setup_file": {
      "additionalProperties": {
        "$ref": "#/$defs/StringOrStrings"
      },
      "type": "object",
      "description": "SQL file(s) to load and run as setup queries."
    },
    "teardown_file": {
      "additionalProperties": {
        "$ref": "#/$defs/StringOrStrings"
      },
      "type": "object",
      "description": "SQL file(s) to load and run as teardown queries."
    },
    "teardown_on_failure": {
      "type": "boolean",
      "description": "Whether teardown runs even when reconciliations fail with infrastructure errors."
    },
    "ignore_setup_errors": {
      "type": "boolean",
      "description": "When true, logs setup query errors as warnings and continues instead of aborting."
    },
    "strict_time_references": {
      "type": "boolean",
      "description": "When true, time reference detection (NOW(), CURRENT_DATE, etc.) returns an error instead of a warning."
    },
    "synq": {
      "$ref": "#/$defs/SYNQConfig",
      "description": "SYNQ API credentials for sending audit logs."
    },
    "annotations": {
      "$ref": "#/$defs/Annotations",
      "description": "Suite-level annotations."
    }
  },
  "additionalProperties": false,
  "type": "object",
  "required": [
    "connections",
    "reconciliations"
  ],
  "title": "Coalesce Quality Recon Configuration",
  "description": "Configuration file format for synq-recon, the Coalesce Quality data reconciliation tool that compares datasets across databases.",
  "x-status": "stable"
}