import app.auth as authmod from conftest import client, jwt, use_jwt_auth def test_command_requires_auth(): response = client.post("/commands", json={"args": ["--version"]}) assert response.status_code == 401 assert response.json()["detail"] == "missing Authorization header; expected 'Bearer '" def test_invalid_token_reports_reason(monkeypatch): monkeypatch.setattr("app.auth.JWT_SECRET", "secret") response = client.post( "/commands", headers={"Authorization": "Bearer not-a-jwt"}, json={"args": ["--version"]}, ) assert response.status_code == 401 assert response.json()["detail"].startswith("invalid token:") def test_jwt_claims_become_policy(): token = jwt({"sub": "file", "vaults": ["work"], "paths": ["Inbox/"], "commands": ["read"]}) claims = authmod.decode_hs256_jwt(token, b"test-jwt-secret") policy = authmod.policy_from_jwt_claims(token, claims) assert policy.token == token assert policy.name == "file" assert policy.vaults == ("work",) assert policy.paths == ("Inbox/",) assert policy.commands == ("read",) def test_token_policy_restricts_command(monkeypatch): token = use_jwt_auth(monkeypatch, {"sub": "limited", "commands": ["read"], "vaults": ["*"], "paths": ["*"]}) response = client.post( "/commands", headers={"Authorization": f"Bearer {token}"}, json={"args": ["create", "path=Inbox/Nope.md", "content=Nope"]}, ) assert response.status_code == 403 assert response.json()["detail"].startswith("token is not allowed to run command: create") def test_token_policy_restricts_vault(monkeypatch): token = use_jwt_auth(monkeypatch, {"sub": "work", "commands": ["*"], "vaults": ["work"], "paths": ["*"]}) response = client.post( "/commands", headers={"Authorization": f"Bearer {token}"}, json={"args": ["vault=personal", "read", "path=Inbox/Test.md"]}, ) assert response.status_code == 403 assert response.json()["detail"].startswith("token is not allowed to access vault: personal") def test_token_policy_restricts_path(monkeypatch): token = use_jwt_auth(monkeypatch, {"sub": "inbox", "commands": ["read"], "vaults": ["*"], "paths": ["Inbox/"]}) response = client.post( "/commands", headers={"Authorization": f"Bearer {token}"}, json={"args": ["read", "path=Private/Secret.md"]}, ) assert response.status_code == 403 assert response.json()["detail"].startswith("token is not allowed to access path: Private/Secret.md") def test_token_policy_allows_allowed_path(monkeypatch): token = use_jwt_auth(monkeypatch, {"sub": "inbox", "commands": ["read"], "vaults": ["*"], "paths": ["Inbox/"]}) response = client.post( "/commands", headers={"Authorization": f"Bearer {token}"}, json={"args": ["-c", "print('ok')"]}, ) assert response.status_code == 403 response = client.post( "/commands", headers={"Authorization": f"Bearer {token}"}, json={"args": ["read", "path=Inbox/Allowed.md"]}, ) assert response.status_code == 200 assert response.json()["command"] == ["python", "read", "path=Inbox/Allowed.md"]