mirror of
https://github.com/superdesigndev/treg.git
synced 2026-10-02 03:24:35 +08:00
refactor(imports): target facade implementations directly
This commit is contained in:
@@ -47,9 +47,9 @@ CATALOG = ROOT / "src" / "treg" / "catalog"
|
||||
sys.path.insert(0, str(ROOT / "src"))
|
||||
# The enums the SERVER reads the same files with. Imported, never re-typed: a validator that
|
||||
# accepts a unit `cost_view` cannot price is worse than no validator.
|
||||
from treg.catalog_store import COST_SOURCES as _SOURCES # noqa: E402
|
||||
from treg.catalog_store import COST_UNITS as _UNITS # noqa: E402
|
||||
from treg.catalog_store import CONFIDENCES as _CONFIDENCES # noqa: E402
|
||||
from treg.domain.catalog.store import COST_SOURCES as _SOURCES # noqa: E402
|
||||
from treg.domain.catalog.store import COST_UNITS as _UNITS # noqa: E402
|
||||
from treg.domain.catalog.store import CONFIDENCES as _CONFIDENCES # noqa: E402
|
||||
|
||||
SCOPES = {"any_account", "own_account"}
|
||||
METHODS = {"GET", "POST", "PUT", "PATCH", "DELETE"}
|
||||
|
||||
@@ -20,7 +20,8 @@ sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src"))
|
||||
|
||||
from sqlalchemy.exc import OperationalError # noqa: E402
|
||||
|
||||
from treg import ledger, reconcile # noqa: E402
|
||||
from treg import reconcile # noqa: E402
|
||||
from treg.domain import money as ledger # noqa: E402
|
||||
from treg.config import get_settings # noqa: E402
|
||||
from treg.infra.db import session_maker # noqa: E402
|
||||
from treg.domain.capacity.collectors import ( # noqa: E402,F401 — re-exported for older callers
|
||||
|
||||
@@ -24,7 +24,7 @@ from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src"))
|
||||
|
||||
from treg import catalog_store as cs # noqa: E402
|
||||
from treg.domain.catalog import store as cs # noqa: E402
|
||||
|
||||
|
||||
# ---- the frozen pre-change engine (every token must match; score = sum of field weights) --------
|
||||
|
||||
+2
-1
@@ -26,9 +26,10 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy.orm import defer
|
||||
from sqlmodel import select
|
||||
|
||||
from . import audit, catalog_store, crypto, localrun, ratestore, runner, sandbox as demo_sandbox
|
||||
from . import audit, crypto, localrun, ratestore, runner, sandbox as demo_sandbox
|
||||
from .caller_metadata import _client_of
|
||||
from .config import get_settings
|
||||
from .domain.catalog import store as catalog_store
|
||||
from .infra.db import get_session, session_maker
|
||||
from .domain.governance.teams import _unique_slug
|
||||
from .domain.identity.access import (
|
||||
|
||||
@@ -14,7 +14,8 @@ from sqlalchemy import func
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
|
||||
from .. import audit, crypto, demo as demo_seed, email as email_sender, ratestore
|
||||
from .. import audit, crypto, email as email_sender, ratestore
|
||||
from ..application.onboard import demo as demo_seed
|
||||
from ..infra import db as database
|
||||
from ..config import get_settings
|
||||
from ..domain.identity import session as sess
|
||||
|
||||
@@ -45,8 +45,8 @@ from .. import adsconv
|
||||
from .. import analytics
|
||||
from ..infra import db as _db
|
||||
from .. import email as email_mod
|
||||
from .. import ledger
|
||||
from .. import referrals
|
||||
from ..domain import money as ledger
|
||||
from ..domain import referrals
|
||||
from ..config import get_settings
|
||||
from ..infra import stripe as stripe_adapter
|
||||
from ..models import CreditBlock, LedgerEntry, Membership, Org, User
|
||||
@@ -55,7 +55,7 @@ from ..models import CreditBlock, LedgerEntry, Membership, Org, User
|
||||
# _run_autotopup retains its relative local import; removing the alias breaks task-owned sessions.
|
||||
sys.modules.setdefault("treg.application.db", _db)
|
||||
|
||||
log = logging.getLogger("treg.billing")
|
||||
log = logging.getLogger("treg.application.billing")
|
||||
|
||||
MICRO_PER_CENT = 10_000
|
||||
MICRO_PER_USD = 1_000_000
|
||||
|
||||
@@ -7,13 +7,15 @@ from sqlalchemy import func
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
|
||||
from ... import billing, catalog_store, ledger
|
||||
from ...application import billing
|
||||
from ...caller_metadata import TAG_DEFAULT
|
||||
from ...config import get_settings
|
||||
from ...infra.db import session_maker
|
||||
from ...domain import money as ledger
|
||||
from ...domain.catalog import store as catalog_store
|
||||
from ...domain.governance import budgets as budget_policy
|
||||
from ...domain.governance.usage import _day_start_utc
|
||||
from ...domain.identity.access import Caller
|
||||
from ...infra.db import session_maker
|
||||
from ...models import CallRecord, Org, TagBudget
|
||||
from .intake import CallMeta, _NO_META
|
||||
from .resolve import MarketplaceCall
|
||||
@@ -48,7 +50,7 @@ async def _enforce_trial_allowance(caller: Caller, provider: str, db: AsyncSessi
|
||||
CallRecord.status_code >= 200, CallRecord.status_code < 300,
|
||||
CallRecord.created_at >= day_start))).scalar_one()
|
||||
except Exception as exc: # noqa: BLE001 — cannot verify the pool ⇒ do not drain it
|
||||
logging.getLogger("treg.ledger").warning(
|
||||
logging.getLogger("treg.domain.money").warning(
|
||||
"trial-allowance check failed for org %s / %s: %s", caller.org_id, provider, exc)
|
||||
raise ReservationFailed("trial_allowance_unavailable", status_code=429, detail=(
|
||||
f"cannot verify today's {provider} trial usage right now — retry shortly, or use "
|
||||
@@ -73,7 +75,7 @@ async def _enforce_platform_daily_cap(caller: Caller, add_micro: int, db: AsyncS
|
||||
try:
|
||||
spent = await ledger.spent_today(db, caller.org_id)
|
||||
except Exception as exc: # noqa: BLE001 — cannot verify the ceiling ⇒ do not spend
|
||||
logging.getLogger("treg.ledger").warning(
|
||||
logging.getLogger("treg.domain.money").warning(
|
||||
"platform daily-cap check failed for org %s: %s", caller.org_id, exc)
|
||||
raise ReservationFailed("platform_cap_unavailable", status_code=429, detail=(
|
||||
"cannot verify today's platform spend right now — refusing to spend the team balance "
|
||||
@@ -152,7 +154,7 @@ async def _enforce_tag_budgets(caller: Caller, meta: CallMeta, db: AsyncSession,
|
||||
raise ReservationFailed(
|
||||
kind, status_code=exc.status_code, detail=exc.detail) from exc
|
||||
except Exception as exc: # noqa: BLE001 — cannot verify a ceiling ⇒ do not spend
|
||||
logging.getLogger("treg.ledger").warning(
|
||||
logging.getLogger("treg.domain.money").warning(
|
||||
"tag budget check failed for org %s (%s=%s): %s", caller.org_id, dim, val, exc)
|
||||
raise ReservationFailed("tag_budget_unavailable", status_code=429, detail={
|
||||
"error": "tag_budget_unavailable", "dim": dim, "val": val,
|
||||
|
||||
@@ -12,14 +12,15 @@ from urllib.parse import quote, urlsplit
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
|
||||
from ... import catalog_store, oauth_providers
|
||||
from ... import oauth_providers
|
||||
from ... import sandbox as demo_sandbox
|
||||
from ...config import get_settings, platform_setting_name
|
||||
from ...domain.capacity.routes_view import view as overflow_routes_view
|
||||
from ...domain.capacity.view import view as capacity_view
|
||||
from ...infra.db import session_maker
|
||||
from ...domain.catalog import store as catalog_store
|
||||
from ...domain.governance import access as access_policy
|
||||
from ...domain.identity.access import Caller
|
||||
from ...infra.db import session_maker
|
||||
from ...models import CapabilityPin, Org, Secret, Tool
|
||||
from ..connect import _host_of, _provider_bindings
|
||||
from .types import ResolutionFailed, ResolvedTarget
|
||||
|
||||
@@ -11,10 +11,11 @@ from urllib.parse import parse_qsl, urlencode, urlsplit
|
||||
|
||||
import httpx
|
||||
|
||||
from ... import analytics, archive, audit, catalog_store, oauth
|
||||
from ... import analytics, archive, audit, oauth
|
||||
from ... import sandbox as demo_sandbox
|
||||
from ...client_identity import _norm_client
|
||||
from ...config import get_settings
|
||||
from ...domain.catalog import store as catalog_store
|
||||
from ...infra.db import session_maker
|
||||
from ...models import Secret
|
||||
from ...sandbox_identity import visitor_name
|
||||
|
||||
@@ -10,10 +10,12 @@ from collections.abc import Callable
|
||||
from sqlalchemy import update
|
||||
from sqlalchemy.exc import TimeoutError as PoolTimeoutError
|
||||
|
||||
from ... import adsconv, catalog_store, ledger
|
||||
from ... import adsconv
|
||||
from ...domain.capacity import marks as capacity_marks
|
||||
from ...domain.capacity import overflow_spend as overflow_spend_ledger
|
||||
from ...domain.capacity import signatures as capacity_signatures
|
||||
from ...domain import money as ledger
|
||||
from ...domain.catalog import store as catalog_store
|
||||
from ...infra.db import session_maker
|
||||
from ...models import Org
|
||||
from ...timeutil import utcnow_naive as _utcnow_naive
|
||||
@@ -447,7 +449,7 @@ async def _platform_settle(
|
||||
await asyncio.sleep(0.5)
|
||||
charged = await _close()
|
||||
except Exception as exc: # noqa: BLE001 — loudly, but never into the caller's response
|
||||
logging.getLogger("treg.ledger").error(
|
||||
logging.getLogger("treg.domain.money").error(
|
||||
"settle/release failed for call %s (%s, status %s): %s",
|
||||
call_id, mk.endpoint_id, status_code, exc, exc_info=True)
|
||||
return charged, observed
|
||||
@@ -469,7 +471,7 @@ async def _finish_cancelled_call(
|
||||
try:
|
||||
await response.close()
|
||||
except (Exception, asyncio.CancelledError): # noqa: BLE001
|
||||
logging.getLogger("treg.proxy").error(
|
||||
logging.getLogger("treg.infra.upstream.relay").error(
|
||||
"upstream close failed for cancelled call %s", call_ref, exc_info=True)
|
||||
if mk is not None and mk.metered:
|
||||
# `ledger.reserve` may have committed without returning, so `mk.call_id` is not an
|
||||
@@ -491,7 +493,7 @@ async def _finish_cancelled_call(
|
||||
)
|
||||
await cleanup_db.commit()
|
||||
except (Exception, asyncio.CancelledError): # noqa: BLE001
|
||||
logging.getLogger("treg.ledger").error(
|
||||
logging.getLogger("treg.domain.money").error(
|
||||
"cancellation release failed for call %s", call_ref, exc_info=True)
|
||||
try:
|
||||
await _release_idempotent_claim(claim)
|
||||
|
||||
@@ -12,8 +12,9 @@ from sqlalchemy import or_
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
|
||||
from .. import catalog_store, crypto, health, oauth, oauth_providers
|
||||
from .. import crypto, health, oauth, oauth_providers
|
||||
from ..config import get_settings
|
||||
from ..domain.catalog import store as catalog_store
|
||||
from ..infra.db import session_maker
|
||||
from ..models import PendingOAuth, Secret, Tool
|
||||
from ..timeutil import as_naive as _as_naive
|
||||
|
||||
@@ -8,10 +8,12 @@ from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
|
||||
from .. import adsconv, health, ledger, referrals, sandbox as demo_sandbox
|
||||
from ..infra.db import session_maker
|
||||
from .. import adsconv, health, sandbox as demo_sandbox
|
||||
from ..domain import money as ledger
|
||||
from ..domain import referrals
|
||||
from ..domain.governance.teams import _make_org_membership, _slugify
|
||||
from ..domain.identity.access import _is_machine_email, _norm_email
|
||||
from ..infra.db import session_maker
|
||||
from ..models import Org, User
|
||||
from ..timeutil import utcnow_naive as _utcnow_naive
|
||||
|
||||
|
||||
+3
-3
@@ -270,7 +270,7 @@ async def _store(
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from . import catalog_store
|
||||
from .domain.catalog import store as catalog_store
|
||||
from .infra.db import session_maker
|
||||
from .models import ArchiveKey, ArchiveSnapshot
|
||||
|
||||
@@ -429,7 +429,7 @@ async def lookup(
|
||||
return None
|
||||
from sqlalchemy import select
|
||||
|
||||
from . import catalog_store
|
||||
from .domain.catalog import store as catalog_store
|
||||
from .infra.db import session_maker
|
||||
from .models import ArchiveKey, ArchiveSnapshot
|
||||
|
||||
@@ -639,7 +639,7 @@ async def refresh_once(client) -> int:
|
||||
return 0
|
||||
from sqlalchemy import func, select
|
||||
|
||||
from . import catalog_store
|
||||
from .domain.catalog import store as catalog_store
|
||||
from .infra.db import session_maker
|
||||
from .models import ArchiveKey, ArchiveSnapshot
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
|
||||
from .. import ledger
|
||||
from . import money as ledger
|
||||
from ..config import get_settings
|
||||
from ..models import CreditBlock, Membership, Org, Referral, User
|
||||
|
||||
|
||||
+2
-1
@@ -15,7 +15,8 @@ import httpx
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
|
||||
from . import crypto, injectors, oauth
|
||||
from . import crypto, oauth
|
||||
from .infra.upstream import injectors
|
||||
from .infra.upstream.ssrf import host_is_public, safe_webhook_url
|
||||
from .models import Invite, Membership, PendingOAuth, Secret, Tool, User
|
||||
from .timeutil import utcnow_naive
|
||||
|
||||
@@ -53,7 +53,7 @@ class PostgresEndpointObservationReader:
|
||||
ids = list(dict.fromkeys(endpoint_ids))
|
||||
if not ids:
|
||||
return {}
|
||||
from .. import catalog_store # the per-success set is a catalog fact, read at query time
|
||||
from ..domain.catalog import store as catalog_store # the per-success set is a catalog fact, read at query time
|
||||
cat = catalog_store.load()
|
||||
per_success = {i for i in ids if ((cat.by_id.get(i) or {}).get("cost") or {}).get("type") == "per_success"}
|
||||
async with self._session_factory() as db:
|
||||
|
||||
@@ -21,7 +21,7 @@ from datetime import datetime, timezone
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from .injectors import _token_from_json # light: pure JSON/token helpers, no DB
|
||||
from .infra.upstream.injectors import _token_from_json # light: pure JSON/token helpers, no DB
|
||||
|
||||
# The DB/crypto/oauth deps are used at runtime ONLY in `render_grant` (the server-side grant path — the
|
||||
# CLI client never calls it). Keeping them out of the module's top-level imports lets the CLI install
|
||||
|
||||
+3
-2
@@ -51,7 +51,8 @@ from mcp.server.transport_security import TransportSecuritySettings
|
||||
from mcp.shared.exceptions import MCPError
|
||||
from mcp.types import METHOD_NOT_FOUND, ToolAnnotations
|
||||
|
||||
from . import audit, catalog_store
|
||||
from . import audit
|
||||
from .domain.catalog import store as catalog_store
|
||||
from .config import PUBLIC_HOST_ALIASES, get_settings
|
||||
from .domain.catalog.stats import EndpointObservationReader
|
||||
|
||||
@@ -1368,7 +1369,7 @@ class RequireAuthForProtectedTools:
|
||||
return None # a live access token, or a per-org token the tool validates itself
|
||||
|
||||
async def _challenge(self, send, *, invalid: bool = False) -> None:
|
||||
from . import mcp_oauth
|
||||
from .domain.identity import mcp_oauth
|
||||
|
||||
base = get_settings().public_url.rstrip("/")
|
||||
suffix = "/mcp/v2" if self.resource_version == "v2" else ""
|
||||
|
||||
@@ -305,6 +305,6 @@ async def shared_plan_recovery(db: AsyncSession, since: datetime) -> dict:
|
||||
def _catalog():
|
||||
"""Deferred so reconcile stays importable without the catalog package in odd contexts, and so
|
||||
tests can monkeypatch the module in one obvious place."""
|
||||
from . import catalog_store
|
||||
from .domain.catalog import store as catalog_store
|
||||
|
||||
return catalog_store
|
||||
|
||||
@@ -4,10 +4,11 @@ from fastapi import APIRouter, Depends, HTTPException, Query, Request
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from .. import billing, ledger
|
||||
from ..application import billing
|
||||
from ..config import get_settings
|
||||
from ..infra.db import get_session
|
||||
from ..domain import money as ledger
|
||||
from ..domain.identity.access import Caller, _role_at_least, require_member
|
||||
from ..infra.db import get_session
|
||||
from ..models import Org
|
||||
from .auth_helpers import _is_https
|
||||
from .orgs import _require_admin_of
|
||||
|
||||
@@ -9,7 +9,7 @@ from fastapi.responses import Response, StreamingResponse
|
||||
from starlette.background import BackgroundTask
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from .. import audit, catalog_store, ledger, oauth_providers
|
||||
from .. import audit, oauth_providers
|
||||
from .. import sandbox as demo_sandbox
|
||||
from ..application.call.idempotency import (
|
||||
_release_idempotent_claim as release_idempotent_claim,
|
||||
@@ -33,10 +33,12 @@ from ..application.call.intake import (
|
||||
from ..application.call.types import CallerSnapshot, CallFailure, CallInput, UpstreamResponse
|
||||
from ..caller_metadata import _client_of
|
||||
from ..config import get_settings
|
||||
from ..infra.db import get_session
|
||||
from ..domain import money as ledger
|
||||
from ..domain.catalog import store as catalog_store
|
||||
from ..domain.governance import access as access_policy
|
||||
from ..domain.governance import publicdemo as publicdemo_policy
|
||||
from ..domain.identity.access import Caller, require_member
|
||||
from ..infra.db import get_session
|
||||
from ..models import Tool
|
||||
from .auth import _client_ip
|
||||
from .orgs import count_today
|
||||
|
||||
@@ -8,8 +8,9 @@ import logging
|
||||
from fastapi import APIRouter, Depends, HTTPException, Request
|
||||
from fastapi.responses import Response
|
||||
|
||||
from .. import audit, catalog_store, oauth_providers
|
||||
from .. import audit, oauth_providers
|
||||
from ..config import get_settings
|
||||
from ..domain.catalog import store as catalog_store
|
||||
from ..domain.catalog import stats as endpoint_stats
|
||||
|
||||
|
||||
|
||||
@@ -12,12 +12,13 @@ from sqlalchemy.exc import IntegrityError
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
|
||||
from .. import crypto, demo as demo_seed, email as email_sender, health, ledger, localrun
|
||||
from .. import crypto, email as email_sender, health, localrun
|
||||
from .. import providers as _providers
|
||||
from ..application.onboard import demo as demo_seed
|
||||
from ..application import signup as signup_use_cases
|
||||
from ..caller_metadata import TAG_DEFAULT, _MAX_BUDGET_DIMS, _META_KEY_RE, _client_of, _norm_client
|
||||
from ..config import get_settings
|
||||
from ..infra.db import get_session
|
||||
from ..domain import money as ledger
|
||||
from ..domain.governance import budgets as budget_policy
|
||||
from ..domain.governance import access as access_policy
|
||||
from ..domain.governance import usage as usage_policy
|
||||
@@ -41,6 +42,7 @@ from ..domain.identity.access import (
|
||||
require_identity,
|
||||
require_member,
|
||||
)
|
||||
from ..infra.db import get_session
|
||||
from ..models import (
|
||||
ROLE_RANK,
|
||||
AdConversion,
|
||||
|
||||
@@ -15,7 +15,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
|
||||
from .. import convert as _convert
|
||||
from .. import crypto, health, injectors, sandbox as demo_sandbox
|
||||
from .. import crypto, health, sandbox as demo_sandbox
|
||||
from ..infra import db as _db
|
||||
from .. import providers as _providers
|
||||
from .. import skills as _skills
|
||||
@@ -33,6 +33,7 @@ from ..domain.identity.access import (
|
||||
_role_at_least,
|
||||
require_member,
|
||||
)
|
||||
from ..infra.upstream import injectors
|
||||
from ..models import Bundle, Secret, Tool
|
||||
from .orgs import _resolve_project
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from fastapi import Request
|
||||
|
||||
from .. import referrals
|
||||
from ..domain import referrals
|
||||
from .auth_helpers import _is_https
|
||||
|
||||
|
||||
|
||||
@@ -17,7 +17,9 @@ from fastapi.responses import (FileResponse, HTMLResponse, JSONResponse, PlainTe
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
|
||||
from .. import adsconv, agent_pages, catalog_store, oauth_providers, referrals
|
||||
from .. import adsconv, agent_pages, oauth_providers
|
||||
from ..domain import referrals
|
||||
from ..domain.catalog import store as catalog_store
|
||||
from ..domain.identity import session as sess
|
||||
from ..config import PUBLIC_HOST_ALIASES, get_settings
|
||||
from ..infra.db import get_session
|
||||
|
||||
+2
-1
@@ -22,7 +22,8 @@ from __future__ import annotations
|
||||
import json
|
||||
import re
|
||||
|
||||
from . import crypto, injectors
|
||||
from . import crypto
|
||||
from .infra.upstream import injectors
|
||||
from .models import Org, Secret, Tool
|
||||
from .sandbox_identity import visitor_name
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from httpx import AsyncClient
|
||||
|
||||
from treg import audit
|
||||
from treg.config import get_settings
|
||||
from treg.ledger import with_margin
|
||||
from treg.domain.money import with_margin
|
||||
|
||||
from test_marketplace_call import EP, EP_DFS, EP_MICRO
|
||||
|
||||
|
||||
@@ -12,9 +12,10 @@ from sqlalchemy.exc import TimeoutError as PoolTimeoutError
|
||||
|
||||
from treg.application.call import service as call_service
|
||||
from treg.routers import call as call_routes
|
||||
from treg import audit, ledger
|
||||
from treg import audit
|
||||
from treg.domain import money as ledger
|
||||
from treg.infra.db import session_maker
|
||||
from treg.ledger import with_margin
|
||||
from treg.domain.money import with_margin
|
||||
from treg.models import CallRecord
|
||||
|
||||
from test_marketplace_call import (
|
||||
|
||||
@@ -15,7 +15,8 @@ import re
|
||||
import pytest
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from treg import agent_pages, catalog_store
|
||||
from treg import agent_pages
|
||||
from treg.domain.catalog import store as catalog_store
|
||||
from treg.api import app
|
||||
from treg.config import get_settings
|
||||
|
||||
|
||||
@@ -178,7 +178,7 @@ async def test_key_hash_is_unique(clients):
|
||||
from httpx import AsyncClient
|
||||
from sqlalchemy import select
|
||||
|
||||
from treg import catalog_store
|
||||
from treg.domain.catalog import store as catalog_store
|
||||
from treg.config import get_settings
|
||||
from treg.infra.db import session_maker
|
||||
|
||||
|
||||
+2
-1
@@ -11,7 +11,8 @@ from fastapi import FastAPI
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
from sqlmodel import select
|
||||
|
||||
from treg import crypto, session as sess
|
||||
from treg import crypto
|
||||
from treg.domain.identity import session as sess
|
||||
from treg.api import app
|
||||
from treg.config import get_settings
|
||||
from treg.infra.db import reset_db, session_maker
|
||||
|
||||
@@ -27,7 +27,9 @@ from sqlmodel import select
|
||||
|
||||
from conftest import make_upstream
|
||||
|
||||
from treg import adsconv, billing, ledger
|
||||
from treg import adsconv
|
||||
from treg.application import billing
|
||||
from treg.domain import money as ledger
|
||||
from treg.api import app
|
||||
from treg.config import get_settings
|
||||
from treg.infra.db import reset_db, session_maker
|
||||
|
||||
@@ -15,7 +15,8 @@ from fastapi import FastAPI, Request
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
from sqlmodel import select
|
||||
|
||||
from treg import audit, crypto, oauth, session as sess
|
||||
from treg import audit, crypto, oauth
|
||||
from treg.domain.identity import session as sess
|
||||
from treg.api import app
|
||||
from treg.config import get_settings
|
||||
from treg.infra.db import reset_db, session_maker
|
||||
|
||||
@@ -15,7 +15,7 @@ from httpx import AsyncClient
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from treg import ledger
|
||||
from treg.domain import money as ledger
|
||||
from treg.application.call import service as call_service
|
||||
from treg.application.call.types import GatewayFailed
|
||||
from treg.routers import call as call_routes
|
||||
|
||||
@@ -7,7 +7,7 @@ import asyncio
|
||||
from httpx import AsyncClient
|
||||
from sqlalchemy import select
|
||||
|
||||
from treg import ledger
|
||||
from treg.domain import money as ledger
|
||||
from treg.application.call import settle as call_settle
|
||||
from treg.application.call.resolve import MarketplaceCall
|
||||
from treg.infra.db import session_maker
|
||||
|
||||
@@ -29,7 +29,8 @@ from treg import api as A
|
||||
from treg.domain.catalog import stats as catalog_stats
|
||||
from treg.application.call import service as call_service
|
||||
from treg.routers import call as call_routes
|
||||
from treg import audit, ledger
|
||||
from treg import audit
|
||||
from treg.domain import money as ledger
|
||||
from treg.config import get_settings
|
||||
from treg.infra.db import _engine, session_maker
|
||||
from treg.infra.upstream.relay import relay as upstream_relay
|
||||
|
||||
@@ -326,7 +326,7 @@ async def test_shadow_mode_probes_records_spend_and_returns_the_vendor_error(cli
|
||||
|
||||
|
||||
async def test_cancellation_cleanup_releases_both_holds_exactly_once(clients: AsyncClient, overflow_on):
|
||||
from treg import ledger
|
||||
from treg.domain import money as ledger
|
||||
from treg.application.call.settle import _finish_cancelled_call
|
||||
from treg.application.call.resolve import MarketplaceCall
|
||||
from treg.models import Tool
|
||||
|
||||
@@ -14,7 +14,7 @@ import re
|
||||
|
||||
from httpx import AsyncClient
|
||||
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
from treg import oauth_providers as P
|
||||
|
||||
|
||||
@@ -726,7 +726,7 @@ def test_a_free_route_needs_no_price_provenance():
|
||||
number, so demanding provenance refused 61 endpoints across 8 providers — 28 of Hunter's 35 —
|
||||
treating "costs nothing" as if it meant "we don't know", which is the one distinction the cost
|
||||
model is otherwise careful to keep apart."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
cat = cs.load()
|
||||
free = {"type": "free", "value": 0, "currency": "USD", "unit": "call"}
|
||||
ep = {"cost": free, "provider": "hunter", "scope": "any_account", "kind": "data"}
|
||||
@@ -736,7 +736,7 @@ def test_a_free_route_needs_no_price_provenance():
|
||||
def test_a_PAID_route_still_needs_provenance():
|
||||
"""The relaxation must not leak: a route with a real price and no provenance stays refused, or
|
||||
we would bill a team using a number nobody checked."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
cat = cs.load()
|
||||
unchecked = {"type": "per_call", "value": 0.05, "currency": "USD", "unit": "call"}
|
||||
ep = {"cost": unchecked, "provider": "hunter", "scope": "any_account", "kind": "data"}
|
||||
@@ -748,7 +748,7 @@ def test_a_PAID_route_still_needs_provenance():
|
||||
|
||||
def test_an_unpriced_route_is_still_refused():
|
||||
"""The original rule, unchanged: no usd → refuse, so treg never pays a provider and charges $0."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
cat = cs.load()
|
||||
ep = {"cost": {"type": "per_call", "currency": "credit", "unit": "credit"},
|
||||
"provider": "pdl", "scope": "any_account", "kind": "data"}
|
||||
@@ -814,7 +814,7 @@ def test_a_shared_plan_rate_converts_like_any_credit():
|
||||
"""The whole design: a flat-fee provider is modelled as a credit provider whose credit is one
|
||||
call on treg's shared plan. cost_view needs ZERO changes — this asserts the pilot entry flows
|
||||
through the existing conversion."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
|
||||
c = cs.load()
|
||||
out = c.cost_view({"type": "per_call", "value": 1, "currency": "credit"}, "alphavantage")
|
||||
@@ -852,7 +852,7 @@ def test_trial_pools_flow_from_fx_to_eligibility_and_display():
|
||||
"""The real file's three pools, end to end through the loader: a $0 price that is platform
|
||||
eligible AND carries its allowance wherever the cost is shown — a bare $0.00 would read as
|
||||
unlimited."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
|
||||
c = cs.load()
|
||||
assert c.trial_pools == {"finnhub": 50, "twelvedata": 20, "tiingo": 20}
|
||||
|
||||
@@ -622,7 +622,7 @@ async def test_slack_style_ok_false_is_reported_not_swallowed(clients: AsyncClie
|
||||
sid = r.json()["id"]
|
||||
|
||||
# /auth.test returns ok:false unless the token contains "good"; swap in a bad one to trigger it
|
||||
async with __import__("treg").db.session_maker() as db:
|
||||
async with session_maker() as db:
|
||||
from sqlmodel import select as _select
|
||||
|
||||
from treg import crypto as _crypto
|
||||
|
||||
@@ -12,7 +12,7 @@ from datetime import datetime, timedelta, timezone
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
|
||||
from treg import endpoint_stats
|
||||
from treg.domain.catalog import stats as endpoint_stats
|
||||
from treg.api import app
|
||||
from treg.infra.db import session_maker
|
||||
from treg.infra.catalog_observations import CachedEndpointObservationReader
|
||||
@@ -255,7 +255,7 @@ async def test_never_worked_is_read_off_DECIDED_samples_only(clients: AsyncClien
|
||||
""""Never worked" has to mean the provider failed the calls that were ITS to answer. Above the
|
||||
floor `ok_rate == 0` says exactly that — 4xx is already excluded from the rate — so ranking can
|
||||
demote a genuinely broken endpoint without a single caller error being able to trigger it."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
for _ in range(6):
|
||||
await _record(EP, 503) # the provider failing, decisively
|
||||
assert (await _observed([EP]))[EP]["ok_rate"] == 0.0
|
||||
@@ -304,7 +304,7 @@ async def test_a_relayed_405_is_the_CATALOGS_failure_not_the_callers(clients: As
|
||||
|
||||
async def test_a_405_endpoint_sinks_in_the_ranking(clients: AsyncClient):
|
||||
"""The payoff for report #4: the row that cannot be called stops being offered first."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
for _ in range(7):
|
||||
await _record(EP, 405)
|
||||
stats = {EP: (await _observed([EP]))[EP],
|
||||
|
||||
@@ -8,7 +8,7 @@ from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from treg.injectors import inject
|
||||
from treg.infra.upstream.injectors import inject
|
||||
|
||||
|
||||
def _b(**kw) -> dict:
|
||||
|
||||
@@ -19,7 +19,7 @@ from sqlmodel import select
|
||||
|
||||
from conftest import make_upstream
|
||||
|
||||
from treg import ledger
|
||||
from treg.domain import money as ledger
|
||||
from treg.api import app
|
||||
from treg.config import get_settings
|
||||
from treg.infra.db import reset_db, session_maker
|
||||
@@ -211,7 +211,7 @@ async def test_concurrent_sweeps_pay_a_referral_once(c: AsyncClient):
|
||||
"""
|
||||
from datetime import timedelta
|
||||
|
||||
from treg import referrals
|
||||
from treg.domain import referrals
|
||||
from treg.models import Referral
|
||||
|
||||
r = await c.post("/users", json={"email": "referrer@superdesign.dev"})
|
||||
@@ -259,7 +259,7 @@ async def test_sweep_grants_and_stamps_commit_together(c: AsyncClient, monkeypat
|
||||
where each grant committed itself, leaves the referee's money durable with no stamp."""
|
||||
from datetime import timedelta
|
||||
|
||||
from treg import referrals
|
||||
from treg.domain import referrals
|
||||
from treg.models import Referral
|
||||
|
||||
r = await c.post("/users", json={"email": "atomic-ref@superdesign.dev"})
|
||||
@@ -305,7 +305,7 @@ async def test_referee_instant_grant_failure_after_staging_never_raises(
|
||||
(MissingGreenlet), which broke the never-raises contract exactly when it mattered."""
|
||||
import logging as _logging
|
||||
|
||||
from treg import referrals
|
||||
from treg.domain import referrals
|
||||
from treg.models import Referral
|
||||
|
||||
r = await c.post("/users", json={"email": "ref-boom-a@superdesign.dev"})
|
||||
@@ -348,7 +348,7 @@ async def test_sweep_grant_failure_after_staging_never_raises(c: AsyncClient, mo
|
||||
import logging as _logging
|
||||
from datetime import timedelta
|
||||
|
||||
from treg import referrals
|
||||
from treg.domain import referrals
|
||||
from treg.models import Referral
|
||||
|
||||
r = await c.post("/users", json={"email": "sweep-boom-ref@superdesign.dev"})
|
||||
@@ -392,7 +392,7 @@ async def test_referrals_page_survives_a_sweep_rollback(c: AsyncClient, monkeypa
|
||||
the user row and `user.id` in the handler would 500 the page it protects."""
|
||||
import logging as _logging
|
||||
|
||||
from treg import referrals
|
||||
from treg.domain import referrals
|
||||
from treg.application import referrals as referrals_app
|
||||
|
||||
r = await c.post("/users", json={"email": "page-boom@superdesign.dev"})
|
||||
|
||||
@@ -7,7 +7,7 @@ from httpx import AsyncClient
|
||||
from sqlalchemy import delete
|
||||
from sqlmodel import select
|
||||
|
||||
from treg import ledger
|
||||
from treg.domain import money as ledger
|
||||
from treg.infra.db import session_maker
|
||||
from treg.models import Hold, LedgerEntry
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ from __future__ import annotations
|
||||
import pytest
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from treg import session as sess
|
||||
from treg.domain.identity import session as sess
|
||||
from treg.api import app
|
||||
from treg.config import get_settings
|
||||
|
||||
@@ -105,7 +105,8 @@ async def test_canonical_host_is_untouched(raw_client):
|
||||
async def test_legacy_mcp_host_and_oauth_audience_stay_valid():
|
||||
# The transport allow-list and the token-audience set must both keep honouring the legacy name —
|
||||
# every pre-move .mcp.json and OAuth grant depends on it.
|
||||
from treg import mcp, mcp_oauth
|
||||
from treg import mcp
|
||||
from treg.domain.identity import mcp_oauth
|
||||
|
||||
# List MEMBERSHIP (exact strings), not substring checks — .count() keeps CodeQL from reading
|
||||
# these as URL-substring sanitization.
|
||||
@@ -169,7 +170,8 @@ async def test_env_revert_is_a_complete_rollback(monkeypatch):
|
||||
treg.to is never a redirect SOURCE, so a browser-cached old→new 301 meets no new→old answer."""
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from treg import mcp, mcp_oauth
|
||||
from treg import mcp
|
||||
from treg.domain.identity import mcp_oauth
|
||||
from treg.api import app
|
||||
from treg.routers.auth import _login_callback_base
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ from __future__ import annotations
|
||||
from httpx import AsyncClient
|
||||
|
||||
import treg.api as api_mod
|
||||
from treg import pubfeed, sandbox
|
||||
from treg import sandbox
|
||||
from treg.application.onboard import pubfeed
|
||||
from treg.domain.governance import publicdemo as publicdemo_policy
|
||||
|
||||
ENV_KEY = "rk_test_ENV_ONLY_KEY"
|
||||
|
||||
@@ -8,7 +8,8 @@ from __future__ import annotations
|
||||
import pytest
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from treg import crypto, session as sess
|
||||
from treg import crypto
|
||||
from treg.domain.identity import session as sess
|
||||
from treg.api import app
|
||||
from treg.config import get_settings
|
||||
from treg.infra.db import reset_db, session_maker
|
||||
|
||||
@@ -22,7 +22,9 @@ from datetime import datetime, timezone
|
||||
import pytest
|
||||
from httpx import AsyncClient
|
||||
|
||||
from treg import api as A, audit, catalog_store, ledger, oauth_providers
|
||||
from treg import api as A, audit, oauth_providers
|
||||
from treg.domain import money as ledger
|
||||
from treg.domain.catalog import store as catalog_store
|
||||
from treg.application.call import resolve as call_resolution
|
||||
from treg.application.call import settle as call_settle
|
||||
from treg.application.call import service as call_service
|
||||
@@ -900,7 +902,7 @@ def test_brightdata_documented_prices_are_billable(platform_on):
|
||||
on our token, so its prices can only ever be `documented` ($1.50/1000 records from the public
|
||||
pricing page) — and documented is now billable. The provider that motivated the policy must
|
||||
actually have eligible endpoints, or "enable all" silently enabled nothing."""
|
||||
from treg import catalog_store
|
||||
from treg.domain.catalog import store as catalog_store
|
||||
|
||||
cat = catalog_store.load()
|
||||
rows = cat.for_provider("brightdata")
|
||||
@@ -1219,7 +1221,7 @@ async def test_the_sweep_clears_labels_NOBODY_COMES_BACK_FOR(clients: AsyncClien
|
||||
drops it. Without a sweep those rows accumulate forever, and they hold response BODIES. Any later
|
||||
call by the same caller clears them.
|
||||
|
||||
Lazy and caller-scoped, matching the hold reaper in ledger.py: a background timer would need a
|
||||
Lazy and caller-scoped, matching the hold reaper in domain/money: a background timer would need a
|
||||
scheduler and a leader election on a multi-instance deploy, and would still only run on a timer.
|
||||
"""
|
||||
from datetime import timedelta
|
||||
@@ -1446,7 +1448,7 @@ async def test_another_orgs_usage_never_burns_MY_trial(clients: AsyncClient, tri
|
||||
# the balance said $0.10, which is the one disagreement a published price must never have.
|
||||
|
||||
def _x_endpoints():
|
||||
from treg import catalog_store
|
||||
from treg.domain.catalog import store as catalog_store
|
||||
return [e for e in catalog_store.load().by_id.values() if e.get("provider") == "x"]
|
||||
|
||||
|
||||
@@ -1530,7 +1532,7 @@ async def test_the_rate_card_is_per_resource_type_not_one_read_and_one_write(cli
|
||||
"""The regression that shipped and was caught in review: every write billed at the post-creation
|
||||
rate. X prices each action separately, and the catalog has to say so — creating a list is $0.010,
|
||||
managing one $0.005, and deleting an interaction $0.010, none of them $0.015."""
|
||||
from treg import catalog_store
|
||||
from treg.domain.catalog import store as catalog_store
|
||||
by_id = catalog_store.load().by_id
|
||||
assert by_id["x.x.create-lists"]["cost"]["value"] == 0.010, "List: Create is $0.010 per request"
|
||||
assert by_id["x.x.update-lists"]["cost"]["value"] == 0.005, "List: Manage is $0.005 per request"
|
||||
@@ -1543,7 +1545,7 @@ def test_the_owned_read_discount_is_never_claimed():
|
||||
"""$0.001 owned reads need the caller to own the developer app. On a registry connect the app is
|
||||
treg's, so no X entry may quote that rate as a per-CALL own-account price — the way `/2/users/me`
|
||||
did until 2026-08-18, under-billing the reads treg pays the most for."""
|
||||
from treg import catalog_store
|
||||
from treg.domain.catalog import store as catalog_store
|
||||
me = catalog_store.load().by_id["x.x.user.profile"]
|
||||
assert me["cost"]["value"] == 0.010 and me["cost"]["type"] == "per_result", (
|
||||
"/2/users/me is an ordinary User read for a registry connect")
|
||||
|
||||
+8
-8
@@ -887,7 +887,7 @@ async def test_an_EXPIRED_access_token_gets_401_invalid_token(clients):
|
||||
refresh grant. Our first challenge only covered the missing-header case, so an expired token
|
||||
sailed through to the tool's friendly prose in a 200 — and Claude Code, told nothing, gave up
|
||||
with "requires re-authorization" instead of refreshing."""
|
||||
from treg import mcp_oauth
|
||||
from treg.domain.identity import mcp_oauth
|
||||
dead = mcp_oauth.make_access_token(user_id=7, org_id=3, audience=mcp_oauth.mcp_resource_url(),
|
||||
scope="treg:call", ttl=-60) # born expired
|
||||
async with mcp_session(clients) as c:
|
||||
@@ -905,7 +905,7 @@ async def test_an_EXPIRED_access_token_gets_401_invalid_token(clients):
|
||||
async def test_a_wrong_audience_access_token_gets_401_invalid_token(clients):
|
||||
"""A grant consented to a DIFFERENT resource must not be honoured here — and the refusal should
|
||||
still be the machine-readable 401, not tool prose."""
|
||||
from treg import mcp_oauth
|
||||
from treg.domain.identity import mcp_oauth
|
||||
other = mcp_oauth.make_access_token(user_id=7, org_id=3,
|
||||
audience="https://evil.example/mcp/", scope="treg:call")
|
||||
async with mcp_session(clients) as c:
|
||||
@@ -1172,7 +1172,7 @@ async def test_catalog_query_arrays_use_the_endpoints_declared_wire_encoding(mon
|
||||
team tool keeps the longstanding repeated-key default. This goes through `call`, not only
|
||||
`_query_values`: the first version stayed green if the MCP call site stopped using the helper.
|
||||
"""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
from treg import mcp as _mcp
|
||||
|
||||
cat = cs.load()
|
||||
@@ -1226,7 +1226,7 @@ async def test_search_survives_missing_a_few_words_of_an_agent_sentence(clients)
|
||||
endpoints matched 6 of its 7 words — the only miss was "linkedin" on rows shelved under
|
||||
`companies`, or "open" on the one shelved under `linkedin`. A query may now miss one word in
|
||||
three, and idf weighting keeps the order on the rare words rather than the filler."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
cat = cs.load()
|
||||
# the two logged SearchMiss queries, verbatim
|
||||
rows, total = cs.search("company job postings hiring open jobs linkedin", cat, 8)
|
||||
@@ -1276,7 +1276,7 @@ async def test_search_breaks_ties_on_what_treg_has_MEASURED(clients):
|
||||
"""Token scoring ties by the dozen — every "ad library" match scores 6 — so with a default limit
|
||||
of 8 the rows an agent saw were decided by file order: seven tikhub rows, one of them
|
||||
uncallable, and the cheapest endpoint with a perfect record cut off below the fold."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
cat = cs.load()
|
||||
ranked, _, truncated = cs.rank_band("ad library", cat, 8)
|
||||
assert not truncated, "24 matches sit well inside the band"
|
||||
@@ -1316,7 +1316,7 @@ async def test_the_tie_band_covers_the_WHOLE_equal_scoring_group(clients, monkey
|
||||
band therefore keeps taking while the score stays equal — and when a query ties so broadly that
|
||||
even the ceiling can't hold the group, it SAYS so rather than presenting an unranked tail as a
|
||||
ranked answer."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
cat = cs.load()
|
||||
rows, total, truncated = cs.rank_band("ad library", cat, 8)
|
||||
scores = [s for _, s in rows]
|
||||
@@ -1351,7 +1351,7 @@ async def test_a_near_miss_never_suggests_a_DIFFERENT_provider(clients):
|
||||
`hunter.people.email.find` — it is another vendor, another price and another credential, so on a
|
||||
path that spends money that is provider routing wearing a spellcheck's clothes. treg compares
|
||||
providers and the caller chooses."""
|
||||
from treg import catalog_store as cs
|
||||
from treg.domain.catalog import store as cs
|
||||
cat = cs.load()
|
||||
assert cs.near_ids("lusha.companies-signals", cat) == ["lusha.x.companies-signals"]
|
||||
for crossing in ("apollo.people.email.find", "fake.companies-signals", "hunter.tiktok.video.comments"):
|
||||
@@ -1391,7 +1391,7 @@ async def test_the_SEARCH_TOOL_itself_ranks_on_evidence_not_just_the_helper(clie
|
||||
"""The helpers were tested; the wiring was not. `rerank()` could have been dropped from both
|
||||
call sites and every ranking test would still have passed, because they call the helper
|
||||
directly. This one goes through the MCP tool with real rows in the database."""
|
||||
from treg import endpoint_stats
|
||||
from treg.domain.catalog import stats as endpoint_stats
|
||||
from treg.infra.db import session_maker
|
||||
from treg.models import CallRecord
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ from fastapi import FastAPI
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
from starlette.routing import Mount
|
||||
|
||||
from treg import mcp, mcp_oauth
|
||||
from treg import mcp
|
||||
from treg.domain.identity import mcp_oauth
|
||||
from treg.routers import auth as auth_routes
|
||||
from treg.bootstrap import create_app
|
||||
from treg.config import Settings, get_settings
|
||||
|
||||
+11
-8
@@ -16,7 +16,8 @@ import time
|
||||
|
||||
import pytest
|
||||
|
||||
from treg import mcp, mcp_oauth, session
|
||||
from treg import mcp
|
||||
from treg.domain.identity import mcp_oauth, session
|
||||
from treg.routers import auth as auth_routes
|
||||
from treg.config import Settings, get_settings
|
||||
|
||||
@@ -205,7 +206,7 @@ async def test_loopback_http_is_allowed_because_a_CLI_cannot_hold_a_certificate(
|
||||
async def test_redirect_matching_is_EXACT_not_prefix():
|
||||
"""The classic defeat of this check. `https://good.test/cb.evil` starts with the registered URI,
|
||||
and an open redirect under a registered host turns one sloppy page into stolen codes."""
|
||||
from treg.mcp_oauth import redirect_uri_allowed
|
||||
from treg.domain.identity.mcp_oauth import redirect_uri_allowed
|
||||
|
||||
class C:
|
||||
redirect_uris = ["https://good.test/cb"]
|
||||
@@ -222,7 +223,7 @@ async def test_loopback_redirect_allows_ANY_port_but_not_other_drift():
|
||||
to vary — treg's pure exact-match rejected `http://localhost:3118/callback` against a registered
|
||||
`http://localhost/callback` and broke every native client. Port varies; scheme, host and path do
|
||||
NOT, and the loopback exception must not leak to public hosts."""
|
||||
from treg.mcp_oauth import redirect_uri_allowed
|
||||
from treg.domain.identity.mcp_oauth import redirect_uri_allowed
|
||||
|
||||
class C: # exactly what Claude Code's client-id metadata document registers
|
||||
redirect_uris = ["http://localhost/callback", "http://127.0.0.1/callback"]
|
||||
@@ -253,7 +254,7 @@ async def test_loopback_redirect_allows_ANY_port_but_not_other_drift():
|
||||
async def test_cimd_refuses_unsafe_urls(url):
|
||||
"""`client_id` is a URL our SERVER fetches, which makes it a request-forgery primitive unless
|
||||
fenced. Reuses the same guard the webhook and tool base_url paths already use."""
|
||||
from treg.mcp_oauth import fetch_client_id_metadata
|
||||
from treg.domain.identity.mcp_oauth import fetch_client_id_metadata
|
||||
|
||||
assert await fetch_client_id_metadata(url) is None
|
||||
|
||||
@@ -263,7 +264,8 @@ async def test_cimd_document_must_claim_its_own_url(monkeypatch):
|
||||
the consent users granted them."""
|
||||
import httpx
|
||||
|
||||
from treg import health, mcp_oauth
|
||||
from treg import health
|
||||
from treg.domain.identity import mcp_oauth
|
||||
|
||||
monkeypatch.setattr(health, "safe_webhook_url", lambda u: True)
|
||||
monkeypatch.setattr(health, "host_is_public", lambda h: True)
|
||||
@@ -282,7 +284,8 @@ async def test_cimd_accepts_a_well_formed_document(monkeypatch):
|
||||
"""Not vacuous: the refusals above only mean something if a good document DOES load."""
|
||||
import httpx
|
||||
|
||||
from treg import health, mcp_oauth
|
||||
from treg import health
|
||||
from treg.domain.identity import mcp_oauth
|
||||
|
||||
monkeypatch.setattr(health, "safe_webhook_url", lambda u: True)
|
||||
monkeypatch.setattr(health, "host_is_public", lambda h: True)
|
||||
@@ -335,7 +338,7 @@ async def _signed_in(clients, email="oauth-user@superdesign.dev"):
|
||||
clients.headers["X-Treg-Token"] = prev
|
||||
from sqlmodel import select
|
||||
|
||||
from treg import session as _sess
|
||||
from treg.domain.identity import session as _sess
|
||||
from treg.infra.db import session_maker
|
||||
from treg.models import User
|
||||
|
||||
@@ -1045,7 +1048,7 @@ async def _as(email: str) -> dict:
|
||||
"""Headers that act as a given user — an identity token, minted the way `treg login` does."""
|
||||
from sqlmodel import select
|
||||
|
||||
from treg import session as _sess
|
||||
from treg.domain.identity import session as _sess
|
||||
from treg.infra.db import session_maker
|
||||
from treg.models import User
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import pytest
|
||||
from httpx import AsyncClient
|
||||
|
||||
import treg.api as api_mod
|
||||
from treg import pubfeed
|
||||
from treg.application.onboard import pubfeed
|
||||
from treg.application import onboard as onboard_use_cases
|
||||
|
||||
SECRET = "whsec_test_secret"
|
||||
|
||||
@@ -27,7 +27,9 @@ from sqlmodel import select
|
||||
|
||||
from conftest import make_upstream
|
||||
|
||||
from treg import billing, ledger, referrals
|
||||
from treg.application import billing
|
||||
from treg.domain import money as ledger
|
||||
from treg.domain import referrals
|
||||
from treg.api import app
|
||||
from treg.config import get_settings
|
||||
from treg.infra.db import reset_db, session_maker
|
||||
|
||||
@@ -10,7 +10,8 @@ import pytest
|
||||
from httpx import AsyncClient
|
||||
from sqlmodel import select
|
||||
|
||||
from treg import audit, ledger
|
||||
from treg import audit
|
||||
from treg.domain import money as ledger
|
||||
from treg.application.call import route as call_route
|
||||
from treg.application.call import service as call_service
|
||||
from treg.application.call.types import UpstreamResponse
|
||||
|
||||
@@ -10,7 +10,8 @@ import pytest
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
from sqlmodel import select
|
||||
|
||||
from treg import api, maintenance, session as sess
|
||||
from treg import api, maintenance
|
||||
from treg.domain.identity import session as sess
|
||||
from treg.__main__ import _prepare_serve
|
||||
from treg.api import LOCAL_ORG_NAME, LOCAL_USER_EMAIL, app
|
||||
from treg.config import Settings, get_settings
|
||||
|
||||
@@ -17,7 +17,8 @@ import pytest
|
||||
from httpx import AsyncClient
|
||||
from sqlmodel import select
|
||||
|
||||
from treg import audit, crypto, ledger
|
||||
from treg import audit, crypto
|
||||
from treg.domain import money as ledger
|
||||
from treg.application.call import service as call_service
|
||||
from treg.application.call import settle as call_settle
|
||||
from treg.application.call.types import UpstreamResponse
|
||||
|
||||
@@ -14,7 +14,8 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlmodel import select
|
||||
from starlette.requests import Request
|
||||
|
||||
from treg import audit, crypto, ledger, localproxy
|
||||
from treg import audit, crypto, localproxy
|
||||
from treg.domain import money as ledger
|
||||
from treg.application.call import idempotency as call_idem
|
||||
from treg.application.call import reserve as call_reserve
|
||||
from treg.application.call import service as call_service
|
||||
@@ -247,7 +248,7 @@ async def test_attack_4_concurrent_prechecks_overshoot_is_bounded_not_exact(
|
||||
# because the balance is a materialized column it can gate on with one conditional UPDATE, while
|
||||
# a per-tag total is an aggregate with no such column. Tightening it would need a second
|
||||
# materialized authority on spend (reset daily, decremented on release, corrected on settle
|
||||
# divergence) — four new ways to disagree with ledger.py, which is the only module allowed to
|
||||
# divergence) — four new ways to disagree with domain/money, which is the only module allowed to
|
||||
# move money. The hard gates (org balance, per-org daily cap) sit behind this one.
|
||||
#
|
||||
# What must hold: the overshoot is bounded and every committed call is accounted for. Never
|
||||
|
||||
@@ -14,7 +14,7 @@ import json
|
||||
import pytest
|
||||
from httpx import ASGITransport, AsyncClient
|
||||
|
||||
from treg import session as sess
|
||||
from treg.domain.identity import session as sess
|
||||
from treg.api import app
|
||||
from treg.infra.db import reset_db
|
||||
|
||||
|
||||
Reference in New Issue
Block a user