feat(server): add Session execution configuration control plane

Persist versioned provider execution revisions, expose Space project admission transitions, and cover configuration and Session routing behavior.
This commit is contained in:
4pmtong 2026-09-25 17:10:36 +08:00 • committed by Tong Chen
parent 0aeeb26015
commit e754d1e32a
9 changed files with 1078 additions and 46 deletions

View file

@ -0,0 +1,54 @@
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
"""Add database-owned exact Provider execution references.
Revision ID: provider_execution_revision
Revises: merge_self_hosted_rc_lineages
"""
from uuid import uuid4
import sqlalchemy as sa
from alembic import op
from app.model.provider.execution_revision import (
install_execution_revision_triggers,
remove_execution_revision_triggers,
)
revision = "provider_execution_revision"
down_revision = "merge_self_hosted_rc_lineages"
branch_labels = None
depends_on = None
def upgrade():
connection = op.get_bind()
op.add_column(
"provider",
sa.Column("execution_revision", sa.String(32), nullable=False, server_default=sa.text("''")),
)
# Existing rows get independent non-secret identities, never key digests.
for row in connection.execute(sa.text("SELECT id FROM provider")).fetchall():
connection.execute(
sa.text("UPDATE provider SET execution_revision=:revision WHERE id=:id"),
{"revision": uuid4().hex, "id": row[0]},
)
install_execution_revision_triggers(connection)
def downgrade():
remove_execution_revision_triggers(op.get_bind())
op.drop_column("provider", "execution_revision")

View file

@ -0,0 +1,71 @@
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
"""Device/account-authenticated configuration and exact credential projection."""
from typing import Annotated, Literal
from fastapi import APIRouter, Depends, HTTPException, Request, Response
from pydantic import BaseModel, ConfigDict, Field
from sqlmodel import Session
from starlette.concurrency import run_in_threadpool
from app.core.database import session
from app.domains.model_provider.service.execution_configuration import ExecutionConfigurationSource
from app.domains.remote_control.api.command_control_controller import DevicePrincipal, device_principal_must
router = APIRouter(prefix="/sync/execution", tags=["Managed Execution Configuration"])
Principal = Annotated[DevicePrincipal, Depends(device_principal_must)]
Database = Annotated[Session, Depends(session)]
class ExactProviderReference(BaseModel):
model_config = ConfigDict(extra="forbid", strict=True, hide_input_in_errors=True)
provider_ref: str = Field(pattern=r"^provider:[1-9][0-9]{0,18}:[0-9a-f]{32}$")
space_id: str = Field(pattern=r"^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$")
session_mode: Literal["single-agent", "workforce"]
def private_response(response):
response.headers["Cache-Control"] = "no-store"
response.headers["Pragma"] = "no-cache"
@router.get("/identity")
def identity(principal: Principal, db: Database, response: Response):
private_response(response)
return ExecutionConfigurationSource.identity(db, principal)
@router.get("/projects/{project_id}/configuration")
def configuration(project_id: str, principal: Principal, db: Database, response: Response):
private_response(response)
return ExecutionConfigurationSource.read(db, principal, project_id)
@router.post("/projects/{project_id}/credentials:resolve")
async def resolve(project_id: str, principal: Principal, db: Database, request: Request, response: Response):
private_response(response)
try:
raw = b""
async for chunk in request.stream():
raw += chunk
if len(raw) > 2048:
raise ValueError("oversized reference")
exact = ExactProviderReference.model_validate_json(raw)
except ValueError:
# FastAPI's default validation payload may echo arbitrary input,
# including an accidentally supplied key. This endpoint never does.
raise HTTPException(status_code=422, detail={"code": "invalid_execution_reference"}) from None
return await run_in_threadpool(ExecutionConfigurationSource.read, db, principal, project_id, exact=exact)

View file

@ -0,0 +1,219 @@
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
"""Authenticated projection of existing Project, Space and Provider records.
This is not a second configuration or credential store. Resolving a pinned
provider requires its exact database-owned revision and a currently authorized
account/device. Values are returned only by the private credential operation.
"""
import copy
import math
import re
from urllib.parse import urlsplit
from fastapi import HTTPException
from sqlmodel import select
from app.domains.remote_control.service.command_control_service import CommandControlService
from app.model.project import Project
from app.model.provider.provider import Provider, VaildStatus
from app.model.remote_control.command_control import DesktopDevice
from app.model.space import Space
def unavailable():
raise HTTPException(status_code=409, detail={"code": "execution_configuration_unavailable"})
def provider_projection(provider):
"""Project only the supported non-secret schema, never arbitrary JSON."""
if (
provider.provider_name != "openai"
or provider.is_valid != VaildStatus.is_valid
or not re.fullmatch(r"[0-9a-f]{32}", provider.execution_revision or "")
or not re.fullmatch(r"[a-zA-Z0-9][a-zA-Z0-9._:-]{0,127}", provider.model_type or "")
or provider.model_type.lower().startswith(("sk-", "sk_"))
):
unavailable()
endpoint = urlsplit(provider.endpoint_url)
if (
endpoint.scheme != "https"
or not endpoint.hostname
or endpoint.username
or endpoint.password
or endpoint.query
or endpoint.fragment
or len(provider.endpoint_url) > 512
):
unavailable()
config = provider.encrypted_config
if config is None:
config = {}
if not isinstance(config, dict) or set(config) - {"model_config_dict", "api_mode", "timeout", "max_retries"}:
unavailable()
parameters = config.get("model_config_dict", {})
numeric = {
"temperature",
"top_p",
"max_tokens",
"max_completion_tokens",
"seed",
"frequency_penalty",
"presence_penalty",
}
if not isinstance(parameters, dict) or set(parameters) - numeric - {"stream", "n", "reasoning_effort"}:
unavailable()
for key, value in parameters.items():
if key in numeric and (type(value) not in (int, float) or not math.isfinite(value)):
unavailable()
if (
parameters.get("stream", False) is not False
or type(parameters.get("n", 1)) is not int
or parameters.get("n", 1) != 1
):
unavailable()
if "reasoning_effort" in parameters and parameters["reasoning_effort"] not in {
"minimal",
"low",
"medium",
"high",
"xhigh",
"max",
"ultra",
}:
unavailable()
constructor = {key: value for key, value in config.items() if key != "model_config_dict"}
timeout = constructor.get("timeout", 60)
retries = constructor.get("max_retries", 0)
if (
constructor.get("api_mode", "chat_completions") != "chat_completions"
or type(timeout) not in (int, float)
or not math.isfinite(timeout)
or not 0 < timeout <= 600
or type(retries) is not int
or not 0 <= retries <= 3
):
unavailable()
# Never derive a durable fingerprint from a secret, including a secret
# accidentally copied into an otherwise non-secret string field.
if provider.api_key and any(provider.api_key in value for value in (provider.model_type, provider.endpoint_url)):
unavailable()
return {
"provider_ref": f"provider:{provider.id}:{provider.execution_revision}",
"model_platform": provider.provider_name,
"model_type": provider.model_type,
"api_url": provider.endpoint_url,
"model_config_dict": parameters,
"extra_params": constructor,
}
class ExecutionConfigurationSource:
@staticmethod
def identity(db, principal):
device = CommandControlService.require_device(principal.desktop_instance_id, principal.user_id, db)
return {
"account_owner_id": str(principal.user_id),
"desktop_instance_id": device.id,
"device_credential_version": device.credential_version,
}
@classmethod
def read(cls, db, principal, project_id, *, exact=None):
identity = cls.identity(db, principal)
owner = identity["account_owner_id"]
# First select intent; the joined read below rechecks that intent and
# returns current membership, device and provider in one DB snapshot.
project = db.exec(select(Project).where(Project.id == project_id, Project.user_id == owner)).first()
if project is None or project.status != "active" or project.mode not in {"single-agent", "workforce"}:
unavailable()
space = db.exec(select(Space).where(Space.id == project.space_id, Space.user_id == owner)).first()
if space is None or space.status != "active" or not space.root_path:
unavailable()
metadata = copy.deepcopy(project.metadata_json or {})
if not isinstance(metadata, dict):
unavailable()
effort = metadata.get("thinkingEffort")
if effort is not None and effort not in {"minimal", "low", "medium", "high", "xhigh", "max", "ultra"}:
unavailable()
providers = select(Provider).where(Provider.user_id == principal.user_id, Provider.no_delete())
selection = metadata.get("modelSelection")
if exact is not None:
if exact.space_id != project.space_id or exact.session_mode != project.mode:
unavailable()
_, provider_id, revision = exact.provider_ref.split(":")
providers = providers.where(Provider.id == int(provider_id), Provider.execution_revision == revision)
elif selection is not None:
if (
not isinstance(selection, dict)
or set(selection) - {"modelType", "provider_id", "model_platform", "model_type"}
or selection.get("modelType") not in {"custom", "local"}
or type(selection.get("provider_id")) is not int
):
unavailable()
providers = providers.where(Provider.id == selection["provider_id"])
else:
providers = providers.where(Provider.prefer == True)
candidates = db.exec(
select(Project, Space, Provider)
.join(Space, Space.id == Project.space_id)
.join(Provider, Provider.user_id == principal.user_id)
.join(DesktopDevice, DesktopDevice.id == principal.desktop_instance_id)
.where(
Project.id == project_id,
Project.user_id == owner,
Project.status == "active",
Space.user_id == owner,
Space.status == "active",
DesktopDevice.user_id == principal.user_id,
DesktopDevice.revoked_at.is_(None),
DesktopDevice.credential_version == identity["device_credential_version"],
Provider.id.in_(providers.with_only_columns(Provider.id)),
)
.execution_options(populate_existing=True)
.with_for_update()
).all()
if len(candidates) != 1:
unavailable()
project, space, provider = candidates[0]
if not space.root_path or project.mode not in {"single-agent", "workforce"}:
unavailable()
if exact is not None:
if (project.space_id, project.mode) != (exact.space_id, exact.session_mode):
unavailable()
elif (project.metadata_json or {}) != metadata:
unavailable()
projection = provider_projection(provider)
if exact is None and selection:
for field in ("model_platform", "model_type"):
if field in selection and selection[field] != projection[field]:
unavailable()
result = {
**identity,
"project_id": project.id,
"space_id": space.id,
"space_source_type": "legacy" if (space.metadata_json or {}).get("legacy") is True else space.source_type,
"session_mode": project.mode,
"space_root": space.root_path,
"thinking_effort": effort,
"provider": projection,
}
if exact is not None:
if not isinstance(provider.api_key, str) or not provider.api_key.strip():
unavailable()
# Never log, hash or persist this response in the Brain.
result["api_key"] = provider.api_key
return result

View file

@ -12,6 +12,8 @@
# limitations under the License.
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
import hashlib
import json
import logging
from datetime import datetime
from uuid import uuid4
@ -33,6 +35,7 @@ from app.model.project import (
ProjectUpdate,
ProjectWorkdirMode,
)
from app.model.project.project import PROJECT_CREATION_INTENT_KEY
from app.model.space import Space, SpaceIn, SpaceOut, SpaceSourceType, SpaceStatus, SpaceUpdate
_LOGGER = logging.getLogger(__name__)
@ -42,9 +45,7 @@ class SpaceHasProjectsError(ValueError):
def __init__(self, project_count: int, projects: list[dict[str, str]]) -> None:
self.project_count = project_count
self.projects = projects
super().__init__(
f"Space has {project_count} project(s); archive or delete them first"
)
super().__init__(f"Space has {project_count} project(s); archive or delete them first")
class ProjectModelAdmissionConflictError(ValueError):
@ -110,7 +111,8 @@ class SpaceService:
placeholder_projects = [
project
for project in projects
if not (project.metadata_json or {}).get("nameSource") and SpaceService._project_name_is_placeholder(
if not (project.metadata_json or {}).get("nameSource")
and SpaceService._project_name_is_placeholder(
project.name,
project.id,
)
@ -223,9 +225,7 @@ class SpaceService:
raise ValueError("Invalid Space status")
@staticmethod
def _prepare_space_root(
data: SpaceIn, user_id: str, s: Session
) -> tuple[str | None, dict | None]:
def _prepare_space_root(data: SpaceIn, user_id: str, s: Session) -> tuple[str | None, dict | None]:
if data.source_type == SpaceSourceType.FOLDER:
root_ref = normalize_folder_root_reference(data.root_path or "")
existing_spaces = s.exec(
@ -271,9 +271,7 @@ class SpaceService:
raise ValueError("Folder is already bound to another Space")
@staticmethod
def _folder_identity_matches(
previous: dict | None, current: dict
) -> bool:
def _folder_identity_matches(previous: dict | None, current: dict) -> bool:
if not previous:
return True
if previous.get("kind") != current.get("kind"):
@ -335,10 +333,7 @@ class SpaceService:
if projects:
raise SpaceHasProjectsError(
len(projects),
[
{"id": project.id, "name": project.name}
for project in projects[:10]
],
[{"id": project.id, "name": project.name} for project in projects[:10]],
)
s.delete(space)
s.commit()
@ -392,20 +387,13 @@ class SpaceService:
root_ref = normalize_folder_root_reference(root_path)
if not force:
if root_fingerprint and space.root_fingerprint:
if not SpaceService._folder_identity_matches(
space.root_fingerprint, root_fingerprint
):
raise ValueError(
"Relocated folder identity does not match this Space"
)
elif space.root_path and not same_folder_reference(
space.root_path, root_ref
):
if not SpaceService._folder_identity_matches(space.root_fingerprint, root_fingerprint):
raise ValueError("Relocated folder identity does not match this Space")
elif space.root_path and not same_folder_reference(space.root_path, root_ref):
# No fingerprint available on either side: require the caller
# to acknowledge the change with force=True.
raise ValueError(
"Relocated folder identity cannot be verified; "
"supply root_fingerprint or use force=True"
"Relocated folder identity cannot be verified; supply root_fingerprint or use force=True"
)
SpaceService._assert_folder_not_bound_to_other_space(
user_id=canonical_user_id,
@ -498,8 +486,7 @@ class SpaceService:
name=display_name[:255] or f"Project {project_id}",
description=description,
mode=mode,
workdir_mode=workdir_mode
or SpaceService._default_project_workdir_mode(space),
workdir_mode=workdir_mode or SpaceService._default_project_workdir_mode(space),
metadata_json=metadata,
)
try:
@ -535,16 +522,8 @@ class SpaceService:
@staticmethod
def list_spaces(user_id: int | str, s: Session) -> list[SpaceOut]:
canonical_user_id = SpaceService.canonical_user_id(user_id)
spaces = s.exec(
select(Space)
.where(Space.user_id == canonical_user_id)
.order_by(Space.updated_at.desc())
).all()
legacy_space_ids = [
space.id
for space in spaces
if space.source_type == SpaceSourceType.LEGACY
]
spaces = s.exec(select(Space).where(Space.user_id == canonical_user_id).order_by(Space.updated_at.desc())).all()
legacy_space_ids = [space.id for space in spaces if space.source_type == SpaceSourceType.LEGACY]
if legacy_space_ids:
legacy_space_ids_with_projects = set(
s.exec(
@ -557,8 +536,7 @@ class SpaceService:
spaces = [
space
for space in spaces
if space.source_type != SpaceSourceType.LEGACY
or space.id in legacy_space_ids_with_projects
if space.source_type != SpaceSourceType.LEGACY or space.id in legacy_space_ids_with_projects
]
return [SpaceOut.from_model(space) for space in spaces]
@ -600,6 +578,11 @@ class SpaceService:
space = SpaceService._get_owned_space(space_id, canonical_user_id, s)
SpaceService._validate_project_payload(data.mode, data.status, data.workdir_mode)
if PROJECT_CREATION_INTENT_KEY in (data.metadata or {}):
raise ValueError("Project creation receipt is server-owned")
if data.space_id is not None and data.space_id != space_id:
raise ValueError("Project Space differs from the creation target")
project_id = data.id or f"project_{uuid4().hex}"
project = Project(
id=project_id,
@ -609,12 +592,70 @@ class SpaceService:
description=data.description,
mode=data.mode,
status=data.status,
workdir_mode=data.workdir_mode
or SpaceService._default_project_workdir_mode(space),
workdir_mode=data.workdir_mode or SpaceService._default_project_workdir_mode(space),
metadata_json=data.metadata,
)
# Compare the original creation intent, not mutable name/settings/status.
# The receipt lives in the existing JSON column and is never client-writable.
creation_intent = hashlib.sha256(
json.dumps(
{
**data.model_dump(exclude={"id", "space_id"}),
"id": project_id,
"user_id": canonical_user_id,
"space_id": space_id,
"name": project.name,
},
sort_keys=True,
separators=(",", ":"),
ensure_ascii=False,
allow_nan=False,
).encode("utf-8")
).hexdigest()
def recover(existing: Project) -> Project:
if existing.user_id != canonical_user_id or existing.space_id != space_id:
raise ValueError("Project id already belongs to another creation target")
receipt = (existing.metadata_json or {}).get(PROJECT_CREATION_INTENT_KEY)
if receipt is not None:
matches = receipt == creation_intent
else:
# Pre-receipt rows retain the strict old collision check. There is
# no evidence permitting reconstruction from subsequently edited data.
fields = ("name", "description", "mode", "status", "workdir_mode", "metadata_json")
matches = all(getattr(existing, field) == getattr(project, field) for field in fields)
if not matches:
raise ValueError("Project id already exists with a different creation intent")
return existing
existing = s.get(Project, project_id)
if existing is not None:
return recover(existing)
project.metadata_json = {**(data.metadata or {}), PROJECT_CREATION_INTENT_KEY: creation_intent}
s.add(project)
s.commit()
try:
s.commit()
except IntegrityError as error:
s.rollback()
# Only the Project identity constraints may be recovered. Foreign
# key, other unique/check constraints and unrelated failures still fail.
original = error.orig
sqlite_duplicate = getattr(original, "sqlite_errorcode", None) in {1555, 2067} and str(original) in {
f"UNIQUE constraint failed: {Project.__tablename__}.id",
f"UNIQUE constraint failed: {Project.__tablename__}.user_id, {Project.__tablename__}.id",
}
postgres_duplicate = (
getattr(original, "sqlstate", None) or getattr(original, "pgcode", None)
) == "23505" and getattr(getattr(original, "diag", None), "constraint_name", None) in {
Project.__table__.primary_key.name or f"{Project.__tablename__}_pkey",
"uix_project_user_id_id",
}
if not (sqlite_duplicate or postgres_duplicate):
raise
winner = s.get(Project, project_id)
if winner is None:
raise
return recover(winner)
s.refresh(project)
return project
@ -646,7 +687,7 @@ class SpaceService:
) -> Project:
canonical_user_id = SpaceService.canonical_user_id(user_id)
SpaceService._get_owned_space(space_id, canonical_user_id, s)
SpaceService._validate_project_payload(status=data.status, workdir_mode=data.workdir_mode)
SpaceService._validate_project_payload(mode=data.mode, status=data.status, workdir_mode=data.workdir_mode)
project_scope = (
Project.id == project_id,
Project.user_id == canonical_user_id,
@ -673,6 +714,8 @@ class SpaceService:
current_metadata = project.metadata_json or {}
current_revision = current_metadata.get("spaceModelAdmissionRevision")
metadata = update_data.pop("metadata", None)
if PROJECT_CREATION_INTENT_KEY in (metadata or {}):
raise ValueError("Project creation receipt is server-owned")
if revision is not None:
# Both assignment and cleanup compare the entire receipt generation.
# Keep the revision after null so an old request cannot exploit ABA.
@ -753,8 +796,7 @@ class SpaceService:
project.workdir_mode = ProjectWorkdirMode.COPY
project.metadata_json = {
**previous_metadata,
"promotedFromSpaceId": previous_metadata.get("promotedFromSpaceId")
or previous_space_id,
"promotedFromSpaceId": previous_metadata.get("promotedFromSpaceId") or previous_space_id,
}
s.add(project)
s.commit()

View file

@ -71,6 +71,10 @@ class Project(AbstractModel, DefaultTimes, table=True):
metadata_json: dict[str, Any] | None = Field(default=None, sa_column=Column("metadata", JSON))
# Server-owned receipt in the existing JSON column; no database migration.
PROJECT_CREATION_INTENT_KEY = "_eigent_creation_intent_v1"
class ProjectIn(BaseModel):
id: str | None = None
space_id: str | None = None
@ -85,6 +89,7 @@ class ProjectIn(BaseModel):
class ProjectUpdate(BaseModel):
name: str | None = None
description: str | None = None
mode: str | None = None
status: str | None = None
workdir_mode: str | None = None
metadata: dict[str, Any] | None = None
@ -135,6 +140,8 @@ class ProjectOut(BaseModel):
@classmethod
def from_model(cls, project: Project) -> "ProjectOut":
metadata = project.metadata_json if isinstance(project.metadata_json, dict) else None
if metadata is not None and PROJECT_CREATION_INTENT_KEY in metadata:
metadata = {key: value for key, value in metadata.items() if key != PROJECT_CREATION_INTENT_KEY} or None
return cls(
id=project.id,
user_id=project.user_id,

View file

@ -0,0 +1,83 @@
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
"""Database-owned opaque Provider revisions, independent of secret values.
Triggers cover ORM, bulk and raw SQL writes, including older CRUD clients.
Changing preference alone does not invalidate a pinned provider. Rollback also
rolls back the revision; deleted/re-created rows receive a fresh identity.
"""
from sqlalchemy import text
FIELDS = "user_id, provider_name, model_type, api_key, endpoint_url, encrypted_config, is_vaild, deleted_at"
def install_execution_revision_triggers(connection):
dialect = connection.dialect.name
if dialect == "sqlite":
connection.execute(
text("""
CREATE TRIGGER provider_execution_revision_insert AFTER INSERT ON provider
BEGIN
UPDATE provider SET execution_revision = lower(hex(randomblob(16)))
WHERE id = NEW.id;
END
""")
)
connection.execute(
text(f"""
CREATE TRIGGER provider_execution_revision_update AFTER UPDATE OF {FIELDS} ON provider
BEGIN
UPDATE provider SET execution_revision = lower(hex(randomblob(16)))
WHERE id = NEW.id;
END
""")
)
elif dialect == "postgresql":
# The repository's server deployment uses PostgreSQL 15.
connection.execute(
text("""
CREATE FUNCTION rotate_provider_execution_revision() RETURNS trigger AS $$
BEGIN
NEW.execution_revision := replace(gen_random_uuid()::text, '-', '');
RETURN NEW;
END;
$$ LANGUAGE plpgsql
""")
)
connection.execute(
text(f"""
CREATE TRIGGER provider_execution_revision_write
BEFORE INSERT OR UPDATE OF {FIELDS} ON provider
FOR EACH ROW EXECUTE FUNCTION rotate_provider_execution_revision()
""")
)
else:
raise RuntimeError("Provider execution revisions require PostgreSQL or SQLite")
def remove_execution_revision_triggers(connection):
if connection.dialect.name == "sqlite":
connection.execute(text("DROP TRIGGER provider_execution_revision_insert"))
connection.execute(text("DROP TRIGGER provider_execution_revision_update"))
elif connection.dialect.name == "postgresql":
connection.execute(text("DROP TRIGGER provider_execution_revision_write ON provider"))
connection.execute(text("DROP FUNCTION rotate_provider_execution_revision()"))
else:
raise RuntimeError("Unsupported Provider revision database")
def after_create(_table, connection, **_kwargs):
install_execution_revision_triggers(connection)

View file

@ -16,11 +16,12 @@ from enum import IntEnum
from typing import Literal
from pydantic import AliasChoices, BaseModel, Field as PydanticField, field_validator
from sqlalchemy import Boolean, Column, SmallInteger, text
from sqlalchemy import Boolean, Column, SmallInteger, String, event, text
from sqlalchemy_utils import ChoiceType
from sqlmodel import JSON, Field
from app.model.abstract.model import AbstractModel, DefaultTimes
from app.model.provider.execution_revision import after_create
class VaildStatus(IntEnum):
@ -34,6 +35,8 @@ class Provider(AbstractModel, DefaultTimes, table=True):
provider_name: str
model_type: str
api_key: str
# Assigned by database triggers. It is random, never a hash of a key/token.
execution_revision: str = Field(default="", sa_column=Column(String(32), nullable=False, server_default=text("''")))
endpoint_url: str = ""
encrypted_config: dict | None = Field(default=None, sa_column=Column(JSON))
prefer: bool = Field(default=False, sa_column=Column(Boolean, server_default=text("false")))
@ -101,3 +104,6 @@ class ProviderModelMetadata(BaseModel):
model_type=model_type,
available=bool(model_type) and is_valid == VaildStatus.is_valid,
)
event.listen(Provider.__table__, "after_create", after_create)

View file

@ -0,0 +1,260 @@
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
"""Real JWT/device/Provider/database paths with synthetic SQLite and no Redis I/O."""
import importlib.util
import re
from concurrent.futures import ThreadPoolExecutor
from datetime import UTC, datetime
from pathlib import Path
from types import SimpleNamespace
import pytest
from alembic.migration import MigrationContext
from alembic.operations import Operations
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.testclient import TestClient
from sqlalchemy import text
from sqlmodel import Session, create_engine
from app.core.database import session
from app.domains.model_provider.api.execution_controller import router
from app.domains.model_provider.service import provider_service
from app.domains.model_provider.service.provider_service import ProviderService
from app.domains.remote_control.api.command_control_controller import router as device_router
from app.model.project import Project
from app.model.provider.provider import Provider, ProviderIn, ProviderOut, VaildStatus
from app.model.remote_control.command_control import DesktopDevice
from app.model.space import Space
from app.model.user.user import User
from app.shared.auth import user_auth
from app.shared.exception import TokenException
@pytest.fixture
def authority(tmp_path, monkeypatch):
engine = create_engine("sqlite:///" + str(tmp_path / "authority.sqlite"), connect_args={"check_same_thread": False})
for model in (User, Space, Project, Provider, DesktopDevice):
model.__table__.create(engine)
with Session(engine) as db:
db.add(User(id=1, email="one@example.test"))
db.add(User(id=2, email="two@example.test"))
db.add(Space(id="space", user_id="1", name="Synthetic", root_path=str(tmp_path)))
db.add(Project(id="project", user_id="1", space_id="space", name="Synthetic", mode="single-agent"))
db.commit()
async def blacklist(_jti):
return False
monkeypatch.setattr(user_auth, "is_blacklisted", blacklist)
monkeypatch.setattr(provider_service, "session_make", lambda: Session(engine))
def database():
with Session(engine) as db:
yield db
app = FastAPI()
app.dependency_overrides[session] = database
app.include_router(device_router)
app.include_router(router)
@app.exception_handler(TokenException)
async def rejected(_request, _exception):
return JSONResponse(status_code=401, content={"code": "authentication_required"})
provider = ProviderService.create(
1,
ProviderIn(
provider_name="openai",
model_type="gpt-5",
api_key="synthetic-provider-secret",
endpoint_url="https://api.openai.com/v1",
is_valid=VaildStatus.is_valid,
prefer=True,
).model_dump(),
)["provider"]
with TestClient(app) as client:
headers = {"Authorization": "Bearer " + user_auth.create_access_token(1), "X-Desktop-Instance-ID": "device"}
assert client.post("/sync/devices/register", headers=headers, json={}).status_code == 200
yield SimpleNamespace(engine=engine, client=client, headers=headers, provider=provider)
engine.dispose()
def reference(authority):
response = authority.client.get("/sync/execution/projects/project/configuration", headers=authority.headers)
assert response.status_code == 200, response.text
assert response.headers["cache-control"] == "no-store"
assert "synthetic-provider-secret" not in response.text
config = response.json()
return {
"provider_ref": config["provider"]["provider_ref"],
"space_id": config["space_id"],
"session_mode": config["session_mode"],
}
def resolve(authority, ref):
return authority.client.post(
"/sync/execution/projects/project/credentials:resolve", headers=authority.headers, json=ref
)
def test_existing_auth_and_exact_reference(authority):
ref = reference(authority)
result = resolve(authority, ref)
assert result.status_code == 200, result.text
assert result.json()["api_key"] == "synthetic-provider-secret"
assert result.headers["cache-control"] == "no-store"
# Legacy DTO remains compatible and never acquires the revision field.
assert "execution_revision" not in ProviderOut.model_fields
assert authority.client.get("/sync/execution/identity").status_code == 401
alien = dict(authority.headers, Authorization="Bearer " + user_auth.create_access_token(2))
assert authority.client.get("/sync/execution/identity", headers=alien).status_code in (403, 404)
with Session(authority.engine) as db:
device = db.get(DesktopDevice, "device")
device.revoked_at = datetime.now(UTC)
db.add(device)
db.commit()
assert resolve(authority, ref).status_code in (403, 404, 409)
@pytest.mark.parametrize("mutation", ["update", "invalidate", "delete", "raw", "orm", "owner"])
def test_every_provider_writer_invalidates_old_reference(authority, mutation):
ref = reference(authority)
identity = authority.provider.id
if mutation == "update":
ProviderService.update(identity, 1, {"api_key": "synthetic-rotated-secret"})
elif mutation == "invalidate":
ProviderService.invalidate(identity, 1)
elif mutation == "delete":
ProviderService.delete(identity, 1)
else:
with Session(authority.engine) as db:
if mutation == "raw":
db.execute(text("UPDATE provider SET encrypted_config='{}' WHERE id=:id"), {"id": identity})
else:
provider = db.get(Provider, identity)
if mutation == "owner":
provider.user_id = 2
else:
provider.model_type = "gpt-4o"
db.add(provider)
db.commit()
with Session(authority.engine) as db:
assert db.get(Provider, identity).execution_revision != ref["provider_ref"].split(":")[-1]
assert resolve(authority, ref).status_code == 409
def test_preference_rollback_and_concurrent_writers(authority):
ref = reference(authority)
ProviderService.set_prefer(authority.provider.id, 1)
assert reference(authority) == ref
with Session(authority.engine) as db:
db.execute(text("UPDATE provider SET api_key='rolled-back'"))
changed = db.execute(text("SELECT execution_revision FROM provider")).scalar_one()
assert changed != ref["provider_ref"].split(":")[-1]
db.rollback()
assert resolve(authority, ref).status_code == 200
def write(index):
with authority.engine.begin() as connection:
connection.execute(text("UPDATE provider SET api_key=:key"), {"key": "synthetic-" + str(index)})
return connection.execute(text("SELECT execution_revision FROM provider")).scalar_one()
with ThreadPoolExecutor(max_workers=2) as pool:
revisions = list(pool.map(write, range(4)))
assert len(set(revisions)) == 4
assert all(re.fullmatch("[0-9a-f]{32}", value) for value in revisions)
assert resolve(authority, ref).status_code == 409
@pytest.mark.parametrize(
"field,value", [("user_id", "2"), ("space_id", "other"), ("mode", "workforce"), ("status", "archived")]
)
def test_membership_and_mode_are_revalidated(authority, field, value):
ref = reference(authority)
with Session(authority.engine) as db:
project = db.get(Project, "project")
setattr(project, field, value)
db.add(project)
db.commit()
assert resolve(authority, ref).status_code == 409
def test_current_intent_cannot_replace_exact_provider(authority):
ref = reference(authority)
with Session(authority.engine) as db:
project = db.get(Project, "project")
project.metadata_json = {
"modelSelection": {"modelType": "custom", "provider_id": 999},
"thinkingEffort": "high",
}
db.add(project)
db.commit()
assert resolve(authority, ref).json()["provider"]["provider_ref"] == ref["provider_ref"]
assert (
authority.client.get("/sync/execution/projects/project/configuration", headers=authority.headers).status_code
== 409
)
@pytest.mark.parametrize(
"config",
[
{"api_key": "input-secret"},
{"model_config_dict": {"n": True}},
{"api_mode": "responses"},
{"model_config_dict": {"headers": {"Authorization": "input-secret"}}},
],
)
def test_unsupported_configuration_and_input_do_not_echo_secrets(authority, config):
ref = reference(authority)
invalid = resolve(authority, dict(ref, api_key="input-secret"))
assert invalid.status_code == 422 and "input-secret" not in invalid.text
ProviderService.update(authority.provider.id, 1, {"encrypted_config": config})
result = authority.client.get("/sync/execution/projects/project/configuration", headers=authority.headers)
assert result.status_code == 409 and "input-secret" not in result.text
def test_upgrade_existing_rows_downgrade_and_old_insert(tmp_path):
engine = create_engine("sqlite:///" + str(tmp_path / "migration.sqlite"))
path = Path(__file__).parents[1] / "alembic/versions/2026_09_21_1200-provider_execution_revision.py"
spec = importlib.util.spec_from_file_location("execution_migration", path)
migration = importlib.util.module_from_spec(spec)
spec.loader.exec_module(migration)
with engine.begin() as connection:
connection.execute(
text(
"CREATE TABLE provider (id INTEGER PRIMARY KEY, user_id INTEGER, provider_name TEXT, model_type TEXT, api_key TEXT, endpoint_url TEXT, encrypted_config TEXT, is_vaild INTEGER, deleted_at TEXT)"
)
)
connection.execute(
text("INSERT INTO provider (id,api_key) VALUES (1,'same-synthetic-secret'),(2,'same-synthetic-secret')")
)
with Operations.context(MigrationContext.configure(connection)):
migration.upgrade()
revisions = connection.execute(text("SELECT execution_revision FROM provider")).scalars().all()
assert len(set(revisions)) == 2 and all(re.fullmatch("[0-9a-f]{32}", value) for value in revisions)
connection.execute(text("INSERT INTO provider (id,api_key) VALUES (3,'same-synthetic-secret')"))
assert (
connection.execute(text("SELECT execution_revision FROM provider WHERE id=3")).scalar_one()
not in revisions
)
migration.downgrade()
assert "execution_revision" not in {
row[1] for row in connection.execute(text("PRAGMA table_info(provider)"))
}
engine.dispose()

View file

@ -0,0 +1,290 @@
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
"""C6 uses the real authenticated Space API and synthetic SQLite only."""
import pytest
from sqlmodel import Session, select
from app.domains.space.api.space_controller import router
from app.model.project import Project
from tests import test_execution_configuration
authority = test_execution_configuration.authority
def test_session_configuration_patch_is_saved_and_returned(authority):
a = authority
a.client.app.include_router(router)
payload = {
"mode": "single-agent",
"metadata": {
"modelSelection": {
"modelType": "custom",
"provider_id": a.provider.id,
"model_platform": "openai",
"model_type": "gpt-5",
},
"thinkingEffort": "high",
},
}
response = a.client.patch("/spaces/space/projects/project", headers=a.headers, json=payload)
assert response.status_code == 200, response.text
assert response.json()["mode"] == "single-agent"
metadata = response.json()["metadata"]
revision = metadata["spaceModelAdmissionRevision"]
assert isinstance(revision, str) and len(revision) == 32
assert metadata == {**payload["metadata"], "spaceModelAdmissionRevision": revision}
with Session(a.engine) as db:
saved = db.get(Project, "project")
assert saved.mode == "single-agent" and saved.metadata_json == metadata
response = a.client.get("/sync/execution/projects/project/configuration", headers=a.headers)
assert response.status_code == 200, response.text
assert response.json()["thinking_effort"] == "high"
assert response.json()["session_mode"] == "single-agent"
assert response.json()["space_source_type"] == "blank"
bad = a.client.patch("/spaces/space/projects/project", headers=a.headers, json={"mode": "unsupported"})
assert bad.status_code == 404
with Session(a.engine) as db:
assert db.get(Project, "project").mode == "single-agent"
def test_lost_create_ack_reuses_exact_creation_and_rejects_collision(authority):
a = authority
a.client.app.include_router(router)
payload = {
"id": "c6-session",
"name": "Synthetic",
"mode": "single-agent",
"metadata": {"thinkingEffort": "medium"},
}
first = a.client.post("/spaces/space/projects", headers=a.headers, json=payload)
assert first.status_code == 200, first.text
assert a.client.post("/spaces/space/projects", headers=a.headers, json=payload).json() == first.json()
assert (
a.client.post("/spaces/space/projects", headers=a.headers, json={**payload, "name": "different"}).status_code
== 404
)
with Session(a.engine) as db:
assert len(db.exec(select(Project).where(Project.id == "c6-session")).all()) == 1
def test_original_creation_receipt_survives_mutable_settings_and_name(authority):
from app.model.project.project import PROJECT_CREATION_INTENT_KEY
a = authority
a.client.app.include_router(router)
payload = {
"id": "receipt-session",
"name": "Original draft",
"mode": "single-agent",
"metadata": {"thinkingEffort": "high"},
}
first = a.client.post("/spaces/space/projects", headers=a.headers, json=payload)
assert first.status_code == 200, first.text
assert PROJECT_CREATION_INTENT_KEY not in first.json()["metadata"]
change = {"name": "Renamed Session", "status": "archived", "metadata": {"thinkingEffort": "low"}}
updated = a.client.patch("/spaces/space/projects/receipt-session", headers=a.headers, json=change)
assert updated.status_code == 200, updated.text
# An ACK retry returns the current owned row without resetting its settings.
retry = a.client.post("/spaces/space/projects", headers=a.headers, json=payload)
assert retry.status_code == 200, retry.text
assert retry.json() == updated.json()
with Session(a.engine) as db:
row = db.get(Project, "receipt-session")
assert row.metadata_json[PROJECT_CREATION_INTENT_KEY]
assert row.name == "Renamed Session" and row.metadata_json["thinkingEffort"] == "low"
for metadata in ({PROJECT_CREATION_INTENT_KEY: "forged"}, {PROJECT_CREATION_INTENT_KEY: None}):
assert (
a.client.patch(
"/spaces/space/projects/receipt-session", headers=a.headers, json={"metadata": metadata}
).status_code
== 404
)
assert (
a.client.post(
"/spaces/space/projects", headers=a.headers, json={**payload, "metadata": metadata}
).status_code
== 404
)
assert (
a.client.post(
"/spaces/space/projects", headers=a.headers, json={**payload, "name": "Changed creation"}
).status_code
== 404
)
def test_creation_receipt_cannot_recover_another_owner_or_space(authority):
from app.model.space import Space
from app.shared.auth import user_auth
a = authority
a.client.app.include_router(router)
payload = {"id": "owned-receipt", "name": "draft", "mode": "single-agent"}
assert a.client.post("/spaces/space/projects", headers=a.headers, json=payload).status_code == 200
with Session(a.engine) as db:
db.add(Space(id="second-space", user_id="1", name="Second"))
db.add(Space(id="alien-space", user_id="2", name="Alien"))
db.commit()
alien = {**a.headers, "Authorization": "Bearer " + user_auth.create_access_token(2)}
assert a.client.post("/spaces/second-space/projects", headers=a.headers, json=payload).status_code == 404
assert a.client.post("/spaces/alien-space/projects", headers=alien, json=payload).status_code == 404
assert (
a.client.post(
"/spaces/space/projects", headers=a.headers, json={**payload, "space_id": "second-space"}
).status_code
== 404
)
with Session(a.engine) as db:
row = db.get(Project, payload["id"])
assert row.space_id == "space" and row.user_id == "1"
def test_concurrent_identical_creates_converge_through_authenticated_api(authority):
from concurrent.futures import ThreadPoolExecutor
from threading import Barrier
from app.core.database import session
a = authority
a.client.app.include_router(router)
barrier = Barrier(2)
class RacingSession(Session):
def get(self, entity, ident, *args, **kwargs):
result = super().get(entity, ident, *args, **kwargs)
if entity is Project and ident == "concurrent-session" and result is None:
barrier.wait(timeout=5)
return result
def database():
with RacingSession(a.engine) as db:
yield db
a.client.app.dependency_overrides[session] = database
payload = {"id": "concurrent-session", "name": "draft", "mode": "single-agent"}
with ThreadPoolExecutor(max_workers=2) as pool:
responses = list(
pool.map(lambda _: a.client.post("/spaces/space/projects", headers=a.headers, json=payload), range(2))
)
assert [response.status_code for response in responses] == [200, 200]
assert responses[0].json() == responses[1].json()
with Session(a.engine) as db:
assert len(db.exec(select(Project).where(Project.id == payload["id"])).all()) == 1
def test_concurrent_different_creations_reject_the_losing_intent(authority):
from concurrent.futures import ThreadPoolExecutor
from threading import Barrier
from app.core.database import session
a = authority
a.client.app.include_router(router)
barrier = Barrier(2)
class RacingSession(Session):
def get(self, entity, ident, *args, **kwargs):
result = super().get(entity, ident, *args, **kwargs)
if entity is Project and ident == "conflicting-session" and result is None:
barrier.wait(timeout=5)
return result
def database():
with RacingSession(a.engine) as db:
yield db
a.client.app.dependency_overrides[session] = database
def create(name):
return a.client.post(
"/spaces/space/projects",
headers=a.headers,
json={"id": "conflicting-session", "name": name, "mode": "single-agent"},
)
with ThreadPoolExecutor(max_workers=2) as pool:
responses = list(pool.map(create, ["First", "Second"]))
assert sorted(response.status_code for response in responses) == [200, 404]
winner = next(response.json() for response in responses if response.status_code == 200)
with Session(a.engine) as db:
assert db.get(Project, "conflicting-session").name == winner["name"]
def test_unrelated_integrity_errors_are_not_recovered(authority, monkeypatch):
import sqlite3
import pytest
from sqlalchemy.exc import IntegrityError
from app.domains.space.service.space_service import SpaceService
from app.model.project import ProjectIn
for code, message in [
(2067, "UNIQUE constraint failed: project.name"),
(787, "FOREIGN KEY constraint failed"),
(1299, "NOT NULL constraint failed: project.user_id"),
]:
original = sqlite3.IntegrityError(message)
original.sqlite_errorcode = code
failure = IntegrityError("synthetic statement", {}, original)
with Session(authority.engine) as db:
def fail():
raise failure
monkeypatch.setattr(db, "commit", fail)
with pytest.raises(IntegrityError) as caught:
SpaceService.create_project(
"space", ProjectIn(id="no-recovery", name="draft", mode="single-agent"), 1, db
)
assert caught.value is failure
with Session(authority.engine) as db:
assert db.get(Project, "no-recovery") is None
@pytest.mark.parametrize("constraint", ["project_pkey", "uix_project_user_id_id", "unrelated_unique"])
def test_postgres_identity_diagnostics_are_narrowly_recognized_without_remote_database(authority, constraint):
from types import SimpleNamespace
from sqlalchemy.exc import IntegrityError
from app.domains.space.service.space_service import SpaceService
from app.model.project import ProjectIn
class SyntheticPostgresError(Exception):
sqlstate = "23505"
diag = SimpleNamespace(constraint_name=constraint)
class CollisionSession(Session):
winner = None
def commit(self):
self.winner = next(row for row in self.new if isinstance(row, Project)).model_copy(deep=True)
raise IntegrityError("synthetic insert", {}, SyntheticPostgresError())
def get(self, entity, ident, *args, **kwargs):
if entity is Project and self.winner is not None:
return self.winner
return super().get(entity, ident, *args, **kwargs)
with CollisionSession(authority.engine) as db:
payload = ProjectIn(id="diagnostic-session", name="draft", mode="single-agent")
if constraint == "unrelated_unique":
with pytest.raises(IntegrityError):
SpaceService.create_project("space", payload, 1, db)
else:
recovered = SpaceService.create_project("space", payload, 1, db)
assert recovered is db.winner and recovered.user_id == "1" and recovered.space_id == "space"