from __future__ import annotations

import json
import hashlib
import os
import re
import sqlite3
import subprocess
import tempfile
import threading
import time
import urllib.error
import urllib.request
import uuid
from contextlib import contextmanager
from pathlib import Path
from typing import Any


METHOD_STATUS = "repository.status"
SQL_LOCK_EVIDENCE = {
    "native_lock_state": "unknown",
    "native_lock_verification": "not_available_via_infobase_sql",
    "excluded_sources": {
        "_ConfigChngR": "exchange_plan_change_registration",
        "_ConfigChngR_ExtProps": "exchange_plan_changed_file_details",
    },
}
METHOD_LOCK_PLAN = "repository.lock.plan"
METHOD_LOCK_REQUEST = "repository.lock.request"
METHOD_LOCK_REQUEST_STATUS = "repository.lock.request.status"
METHOD_LOCK_REQUEST_CANCEL = "repository.lock.request.cancel"
METHOD_LOCK = "repository.lock"
METHOD_CONFIRM = "repository.lock.confirm"
METHOD_VERIFY = "repository.lock.verify"
METHOD_CLOSE = "repository.lock.close"
METHOD_UNLOCK = "repository.unlock"
METHOD_COMMIT_PLAN = "repository.commit.plan"
METHOD_COMMIT = "repository.commit"
METHODS = {METHOD_STATUS, METHOD_LOCK_PLAN, METHOD_LOCK_REQUEST, METHOD_LOCK_REQUEST_STATUS, METHOD_LOCK_REQUEST_CANCEL, METHOD_LOCK, METHOD_CONFIRM, METHOD_VERIFY, METHOD_CLOSE, METHOD_UNLOCK, METHOD_COMMIT_PLAN, METHOD_COMMIT}
SUPPORTED_BACKENDS = {"direct", "karman_bridge"}
SUPPORTED_LOCK_MODES = {"automatic", "manual"}
SUPPORTED_REPOSITORY_MODES = {"none", "manual", "automatic", "unknown"}
SUPPORTED_REPOSITORY_CONNECTION_STATES = {"not_configured", "configured", "unavailable", "unknown"}
SUPPORTED_SUPPORT_MODES = {"none", "editable", "locked", "rules", "unknown"}
_BASE_LOCKS: dict[str, threading.Lock] = {}
_BASE_LOCKS_GUARD = threading.Lock()
_STATE_LOCK = threading.RLock()
REPOSITORY_STATE_SCHEMA_VERSION = 2


def external_1c_enabled() -> bool:
    return str(os.environ.get("ONEC_ADAPTER_ENABLE_EXTERNAL_1C") or "").strip().casefold() in {"1", "true", "yes", "on"}


def _base_lock(base_id: str, layer: str) -> threading.Lock:
    key = f"{base_id}:{layer}"
    with _BASE_LOCKS_GUARD:
        return _BASE_LOCKS.setdefault(key, threading.Lock())


def _load_json_map(env_name: str, file_env_name: str) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
    raw = os.environ.get(env_name)
    path = os.environ.get(file_env_name)
    if not raw and path:
        try:
            raw = Path(path).read_text(encoding="utf-8-sig")
        except Exception as exc:
            return None, {"status": "invalid_config", "message": f"Cannot read {file_env_name}: {exc}"}
    if not raw:
        return None, {
            "status": "not_configured",
            "message": f"Set {env_name} or {file_env_name} with an explicit entry for this base_id.",
        }
    try:
        value = json.loads(raw)
    except json.JSONDecodeError as exc:
        return None, {"status": "invalid_config", "message": f"{env_name} is not valid JSON: {exc}"}
    if not isinstance(value, dict):
        return None, {"status": "invalid_config", "message": f"{env_name} must be an object keyed by base_id."}
    return value, None


def development_layer_id(payload: dict[str, Any] | None = None) -> str:
    value = payload if isinstance(payload, dict) else {}
    target = value.get("target") if isinstance(value.get("target"), dict) else {}
    origin = target.get("origin") if isinstance(target.get("origin"), dict) else {}
    origin_extension = origin.get("extension") if isinstance(origin.get("extension"), dict) else {}
    extension_guid = str(value.get("extension_guid") or target.get("extension_guid") or origin_extension.get("guid") or "").strip().lower()
    layer_id = str(value.get("layer_id") or target.get("layer_id") or "").strip().lower()
    if extension_guid:
        return f"extension:{extension_guid}"
    if layer_id.startswith("extension:"):
        return layer_id
    return "base"


def _base_settings(base_id: str) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
    values, error = _load_json_map("ONEC_SQL_BASES_JSON", "ONEC_SQL_BASES_JSON_FILE")
    base_item = values.get(base_id) if values and isinstance(values.get(base_id), dict) else None
    if base_item is not None:
        return base_item, None
    return None, error or {"status": "not_configured", "message": f"No SQL configuration for base_id '{base_id}'."}


def development_layer_config(base_id: str, layer_id: str) -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
    base_item, base_error = _base_settings(base_id)
    if base_error:
        return None, base_error
    layers = base_item.get("development_layers") if isinstance(base_item.get("development_layers"), dict) else None
    if layers is not None:
        item = layers.get(layer_id)
        if not isinstance(item, dict):
            return None, {"status": "layer_not_configured", "message": f"No development layer configuration for '{layer_id}' in base_id '{base_id}'."}
        return dict(item), None
    if layer_id == "base" and isinstance(base_item.get("repository"), dict):
        return {"repository": dict(base_item["repository"]), "legacy": True}, None
    return None, {"status": "layer_not_configured", "message": f"No development layer configuration for '{layer_id}' in base_id '{base_id}'."}


def repository_config(base_id: str, layer_id: str = "base") -> tuple[dict[str, Any] | None, dict[str, Any] | None]:
    base_item, _ = _base_settings(base_id)
    layer, layer_error = development_layer_config(base_id, layer_id)
    if layer_error is None:
        item = layer.get("repository")
        if item is None:
            return {"mode": "unknown", "lock_mode": "manual", "layer_id": layer_id, "layer": layer_id}, None
    else:
        item = None
        if isinstance(base_item, dict) and isinstance(base_item.get("development_layers"), dict):
            # A disposable base can explicitly declare that its base layer has
            # no repository at all.  Extensions in such a base are not new
            # repository layers merely because the adapter has discovered them
            # after the configuration file was written.  Inherit only this
            # unambiguous no-repository fact; never inherit a manual/automatic
            # repository policy to an extension.
            base_layer = base_item["development_layers"].get("base")
            base_repository = base_layer.get("repository") if isinstance(base_layer, dict) and isinstance(base_layer.get("repository"), dict) else None
            base_mode = str((base_repository or {}).get("mode") or (base_repository or {}).get("lock_mode") or "").strip().casefold()
            base_connection = str((base_repository or {}).get("connection_state") or "").strip().casefold()
            if layer_id != "base" and (base_mode == "none" or base_connection == "not_configured"):
                item = {"mode": "none", "connection_state": "not_configured", "inherited_from_layer": "base"}
            else:
                return None, layer_error
    # Legacy repository-only configuration remains readable for the base layer.
    if item is None and layer_id == "base" and isinstance(base_item, dict):
        item = base_item.get("repository")
    if item is None:
        values, repository_error = _load_json_map("ONEC_REPOSITORY_BASES_JSON", "ONEC_REPOSITORY_BASES_JSON_FILE")
        if repository_error and layer_error:
            return None, repository_error
        item = values.get(base_id) if values else None
    if item is None:
        return None, {"status": "not_configured", "message": f"No repository configuration for base_id '{base_id}'."}
    if not isinstance(item, dict):
        return None, {"status": "invalid_config", "message": f"Repository configuration for '{base_id}' must be an object."}
    configured = dict(item)
    configured["mode"] = str(configured.get("mode") or configured.get("lock_mode") or "automatic").strip().casefold()
    if configured["mode"] not in SUPPORTED_REPOSITORY_MODES:
        return None, {"status": "invalid_config", "message": "repository mode must be none, manual, automatic, or unknown."}
    default_connection_state = "unknown" if configured["mode"] == "unknown" else ("not_configured" if configured["mode"] == "none" else "configured")
    configured["connection_state"] = str(configured.get("connection_state") or configured.get("repository_connection") or configured.get("connection") or default_connection_state).strip().casefold()
    if configured["connection_state"] not in SUPPORTED_REPOSITORY_CONNECTION_STATES:
        return None, {"status": "invalid_config", "message": "repository connection_state must be not_configured, configured, unavailable, or unknown."}
    if configured["mode"] == "unknown":
        return {"mode": "unknown", "lock_mode": "manual", "connection_state": configured["connection_state"], "layer_id": layer_id, "layer": layer_id}, None
    if configured["mode"] == "none":
        return {
            "mode": "none", "lock_mode": "manual", "connection_state": configured["connection_state"],
            "layer_id": layer_id, "layer": layer_id,
            **({"inherited_from_layer": configured["inherited_from_layer"]} if configured.get("inherited_from_layer") else {}),
        }, None
    configured["backend"] = str(configured.get("backend") or "direct").strip().casefold()
    configured["layer_id"] = layer_id
    configured["layer"] = layer_id
    configured["lock_mode"] = configured["mode"]
    if configured["backend"] not in SUPPORTED_BACKENDS:
        return None, {"status": "invalid_config", "message": "repository backend must be direct or karman_bridge."}
    if configured["lock_mode"] not in SUPPORTED_LOCK_MODES:
        return None, {"status": "invalid_config", "message": "repository lock_mode must be automatic or manual."}
    runner = configured.get("runner") if isinstance(configured.get("runner"), dict) else {}
    configured["runner"] = runner
    runner_kind = str(runner.get("kind") or "local").strip().casefold()
    if runner_kind not in {"local", "http"}:
        return None, {"status": "invalid_config", "message": "repository runner.kind must be local or http."}
    runner["kind"] = runner_kind
    required = ("endpoint", "designer_path") if runner_kind == "local" and configured["lock_mode"] == "automatic" else ()
    for key in required:
        if not str(configured.get(key) or "").strip():
            return None, {"status": "invalid_config", "message": f"Repository configuration requires {key}."}
    if runner_kind == "http" and configured["lock_mode"] == "automatic" and not str(runner.get("url") or "").strip():
        return None, {"status": "invalid_config", "message": "repository runner.url is required for runner.kind=http."}
    infobase = configured.get("infobase")
    if runner_kind == "local" and configured["lock_mode"] == "automatic" and (not isinstance(infobase, dict) or sum(bool(str(infobase.get(key) or "").strip()) for key in ("file", "server", "name")) != 1):
        return None, {"status": "invalid_config", "message": "infobase must contain exactly one of file, server, or name for runner.kind=local."}
    return configured, None


def manual_confirmation_required(config: dict[str, Any]) -> bool:
    """Whether SQL-only operation needs the user's exact Configurator capture confirmation."""
    if config.get("mode") in {"none", "unknown"} or config.get("connection_state") == "not_configured":
        return False
    return config.get("connection_state") == "unavailable" or config.get("lock_mode") == "manual" or not external_1c_enabled()


def manual_confirmation_next_call(base_id: str, request_id: str) -> dict[str, Any]:
    """Machine-readable continuation; clients must not infer confirmation keys."""
    return {
        "method": METHOD_CONFIRM,
        "params": {
            "base_id": base_id,
            "request_id": request_id,
            "user_confirmed_locked": True,
        },
    }


def _secret(config: dict[str, Any], field: str) -> str:
    env_name = str(config.get(f"{field}_env") or "").strip()
    return os.environ.get(env_name, "") if env_name else ""


def _public_config(config: dict[str, Any]) -> dict[str, Any]:
    return {
        "mode": config.get("mode") or config.get("lock_mode"),
        "layer_id": config.get("layer_id") or config.get("layer"),
        "backend": config.get("backend"),
        "layer": config.get("layer"),
        "lock_mode": config.get("lock_mode"),
        "connection_state": config.get("connection_state"),
        "inherited_from_layer": config.get("inherited_from_layer"),
        "adapter_access_mode": "sql_only" if not external_1c_enabled() else "sql_and_external_1c",
        "automatic_repository_operations_available": external_1c_enabled(),
        "endpoint": config.get("endpoint"),
        "bridge_id": config.get("bridge_id") if config.get("backend") == "karman_bridge" else None,
        "runtime_version": config.get("runtime_version"),
        "runner_kind": (config.get("runner") or {}).get("kind"),
        "runner_url": (config.get("runner") or {}).get("url"),
        "runner_token_env": (config.get("runner") or {}).get("token_env"),
        "repository_user": str(config.get("repository_user") or ""),
        "repository_password_env": str(config.get("repository_password_env") or ""),
        "repository_user_configured": bool(str(config.get("repository_user") or "").strip()),
        "repository_password_configured": bool(_secret(config, "repository_password")),
        "infobase_user": str(config.get("infobase_user") or ""),
        "infobase_password_env": str(config.get("infobase_password_env") or ""),
        "infobase_user_configured": bool(str(config.get("infobase_user") or "").strip()),
        "infobase_password_configured": bool(_secret(config, "infobase_password")),
    }


def public_development_layers(base_id: str) -> dict[str, Any]:
    base_item, error = _base_settings(base_id)
    if error or not isinstance(base_item, dict):
        return {}
    layers = base_item.get("development_layers") if isinstance(base_item.get("development_layers"), dict) else {}
    result: dict[str, Any] = {}
    for layer_id, layer in layers.items():
        if not isinstance(layer, dict):
            continue
        repository, repository_error = repository_config(base_id, str(layer_id))
        support = layer.get("support") if isinstance(layer.get("support"), dict) else {"mode": "unknown"}
        result[str(layer_id)] = {
            "repository": _public_config(repository) if repository and not repository_error else {"status": "invalid", "problem": repository_error},
            "support": {"mode": str(support.get("mode") or "unknown"), "rules": dict(support.get("rules") or {}) if isinstance(support.get("rules"), dict) else {}},
        }
    return result


def _infobase_args(config: dict[str, Any]) -> list[str]:
    infobase = config["infobase"]
    if infobase.get("file"):
        args = ["/F", str(infobase["file"])]
    elif infobase.get("server"):
        args = ["/S", str(infobase["server"])]
    else:
        args = ["/IBName", str(infobase["name"])]
    user = str(config.get("infobase_user") or "").strip()
    if user:
        args += ["/N", user]
        password = _secret(config, "infobase_password")
        if password:
            args += ["/P", password]
    return args


def _repository_args(config: dict[str, Any]) -> list[str]:
    args = ["/ConfigurationRepositoryF", str(config["endpoint"])]
    user = str(config.get("repository_user") or "").strip()
    if user:
        args += ["/ConfigurationRepositoryN", user]
        password = _secret(config, "repository_password")
        if password:
            args += ["/ConfigurationRepositoryP", password]
    extension = str(config.get("extension") or "").strip()
    if extension:
        args += ["-Extension", extension]
    return args


def _safe_excerpt(value: str, config: dict[str, Any], limit: int = 4000) -> str:
    safe = value
    for secret in (_secret(config, "repository_password"), _secret(config, "infobase_password")):
        if secret:
            safe = safe.replace(secret, "[REDACTED]")
    return safe[-limit:]


def _run_designer(config: dict[str, Any], operation: list[str], timeout_seconds: int) -> dict[str, Any]:
    started = time.monotonic()
    with tempfile.TemporaryDirectory(prefix="onec-repository-") as directory:
        log_path = Path(directory) / "designer.log"
        args = [str(config["designer_path"]), "DESIGNER"]
        args += _infobase_args(config)
        args += ["/DisableStartupMessages", "/DisableStartupDialogs", "/Out", str(log_path)]
        args += _repository_args(config)
        args += operation
        try:
            completed = subprocess.run(args, capture_output=True, text=True, timeout=timeout_seconds, check=False)
        except subprocess.TimeoutExpired as exc:
            return {
                "status": "timeout",
                "exit_code": None,
                "duration_ms": round((time.monotonic() - started) * 1000),
                "output": _safe_excerpt(str(exc.stdout or "") + str(exc.stderr or ""), config),
            }
        except OSError as exc:
            return {"status": "runner_error", "exit_code": None, "message": str(exc), "duration_ms": round((time.monotonic() - started) * 1000)}
        log = ""
        try:
            log = log_path.read_text(encoding="utf-8-sig", errors="replace")
        except OSError:
            pass
        output = "\n".join(part for part in (completed.stdout, completed.stderr, log) if part)
        return {
            "status": "ok" if completed.returncode == 0 else "failed",
            "exit_code": completed.returncode,
            "duration_ms": round((time.monotonic() - started) * 1000),
            "output": _safe_excerpt(output, config),
        }


def activation_debug_probe(
    base_id: str,
    config: dict[str, Any],
    *,
    layer: str,
    timeout_seconds: int,
    request_id: str = "",
    fingerprint: str = "",
) -> dict[str, Any]:
    """Probe runner readiness without starting Designer or reading configured credentials."""

    runner = config.get("runner") if isinstance(config.get("runner"), dict) else {"kind": "local"}
    runner_kind = str(runner.get("kind") or "local").strip().casefold()
    if runner_kind == "http":
        url = str(runner.get("url") or "").rstrip("/") + "/configuration/activation/debug"
        request_body = {
            "base_id": base_id,
            "layer": layer,
            "mode": "debug",
        }
        if request_id and fingerprint:
            request_body["request_id"] = request_id
            request_body["fingerprint"] = fingerprint
        body = json.dumps(
            request_body,
            ensure_ascii=False,
        ).encode("utf-8")
        headers = {"Content-Type": "application/json", "Accept": "application/json"}
        token_env = str(runner.get("token_env") or "").strip()
        token = os.environ.get(token_env, "") if token_env else ""
        if token:
            headers["Authorization"] = f"Bearer {token}"
        try:
            with urllib.request.urlopen(
                urllib.request.Request(url, data=body, headers=headers, method="POST"),
                timeout=timeout_seconds,
            ) as response:
                result = json.loads(response.read().decode("utf-8"))
        except urllib.error.HTTPError as exc:
            try:
                result = json.loads(exc.read().decode("utf-8"))
            except (OSError, json.JSONDecodeError, UnicodeDecodeError):
                result = {
                    "status": "runner_error",
                    "message": f"Activation debug runner returned HTTP {exc.code}.",
                }
            return result if isinstance(result, dict) else {
                "status": "runner_error",
                "message": f"Activation debug runner returned HTTP {exc.code}.",
            }
        except (OSError, urllib.error.URLError, json.JSONDecodeError) as exc:
            return {"status": "runner_error", "message": str(exc)}
        return result if isinstance(result, dict) else {
            "status": "runner_error",
            "message": "Activation debug runner returned a non-object response.",
        }
    infobase = config.get("infobase") if isinstance(config.get("infobase"), dict) else {}
    selector_configured = (
        sum(bool(str(infobase.get(key) or "").strip()) for key in ("file", "server", "name")) == 1
    )
    designer_path = str(config.get("designer_path") or "").strip()
    try:
        designer_available = bool(designer_path and Path(designer_path).is_file())
    except OSError:
        designer_available = False
    ready = bool(selector_configured and designer_available)
    debug_acceptance = None
    if request_id and fingerprint:
        receipt_source = json.dumps(
            {
                "base_id": base_id,
                "layer": layer,
                "request_id": request_id,
                "fingerprint": fingerprint,
                "mode": "debug",
            },
            ensure_ascii=False,
            sort_keys=True,
            separators=(",", ":"),
        ).encode("utf-8")
        debug_acceptance = {
            "accepted": ready,
            "request_id": request_id,
            "fingerprint": fingerprint,
            "receipt": hashlib.sha256(receipt_source).hexdigest() if ready else None,
        }
    return {
        "schema": "onec_configuration_activation_runner_probe.v1",
        "status": "ready" if ready else "not_ready",
        "base_id": base_id,
        "layer": layer,
        "runner": {
            "kind": "local",
            "reachable": True,
            "designer_path_configured": bool(designer_path),
            "designer_available": designer_available,
            "infobase_selector_configured": selector_configured,
        },
        "operation": {
            "kind": "/UpdateDBCfg" if layer == "base_saved_state" else None,
            "execution_supported": False,
            "extension_manual_only": layer in {"all", "extension_saved_state"},
        },
        "debug_acceptance": debug_acceptance,
        "execution": {
            "mode": "debug",
            "performed": False,
            "designer_started": False,
            "active_configuration_changed": False,
        },
    }


def _execute_repository(
    base_id: str,
    config: dict[str, Any],
    action: str,
    timeout_seconds: int,
    *,
    objects: list[str] | None = None,
    comment: str = "",
    keep_locked: bool = False,
) -> dict[str, Any]:
    if not external_1c_enabled():
        return {
            "status": "external_1c_disabled",
            "message": "This adapter version is SQL-only. Use repository.lock.plan and the manual confirmation workflow.",
        }
    runner = config.get("runner") if isinstance(config.get("runner"), dict) else {"kind": "local"}
    if runner.get("kind") == "http":
        url = str(runner.get("url") or "").rstrip("/") + "/repository/execute"
        body = json.dumps(
            {"base_id": base_id, "action": action, "objects": objects or [], "comment": comment, "keep_locked": keep_locked},
            ensure_ascii=False,
        ).encode("utf-8")
        headers = {"Content-Type": "application/json", "Accept": "application/json"}
        token_env = str(runner.get("token_env") or "").strip()
        token = os.environ.get(token_env, "") if token_env else ""
        if token:
            headers["Authorization"] = f"Bearer {token}"
        try:
            with urllib.request.urlopen(urllib.request.Request(url, data=body, headers=headers, method="POST"), timeout=timeout_seconds) as response:
                result = json.loads(response.read().decode("utf-8"))
        except urllib.error.HTTPError as exc:
            try:
                result = json.loads(exc.read().decode("utf-8"))
            except (OSError, json.JSONDecodeError, UnicodeDecodeError):
                result = {"status": "runner_error", "message": f"Repository runner returned HTTP {exc.code}."}
            return result if isinstance(result, dict) else {"status": "runner_error", "message": f"Repository runner returned HTTP {exc.code}."}
        except (OSError, urllib.error.URLError, json.JSONDecodeError) as exc:
            return {"status": "runner_error", "message": str(exc)}
        return result if isinstance(result, dict) else {"status": "runner_error", "message": "Repository runner returned a non-object response."}
    if action == "report":
        with tempfile.TemporaryDirectory(prefix="onec-repository-report-") as directory:
            report = Path(directory) / "report.txt"
            return _run_designer(config, ["/ConfigurationRepositoryReport", str(report), "-NBegin", "-1", "-ReportFormat", "txt"], timeout_seconds)
    with tempfile.TemporaryDirectory(prefix="onec-repository-objects-") as directory:
        objects_path = Path(directory) / "objects.txt"
        objects_path.write_text("\n".join(objects or []) + "\n", encoding="utf-8")
        if action == "lock":
            operation = ["/ConfigurationRepositoryLock", "-Objects", str(objects_path)]
        elif action == "unlock":
            operation = ["/ConfigurationRepositoryUnlock", "-Objects", str(objects_path)]
        elif action == "commit":
            operation = ["/ConfigurationRepositoryCommit", "-Objects", str(objects_path), "-Comment", comment]
            if keep_locked:
                operation.append("-KeepLocked")
        else:
            return {"status": "runner_error", "message": f"Unsupported repository action: {action}"}
        return _run_designer(config, operation, timeout_seconds)


_CHILD_MARKERS = re.compile(
    r"\.(?:Реквизит|Attribute|ТабличнаяЧасть|TabularSection|Измерение|Dimension|Ресурс|Resource)\.",
    re.IGNORECASE,
)


def development_object(ref: str) -> str:
    value = ref.strip().strip(".")
    match = _CHILD_MARKERS.search(value)
    if match:
        return value[: match.start()]
    for marker in (".МодульОбъекта", ".ObjectModule", ".МодульМенеджера", ".ManagerModule"):
        if value.casefold().endswith(marker.casefold()):
            return value[: -len(marker)]
    return value


def _requested_objects(payload: dict[str, Any]) -> tuple[list[str] | None, dict[str, Any] | None]:
    raw = payload.get("objects")
    if raw is None:
        raw = [payload.get("object") or payload.get("ref") or payload.get("path")]
    if not isinstance(raw, list) or not raw:
        return None, {"status": "invalid_argument", "argument": "objects", "message": "Pass object/ref/path or a non-empty objects array."}
    values: list[str] = []
    for index, item in enumerate(raw):
        if not isinstance(item, str) or not item.strip():
            return None, {"status": "invalid_argument", "argument": f"objects[{index}]", "message": "Repository object must be a non-empty public 1C reference."}
        resolved = development_object(item)
        if resolved not in values:
            values.append(resolved)
    return values, None


def lock_plan(payload: dict[str, Any]) -> dict[str, Any]:
    objects, error = _requested_objects(payload)
    if error:
        return {"schema": "onec_repository_lock_plan.v1", "method": METHOD_LOCK_PLAN, **error}
    operation = str(payload.get("operation") or "modify").strip().casefold()
    warnings: list[dict[str, str]] = []
    if operation in {"add", "delete", "rename"}:
        warnings.append({"code": "parent_scope_requires_confirmation", "message": "Structural operations can require the parent/root and referenced objects; confirm the complete set before lock/apply."})
    result = {
        "schema": "onec_repository_lock_plan.v1",
        "method": METHOD_LOCK_PLAN,
        "status": "ready" if not warnings else "needs_confirmation",
        "scope_status": "resolved",
        "operation": operation,
        "requested_objects": [str(x) for x in (payload.get("objects") or [payload.get("object") or payload.get("ref") or payload.get("path")])],
        "lock_objects": objects,
        "warnings": warnings,
        "native_lock_state": "unknown",
        "native_lock_verification": "not_available_via_infobase_sql" if not external_1c_enabled() else "not_checked",
        "capture_required": None,
        "sql_resolution": payload.get("sql_resolution") if isinstance(payload.get("sql_resolution"), list) else [],
    }
    base_id = str(payload.get("base_id") or "").strip()
    if base_id:
        layer_id = development_layer_id(payload)
        result["layer_id"] = layer_id
        config, config_error = repository_config(base_id, layer_id)
        if config_error:
            result["repository_problem"] = config_error
        elif config.get("mode") == "unknown" or config.get("connection_state") == "unknown":
            result["workflow"] = "blocked"
            result["status"] = "blocked_repository_connection_unknown"
            result["next_method"] = None
        elif config.get("mode") == "none" or config.get("connection_state") == "not_configured":
            result["workflow"] = "not_required"
            result["next_method"] = None
        elif manual_confirmation_required(config):
            result["workflow"] = "manual"
            result["next_method"] = METHOD_LOCK_REQUEST if not external_1c_enabled() else METHOD_CONFIRM
            result["user_action"] = {
                "action": "confirm_lock_in_configurator",
                "base_id": base_id,
                "objects": objects,
                "message": "SQL информационной базы не показывает нативное состояние захвата. Убедитесь в Конфигураторе, что перечисленные объекты уже захвачены указанным пользователем хранилища, и явно подтвердите тот же список через repository.lock.confirm.",
            }
        else:
            result["workflow"] = "automatic"
            result["next_method"] = METHOD_LOCK
    return result


def create_lock_request(payload: dict[str, Any]) -> dict[str, Any]:
    base_id = str(payload.get("base_id") or "").strip()
    layer_id = development_layer_id(payload)
    config, error = repository_config(base_id, layer_id)
    if error:
        return {"schema": "onec_repository_lock_request.v1", "method": METHOD_LOCK_REQUEST, "base_id": base_id, **error}
    plan = lock_plan(payload)
    if plan.get("workflow") == "not_required":
        return {"schema": "onec_repository_lock_request.v1", "method": METHOD_LOCK_REQUEST, "base_id": base_id, "layer_id": layer_id, "status": "not_required", "plan": plan}
    if plan.get("status") == "needs_confirmation" and payload.get("confirm_repository_scope") is True:
        plan["status"] = "ready"
    if plan.get("status") != "ready":
        return {"schema": "onec_repository_lock_request.v1", "method": METHOD_LOCK_REQUEST, "base_id": base_id, "status": "blocked", "plan": plan}
    configured_repository_user = str(config.get("repository_user") or "").strip()
    requested_repository_user = str(payload.get("confirmed_repository_user") or payload.get("repository_user") or "").strip()
    if requested_repository_user and configured_repository_user and requested_repository_user.casefold() != configured_repository_user.casefold():
        return {
            "schema": "onec_repository_lock_request.v1", "method": METHOD_LOCK_REQUEST,
            "base_id": base_id, "layer_id": layer_id, "status": "blocked",
            "error": "repository_user_mismatch", "expected_repository_user": configured_repository_user,
        }
    repository_user = requested_repository_user or configured_repository_user
    request_id = "rreq-" + uuid.uuid4().hex
    with _state_transaction() as state:
        state.setdefault("requests", {})[request_id] = {
            "base_id": base_id,
            "layer": layer_id,
            "layer_id": layer_id,
            "backend": config.get("backend"),
            "operation": plan.get("operation"),
            "objects": plan["lock_objects"],
            "created_at": time.time(),
            "status": "pending_user_lock",
            "execution": "manual",
            "repository_user": repository_user,
            "sql_resolution": payload.get("sql_resolution") if isinstance(payload.get("sql_resolution"), list) else [],
        }
        _audit(state, "lock_request_created", request_id=request_id, base_id=base_id, objects=plan["lock_objects"])
    return {
        "schema": "onec_repository_lock_request.v1", "method": METHOD_LOCK_REQUEST,
        "base_id": base_id, "layer_id": layer_id, "status": "pending_user_lock", "request_id": request_id,
        "objects": plan["lock_objects"], "automatically_locked": False,
        "sql_resolution": payload.get("sql_resolution") if isinstance(payload.get("sql_resolution"), list) else [],
        "native_lock_state": "unknown",
        "native_lock_verification": "not_available_via_infobase_sql",
        "capture_required": None,
        "repository_user": repository_user or None,
        "repository_user_source": "layer_connection_setting" if configured_repository_user and not requested_repository_user else ("request" if requested_repository_user else "not_configured"),
        "user_action": "Убедитесь в Конфигураторе, что перечисленные объекты захвачены вами под настроенным пользователем хранилища, и явно подтвердите захват через repository.lock.confirm.",
        "next_method": METHOD_CONFIRM,
        "next_call": manual_confirmation_next_call(base_id, request_id),
    }


def lock_request_status(payload: dict[str, Any]) -> dict[str, Any]:
    request_id = str(payload.get("request_id") or "").strip()
    request = (_read_state().get("requests") or {}).get(request_id)
    if not isinstance(request, dict):
        return {"schema": "onec_repository_lock_request_status.v1", "method": METHOD_LOCK_REQUEST_STATUS, "status": "not_found", "request_id": request_id}
    result = {
        "schema": "onec_repository_lock_request_status.v1",
        "method": METHOD_LOCK_REQUEST_STATUS,
        "status": request.get("status"),
        "request_id": request_id,
        # Surface the manual-confirmation scope at top level.  Requiring
        # callers to inspect an opaque persisted request made a pending lock
        # look context-free and encouraged unsafe confirmation guesses.
        "base_id": request.get("base_id"),
        "layer_id": request.get("layer_id") or request.get("layer"),
        "objects": list(request.get("objects") or []),
        "repository_user": request.get("repository_user") or None,
        "native_lock_state": "unknown",
        "request": request,
    }
    if request.get("status") == "pending_user_lock":
        result["next_method"] = METHOD_CONFIRM
        result["next_call"] = manual_confirmation_next_call(str(request.get("base_id") or ""), request_id)
    return result


def cancel_lock_request(payload: dict[str, Any]) -> dict[str, Any]:
    request_id = str(payload.get("request_id") or "").strip()
    if payload.get("confirm_cancel") is not True:
        return {"schema": "onec_repository_lock_request_cancel.v1", "method": METHOD_LOCK_REQUEST_CANCEL, "status": "confirmation_required", "request_id": request_id}
    with _state_transaction() as state:
        request = (state.get("requests") or {}).get(request_id)
        if not isinstance(request, dict):
            return {"schema": "onec_repository_lock_request_cancel.v1", "method": METHOD_LOCK_REQUEST_CANCEL, "status": "not_found", "request_id": request_id}
        if request.get("status") != "pending_user_lock":
            return {"schema": "onec_repository_lock_request_cancel.v1", "method": METHOD_LOCK_REQUEST_CANCEL, "status": "blocked", "error": "lock_request_not_pending", "request_id": request_id}
        request["status"] = "cancelled"
        request["cancelled_at"] = time.time()
        _audit(state, "lock_request_cancelled", request_id=request_id, base_id=request.get("base_id"), objects=request.get("objects"))
    return {"schema": "onec_repository_lock_request_cancel.v1", "method": METHOD_LOCK_REQUEST_CANCEL, "status": "cancelled", "request_id": request_id}


def _state_path() -> Path:
    """Legacy JSON path used only for one-time migration to local SQLite."""

    return Path(os.environ.get("ONEC_REPOSITORY_STATE_FILE") or "/data/onec-repository-locks.json")


def _state_db_path() -> Path:
    """Adapter-local state database; never points at a configured 1C database."""

    configured = os.environ.get("ONEC_ADAPTER_STATE_DB") or os.environ.get("ONEC_ADAPTER_CACHE_DB")
    if configured:
        return Path(configured)
    legacy_override = os.environ.get("ONEC_REPOSITORY_STATE_FILE")
    if legacy_override:
        return Path(legacy_override).with_suffix(".sqlite")
    return Path("/data/adapter-cache.sqlite")


def _empty_state() -> dict[str, Any]:
    return {"sessions": {}, "requests": {}, "audit": []}


def _read_legacy_state() -> dict[str, Any]:
    try:
        value = json.loads(_state_path().read_text(encoding="utf-8-sig"))
        return value if isinstance(value, dict) else _empty_state()
    except (OSError, json.JSONDecodeError):
        return _empty_state()


def _state_connection() -> sqlite3.Connection:
    path = _state_db_path()
    path.parent.mkdir(parents=True, exist_ok=True)
    conn = sqlite3.connect(path, timeout=30)
    conn.row_factory = sqlite3.Row
    conn.execute("PRAGMA journal_mode=WAL")
    conn.execute("PRAGMA synchronous=NORMAL")
    conn.execute("PRAGMA busy_timeout=30000")
    conn.execute(
        """
        CREATE TABLE IF NOT EXISTS adapter_state_meta (
            key TEXT PRIMARY KEY,
            value TEXT,
            updated_at REAL NOT NULL
        )
        """
    )
    conn.execute(
        """
        CREATE TABLE IF NOT EXISTS repository_lock_requests (
            request_id TEXT PRIMARY KEY,
            base_id TEXT NOT NULL,
            layer_id TEXT NOT NULL,
            status TEXT NOT NULL,
            created_at REAL NOT NULL,
            updated_at REAL NOT NULL,
            payload_json TEXT NOT NULL
        )
        """
    )
    conn.execute(
        """
        CREATE TABLE IF NOT EXISTS repository_lock_sessions (
            lock_session_id TEXT PRIMARY KEY,
            base_id TEXT NOT NULL,
            layer_id TEXT NOT NULL,
            status TEXT NOT NULL,
            created_at REAL NOT NULL,
            updated_at REAL NOT NULL,
            payload_json TEXT NOT NULL
        )
        """
    )
    conn.execute(
        """
        CREATE TABLE IF NOT EXISTS repository_lock_events (
            event_id TEXT PRIMARY KEY,
            event TEXT NOT NULL,
            occurred_at REAL NOT NULL,
            base_id TEXT,
            request_id TEXT,
            lock_session_id TEXT,
            details_json TEXT NOT NULL
        )
        """
    )
    conn.execute(
        "CREATE INDEX IF NOT EXISTS idx_repository_lock_requests_base_status "
        "ON repository_lock_requests(base_id, status, created_at)"
    )
    conn.execute(
        "CREATE INDEX IF NOT EXISTS idx_repository_lock_sessions_base_status "
        "ON repository_lock_sessions(base_id, status, created_at)"
    )
    conn.execute(
        "CREATE INDEX IF NOT EXISTS idx_repository_lock_events_base_time "
        "ON repository_lock_events(base_id, occurred_at)"
    )
    conn.execute(
        """
        INSERT INTO adapter_state_meta(key, value, updated_at)
        VALUES('adapter_state_schema_version', ?, ?)
        ON CONFLICT(key) DO UPDATE SET
            value=CASE
                WHEN CAST(adapter_state_meta.value AS INTEGER) < CAST(excluded.value AS INTEGER)
                THEN excluded.value
                ELSE adapter_state_meta.value
            END,
            updated_at=excluded.updated_at
        """,
        (str(REPOSITORY_STATE_SCHEMA_VERSION), time.time()),
    )
    migration = conn.execute(
        "SELECT value FROM adapter_state_meta WHERE key='legacy_repository_state_imported'"
    ).fetchone()
    if not migration:
        legacy = _read_legacy_state()
        _sync_state_to_connection(conn, legacy)
        conn.execute(
            "INSERT INTO adapter_state_meta(key, value, updated_at) VALUES(?, ?, ?)",
            ("legacy_repository_state_imported", "1", time.time()),
        )
    conn.commit()
    return conn


def _event_id(row: dict[str, Any], index: int) -> str:
    explicit = str(row.get("event_id") or "").strip()
    if explicit:
        return explicit
    source = json.dumps(
        {
            "index": index,
            "event": row.get("event"),
            "time": row.get("time"),
            "request_id": row.get("request_id"),
            "lock_session_id": row.get("lock_session_id"),
            "base_id": row.get("base_id"),
        },
        ensure_ascii=False,
        sort_keys=True,
        separators=(",", ":"),
    )
    return "legacy-" + hashlib.sha1(source.encode("utf-8")).hexdigest()


def _load_state_from_connection(conn: sqlite3.Connection) -> dict[str, Any]:
    state = _empty_state()
    for row in conn.execute("SELECT request_id, payload_json FROM repository_lock_requests"):
        try:
            payload = json.loads(row["payload_json"])
        except (TypeError, json.JSONDecodeError):
            continue
        if isinstance(payload, dict):
            state["requests"][str(row["request_id"])] = payload
    for row in conn.execute("SELECT lock_session_id, payload_json FROM repository_lock_sessions"):
        try:
            payload = json.loads(row["payload_json"])
        except (TypeError, json.JSONDecodeError):
            continue
        if isinstance(payload, dict):
            state["sessions"][str(row["lock_session_id"])] = payload
    for row in conn.execute(
        "SELECT event_id, event, occurred_at, details_json FROM repository_lock_events "
        "ORDER BY occurred_at, event_id"
    ):
        try:
            payload = json.loads(row["details_json"])
        except (TypeError, json.JSONDecodeError):
            payload = {}
        if not isinstance(payload, dict):
            payload = {}
        payload.setdefault("event_id", str(row["event_id"]))
        payload.setdefault("event", str(row["event"]))
        payload.setdefault("time", float(row["occurred_at"]))
        state["audit"].append(payload)
    return state


def _sync_state_to_connection(conn: sqlite3.Connection, value: dict[str, Any]) -> None:
    now = time.time()
    for request_id, raw in (value.get("requests") or {}).items():
        if not isinstance(raw, dict):
            continue
        request = dict(raw)
        created_at = float(request.get("created_at") or now)
        updated_at = float(
            request.get("cancelled_at")
            or request.get("confirmed_at")
            or request.get("closed_at")
            or request.get("expired_at")
            or created_at
        )
        conn.execute(
            """
            INSERT INTO repository_lock_requests(
                request_id, base_id, layer_id, status, created_at, updated_at, payload_json
            ) VALUES(?, ?, ?, ?, ?, ?, ?)
            ON CONFLICT(request_id) DO UPDATE SET
                base_id=excluded.base_id,
                layer_id=excluded.layer_id,
                status=excluded.status,
                updated_at=excluded.updated_at,
                payload_json=excluded.payload_json
            """,
            (
                str(request_id),
                str(request.get("base_id") or ""),
                str(request.get("layer_id") or request.get("layer") or "base"),
                str(request.get("status") or "unknown"),
                created_at,
                updated_at,
                json.dumps(request, ensure_ascii=False, separators=(",", ":")),
            ),
        )
    for session_id, raw in (value.get("sessions") or {}).items():
        if not isinstance(raw, dict):
            continue
        session = dict(raw)
        created_at = float(session.get("created_at") or now)
        updated_at = float(
            session.get("committed_at")
            or session.get("released_at")
            or session.get("closed_at")
            or session.get("expired_at")
            or created_at
        )
        conn.execute(
            """
            INSERT INTO repository_lock_sessions(
                lock_session_id, base_id, layer_id, status, created_at, updated_at, payload_json
            ) VALUES(?, ?, ?, ?, ?, ?, ?)
            ON CONFLICT(lock_session_id) DO UPDATE SET
                base_id=excluded.base_id,
                layer_id=excluded.layer_id,
                status=excluded.status,
                updated_at=excluded.updated_at,
                payload_json=excluded.payload_json
            """,
            (
                str(session_id),
                str(session.get("base_id") or ""),
                str(session.get("layer_id") or session.get("layer") or "base"),
                str(session.get("status") or "unknown"),
                created_at,
                updated_at,
                json.dumps(session, ensure_ascii=False, separators=(",", ":")),
            ),
        )
    audit = [row for row in (value.get("audit") or []) if isinstance(row, dict)][-5000:]
    for index, raw in enumerate(audit):
        event = dict(raw)
        event_id = _event_id(event, index)
        event["event_id"] = event_id
        occurred_at = float(event.get("time") or now)
        conn.execute(
            """
            INSERT OR IGNORE INTO repository_lock_events(
                event_id, event, occurred_at, base_id, request_id, lock_session_id, details_json
            ) VALUES(?, ?, ?, ?, ?, ?, ?)
            """,
            (
                event_id,
                str(event.get("event") or "unknown"),
                occurred_at,
                str(event.get("base_id") or "") or None,
                str(event.get("request_id") or "") or None,
                str(event.get("lock_session_id") or "") or None,
                json.dumps(event, ensure_ascii=False, separators=(",", ":")),
            ),
        )


def _expire_state(state: dict[str, Any]) -> bool:
    changed = False
    now = time.time()
    request_ttl = max(60, int(os.environ.get("ONEC_REPOSITORY_REQUEST_TTL_SECONDS") or 86400))
    session_ttl = max(60, int(os.environ.get("ONEC_REPOSITORY_CONFIRMATION_TTL_SECONDS") or 7200))
    for request in (state.get("requests") or {}).values():
        if isinstance(request, dict) and request.get("status") == "pending_user_lock" and now - float(request.get("created_at") if request.get("created_at") is not None else now) > request_ttl:
            request["status"] = "expired"
            request["expired_at"] = now
            changed = True
    for session in (state.get("sessions") or {}).values():
        if isinstance(session, dict) and session.get("status") == "manual_confirmed" and now - float(session.get("created_at") if session.get("created_at") is not None else now) > session_ttl:
            session["status"] = "expired"
            session["expired_at"] = now
            changed = True
    return changed


def _read_state() -> dict[str, Any]:
    with _STATE_LOCK:
        with _state_connection() as conn:
            state = _load_state_from_connection(conn)
            if _expire_state(state):
                conn.execute("BEGIN IMMEDIATE")
                _sync_state_to_connection(conn, state)
                conn.commit()
    return state


def _write_state(value: dict[str, Any]) -> None:
    with _STATE_LOCK:
        with _state_connection() as conn:
            conn.execute("BEGIN IMMEDIATE")
            _sync_state_to_connection(conn, value)
            conn.commit()


@contextmanager
def _state_transaction() -> Any:
    """Serialize a repository state mutation across adapter processes."""

    with _STATE_LOCK:
        conn = _state_connection()
        try:
            conn.execute("BEGIN IMMEDIATE")
            state = _load_state_from_connection(conn)
            _expire_state(state)
            yield state
            _sync_state_to_connection(conn, state)
            conn.commit()
        except Exception:
            conn.rollback()
            raise
        finally:
            conn.close()


def _audit(state: dict[str, Any], event: str, **details: Any) -> None:
    rows = state.setdefault("audit", [])
    rows.append({"event_id": "revt-" + uuid.uuid4().hex, "event": event, "time": time.time(), **details})
    if len(rows) > 5000:
        del rows[:-5000]


def admin_state(base_id: str = "") -> dict[str, Any]:
    state = _read_state()
    requests = [{"request_id": key, **row} for key, row in (state.get("requests") or {}).items() if isinstance(row, dict) and (not base_id or row.get("base_id") == base_id)]
    sessions = [{"lock_session_id": key, **row} for key, row in (state.get("sessions") or {}).items() if isinstance(row, dict) and (not base_id or row.get("base_id") == base_id)]
    audit = [row for row in (state.get("audit") or []) if isinstance(row, dict) and (not base_id or row.get("base_id") == base_id)]
    requests.sort(key=lambda row: float(row.get("created_at") or 0), reverse=True)
    sessions.sort(key=lambda row: float(row.get("created_at") or 0), reverse=True)
    audit.sort(key=lambda row: float(row.get("time") or 0), reverse=True)
    return {"schema": "onec_repository_admin_state.v1", "base_id": base_id or None, "requests": requests, "sessions": sessions, "audit": audit[:200], "counts": {"requests": len(requests), "sessions": len(sessions), "audit": len(audit)}}


def status(payload: dict[str, Any]) -> dict[str, Any]:
    base_id = str(payload.get("base_id") or "").strip()
    layer_id = development_layer_id(payload)
    config, error = repository_config(base_id, layer_id)
    if error:
        return {"schema": "onec_repository_status.v1", "method": METHOD_STATUS, "base_id": base_id, "connected": False, **error}
    result: dict[str, Any] = {
        "schema": "onec_repository_status.v1", "method": METHOD_STATUS, "base_id": base_id, "layer_id": layer_id,
        "status": "configured", "connected": True, "available": None, "repository": _public_config(config),
        "sql_lock_evidence": SQL_LOCK_EVIDENCE,
    }
    if config.get("mode") == "none" or config.get("connection_state") == "not_configured":
        result.update({"status": "repository_not_connected", "connected": False, "available": None})
        return result
    if config.get("mode") == "unknown" or config.get("connection_state") == "unknown":
        result.update({"status": "repository_connection_unknown", "connected": False, "available": None})
        return result
    if manual_confirmation_required(config):
        result.update({"status": "manual_confirmation_required", "connected": False, "available": False if config.get("connection_state") == "unavailable" else None})
        if bool(payload.get("probe")):
            result["probe"] = {"status": "not_applicable", "message": "Manual SQL-only workflow does not establish a native repository connection."}
        return result
    if not bool(payload.get("probe")):
        return result
    if not external_1c_enabled():
        result["status"] = "sql_only"
        result["connected"] = False
        result["available"] = None
        result["probe"] = {"status": "not_supported", "message": "External 1C access is disabled in this SQL-only adapter version."}
        return result
    timeout_seconds = int(payload.get("timeout_seconds") or 60)
    executed = _execute_repository(base_id, config, "report", timeout_seconds)
    result["probe"] = executed
    result["available"] = executed.get("status") == "ok"
    result["status"] = "ready" if result["available"] else "blocked_repository_unavailable"
    return result


def lock(payload: dict[str, Any]) -> dict[str, Any]:
    base_id = str(payload.get("base_id") or "").strip()
    layer_id = development_layer_id(payload)
    config, error = repository_config(base_id, layer_id)
    if error:
        return {"schema": "onec_repository_lock.v1", "method": METHOD_LOCK, "base_id": base_id, **error}
    if manual_confirmation_required(config):
        return {
            "schema": "onec_repository_lock.v1", "method": METHOD_LOCK, "base_id": base_id,
            "status": "manual_action_required", "plan": lock_plan(payload), "next_method": METHOD_CONFIRM,
        }
    plan = lock_plan(payload)
    if plan.get("status") == "needs_confirmation" and payload.get("confirm_repository_scope") is True:
        plan["status"] = "ready"
        plan["scope_confirmed"] = True
    if plan.get("status") != "ready":
        return {"schema": "onec_repository_lock.v1", "method": METHOD_LOCK, "base_id": base_id, "status": "blocked", "plan": plan}
    if not payload.get("allow_repository_lock") is True:
        return {"schema": "onec_repository_lock.v1", "method": METHOD_LOCK, "base_id": base_id, "status": "blocked", "error": "explicit_repository_lock_required", "plan": plan}
    layer = str(config.get("layer") or "base")
    with _base_lock(base_id, layer):
        executed = _execute_repository(base_id, config, "lock", int(payload.get("timeout_seconds") or 120), objects=plan["lock_objects"])
        if executed.get("status") != "ok":
            return {"schema": "onec_repository_lock.v1", "method": METHOD_LOCK, "base_id": base_id, "status": "blocked", "error": "repository_lock_failed", "plan": plan, "execution": executed}
        session_id = "rlock-" + uuid.uuid4().hex
        with _state_transaction() as state:
            sessions = state.setdefault("sessions", {})
            sessions[session_id] = {"base_id": base_id, "layer": layer_id, "layer_id": layer_id, "backend": config.get("backend"), "objects": plan["lock_objects"], "created_at": time.time(), "status": "acquired"}
        return {"schema": "onec_repository_lock.v1", "method": METHOD_LOCK, "base_id": base_id, "status": "acquired", "lock_session_id": session_id, "acquired": plan["lock_objects"], "backend": config.get("backend"), "execution": executed}


def confirm_manual_lock(payload: dict[str, Any]) -> dict[str, Any]:
    base_id = str(payload.get("base_id") or "").strip()
    layer_id = development_layer_id(payload)
    config, error = repository_config(base_id, layer_id)
    if error:
        return {"schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id, **error}
    if not manual_confirmation_required(config):
        return {"schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id, "status": "blocked", "error": "manual_lock_mode_required"}
    if not external_1c_enabled() and not str(payload.get("request_id") or "").strip():
        return {"schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id, "status": "blocked", "error": "lock_request_required", "next_method": METHOD_LOCK_REQUEST}
    state = _read_state()
    request_id = str(payload.get("request_id") or "").strip()
    request = (state.get("requests") or {}).get(request_id) if request_id else None
    if request_id and (not isinstance(request, dict) or request.get("base_id") != base_id):
        return {"schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id, "status": "blocked", "error": "lock_request_not_found", "request_id": request_id}
    if isinstance(request, dict) and request.get("status") != "pending_user_lock":
        return {"schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id, "status": "blocked", "error": "lock_request_not_pending", "request_id": request_id}
    effective_payload = dict(payload)
    if isinstance(request, dict):
        layer_id = str(request.get("layer_id") or request.get("layer") or "base")
        config, error = repository_config(base_id, layer_id)
        if error:
            return {"schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id, **error}
        if not manual_confirmation_required(config):
            return {"schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id, "status": "blocked", "error": "manual_lock_mode_required"}
        effective_payload["objects"] = [str(item) for item in request.get("objects") or []]
        effective_payload["layer_id"] = layer_id
        effective_payload["sql_resolution"] = request.get("sql_resolution") if isinstance(request.get("sql_resolution"), list) else []
    if payload.get("user_confirmed_locked") is not True:
        response: dict[str, Any] = {
            "schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM,
            "base_id": base_id, "layer_id": layer_id, "status": "confirmation_required",
            "error": "user_confirmed_locked_required",
            "required_fields": ["base_id", "request_id", "user_confirmed_locked"],
            "next_call": manual_confirmation_next_call(base_id, request_id),
        }
        if isinstance(request, dict):
            response.update({
                "request_id": request_id,
                "objects": list(request.get("objects") or []),
                "repository_user": str(request.get("repository_user") or config.get("repository_user") or "") or None,
                "sql_resolution": effective_payload["sql_resolution"],
            })
        return response
    plan = lock_plan(effective_payload)
    if plan.get("status") == "needs_confirmation" and payload.get("confirm_repository_scope") is True:
        plan["status"] = "ready"
    if plan.get("status") != "ready":
        return {"schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id, "status": "blocked", "plan": plan}
    requested_repository_user = str(payload.get("confirmed_repository_user") or payload.get("repository_user") or "").strip()
    expected_repository_user = str(config.get("repository_user") or "").strip()
    request_repository_user = str(request.get("repository_user") or "").strip() if isinstance(request, dict) else ""
    confirmed_repository_user = requested_repository_user or request_repository_user or expected_repository_user
    if not confirmed_repository_user:
        return {"schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id, "status": "confirmation_required", "error": "repository_user_confirmation_required", "plan": plan}
    if expected_repository_user and confirmed_repository_user.casefold() != expected_repository_user.casefold():
        return {"schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id, "status": "blocked", "error": "repository_user_mismatch", "expected_repository_user": expected_repository_user}
    session_id = "rlock-" + uuid.uuid4().hex
    with _state_transaction() as current_state:
        current_request = (current_state.get("requests") or {}).get(request_id) if request_id else None
        if request_id and (
            not isinstance(current_request, dict)
            or current_request.get("base_id") != base_id
            or current_request.get("status") != "pending_user_lock"
        ):
            return {
                "schema": "onec_repository_manual_lock.v1",
                "method": METHOD_CONFIRM,
                "base_id": base_id,
                "status": "blocked",
                "error": "lock_request_not_pending",
                "request_id": request_id,
            }
        current_state.setdefault("sessions", {})[session_id] = {
            "base_id": base_id, "layer": layer_id, "layer_id": layer_id, "backend": config.get("backend"),
            "objects": plan["lock_objects"], "created_at": time.time(), "status": "manual_confirmed",
            "verification": "user_confirmation_only", "automatically_verified": False,
            "repository_user": confirmed_repository_user,
            **({"request_id": request_id} if request_id else {}),
        }
        if isinstance(current_request, dict):
            current_request["status"] = "confirmed_by_user"
            current_request["confirmed_at"] = time.time()
            current_request["lock_session_id"] = session_id
        _audit(current_state, "manual_lock_confirmed", request_id=request_id or None, lock_session_id=session_id, base_id=base_id, objects=plan["lock_objects"], repository_user=confirmed_repository_user)
    return {
        "schema": "onec_repository_manual_lock.v1", "method": METHOD_CONFIRM, "base_id": base_id,
        "status": "manual_confirmed", "layer_id": layer_id, "lock_session_id": session_id, "request_id": request_id or None, "objects": plan["lock_objects"],
        "capture_state": "manually_confirmed",
        "native_lock_state": "unknown",
        "native_lock_verification": "not_available_via_infobase_sql",
        "automatically_verified": False,
        "repository_user": confirmed_repository_user,
        "write_context": {
            "lock_session_id": session_id,
            "repository_object": plan["lock_objects"][0] if len(plan["lock_objects"]) == 1 else None,
            "layer_id": layer_id,
            "locked_objects": plan["lock_objects"],
            "instruction": "Copy lock_session_id into metadata.write.preflight and code.write. For one object, repository_object is supplied for clients that do not resolve module ownership themselves.",
        },
        "warning": "Адаптер принял явное подтверждение пользователя, но не проверял захват через API хранилища.",
    }


def verify(payload: dict[str, Any]) -> dict[str, Any]:
    session_id = str(payload.get("lock_session_id") or "").strip()
    session = (_read_state().get("sessions") or {}).get(session_id)
    if not isinstance(session, dict):
        return {"schema": "onec_repository_lock_verify.v1", "method": METHOD_VERIFY, "status": "not_found", "lock_session_id": session_id}
    verify_status = "owned_by_adapter" if session.get("status") == "acquired" else ("manual_confirmation_unverified" if session.get("status") == "manual_confirmed" else session.get("status"))
    return {"schema": "onec_repository_lock_verify.v1", "method": METHOD_VERIFY, "status": verify_status, "lock_session_id": session_id, "session": session}


def close_manual_lock(payload: dict[str, Any]) -> dict[str, Any]:
    session_id = str(payload.get("lock_session_id") or "").strip()
    if payload.get("user_confirmed_released") is not True:
        return {"schema": "onec_repository_lock_close.v1", "method": METHOD_CLOSE, "status": "confirmation_required", "lock_session_id": session_id}
    with _state_transaction() as state:
        session = (state.get("sessions") or {}).get(session_id)
        if not isinstance(session, dict):
            return {"schema": "onec_repository_lock_close.v1", "method": METHOD_CLOSE, "status": "not_found", "lock_session_id": session_id}
        if session.get("status") not in {"manual_confirmed", "closed"}:
            return {"schema": "onec_repository_lock_close.v1", "method": METHOD_CLOSE, "status": "blocked", "error": "manual_confirmation_not_active", "lock_session_id": session_id}
        already_closed = session.get("status") == "closed"
        session["status"] = "closed"
        closed_at = float(session.get("closed_at") or time.time())
        session["closed_at"] = closed_at
        request_id = str(session.get("request_id") or "").strip()
        request = (state.get("requests") or {}).get(request_id) if request_id else None
        if not isinstance(request, dict):
            request_id = next(
                (
                    str(candidate_id)
                    for candidate_id, candidate in (state.get("requests") or {}).items()
                    if isinstance(candidate, dict) and candidate.get("lock_session_id") == session_id
                ),
                "",
            )
            request = (state.get("requests") or {}).get(request_id) if request_id else None
        if isinstance(request, dict):
            request["status"] = "closed"
            request["closed_at"] = closed_at
        if not already_closed:
            _audit(state, "manual_lock_closed", request_id=request_id or None, lock_session_id=session_id, base_id=session.get("base_id"), objects=session.get("objects"))
    return {
        "schema": "onec_repository_lock_close.v1", "method": METHOD_CLOSE, "status": "closed",
        "lock_session_id": session_id, "request_id": request_id or None,
    }


def write_gate(payload: dict[str, Any]) -> dict[str, Any]:
    base_id = str(payload.get("base_id") or "").strip()
    layer_id = development_layer_id(payload)
    config, error = repository_config(base_id, layer_id)
    if error and error.get("status") == "not_configured":
        return {"required": False, "allowed": True, "status": "not_configured", "layer_id": layer_id}
    if error:
        return {"required": True, "allowed": False, "status": "blocked_repository_configuration", "layer_id": layer_id, "problem": error}
    if config.get("mode") == "none" or config.get("connection_state") == "not_configured":
        return {"required": False, "allowed": True, "status": "repository_not_connected", "layer_id": layer_id}
    if config.get("mode") == "unknown" or config.get("connection_state") == "unknown":
        return {"required": True, "allowed": False, "status": "blocked_repository_connection_unknown", "layer_id": layer_id}
    session_id = str(payload.get("lock_session_id") or "").strip()
    if not session_id:
        return {
            "required": True, "allowed": False, "status": "needs_repository_lock",
            "backend": config.get("backend"), "layer_id": layer_id, "next_method": METHOD_LOCK_PLAN,
        }
    session = (_read_state().get("sessions") or {}).get(session_id)
    if not isinstance(session, dict):
        return {"required": True, "allowed": False, "status": "blocked_repository_lock_session", "error": "lock_session_not_found", "layer_id": layer_id, "lock_session_id": session_id}
    if session.get("base_id") != base_id:
        return {"required": True, "allowed": False, "status": "blocked_repository_lock_session", "error": "lock_session_base_mismatch", "layer_id": layer_id, "lock_session_id": session_id, "session_base_id": session.get("base_id")}
    session_layer_id = str(session.get("layer_id") or session.get("layer") or "base")
    if session_layer_id != layer_id:
        return {"required": True, "allowed": False, "status": "blocked_repository_lock_session", "error": "lock_layer_mismatch", "layer_id": layer_id, "session_layer_id": session_layer_id, "lock_session_id": session_id}
    if session.get("status") not in {"acquired", "manual_confirmed"}:
        return {"required": True, "allowed": False, "status": "blocked_repository_lock_session", "error": "lock_session_inactive", "layer_id": layer_id, "lock_session_id": session_id, "session_status": session.get("status")}
    target = payload.get("target") if isinstance(payload.get("target"), dict) else {}
    requested = ""
    for value in (
        payload.get("repository_object"), target.get("repository_object"), target.get("canonical_path"),
        payload.get("canonical_path"), target.get("path"), payload.get("path"), payload.get("ref"), payload.get("object"),
    ):
        if isinstance(value, str) and value.strip():
            requested = development_object(value)
            break
    if not requested:
        kind = str(payload.get("object_type") or payload.get("kind") or target.get("object_type") or target.get("kind") or "").strip()
        name = str(payload.get("object_name") or payload.get("name") or target.get("object_name") or target.get("name") or "").strip()
        if kind and name:
            requested = development_object(f"{kind}.{name}")
    if not requested:
        return {
            "required": True, "allowed": False, "status": "blocked_repository_scope_unresolved",
            "lock_session_id": session_id, "message": "Pass repository_object with the public 1C development-object reference for this low-level write route.",
        }
    locked = [str(item) for item in session.get("objects") or []]
    if requested.casefold() not in {item.casefold() for item in locked}:
        return {
            "required": True, "allowed": False, "status": "blocked_repository_scope_mismatch",
            "error": "lock_object_mismatch", "lock_session_id": session_id, "requested_object": requested, "locked_objects": locked,
        }
    return {
        "required": True, "allowed": True, "status": "ready", "backend": config.get("backend"), "layer_id": layer_id,
        "lock_session_id": session_id, "requested_object": requested, "objects": locked,
        "verification": "automatic" if session.get("status") == "acquired" else "user_confirmation_only",
    }


def support_gate(payload: dict[str, Any]) -> dict[str, Any]:
    """Evaluate the independently configured support policy for one exact target.

    Repository scope may collapse a child to its development owner. Support scope
    intentionally does not: a form or another child can have its own support rule.
    """
    base_id = str(payload.get("base_id") or "").strip()
    layer_id = development_layer_id(payload)
    base_item, base_error = _base_settings(base_id)
    if base_error:
        if base_error.get("status") == "not_configured":
            return {"required": False, "allowed": True, "status": "support_not_configured_legacy", "layer_id": layer_id, "source": "legacy_configuration"}
        return {"required": True, "allowed": False, "status": "blocked_support_configuration", "layer_id": layer_id, "problem": base_error}
    layers = base_item.get("development_layers") if isinstance(base_item.get("development_layers"), dict) else None
    if layers is None:
        return {"required": False, "allowed": True, "status": "support_not_configured_legacy", "layer_id": layer_id, "source": "legacy_configuration"}
    layer = layers.get(layer_id)
    if not isinstance(layer, dict):
        # See repository_config(): an explicit repository-less base is the
        # disposable-test profile.  It applies to newly discovered extensions
        # as well, so a missing per-extension policy cannot turn a permitted
        # test write into a false "unknown support" block.
        repository, repository_error = repository_config(base_id, layer_id)
        if repository_error is None and isinstance(repository, dict) and repository.get("mode") == "none":
            return {
                "required": False, "allowed": True,
                "status": "not_on_support_inherited_no_repository",
                "layer_id": layer_id,
                "inherited_from_layer": repository.get("inherited_from_layer"),
            }
        return {"required": True, "allowed": False, "status": "blocked_support_layer_unknown", "layer_id": layer_id}
    support = layer.get("support")
    if not isinstance(support, dict):
        return {"required": True, "allowed": False, "status": "blocked_support_unknown", "layer_id": layer_id, "source": "development_layer_configuration"}
    mode = str(support.get("mode") or "unknown").strip().casefold()
    if mode not in SUPPORTED_SUPPORT_MODES:
        return {"required": True, "allowed": False, "status": "blocked_support_configuration", "layer_id": layer_id, "problem": {"message": "support.mode must be none, editable, locked, rules, or unknown."}}
    if mode == "none":
        return {"required": False, "allowed": True, "status": "not_on_support", "layer_id": layer_id, "mode": mode}
    if mode == "editable":
        return {"required": True, "allowed": True, "status": "support_editable", "layer_id": layer_id, "mode": mode}
    if mode == "locked":
        return {"required": True, "allowed": False, "status": "blocked_by_support", "layer_id": layer_id, "mode": mode}
    target = payload.get("target") if isinstance(payload.get("target"), dict) else {}
    scope = str(target.get("support_scope") or target.get("canonical_path") or target.get("path") or payload.get("support_scope") or payload.get("canonical_path") or payload.get("path") or payload.get("ref") or payload.get("object") or "").strip()
    if mode == "rules" and scope:
        rules = support.get("rules") if isinstance(support.get("rules"), dict) else {}
        candidates = []
        folded = scope.casefold()
        for rule_scope, rule_value in rules.items():
            key = str(rule_scope).strip()
            if key and (folded == key.casefold() or folded.startswith(key.casefold() + ".")):
                candidates.append((len(key), key, str(rule_value or "unknown").strip().casefold()))
        if candidates:
            _, matched_scope, rule = max(candidates)
            allowed = rule in {"editable", "vendor_editable_support_preserved", "not_supported"}
            return {
                "required": True, "allowed": allowed,
                "status": "support_rule_editable" if allowed else ("blocked_by_support_rule" if rule in {"locked", "vendor_not_editable"} else "blocked_support_unknown"),
                "layer_id": layer_id, "mode": mode, "scope": scope, "matched_scope": matched_scope, "rule": rule,
            }
    return {"required": True, "allowed": False, "status": "blocked_support_unknown", "layer_id": layer_id, "mode": mode, "scope": scope or None}


def commit_plan(payload: dict[str, Any]) -> dict[str, Any]:
    session_id = str(payload.get("lock_session_id") or "").strip()
    session = (_read_state().get("sessions") or {}).get(session_id)
    if not isinstance(session, dict):
        return {"schema": "onec_repository_commit_plan.v1", "method": METHOD_COMMIT_PLAN, "status": "not_found", "lock_session_id": session_id}
    comment = str(payload.get("comment") or "").strip()
    problems: list[dict[str, str]] = []
    if session.get("status") != "acquired":
        problems.append({"code": "lock_session_not_acquired", "message": "Commit requires an active adapter lock session."})
    if not comment:
        problems.append({"code": "commit_comment_required", "message": "A non-empty repository version comment is required."})
    return {
        "schema": "onec_repository_commit_plan.v1", "method": METHOD_COMMIT_PLAN,
        "status": "ready" if not problems else "blocked", "allowed": not problems,
        "lock_session_id": session_id, "base_id": session.get("base_id"),
        "objects": session.get("objects") or [], "comment": comment, "problems": problems,
    }


def commit(payload: dict[str, Any]) -> dict[str, Any]:
    plan = commit_plan(payload)
    session_id = str(payload.get("lock_session_id") or "").strip()
    if not plan.get("allowed"):
        return {"schema": "onec_repository_commit.v1", "method": METHOD_COMMIT, "status": "blocked", "lock_session_id": session_id, "plan": plan}
    if payload.get("allow_repository_commit") is not True:
        return {"schema": "onec_repository_commit.v1", "method": METHOD_COMMIT, "status": "blocked", "error": "explicit_repository_commit_required", "lock_session_id": session_id, "plan": plan}
    state = _read_state()
    session = (state.get("sessions") or {}).get(session_id)
    base_id = str(session.get("base_id") or "")
    config, error = repository_config(base_id, str(session.get("layer_id") or session.get("layer") or "base"))
    if error:
        return {"schema": "onec_repository_commit.v1", "method": METHOD_COMMIT, "lock_session_id": session_id, **error}
    with _base_lock(base_id, str(session.get("layer") or "base")):
        executed = _execute_repository(base_id, config, "commit", int(payload.get("timeout_seconds") or 180), objects=[str(item) for item in session.get("objects") or []], comment=str(plan["comment"]), keep_locked=payload.get("keep_locked") is True)
        if executed.get("status") != "ok":
            return {"schema": "onec_repository_commit.v1", "method": METHOD_COMMIT, "status": "blocked", "error": "repository_commit_failed", "lock_session_id": session_id, "execution": executed}
        with _state_transaction() as current_state:
            current_session = (current_state.get("sessions") or {}).get(session_id)
            if not isinstance(current_session, dict) or current_session.get("status") != "acquired":
                return {"schema": "onec_repository_commit.v1", "method": METHOD_COMMIT, "status": "blocked", "error": "lock_session_not_acquired", "lock_session_id": session_id}
            current_session["status"] = "acquired" if payload.get("keep_locked") is True else "committed"
            current_session["committed_at"] = time.time()
            current_session["commit_comment"] = str(plan["comment"])
            final_status = str(current_session["status"])
            committed_objects = current_session.get("objects")
        return {"schema": "onec_repository_commit.v1", "method": METHOD_COMMIT, "status": final_status, "lock_session_id": session_id, "committed": committed_objects, "keep_locked": payload.get("keep_locked") is True, "execution": executed}


def unlock(payload: dict[str, Any]) -> dict[str, Any]:
    session_id = str(payload.get("lock_session_id") or "").strip()
    state = _read_state()
    session = (state.get("sessions") or {}).get(session_id)
    if not isinstance(session, dict):
        return {"schema": "onec_repository_unlock.v1", "method": METHOD_UNLOCK, "status": "not_found", "lock_session_id": session_id}
    if session.get("status") != "acquired":
        return {"schema": "onec_repository_unlock.v1", "method": METHOD_UNLOCK, "status": str(session.get("status")), "lock_session_id": session_id}
    if not payload.get("allow_repository_unlock") is True:
        return {"schema": "onec_repository_unlock.v1", "method": METHOD_UNLOCK, "status": "blocked", "error": "explicit_repository_unlock_required", "lock_session_id": session_id}
    base_id = str(session.get("base_id") or "")
    config, error = repository_config(base_id, str(session.get("layer_id") or session.get("layer") or "base"))
    if error:
        return {"schema": "onec_repository_unlock.v1", "method": METHOD_UNLOCK, "lock_session_id": session_id, **error}
    with _base_lock(base_id, str(session.get("layer") or "base")):
        executed = _execute_repository(base_id, config, "unlock", int(payload.get("timeout_seconds") or 120), objects=[str(item) for item in session.get("objects") or []])
        if executed.get("status") != "ok":
            return {"schema": "onec_repository_unlock.v1", "method": METHOD_UNLOCK, "status": "blocked", "error": "repository_unlock_failed", "lock_session_id": session_id, "execution": executed}
        with _state_transaction() as current_state:
            current_session = (current_state.get("sessions") or {}).get(session_id)
            if not isinstance(current_session, dict) or current_session.get("status") != "acquired":
                return {"schema": "onec_repository_unlock.v1", "method": METHOD_UNLOCK, "status": "blocked", "error": "lock_session_not_acquired", "lock_session_id": session_id}
            current_session["status"] = "released"
            current_session["released_at"] = time.time()
            released_objects = current_session.get("objects")
        return {"schema": "onec_repository_unlock.v1", "method": METHOD_UNLOCK, "status": "released", "lock_session_id": session_id, "released": released_objects, "execution": executed}


def call(method: str, payload: dict[str, Any]) -> dict[str, Any]:
    if method == METHOD_STATUS:
        return status(payload)
    if method == METHOD_LOCK_PLAN:
        return lock_plan(payload)
    if method == METHOD_LOCK_REQUEST:
        return create_lock_request(payload)
    if method == METHOD_LOCK_REQUEST_STATUS:
        return lock_request_status(payload)
    if method == METHOD_LOCK_REQUEST_CANCEL:
        return cancel_lock_request(payload)
    if method == METHOD_LOCK:
        return lock(payload)
    if method == METHOD_CONFIRM:
        return confirm_manual_lock(payload)
    if method == METHOD_VERIFY:
        return verify(payload)
    if method == METHOD_CLOSE:
        return close_manual_lock(payload)
    if method == METHOD_UNLOCK:
        return unlock(payload)
    if method == METHOD_COMMIT_PLAN:
        return commit_plan(payload)
    if method == METHOD_COMMIT:
        return commit(payload)
    return {"status": "method_not_found", "method": method}
