Files
ServerKit/backend/tests/test_connect_managed_profile.py
Juan Denis d866de5439 feat(connect): apply the managed presentation profile (plan 25)
Panel side of the managed profile: the panel receives a presentation
profile from Cloud over the existing command channel, stores it,
acknowledges it, and hides or simplifies fleet-owner-only surfaces
until the profile is lifted or the link is revoked.

- ui.managed_profile command handler with managed-profile.json
  storage, audit entries, and ack-by-output; profile is cleared on
  disconnect and on consent revoke
- GET /api/v1/connect/managed-profile for the local UI
- ManagedProfileContext with capability-driven filtering of sidebar
  items, command palette actions, and sidebar settings; ManagedCard
  explains the managed state
- In-page collapses for Templates deploy, About self-update, and
  Backup schedules/storage (restore stays available)
- Settings gains a ServerKit Cloud tab showing link and profile state

Local verification: 153 backend tests pass, 198 frontend node tests
pass, lint clean, build ok. No live policy has been pushed to a real
panel yet.
2026-09-13 03:50:02 -04:00

138 lines
4.6 KiB
Python

"""Managed profile (plan 25 M1): apply, expiry, override, clear, audit."""
import json
from datetime import datetime, timedelta, timezone
import pytest
from app.services import connect_managed_profile as mp
@pytest.fixture(autouse=True)
def profile_dir(tmp_path, monkeypatch):
monkeypatch.setattr(mp.paths, 'SERVERKIT_CONFIG_DIR', str(tmp_path))
yield tmp_path
def _args(**over):
base = {
'policy_id': 'mpol_test1',
'profile': 'managed',
'capabilities': ['fleet', 'updates'],
'held_by': 'ServerKit Cloud',
'since': '2026-10-01T00:00:00Z',
'expires_at': (datetime.now(timezone.utc) + timedelta(days=7)).isoformat(),
'support_url': 'https://app.serverkit.ai/orgs/acme/servers/dev_1',
'override': None,
}
base.update(over)
return base
def _read_doc(profile_dir):
with open(profile_dir / 'managed-profile.json', 'r', encoding='utf-8') as f:
return json.load(f)
def test_apply_stores_document_and_acks_policy_id(profile_dir):
out = mp.apply_profile(_args())
assert out['ok'] is True
doc = _read_doc(profile_dir)
assert doc['policy_id'] == 'mpol_test1'
assert doc['capabilities'] == ['fleet', 'updates']
assert doc['override'] is None
assert doc['applied_at']
ack = json.loads(out['output'])
assert ack == {'policy_id': 'mpol_test1', 'applied': True}
def test_current_active_profile():
mp.apply_profile(_args())
state = mp.current()
assert state['active'] is True
assert state['capabilities'] == ['fleet', 'updates']
assert state['held_by'] == 'ServerKit Cloud'
assert state['expired'] is False
assert state['override'] is None
def test_no_profile_is_inactive():
state = mp.current()
assert state['active'] is False
assert state['profile'] == 'none'
assert state['capabilities'] == []
def test_expired_policy_holds_nothing_but_stays_visible():
mp.apply_profile(_args(expires_at=(datetime.now(timezone.utc)
- timedelta(hours=1)).isoformat()))
state = mp.current()
assert state['active'] is False
assert state['capabilities'] == []
assert state['expired'] is True
# The document's detail survives so Settings can say what lapsed.
assert state['held_capabilities'] == ['fleet', 'updates']
assert state['policy_id'] == 'mpol_test1'
def test_override_lifts_profile_until_its_end():
until = (datetime.now(timezone.utc) + timedelta(hours=2)).isoformat()
mp.apply_profile(_args(override={'until': until, 'reason': 'support session'}))
state = mp.current()
assert state['active'] is False
assert state['capabilities'] == []
assert state['override'] == {'until': until, 'reason': 'support session'}
def test_elapsed_override_returns_the_profile():
until = (datetime.now(timezone.utc) - timedelta(minutes=5)).isoformat()
mp.apply_profile(_args(override={'until': until, 'reason': 'support session'}))
state = mp.current()
assert state['active'] is True
assert state['capabilities'] == ['fleet', 'updates']
assert state['override'] is None
def test_profile_none_clears_and_acks(profile_dir):
mp.apply_profile(_args())
out = mp.apply_profile(_args(policy_id='mpol_clear1', profile='none',
capabilities=[]))
assert out['ok'] is True
assert 'lifted' in out['summary']
assert not (profile_dir / 'managed-profile.json').exists()
assert mp.current()['active'] is False
ack = json.loads(out['output'])
assert ack == {'policy_id': 'mpol_clear1', 'applied': False}
def test_empty_capability_list_clears():
mp.apply_profile(_args())
out = mp.apply_profile(_args(capabilities=[]))
assert out['ok'] is True
assert mp.current()['active'] is False
def test_policy_without_expiry_is_refused(profile_dir):
out = mp.apply_profile(_args(expires_at=None))
assert out['ok'] is False
assert 'expiry' in out['summary']
assert not (profile_dir / 'managed-profile.json').exists()
def test_policy_without_id_is_refused(profile_dir):
out = mp.apply_profile(_args(policy_id=''))
assert out['ok'] is False
assert not (profile_dir / 'managed-profile.json').exists()
def test_override_without_end_is_refused(profile_dir):
out = mp.apply_profile(_args(override={'reason': 'support session'}))
assert out['ok'] is False
assert not (profile_dir / 'managed-profile.json').exists()
def test_clear_reports_whether_one_was_in_force():
assert mp.clear('revoked') is False
mp.apply_profile(_args())
assert mp.clear('revoked') is True
assert mp.current()['active'] is False