Files
ss-tools/backend/src/core/superset_profile_lookup.py
busya 8e8a3c3235 feat: attention-optimized semantic protocol v2.7
Core changes:
- Add @defgroup/@ingroup to 1791 C2+ contracts (555 files) for HCA 128× pre-training DSA grouping
- Add §0.1 Pre-Training Frequency matrix to semantics-core
- Add §VIII Attention Architecture rules (ATTN_1-4) with MLA/CSA/HCA/DSA mechanics
- Add @defgroup/@ingroup to canonical syntax (§II) and all contract examples

Agent prompts (5 files):
- Add ZERO-STATE RATIONALE with MLA/CSA/HCA/DSA compression mechanics
- Add pre-training note: @RATIONALE/@REJECTED are in-context learned tags
- svelte-coder: add missing #region contract, fix Svelte rule violations
- python-coder/fullstack-coder: honor function contracts from speckit plan
- qa-tester: add attention compliance audit (P3 ATTN_1-4 checks)

Skills (6 files):
- Translate all axiom_config descriptions to English
- Fix doc_dirs to index .opencode/ and .specify/
- Deduplicate 5× complexity_rules → single global_tags catalog
- Reduce semantics-svelte 591→485 lines (remove duplicate code blocks)
- Fix semantics-testing: 'Short IDs' → 'Short hierarchical IDs'
- Fix all examples: flat IDs → hierarchical Domain.Name format
- Fix Svelte examples: replace raw Tailwind + <button> with semantic tokens + /ui

Speckit workflow (commands + templates):
- speckit.plan: add Function-Level Contracts for C3+ with @PRE/@POST/@TEST_EDGE
- speckit.plan: add Attention Compliance Gate (ATTN_1-4 before contract generation)
- speckit.tasks: add function contract inlining format (constraints in task description)
- speckit.specify: load semantics-core for spec density rules
- spec-template: add #region contract, @SEMANTICS grouping, hierarchical IDs
- ux-reference-template: add #region wrapper
- plan-template: add attention gate, @defgroup/@ingroup guidance
- tasks-template: add attention audit + rebuild + orphan check tasks
- constitution.md: translate to English, add Principle VIII (attention-optimized contracts)

Reference modules rewritten (hierarchical IDs + full contracts):
- Auth.Jwt: 6 child contracts with @RATIONALE/@REJECTED/@TEST_EDGE
- Api.Auth: 5 endpoints with @TEST_EDGE + molecular CoT markers
- Migration.Model: @defgroup Migration with 18 @ACTION + 6 @INVARIANT

Scripts:
- add_defgroup_ingroup.py: zero-risk additive @ingroup migration (1791 insertions)
- migrate_hierarchical.py: flat→hierarchical ID dry-run analysis (792 contracts)
- merge_prompts.py: merge all prompts/skills/commands into one review file

Config:
- axiom_config.yaml: 749→395 lines (-47%), English, doc_dirs include prompts
- Fix test_datasets.py import collision (rename → test_datasets_routes.py)
- Fix test_preview.py: SupersetClient→get_superset_client, AsyncMock, logger f-string
2026-06-08 16:30:59 +03:00

217 lines
11 KiB
Python

# #region SupersetProfileLookup [C:5] [TYPE Module] [SEMANTICS superset, profile, account, lookup, adapter]
# @defgroup Core Module group.
#
# @BRIEF Provides environment-scoped Superset account lookup adapter with stable normalized output.
# @LAYER Service
# @RELATION DEPENDS_ON -> [APIClient]
# @RELATION DEPENDS_ON -> [SupersetAPIError]
# @RELATION DEPENDS_ON -> [SupersetAccountLookupAdapter]
#
# @INVARIANT Adapter never leaks raw upstream payload shape to API consumers.
# @SIDE_EFFECT Makes HTTP requests to Superset
# @DATA_CONTRACT ProfileQuery -> SupersetProfile
import json
from typing import Any
from .logger import belief_scope, logger
from .utils.async_network import AsyncAPIClient
from .utils.network import AuthenticationError, SupersetAPIError
# #region SupersetAccountLookupAdapter [C:3] [TYPE Class]
# @defgroup Core Module group.
# @BRIEF Lookup Superset users and normalize candidates for profile binding.
# @RELATION DEPENDS_ON -> [APIClient]
# @RELATION DEPENDS_ON -> [SupersetProfileLookup]
class SupersetAccountLookupAdapter:
# #region __init__ [TYPE Function]
# @PURPOSE: Initializes lookup adapter with authenticated async API client and environment context.
# @PRE network_client supports async request(method, endpoint, params=...).
# @POST Adapter is ready to perform async users lookup requests.
def __init__(self, network_client: AsyncAPIClient, environment_id: str):
self.network_client = network_client
self.environment_id = str(environment_id or "")
# #endregion __init__
# #region get_users_page [TYPE Function]
# @ingroup Core
# @PURPOSE: Fetch one users page from Superset with passthrough search/sort parameters asynchronously.
# @SIDE_EFFECT Асинхронный HTTP-вызов к Superset API для поиска пользователей.
# @PRE page_index >= 0 and page_size >= 1.
# @POST Returns deterministic payload with normalized items and total count.
# @RETURN Dict[str, Any]
async def get_users_page(
self,
search: str | None = None,
page_index: int = 0,
page_size: int = 20,
sort_column: str = "username",
sort_order: str = "desc",
) -> dict[str, Any]:
with belief_scope("SupersetAccountLookupAdapter.get_users_page"):
normalized_page_index = max(int(page_index), 0)
normalized_page_size = max(int(page_size), 1)
normalized_sort_column = str(sort_column or "username").strip().lower() or "username"
normalized_sort_order = str(sort_order or "desc").strip().lower()
if normalized_sort_order not in {"asc", "desc"}:
normalized_sort_order = "desc"
query: dict[str, Any] = {
"page": normalized_page_index,
"page_size": normalized_page_size,
"order_column": normalized_sort_column,
"order_direction": normalized_sort_order,
}
normalized_search = str(search or "").strip()
if normalized_search:
query["filters"] = [{"col": "username", "opr": "ct", "value": normalized_search}]
logger.reason(
"Lookup Superset users",
extra={"src": "SupersetAccountLookupAdapter.get_users_page", "payload": {"env": self.environment_id, "page": normalized_page_index, "page_size": normalized_page_size}},
)
logger.reflect(
"Prepared Superset users lookup query",
extra={"src": "SupersetAccountLookupAdapter.get_users_page", "payload": {"env": self.environment_id, "order_column": normalized_sort_column, "sort_order": normalized_sort_order, "direction": query.get("order_direction")}},
)
primary_error: Exception | None = None
last_error: Exception | None = None
for attempt_index, endpoint in enumerate(("/security/users/", "/security/users"), start=1):
try:
logger.reason(
"Users lookup request attempt",
extra={"src": "SupersetAccountLookupAdapter.get_users_page", "payload": {"env": self.environment_id, "attempt": attempt_index, "endpoint": endpoint}},
)
response = await self.network_client.request(
method="GET",
endpoint=endpoint,
params={"q": json.dumps(query)},
)
logger.reflect(
"Users lookup endpoint succeeded",
extra={"src": "SupersetAccountLookupAdapter.get_users_page", "payload": {"env": self.environment_id, "attempt": attempt_index, "endpoint": endpoint}},
)
return self._normalize_lookup_payload(
response=response,
page_index=normalized_page_index,
page_size=normalized_page_size,
)
except Exception as exc:
if primary_error is None:
primary_error = exc
last_error = exc
cause = getattr(exc, "__cause__", None)
cause_response = getattr(cause, "response", None)
status_code = getattr(cause_response, "status_code", None)
logger.explore(
"Users lookup endpoint failed",
extra={"src": "SupersetAccountLookupAdapter.get_users_page", "payload": {"env": self.environment_id, "attempt": attempt_index, "endpoint": endpoint, "error_type": type(exc).__name__, "status_code": status_code, "direction": query.get("order_direction")}, "error": str(exc)},
)
if last_error is not None:
selected_error: Exception = last_error
if (
primary_error is not None
and primary_error is not last_error
and isinstance(last_error, AuthenticationError)
and not isinstance(primary_error, AuthenticationError)
):
selected_error = primary_error
logger.reflect(
"Preserving primary lookup failure over fallback auth error",
extra={"src": "SupersetAccountLookupAdapter.get_users_page", "payload": {"env": self.environment_id, "primary_error_type": type(primary_error).__name__, "fallback_error_type": type(last_error).__name__}},
)
logger.explore(
"All Superset users lookup endpoints failed",
extra={"src": "SupersetAccountLookupAdapter.get_users_page", "payload": {"env": self.environment_id, "direction": query.get("order_direction"), "selected_error_type": type(selected_error).__name__}},
)
raise selected_error
raise SupersetAPIError("Superset users lookup failed without explicit error")
# #endregion get_users_page
# #region _normalize_lookup_payload [TYPE Function]
# @PURPOSE: Convert Superset users response variants into stable candidates payload.
# @PRE response can be dict/list in any supported upstream shape.
# @POST Output contains canonical keys: status, environment_id, page_index, page_size, total, items.
# @RETURN Dict[str, Any]
def _normalize_lookup_payload(
self,
response: Any,
page_index: int,
page_size: int,
) -> dict[str, Any]:
with belief_scope("SupersetAccountLookupAdapter._normalize_lookup_payload"):
payload = response
if isinstance(payload, dict) and isinstance(payload.get("result"), dict):
payload = payload.get("result")
raw_items: list[Any] = []
total = 0
if isinstance(payload, dict):
if isinstance(payload.get("result"), list):
raw_items = payload.get("result") or []
total = int(payload.get("count", len(raw_items)) or 0)
elif isinstance(payload.get("users"), list):
raw_items = payload.get("users") or []
total = int(payload.get("total", len(raw_items)) or 0)
elif isinstance(payload.get("items"), list):
raw_items = payload.get("items") or []
total = int(payload.get("total", len(raw_items)) or 0)
elif isinstance(payload, list):
raw_items = payload
total = len(raw_items)
normalized_items: list[dict[str, Any]] = []
seen_usernames = set()
for raw_user in raw_items:
candidate = self.normalize_user_payload(raw_user)
username_key = str(candidate.get("username") or "").strip().lower()
if not username_key:
continue
if username_key in seen_usernames:
continue
seen_usernames.add(username_key)
normalized_items.append(candidate)
logger.reflect(
"Normalized lookup payload",
extra={"src": "SupersetAccountLookupAdapter._normalize_lookup_payload", "payload": {"env": self.environment_id, "items": len(normalized_items), "total": max(total, len(normalized_items))}},
)
return {
"status": "success",
"environment_id": self.environment_id,
"page_index": max(int(page_index), 0),
"page_size": max(int(page_size), 1),
"total": max(int(total), len(normalized_items)),
"items": normalized_items,
}
# #endregion _normalize_lookup_payload
# #region normalize_user_payload [TYPE Function]
# @ingroup Core
# @PURPOSE: Project raw Superset user object to canonical candidate shape.
# @PRE raw_user may have heterogenous key names between Superset versions.
# @POST Returns normalized candidate keys (environment_id, username, display_name, email, is_active).
# @RETURN Dict[str, Any]
def normalize_user_payload(self, raw_user: Any) -> dict[str, Any]:
if not isinstance(raw_user, dict):
raw_user = {}
username = str(
raw_user.get("username")
or raw_user.get("userName")
or raw_user.get("name")
or ""
).strip()
full_name = str(raw_user.get("full_name") or "").strip()
first_name = str(raw_user.get("first_name") or "").strip()
last_name = str(raw_user.get("last_name") or "").strip()
display_name = full_name or " ".join(
part for part in [first_name, last_name] if part
).strip()
if not display_name:
display_name = username or None
email = str(raw_user.get("email") or "").strip() or None
is_active_raw = raw_user.get("is_active")
is_active = bool(is_active_raw) if is_active_raw is not None else None
return {
"environment_id": self.environment_id,
"username": username,
"display_name": display_name,
"email": email,
"is_active": is_active,
}
# #endregion normalize_user_payload
# #endregion SupersetAccountLookupAdapter
# #endregion SupersetProfileLookup