mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
[auth] Omit UNSIGNED self-call token in dev mode + video-engine test mypy fix
_agent_api_headers sent the UNSIGNED sentinel when ROBOCO_AGENT_AUTH_SECRET was unset, but the dev-mode middleware rejects a presented-but-unverifiable token with 401 signature mismatch (while accepting a missing one). The cell-PM auto-submit self-call 401'd in every dev run, regressing test_auto_submit_cuts_the_pm_turn. Attach the token only when a secret is set. Also fix the FromClause.update mypy error in the per-project video-engine opt-out test (ORM row load + flush).
This commit is contained in:
@@ -169,14 +169,21 @@ def _agent_api_headers(agent_uuid: str, role: str) -> dict[str, str]:
|
||||
gate — a hand-built ``{X-Agent-ID, X-Agent-Role}`` dict 401s with
|
||||
"Missing X-Agent-Token" under auth-required (F038/F039 — the same gap the
|
||||
system-headers helper closes for the system identity).
|
||||
|
||||
The token is attached only when ``ROBOCO_AGENT_AUTH_SECRET`` is set: the
|
||||
dev-mode middleware rejects a presented-but-unverifiable token (the
|
||||
``UNSIGNED`` sentinel) with 401 "signature mismatch" while accepting a
|
||||
missing token, so sending ``UNSIGNED`` would turn a clean dev self-call
|
||||
into a 401. With the secret armed the token is signed and verifies.
|
||||
"""
|
||||
from roboco.agents_config import issue_agent_token
|
||||
from roboco.agents_config import _auth_secret, issue_agent_token
|
||||
|
||||
team = get_agent_team(agent_uuid) or ""
|
||||
headers = {"X-Agent-ID": agent_uuid, "X-Agent-Role": role}
|
||||
if team:
|
||||
headers["X-Agent-Team"] = team
|
||||
headers["X-Agent-Token"] = issue_agent_token(agent_uuid, role, team)
|
||||
if _auth_secret():
|
||||
headers["X-Agent-Token"] = issue_agent_token(agent_uuid, role, team)
|
||||
return headers
|
||||
|
||||
|
||||
|
||||
@@ -82,3 +82,18 @@ def test_agent_api_headers_carry_signed_token_and_team(
|
||||
token = headers["X-Agent-Token"]
|
||||
assert token and token != "UNSIGNED"
|
||||
assert verify_agent_token(token, be_pm_uuid, role, team)
|
||||
|
||||
|
||||
def test_agent_api_headers_omit_token_when_secret_unset(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
# Dev mode: with no secret set, issue_agent_token returns the UNSIGNED
|
||||
# sentinel, but the dev-mode middleware rejects a presented-but-unverifiable
|
||||
# token with 401 "signature mismatch" while accepting a missing token.
|
||||
# Sending UNSIGNED would 401 the cell-PM auto-submit self-call in every dev
|
||||
# run (the e2e test_auto_submit_cuts_the_pm_turn regression), so the token
|
||||
# header is omitted entirely when the secret is unset.
|
||||
monkeypatch.delenv("ROBOCO_AGENT_AUTH_SECRET", raising=False)
|
||||
be_pm = _foundation.AGENTS["be-pm"]
|
||||
headers = _agent_api_headers(str(be_pm.uuid), be_pm.role.value)
|
||||
assert "X-Agent-Token" not in headers
|
||||
|
||||
@@ -221,11 +221,10 @@ async def test_open_video_task_no_op_when_project_not_opted_in(
|
||||
) -> None:
|
||||
await _seed(db_session)
|
||||
# Flip the per-project opt-in back off — the global flag stays on.
|
||||
await db_session.execute(
|
||||
ProjectTable.__table__.update()
|
||||
.where(ProjectTable.__table__.c.slug == SLUG)
|
||||
.values(video_engine_enabled=False)
|
||||
)
|
||||
project = (
|
||||
await db_session.execute(select(ProjectTable).where(ProjectTable.slug == SLUG))
|
||||
).scalar_one()
|
||||
project.video_engine_enabled = False
|
||||
await db_session.flush()
|
||||
_enable(monkeypatch)
|
||||
engine = video_engine_module.VideoEngine(db_session)
|
||||
|
||||
Reference in New Issue
Block a user