feat(v3.13.0): settings live DB reads, remove Directus/Appwrite, admin stats

Settings fixes:
- MAX_SITES_PER_USER, USER_RATE_LIMIT_PER_MIN/HR now read from DB settings
  table (DB > ENV > default), so dashboard/settings changes apply without
  restart. Sync cache refreshed on every save or delete.
- /api/me reports the live DB value for max_sites_per_user.

Admin improvements:
- Admin users bypass per-user rate limiting entirely (role=admin or ADMIN_EMAILS).
- Admin Overview now shows platform stats: registered users, new users (7d),
  total user sites, available tools.

Plugin cleanup:
- Appwrite and Directus plugins removed from the active registry (8 plugins
  now: WordPress, WooCommerce, WordPress Specialist, Gitea, n8n, Supabase,
  OpenPanel, Coolify). Plugin code is retained for future re-enabling.
- Settings page plugin visibility list updated to match.

Mobile onboarding:
- Stepper steps on narrow viewports stack vertically with correct full border
  and rounded corners on each step.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-20 23:33:20 +02:00
parent f203ca88de
commit 43fd2201a0
223 changed files with 36183 additions and 4115 deletions

View File

@@ -155,6 +155,61 @@ class TestToolDefinitionDefaults:
# ---------------------------------------------------------------------------
class TestUniversalScopeTierLadder:
"""F.19.2.0: the universal tier ladder must be a strict chain.
Each higher tier is a superset of every lower tier; every tier
includes ``read`` (so any keyholder can list inventory before
acting); ``admin`` includes everything else.
"""
def test_each_tier_is_a_strict_superset(self):
from core.tool_access import UNIVERSAL_SCOPE_TIERS
ladder = ["read", "editor", "settings", "install", "write", "admin"]
for lower, higher in zip(ladder[:-1], ladder[1:], strict=True):
lower_set = UNIVERSAL_SCOPE_TIERS[lower]
higher_set = UNIVERSAL_SCOPE_TIERS[higher]
assert lower_set <= higher_set, f"{higher} must be superset of {lower}"
assert higher_set - lower_set, f"{higher} must add at least one new scope over {lower}"
def test_every_tier_includes_read(self):
from core.tool_access import UNIVERSAL_SCOPE_TIERS
for tier_name, allowed in UNIVERSAL_SCOPE_TIERS.items():
assert "read" in allowed, f"{tier_name} must include read scope"
def test_admin_is_universal(self):
from core.tool_access import UNIVERSAL_SCOPE_TIERS
# Every required-scope value used elsewhere in the ladder must be
# reachable from an admin key.
all_scopes = set().union(*UNIVERSAL_SCOPE_TIERS.values())
assert UNIVERSAL_SCOPE_TIERS["admin"] == all_scopes
def test_settings_below_install_below_write(self):
"""Confirms the F.19.2.0 ordering: settings ⊂ install ⊂ write."""
from core.tool_access import UNIVERSAL_SCOPE_TIERS
s = UNIVERSAL_SCOPE_TIERS["settings"]
i = UNIVERSAL_SCOPE_TIERS["install"]
w = UNIVERSAL_SCOPE_TIERS["write"]
assert s < i < w
# Specifically: install adds "install"; write adds "write".
assert i - s == {"install"}
assert w - i == {"write"}
def test_tier_descriptions_cover_every_tier(self):
"""Every UNIVERSAL_SCOPE_TIERS key must have an EN+FA tooltip."""
from core.tool_access import TIER_DESCRIPTIONS, UNIVERSAL_SCOPE_TIERS
for tier_name in UNIVERSAL_SCOPE_TIERS:
assert tier_name in TIER_DESCRIPTIONS, f"missing description for tier {tier_name}"
entry = TIER_DESCRIPTIONS[tier_name]
for field in ("label_en", "label_fa", "hint_en", "hint_fa"):
assert field in entry and entry[field], f"{tier_name}.{field} missing or empty"
class TestScopesToCategories:
def test_read_only(self):
assert scopes_to_categories(["read"]) == {"read"}