Clear stale worker identity on project attach

This commit is contained in:
HumbleTurtle
2026-08-01 03:59:52 -03:00
parent 463caec13b
commit b555779bef
2 changed files with 33 additions and 12 deletions
+15 -2
View File
@@ -7059,7 +7059,8 @@ def operator_project_attach(args=None):
if not project_id: if not project_id:
raise RuntimeError("OAuth authorization did not return a selected project_id") raise RuntimeError("OAuth authorization did not return a selected project_id")
token_expires_at = iso_timestamp_after_seconds(int(result.get("expires_in") or 0)) token_expires_at = iso_timestamp_after_seconds(int(result.get("expires_in") or 0))
save_auth({ replace_public_auth_state(
{
"base_url": result.get("api_base_url") or BASE_URL, "base_url": result.get("api_base_url") or BASE_URL,
"token": result.get("access_token"), "token": result.get("access_token"),
"refresh_token": result.get("refresh_token"), "refresh_token": result.get("refresh_token"),
@@ -7069,7 +7070,9 @@ def operator_project_attach(args=None):
"account_mode": "operator_project", "account_mode": "operator_project",
"oauth_client_id": "nap-cli", "oauth_client_id": "nap-cli",
"oauth_scope": result.get("scope"), "oauth_scope": result.get("scope"),
}) },
clear_keys=WORKER_BINDING_AUTH_KEYS,
)
try: try:
project = request_json("GET", f"/v1/projects/{project_id}") project = request_json("GET", f"/v1/projects/{project_id}")
save_auth_file_credentials({ save_auth_file_credentials({
@@ -13921,6 +13924,16 @@ PROJECT_BINDING_AUTH_KEYS = {
"service_registration_id", "service_registration_id",
} }
WORKER_BINDING_AUTH_KEYS = {
"worker_id",
"agent_id",
"worker_name",
"worker_capabilities",
"claimed_account_id",
"claimed_at",
"service_registration_id",
}
def replace_public_auth_state(updates, *, clear_keys=()): def replace_public_auth_state(updates, *, clear_keys=()):
current_public = load_public_auth_file() current_public = load_public_auth_file()
+9 -1
View File
@@ -25,6 +25,7 @@ def run():
test_state = tempfile.TemporaryDirectory() test_state = tempfile.TemporaryDirectory()
mod.AUTH_PATH = pathlib.Path(test_state.name) / "auth.json" mod.AUTH_PATH = pathlib.Path(test_state.name) / "auth.json"
saves = [] saves = []
replacements = []
def save_auth(updates): def save_auth(updates):
saves.append(dict(updates)) saves.append(dict(updates))
@@ -40,7 +41,11 @@ def run():
} }
mod.save_auth = save_auth mod.save_auth = save_auth
mod.save_auth_file_credentials = save_auth mod.save_auth_file_credentials = save_auth
mod.replace_public_auth_state = lambda updates, clear_keys=(): save_auth(updates) def replace_public_auth_state(updates, clear_keys=()):
replacements.append(set(clear_keys))
save_auth(updates)
mod.replace_public_auth_state = replace_public_auth_state
mod.request_json = lambda method, path: { mod.request_json = lambda method, path: {
"id": PROJECT_ID, "id": PROJECT_ID,
"slug": "existing-project", "slug": "existing-project",
@@ -54,12 +59,15 @@ def run():
assert saves[0]["refresh_token"] == "oauth-refresh-token" assert saves[0]["refresh_token"] == "oauth-refresh-token"
assert saves[0]["project_id"] == PROJECT_ID assert saves[0]["project_id"] == PROJECT_ID
assert saves[0]["account_mode"] == "operator_project" assert saves[0]["account_mode"] == "operator_project"
assert replacements[0] == mod.WORKER_BINDING_AUTH_KEYS
assert "project_id" not in replacements[0]
assert "napseer.projects.read" in saves[0]["oauth_scope"] assert "napseer.projects.read" in saves[0]["oauth_scope"]
assert saves[1]["project_slug"] == "existing-project" assert saves[1]["project_slug"] == "existing-project"
assert result["project_id"] == PROJECT_ID assert result["project_id"] == PROJECT_ID
assert result["project"]["name"] == "Existing Project" assert result["project"]["name"] == "Existing Project"
saves.clear() saves.clear()
replacements.clear()
mod.oauth_loopback_authorize = lambda args: { mod.oauth_loopback_authorize = lambda args: {
"api_base_url": "https://api.example.test", "api_base_url": "https://api.example.test",
"access_token": "account-token", "access_token": "account-token",