admin felület különválasztva

This commit is contained in:
Roo
2026-06-24 11:29:45 +00:00
parent 71ef33bb85
commit 80a5d67f79
462 changed files with 87873 additions and 312 deletions

View File

@@ -0,0 +1,265 @@
# P0 Audit: 3D Capability Matrix (RBAC) — SQLAlchemy Model Audit Report
**Author:** Service Finder Rendszer-Architect
**Date:** 2026-06-24
**Gitea Issue:** #283
**Scope:** Read-only model analysis for 3-Dimensional RBAC system (Global Roles × Tenant Roles × Subscription Capabilities)
---
## Executive Summary
This report audits 4 critical dimensions against the existing SQLAlchemy model layer. The goal is to determine **what exists**, **what is missing**, and what **database migration steps** are needed to implement a full 3D Capability Matrix.
**Files examined:**
- `backend/app/models/identity/identity.py` — User/Person models
- `backend/app/models/marketplace/organization.py` — Organization, OrganizationMember, OrgRole models
- `backend/app/models/core_logic.py` — SubscriptionTier, OrganizationSubscription, UserSubscription models
- `backend/app/models/fleet_finance/models.py` — CostCategory model
- `backend/scripts/seed_finance_dictionaries.py` — CostCategory seed data
---
## DIMENSION 1: Global / System Roles
**Model:** `User``identity.users`
**Enum:** `UserRole`
### What EXISTS
| Field | Type | Details |
|---|---|---|
| `role` | `PG_ENUM(UserRole)` | System-level role: SUPERADMIN, ADMIN, MODERATOR, SALES_REP, SERVICE_MGR, USER |
| `is_superuser` | **NOT FOUND** | There is no is_superuser boolean. Role-based only. |
| `custom_permissions` | `JSON` | Per-user permission overrides — `{}::jsonb` default |
| `scope_level` | `String(30)` | "individual" default — hierarchical scope context |
| `scope_id` | `String(50)` | The ID of the scope context |
| `is_vip` | `Boolean` | VIP flag |
| `subscription_plan` | `String(30)` | "FREE" default |
| `subscription_expires_at` | `DateTime` | Subscription expiry |
### Verdict
**Dimension 1 is sufficiently covered.** The `UserRole` enum provides 6 system-level roles. The `custom_permissions` JSON column allows per-user capability overrides. However, there is **no standardized capability/feature matrix** at the global level — everything is ad-hoc JSON.
---
## DIMENSION 2: Tenant / Local Roles
**Model:** `OrganizationMember``fleet.organization_members`
**Enum:** `OrgUserRole`
### What EXISTS
| Field | Type | Details |
|---|---|---|
| `role` | `PG_ENUM(OrgUserRole)` | OWNER, ADMIN, ACCOUNTANT, DRIVER, VIEWER |
| `permissions` | `JSON` | Per-member capability flags — `{}::jsonb` |
| `is_permanent` | `Boolean` | Permanent member flag |
| `is_verified` | `Boolean` | Verified member flag |
| `status` | `String(20)` | "active" default |
### Bonus: Dynamic OrgRole RBAC System
**Model:** `OrgRole``fleet.org_roles`
| Field | Type | Details |
|---|---|---|
| `name_key` | `String(50)` | Unique role identifier (e.g., "OWNER") |
| `display_name` | `String(100)` | Human-readable name |
| `permissions` | `JSONB` | **Capability flags** per role — e.g. {"can_add_expense": true, "can_approve_expense": false} |
| `is_system` | `Boolean` | System role (cannot be deleted) |
| `priority` | `Integer` | Role hierarchy priority |
### Verdict
**Dimension 2 is well-covered.** The `OrgRole` model with its `permissions` JSONB column is exactly what Phase 2 RBAC needs. Each `OrganizationMember` also has an individual `permissions` JSON column for user-level overrides above the role.
---
## DIMENSION 3: Subscription Tier & Feature Capabilities
### 3A. SubscriptionTier Model
**Model:** `SubscriptionTier``system.subscription_tiers`
| Field | Type | Details |
|---|---|---|
| `name` | `String` | e.g., "free", "premium", "vip" |
| `rules` | `JSONB` | **Generic limits**: {"max_vehicles": 5} — NO standardized feature capability format |
| `is_custom` | `Boolean` | Custom tier flag |
### 3B. Organization Model (fleet schema)
| Field | Type | Details |
|---|---|---|
| `subscription_plan` | `String(30)` | "FREE" default — denormalized quick-ref |
| `subscription_expires_at` | `DateTime` | Subscription expiry |
| `subscription_tier_id` | `Integer (FK)` | References system.subscription_tiers.id |
| `base_asset_limit` | `Integer` | Base vehicle limit (1 default) |
| `purchased_extra_slots` | `Integer` | Extra purchased vehicle slots |
| `settings` | `JSONB` | **Operational settings only** — NOT feature capabilities |
### 3C. OrganizationSubscription Model
**Model:** `OrganizationSubscription``finance.org_subscriptions`
| Field | Type | Details |
|---|---|---|
| `extra_allowances` | `JSONB` | Extra quotas: {"extra_vehicles": 1, "extra_garages": 1} |
| `tier_id` | `Integer (FK)` | References system.subscription_tiers.id |
### CRITICAL GAP: Missing custom_features / capabilities_override on Organization
**There is NO dedicated JSONB column** on the `Organization` model to store feature-level capability overrides like:
```json
{
"feature_fuel_logging": true,
"feature_gps_tracking": false,
"feature_analytics": true,
"feature_multi_driver": true,
"feature_service_booking": false,
"feature_tco_reports": false
}
```
The existing `settings` JSONB column is for *operational* settings, not *feature capability* gates.
Similarly, the `SubscriptionTier.rules` JSONB has **no standardized format** for feature capability flags — it only stores numeric limits.
---
## DIMENSION 4: Cost Category Feature Linkage
**Model:** `CostCategory``fleet_finance.cost_categories`
| Field | Type | Details |
|---|---|---|
| `min_tier` | `String(20)` | "free" default — minimum subscription tier to access this category |
| `visibility` | `String(20)` | "both" default — visibility scope |
| `is_system` | `Boolean` | System category flag |
| `required_feature` | **NOT FOUND** | No column to tie category to a specific subscription feature |
| `min_capability` | **NOT FOUND** | No column for minimum capability requirement |
### Verdict
**Partially covered.** The `min_tier` field gates categories by subscription tier (e.g., "free", "premium"), but there is **no way to gate by individual feature capability**. For example, we cannot say "this category requires the feature_fuel_logging capability."
---
## 3D Capability Matrix — Current vs. Required
| Dimension | What We Have | What We Need |
|---|---|---|
| D1: Global Roles | UserRole enum with 6 values + custom_permissions JSON | Sufficient. No DB changes needed. |
| D2: Tenant Roles | OrgUserRole enum + OrgRole.permissions JSONB + per-member permissions JSON | Sufficient. No DB changes needed. |
| D3a: Subscription Tiers | SubscriptionTier.rules JSONB (generic limits) | Need standardized feature capability format |
| D3b: Org Feature Overrides | Organization.settings JSONB (operational only) | **NEED custom_features JSONB column** |
| D4: Cost Category Gating | CostCategory.min_tier (tier-level only) | Need required_feature column + feature-based gating |
---
## Proposed Database Migration Steps
The following migrations must be executed **in order** to build the 3D Capability Matrix architecture:
### Migration 1: Add feature_capabilities JSONB to SubscriptionTier
**Target:** `SubscriptionTier``system.subscription_tiers`
```sql
ALTER TABLE system.subscription_tiers
ADD COLUMN feature_capabilities JSONB NOT NULL DEFAULT '{}'::jsonb;
```
**Purpose:** Define which features each tier enables. Example:
| Tier | Feature Capabilities |
|---|---|
| free | {"feature_fuel_logging": true, "feature_basic_reports": true, "feature_service_reminders": false, "feature_gps_tracking": false} |
| premium | {"feature_fuel_logging": true, "feature_basic_reports": true, "feature_analytics": true, "feature_gps_tracking": true, "feature_multi_driver": true} |
| vip | All features enabled |
### Migration 2: Add custom_features JSONB to Organization
**Target:** `Organization``fleet.organizations`
```sql
ALTER TABLE fleet.organizations
ADD COLUMN custom_features JSONB NOT NULL DEFAULT '{}'::jsonb;
```
**Purpose:** Allow per-organization feature overrides. These overrides **merge on top of** the tier defaults. A `false` value can disable a tier feature for a specific org.
### Migration 3: Add required_feature to CostCategory
**Target:** `CostCategory``fleet_finance.cost_categories`
```sql
ALTER TABLE fleet_finance.cost_categories
ADD COLUMN required_feature VARCHAR(50) DEFAULT NULL;
```
**Purpose:** Tie a cost category to a specific feature capability.
| Category | required_feature |
|---|---|
| OPERATION_FUEL | NULL (free for all) |
| SERVICE_SCHEDULED | NULL (free for all) |
| FINANCING_LEASE | "feature_financing" |
| INSURANCE_CASCO | "feature_insurance" |
| ANALYTICS_TCO | "feature_analytics" |
### Migration 4 (Optional): Create FeatureCapability Enum
```sql
CREATE TYPE system.feature_capability AS ENUM (
'feature_fuel_logging',
'feature_basic_reports',
'feature_analytics',
'feature_gps_tracking',
'feature_multi_driver',
'feature_service_booking',
'feature_tco_reports',
'feature_financing',
'feature_insurance',
'feature_ad_free'
);
```
**Purpose:** Standardize feature names across the system.
---
## Capability Resolution Algorithm (Proposed)
The final capability check for any feature at runtime follows this resolution chain:
```
1. Organization.custom_features["feature_xxx"] <- explicit override (highest priority)
2. SubscriptionTier.feature_capabilities["feature_xxx"] <- tier default
3. false <- implicit default (feature not available)
```
**For CostCategory visibility:**
```
If category.min_tier > org.subscription_plan -> HIDE
If category.required_feature IS NOT NULL AND NOT resolved_feature_capability -> HIDE
Otherwise -> SHOW
```
---
## Summary
| Component | Status | Action Required |
|---|---|---|
| D1: Global Roles | Complete | None |
| D2: Tenant Roles | Complete | None |
| D3: Subscription Tier Features | Partial | Add feature_capabilities JSONB to SubscriptionTier |
| D3: Org Feature Overrides | Missing | Add custom_features JSONB to Organization |
| D4: Cost Category Feature Gate | Partial | Add required_feature column to CostCategory |
| Standardization | Missing | (Optional) Create FeatureCapability Enum |
**Total proposed DB changes: 3 ALTER TABLE statements + 1 optional ENUM type.**