---------------------------- MODULE metabuilder ---------------------------- (*************************************************************************** * MetaBuilder Formal Specification * * * * This TLA+ specification models the core behavior of MetaBuilder, * * a data-driven, multi-tenant platform with: * * - 6-level hierarchical permission system * * - Multi-tenant data isolation * * - Database Abstraction Layer (DBAL) with dual implementations * * - Package management system * * - Declarative component rendering * ***************************************************************************) EXTENDS Naturals, Sequences, FiniteSets, TLC CONSTANTS Users, \* Set of all users in the system Tenants, \* Set of all tenants Packages, \* Set of available packages DataRecords, \* Set of data records MaxLevel \* Maximum permission level (6 for Supergod) VARIABLES userLevels, \* User -> Permission Level (1-6) userTenants, \* User -> Tenant mapping tenantData, \* Tenant -> Set of data records installedPackages, \* Tenant -> Set of installed packages packageStates, \* Package -> {available, installing, installed, disabled} dbalState, \* DBAL daemon state {ready, processing, error} activeQueries, \* Set of active database queries auditLog \* Sequence of audit events vars == <> ----------------------------------------------------------------------------- (* Permission Levels *) PermissionLevel == 1..MaxLevel Level == [ Public |-> 1, User |-> 2, Moderator |-> 3, Admin |-> 4, God |-> 5, Supergod |-> 6 ] ----------------------------------------------------------------------------- (* Type Invariants *) TypeOK == /\ userLevels \in [Users -> PermissionLevel] /\ userTenants \in [Users -> Tenants] /\ tenantData \in [Tenants -> SUBSET DataRecords] /\ installedPackages \in [Tenants -> SUBSET Packages] /\ packageStates \in [Packages -> {"available", "installing", "installed", "disabled"}] /\ dbalState \in {"ready", "processing", "error"} /\ activeQueries \subseteq (Users \X Tenants \X {"read", "write", "delete"}) /\ auditLog \in Seq([user: Users, action: STRING, tenant: Tenants, level: PermissionLevel]) ----------------------------------------------------------------------------- (* Permission System *) \* Check if a user has at least the required permission level HasPermission(user, requiredLevel) == userLevels[user] >= requiredLevel \* Hierarchical permission inheritance: higher levels inherit all lower permissions CanAccessLevel(user, targetLevel) == userLevels[user] >= targetLevel \* User can only access data within their tenant CanAccessTenantData(user, tenant) == userTenants[user] = tenant \* Combined permission and tenant check CanPerformAction(user, tenant, requiredLevel) == /\ HasPermission(user, requiredLevel) /\ CanAccessTenantData(user, tenant) ----------------------------------------------------------------------------- (* Initial State *) Init == /\ userLevels \in [Users -> PermissionLevel] /\ userTenants \in [Users -> Tenants] /\ tenantData = [t \in Tenants |-> {}] /\ installedPackages = [t \in Tenants |-> {}] /\ packageStates = [p \in Packages |-> "available"] /\ dbalState = "ready" /\ activeQueries = {} /\ auditLog = <<>> ----------------------------------------------------------------------------- (* Data Access Operations *) \* User reads data from their tenant (requires Level 2+) ReadData(user) == /\ CanPerformAction(user, userTenants[user], Level.User) /\ dbalState = "ready" /\ activeQueries' = activeQueries \cup {<>} /\ auditLog' = Append(auditLog, [ user |-> user, action |-> "read_data", tenant |-> userTenants[user], level |-> userLevels[user] ]) /\ UNCHANGED <> \* User writes data to their tenant (requires Level 2+) WriteData(user, record) == /\ record \in DataRecords /\ CanPerformAction(user, userTenants[user], Level.User) /\ dbalState = "ready" /\ LET tenant == userTenants[user] IN /\ tenantData' = [tenantData EXCEPT ![tenant] = @ \cup {record}] /\ activeQueries' = activeQueries \cup {<>} /\ auditLog' = Append(auditLog, [ user |-> user, action |-> "write_data", tenant |-> tenant, level |-> userLevels[user] ]) /\ UNCHANGED <> \* User deletes data from their tenant (requires Level 2+) DeleteData(user, record) == /\ record \in DataRecords /\ CanPerformAction(user, userTenants[user], Level.User) /\ dbalState = "ready" /\ LET tenant == userTenants[user] IN /\ record \in tenantData[tenant] /\ tenantData' = [tenantData EXCEPT ![tenant] = @ \ {record}] /\ activeQueries' = activeQueries \cup {<>} /\ auditLog' = Append(auditLog, [ user |-> user, action |-> "delete_data", tenant |-> tenant, level |-> userLevels[user] ]) /\ UNCHANGED <> \* Query completes and is removed from active set CompleteQuery(user, tenant, operation) == /\ <> \in activeQueries /\ activeQueries' = activeQueries \ {<>} /\ UNCHANGED <> ----------------------------------------------------------------------------- (* User Management Operations *) \* Admin can modify user levels (requires Level 4+) ModifyUserLevel(admin, targetUser, newLevel) == /\ admin /= targetUser \* Cannot modify own level /\ CanPerformAction(admin, userTenants[admin], Level.Admin) /\ userTenants[admin] = userTenants[targetUser] \* Same tenant only /\ newLevel \in PermissionLevel /\ newLevel < userLevels[admin] \* Cannot grant higher level than own /\ userLevels' = [userLevels EXCEPT ![targetUser] = newLevel] /\ auditLog' = Append(auditLog, [ user |-> admin, action |-> "modify_user_level", tenant |-> userTenants[admin], level |-> userLevels[admin] ]) /\ UNCHANGED <> ----------------------------------------------------------------------------- (* Package Management Operations *) \* Admin can install a package (requires Level 4+) InstallPackage(user, pkg) == /\ pkg \in Packages /\ CanPerformAction(user, userTenants[user], Level.Admin) /\ packageStates[pkg] = "available" /\ LET tenant == userTenants[user] IN /\ pkg \notin installedPackages[tenant] /\ packageStates' = [packageStates EXCEPT ![pkg] = "installing"] /\ installedPackages' = [installedPackages EXCEPT ![tenant] = @ \cup {pkg}] /\ auditLog' = Append(auditLog, [ user |-> user, action |-> "install_package", tenant |-> tenant, level |-> userLevels[user] ]) /\ UNCHANGED <> \* Package installation completes CompletePackageInstall(pkg) == /\ packageStates[pkg] = "installing" /\ packageStates' = [packageStates EXCEPT ![pkg] = "installed"] /\ UNCHANGED <> \* Admin can uninstall a package (requires Level 4+) UninstallPackage(user, pkg) == /\ pkg \in Packages /\ CanPerformAction(user, userTenants[user], Level.Admin) /\ LET tenant == userTenants[user] IN /\ pkg \in installedPackages[tenant] /\ installedPackages' = [installedPackages EXCEPT ![tenant] = @ \ {pkg}] /\ packageStates' = [packageStates EXCEPT ![pkg] = "available"] /\ auditLog' = Append(auditLog, [ user |-> user, action |-> "uninstall_package", tenant |-> tenant, level |-> userLevels[user] ]) /\ UNCHANGED <> \* Admin can toggle package state (requires Level 4+) TogglePackage(user, pkg) == /\ pkg \in Packages /\ CanPerformAction(user, userTenants[user], Level.Admin) /\ LET tenant == userTenants[user] IN /\ pkg \in installedPackages[tenant] /\ packageStates[pkg] \in {"installed", "disabled"} /\ packageStates' = [packageStates EXCEPT ![pkg] = IF @ = "installed" THEN "disabled" ELSE "installed"] /\ auditLog' = Append(auditLog, [ user |-> user, action |-> "toggle_package", tenant |-> tenant, level |-> userLevels[user] ]) /\ UNCHANGED <> ----------------------------------------------------------------------------- (* DBAL State Transitions *) \* DBAL starts processing a query DBALStartProcessing == /\ dbalState = "ready" /\ activeQueries /= {} /\ dbalState' = "processing" /\ UNCHANGED <> \* DBAL completes processing and returns to ready DBALCompleteProcessing == /\ dbalState = "processing" /\ dbalState' = "ready" /\ UNCHANGED <> \* DBAL encounters an error (can recover) DBALError == /\ dbalState = "processing" /\ dbalState' = "error" /\ UNCHANGED <> \* DBAL recovers from error DBALRecover == /\ dbalState = "error" /\ dbalState' = "ready" /\ UNCHANGED <> ----------------------------------------------------------------------------- (* Next State Relation *) Next == \/ \E u \in Users: ReadData(u) \/ \E u \in Users, r \in DataRecords: WriteData(u, r) \/ \E u \in Users, r \in DataRecords: DeleteData(u, r) \/ \E u \in Users, t \in Tenants, op \in {"read", "write", "delete"}: CompleteQuery(u, t, op) \/ \E admin \in Users, target \in Users, lvl \in PermissionLevel: ModifyUserLevel(admin, target, lvl) \/ \E u \in Users, p \in Packages: InstallPackage(u, p) \/ \E p \in Packages: CompletePackageInstall(p) \/ \E u \in Users, p \in Packages: UninstallPackage(u, p) \/ \E u \in Users, p \in Packages: TogglePackage(u, p) \/ DBALStartProcessing \/ DBALCompleteProcessing \/ DBALError \/ DBALRecover ----------------------------------------------------------------------------- (* Safety Properties *) \* Multi-tenant isolation: users can only access their own tenant's data TenantIsolation == \A u \in Users, t \in Tenants: (userTenants[u] /= t) => ~\E record \in DataRecords, op \in {"read", "write", "delete"}: /\ <> \in activeQueries \* Permission enforcement: operations require appropriate level PermissionEnforcement == /\ \A u \in Users: (\E t \in Tenants, op \in {"read", "write", "delete"}: <> \in activeQueries) => userLevels[u] >= Level.User /\ Len(auditLog) > 0 => LET lastEvent == auditLog[Len(auditLog)] IN lastEvent.action \in {"modify_user_level", "install_package", "uninstall_package", "toggle_package"} => lastEvent.level >= Level.Admin \* Users cannot elevate their own permissions NoSelfElevation == \A i \in 1..Len(auditLog): auditLog[i].action = "modify_user_level" => auditLog[i].user /= auditLog[i].user \* This is always true in our model \* Data consistency: records belong to exactly one tenant DataConsistency == \A t1, t2 \in Tenants: t1 /= t2 => tenantData[t1] \cap tenantData[t2] = {} \* Package consistency: installed packages must be in installed or disabled state PackageConsistency == \A t \in Tenants: \A p \in installedPackages[t]: packageStates[p] \in {"installed", "disabled", "installing"} \* DBAL safety: no queries processed in error state DBALSafety == dbalState = "error" => ~\E u \in Users, r \in DataRecords: WriteData(u, r) \/ DeleteData(u, r) \* Audit completeness: all privileged operations are logged AuditCompleteness == \A i \in 1..Len(auditLog): auditLog[i].action \in { "read_data", "write_data", "delete_data", "modify_user_level", "install_package", "uninstall_package", "toggle_package" } ----------------------------------------------------------------------------- (* Liveness Properties *) \* Eventually, DBAL processes all queries (if it stays ready) EventualProcessing == activeQueries /= {} ~> (activeQueries = {} \/ dbalState /= "ready") \* If DBAL enters error state, it eventually recovers EventualRecovery == dbalState = "error" ~> dbalState = "ready" \* Package installation eventually completes EventualPackageInstall == \A p \in Packages: packageStates[p] = "installing" ~> packageStates[p] = "installed" ----------------------------------------------------------------------------- (* System Specification *) Spec == /\ Init /\ [][Next]_vars /\ WF_vars(DBALCompleteProcessing) /\ WF_vars(DBALRecover) /\ \A p \in Packages: WF_vars(CompletePackageInstall(p)) ----------------------------------------------------------------------------- (* Invariants to Check *) Invariants == /\ TypeOK /\ TenantIsolation /\ PermissionEnforcement /\ DataConsistency /\ PackageConsistency /\ DBALSafety /\ AuditCompleteness =============================================================================