diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java
index 47fd03a6..49de8f08 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/coopassets/HsOfficeCoopAssetsTransactionEntity.java
@@ -10,7 +10,6 @@ import net.hostsharing.hsadminng.errors.DisplayName;
 import net.hostsharing.hsadminng.hs.office.membership.HsOfficeMembershipEntity;
 import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
 import net.hostsharing.hsadminng.rbac.rbacdef.RbacView;
-import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
 import net.hostsharing.hsadminng.stringify.Stringify;
 import net.hostsharing.hsadminng.stringify.Stringifyable;
 import org.hibernate.annotations.GenericGenerator;
@@ -25,8 +24,6 @@ import jakarta.persistence.JoinColumn;
 import jakarta.persistence.ManyToOne;
 import jakarta.persistence.Table;
 import java.io.IOException;
-import java.io.IOException;
-import java.io.IOException;
 import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.util.Optional;
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java
index 08c70f66..509cb165 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorEntity.java
@@ -1,6 +1,10 @@
 package net.hostsharing.hsadminng.hs.office.debitor;
 
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
 import net.hostsharing.hsadminng.errors.DisplayName;
 import net.hostsharing.hsadminng.hs.office.bankaccount.HsOfficeBankAccountEntity;
 import net.hostsharing.hsadminng.hs.office.partner.HsOfficePartnerEntity;
@@ -15,7 +19,13 @@ import org.hibernate.annotations.JoinFormula;
 import org.hibernate.annotations.NotFound;
 import org.hibernate.annotations.NotFoundAction;
 
-import jakarta.persistence.*;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.Table;
 import jakarta.validation.constraints.Pattern;
 import java.io.IOException;
 import java.util.UUID;
@@ -26,6 +36,7 @@ import static jakarta.persistence.CascadeType.PERSIST;
 import static jakarta.persistence.CascadeType.REFRESH;
 import static java.util.Optional.ofNullable;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
+import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NULLABLE;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
@@ -157,6 +168,8 @@ public class HsOfficeDebitorEntity implements RbacObject, Stringifyable {
                 .toRole("global", ADMIN).grantPermission(INSERT)
 
                 .importRootEntityAliasProxy("debitorRel", HsOfficeRelationEntity.class,
+                        // TODO.spec: do we need a distinct case for DEBITOR-Relation?
+                        usingDefaultCase(),
                         directlyFetchedByDependsOnColumn(),
                         dependsOnColumn("debitorRelUuid"))
                 .createPermission(DELETE).grantedTo("debitorRel", OWNER)
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java
index c486dc92..26c5706a 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipEntity.java
@@ -29,8 +29,6 @@ import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.ADMIN;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.AGENT;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.OWNER;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
-import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
-import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.TENANT;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.fetchedBySql;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
 import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java
index 43b78fca..6b019f62 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerEntity.java
@@ -29,6 +29,7 @@ import java.util.UUID;
 
 import static jakarta.persistence.CascadeType.*;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
+import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.SELECT;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
@@ -98,18 +99,19 @@ public class HsOfficePartnerEntity implements Stringifyable, RbacObject {
                 .toRole("global", ADMIN).grantPermission(INSERT)
 
                 .importRootEntityAliasProxy("partnerRel", HsOfficeRelationEntity.class,
+                        usingDefaultCase(),
                         directlyFetchedByDependsOnColumn(),
                         dependsOnColumn("partnerRelUuid"))
-                .createPermission(DELETE).grantedTo("partnerRel", ADMIN)
-                .createPermission(UPDATE).grantedTo("partnerRel", AGENT)
+                .createPermission(DELETE).grantedTo("partnerRel", OWNER)
+                .createPermission(UPDATE).grantedTo("partnerRel", ADMIN)
                 .createPermission(SELECT).grantedTo("partnerRel", TENANT)
 
                 .importSubEntityAlias("partnerDetails", HsOfficePartnerDetailsEntity.class,
                         directlyFetchedByDependsOnColumn(),
                         dependsOnColumn("detailsUuid"))
-                .createPermission("partnerDetails", DELETE).grantedTo("partnerRel", ADMIN)
+                .createPermission("partnerDetails", DELETE).grantedTo("partnerRel", OWNER)
                 .createPermission("partnerDetails", UPDATE).grantedTo("partnerRel", AGENT)
-                .createPermission("partnerDetails", SELECT).grantedTo("partnerRel", AGENT);
+                .createPermission("partnerDetails", SELECT).grantedTo("partnerRel", AGENT); // not TENANT!
     }
 
     public static void main(String[] args) throws IOException {
diff --git a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java
index 8d6c6fe8..1dbed5cc 100644
--- a/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java
+++ b/src/main/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationEntity.java
@@ -11,17 +11,19 @@ import net.hostsharing.hsadminng.stringify.Stringify;
 import net.hostsharing.hsadminng.stringify.Stringifyable;
 
 import jakarta.persistence.*;
+import jakarta.persistence.Column;
 import java.io.IOException;
 import java.util.UUID;
 
+import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.*;
+import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef.inCaseOf;
+import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef.inOtherCases;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Column.dependsOnColumn;
-import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.GLOBAL;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Permission.*;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Role.*;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.directlyFetchedByDependsOnColumn;
-import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.rbacViewFor;
 import static net.hostsharing.hsadminng.stringify.Stringify.stringify;
 
 @Entity
@@ -101,31 +103,55 @@ public class HsOfficeRelationEntity implements RbacObject, Stringifyable {
                         dependsOnColumn("contactUuid"),
                         directlyFetchedByDependsOnColumn(),
                         NOT_NULL)
-                .createRole(OWNER, (with) -> {
-                    with.owningUser(CREATOR);
-                    with.incomingSuperRole(GLOBAL, ADMIN);
-                    // TODO: if type=REPRESENTATIIVE
-                    // with.incomingSuperRole("holderPerson", ADMIN);
-                    with.permission(DELETE);
-                })
-                .createSubRole(ADMIN, (with) -> {
-                    with.incomingSuperRole("anchorPerson", ADMIN);
-                    // TODO: if type=REPRESENTATIIVE
-                    // with.outgoingSuperRole("anchorPerson", OWNER);
-                    with.permission(UPDATE);
-                })
-                .createSubRole(AGENT, (with) -> {
-                    with.incomingSuperRole("holderPerson", ADMIN);
-                })
-                .createSubRole(TENANT, (with) -> {
-                    with.incomingSuperRole("holderPerson", ADMIN);
-                    with.incomingSuperRole("contact", ADMIN);
-                    with.outgoingSubRole("anchorPerson", REFERRER);
-                    with.outgoingSubRole("holderPerson", REFERRER);
-                    with.outgoingSubRole("contact", REFERRER);
-                    with.permission(SELECT);
-                })
-
+                .switchOnColumn("type",
+                    inCaseOf("REPRESENTATIVE", then -> {
+                        then.createRole(OWNER, (with) -> {
+                                with.owningUser(CREATOR);
+                                with.incomingSuperRole(GLOBAL, ADMIN);
+                                with.incomingSuperRole("holderPerson", ADMIN);
+                                with.permission(DELETE);
+                            })
+                            .createSubRole(ADMIN, (with) -> {
+                                with.outgoingSubRole("anchorPerson", OWNER);
+                                with.permission(UPDATE);
+                            })
+                            .createSubRole(AGENT, (with) -> {
+                                with.incomingSuperRole("anchorPerson", ADMIN);
+                            })
+                            .createSubRole(TENANT, (with) -> {
+                                with.incomingSuperRole("contact", ADMIN);
+                                with.outgoingSubRole("anchorPerson", REFERRER);
+                                with.outgoingSubRole("holderPerson", REFERRER);
+                                with.outgoingSubRole("contact", REFERRER);
+                                with.permission(SELECT);
+                            });
+                    }),
+                    // inCaseOf("DEBITOR", then -> {}), TODO.spec: needs to be defined
+                    inOtherCases(then -> {
+                        then.createRole(OWNER, (with) -> {
+                                with.owningUser(CREATOR);
+                                with.incomingSuperRole(GLOBAL, ADMIN);
+                                with.incomingSuperRole("anchorPerson", ADMIN);
+                                with.permission(DELETE);
+                            })
+                            .createSubRole(ADMIN, (with) -> {
+                                with.permission(UPDATE);
+                            })
+                            .createSubRole(AGENT, (with) -> {
+                                // TODO.spec: we need relation:PROXY, to allow changing the relation contact.
+                                // the alternative would be to move this to the relation:ADMIN role,
+                                // but then the partner holder person could update the partner relation itself,
+                                // see partner entity.
+                                with.incomingSuperRole("holderPerson", ADMIN);
+                            })
+                            .createSubRole(TENANT, (with) -> {
+                                with.incomingSuperRole("contact", ADMIN);
+                                with.outgoingSubRole("anchorPerson", REFERRER);
+                                with.outgoingSubRole("holderPerson", REFERRER);
+                                with.outgoingSubRole("contact", REFERRER);
+                                with.permission(SELECT);
+                            });
+                    }))
                 .toRole("anchorPerson", ADMIN).grantPermission(INSERT);
     }
 
diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java
index cb048455..d052b958 100644
--- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacView.java
@@ -14,7 +14,6 @@ import net.hostsharing.hsadminng.hs.office.person.HsOfficePersonEntity;
 import net.hostsharing.hsadminng.hs.office.relation.HsOfficeRelationEntity;
 import net.hostsharing.hsadminng.hs.office.sepamandate.HsOfficeSepaMandateEntity;
 import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
-import net.hostsharing.hsadminng.rbac.rbacobject.RbacObject;
 import net.hostsharing.hsadminng.test.cust.TestCustomerEntity;
 import net.hostsharing.hsadminng.test.dom.TestDomainEntity;
 import net.hostsharing.hsadminng.test.pac.TestPackageEntity;
@@ -27,18 +26,22 @@ import java.lang.reflect.Method;
 import java.nio.file.Path;
 import java.util.*;
 import java.util.function.Consumer;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import static java.lang.reflect.Modifier.isStatic;
 import static java.util.Arrays.stream;
 import static java.util.Optional.ofNullable;
+import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.ColumnValue.usingDefaultCase;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.Nullable.NOT_NULL;
+import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition.GrantType.PERM_TO_ROLE;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacUserReference.UserRole.CREATOR;
 import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.Part.AUTO_FETCH;
-import static net.hostsharing.hsadminng.rbac.rbacdef.RbacView.SQL.directlyFetchedByDependsOnColumn;
+import static org.apache.commons.collections4.SetUtils.hashSet;
 import static org.apache.commons.lang3.StringUtils.uncapitalize;
 
 @Getter
+// TODO.refa: rename to RbacDSL
 public class RbacView {
 
     public static final String GLOBAL = "global";
@@ -61,11 +64,23 @@ public class RbacView {
     };
     private final Set<String> updatableColumns = new LinkedHashSet<>();
     private final Set<RbacGrantDefinition> grantDefs = new LinkedHashSet<>();
+    private final Set<CaseDef> allCases = new LinkedHashSet<>();
 
+    private String discriminatorColumName;
+    private CaseDef processingCase;
     private SQL identityViewSqlQuery;
     private SQL orderBySqlExpression;
     private EntityAlias rootEntityAliasProxy;
     private RbacRoleDefinition previousRoleDef;
+    private final Map<String, CaseDef> cases = new LinkedHashMap<>() {
+        @Override
+        public CaseDef put(final String key, final CaseDef value) {
+            if (containsKey(key)) {
+                throw new IllegalArgumentException("duplicate case: " + key);
+            }
+            return super.put(key, value);
+        }
+    };
 
     /** Crates an RBAC definition template for the given entity class and defining the given alias.
      *
@@ -239,7 +254,11 @@ public class RbacView {
     }
 
     private RbacPermissionDefinition createPermission(final EntityAlias entityAlias, final Permission permission) {
-        return new RbacPermissionDefinition(entityAlias, permission, null, true);
+        return permDefs.stream()
+                .filter(p -> p.permission == permission && p.entityAlias == entityAlias)
+                .findFirst()
+                // .map(g -> g.forCase(processingCase)) TODO.impl: not implemented case dependent
+                .orElseGet(() -> new RbacPermissionDefinition(entityAlias, permission, null, true));
     }
 
     public <EC extends RbacObject> RbacView declarePlaceholderEntityAliases(final String... aliasNames) {
@@ -278,12 +297,13 @@ public class RbacView {
     public <EC extends RbacObject> RbacView importRootEntityAliasProxy(
             final String aliasName,
             final Class<? extends RbacObject> entityClass,
+            final ColumnValue forCase,
             final SQL fetchSql,
             final Column dependsOnColum) {
         if (rootEntityAliasProxy != null) {
             throw new IllegalStateException("there is already an entityAliasProxy: " + rootEntityAliasProxy);
         }
-        rootEntityAliasProxy = importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, false, NOT_NULL);
+        rootEntityAliasProxy = importEntityAliasImpl(aliasName, entityClass, forCase, fetchSql, dependsOnColum, false, NOT_NULL);
         return this;
     }
 
@@ -302,7 +322,7 @@ public class RbacView {
     public RbacView importSubEntityAlias(
             final String aliasName, final Class<? extends RbacObject> entityClass,
             final SQL fetchSql, final Column dependsOnColum) {
-        importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, true, NOT_NULL);
+        importEntityAliasImpl(aliasName, entityClass, usingDefaultCase(), fetchSql, dependsOnColum, true, NOT_NULL);
         return this;
     }
 
@@ -336,25 +356,17 @@ public class RbacView {
     public RbacView importEntityAlias(
             final String aliasName, final Class<? extends RbacObject> entityClass,
             final Column dependsOnColum, final SQL fetchSql, final Nullable nullable) {
-        importEntityAliasImpl(aliasName, entityClass, fetchSql, dependsOnColum, false, nullable);
-        return this;
-    }
-
-    // TODO: remove once it's not used in HsOffice...Entity anymore
-    public RbacView importEntityAlias(
-            final String aliasName, final Class<? extends RbacObject> entityClass,
-            final Column dependsOnColum) {
-        importEntityAliasImpl(aliasName, entityClass, directlyFetchedByDependsOnColumn(), dependsOnColum, false, null);
+        importEntityAliasImpl(aliasName, entityClass, usingDefaultCase(), fetchSql, dependsOnColum, false, nullable);
         return this;
     }
 
     private EntityAlias importEntityAliasImpl(
-            final String aliasName, final Class<? extends RbacObject> entityClass,
+            final String aliasName, final Class<? extends RbacObject> entityClass, final ColumnValue forCase,
             final SQL fetchSql, final Column dependsOnColum, boolean asSubEntity, final Nullable nullable) {
         final var entityAlias = new EntityAlias(aliasName, entityClass, fetchSql, dependsOnColum, asSubEntity, nullable);
         entityAliases.put(aliasName, entityAlias);
         try {
-            importAsAlias(aliasName, rbacDefinition(entityClass), asSubEntity);
+            importAsAlias(aliasName, rbacDefinition(entityClass), forCase, asSubEntity);
         } catch (final ReflectiveOperationException exc) {
             throw new RuntimeException("cannot import entity: " + entityClass, exc);
         }
@@ -366,7 +378,7 @@ public class RbacView {
         return (RbacView) entityClass.getMethod("rbac").invoke(null);
     }
 
-    private RbacView importAsAlias(final String aliasName, final RbacView importedRbacView, final boolean asSubEntity) {
+    private RbacView importAsAlias(final String aliasName, final RbacView importedRbacView, final ColumnValue forCase, final boolean asSubEntity) {
         final var mapper = new AliasNameMapper(importedRbacView, aliasName,
                 asSubEntity ? entityAliases.keySet() : null);
         importedRbacView.getEntityAliases().values().stream()
@@ -381,7 +393,8 @@ public class RbacView {
             new RbacRoleDefinition(findEntityAlias(mapper.map(roleDef.entityAlias.aliasName)), roleDef.role);
         });
         importedRbacView.getGrantDefs().forEach(grantDef -> {
-            if (grantDef.grantType() == RbacGrantDefinition.GrantType.ROLE_TO_ROLE) {
+            if ( grantDef.grantType() == RbacGrantDefinition.GrantType.ROLE_TO_ROLE &&
+                    (grantDef.forCases == null || grantDef.matchesCase(forCase)) ) {
                 final var importedGrantDef = findOrCreateGrantDef(
                         findRbacRole(
                                 mapper.map(grantDef.getSubRoleDef().entityAlias.aliasName),
@@ -398,6 +411,18 @@ public class RbacView {
         return this;
     }
 
+    public RbacView switchOnColumn(final String discriminatorColumName, final CaseDef... caseDefs) {
+        this.discriminatorColumName = discriminatorColumName;
+        allCases.addAll(stream(caseDefs).toList());
+
+        stream(caseDefs).forEach(caseDef -> {
+            this.processingCase = caseDef;
+            caseDef.def.accept(this);
+            this.processingCase = null;
+        });
+        return this;
+    }
+
     private void verifyVersionColumnExists() {
         if (stream(rootEntityAlias.entityClass.getDeclaredFields())
                 .noneMatch(f -> f.getAnnotation(Version.class) != null)) {
@@ -456,7 +481,15 @@ public class RbacView {
     }
 
     public void generateWithBaseFileName(final String baseFileName) {
-        new RbacViewMermaidFlowchartGenerator(this).generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, baseFileName + ".md"));
+        if (allCases.size() > 1) {
+            allCases.forEach(caseDef -> {
+                final var fileName = baseFileName + (caseDef.isDefaultCase() ? "" : "-" + caseDef.value) + ".md";
+                new RbacViewMermaidFlowchartGenerator(this, caseDef)
+                        .generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, fileName));
+            });
+        } else {
+            new RbacViewMermaidFlowchartGenerator(this).generateToMarkdownFile(Path.of(OUTPUT_BASEDIR, baseFileName + ".md"));
+        }
         new RbacViewPostgresGenerator(this).generateToChangeLog(Path.of(OUTPUT_BASEDIR, baseFileName + ".sql"));
     }
 
@@ -496,22 +529,28 @@ public class RbacView {
         private final RbacPermissionDefinition permDef;
         private boolean assumed = true;
         private boolean toCreate = false;
+        private Set<CaseDef> forCases = new HashSet<>();
 
         @Override
         public String toString() {
             final var arrow = isAssumed() ? " --> " : " -- // --> ";
-            return switch (grantType()) {
+            final var grant = switch (grantType()) {
                 case ROLE_TO_USER -> userDef.toString() + arrow + subRoleDef.toString();
                 case ROLE_TO_ROLE -> superRoleDef + arrow + subRoleDef;
                 case PERM_TO_ROLE -> superRoleDef + arrow + permDef;
             };
+            final var condition = isConditional()
+                    ? (" (" +forCases.stream().map(CaseDef::toString).collect(Collectors.joining("||")) + ")")
+                    : "";
+            return grant + condition;
         }
 
-        RbacGrantDefinition(final RbacRoleDefinition subRoleDef, final RbacRoleDefinition superRoleDef) {
+        RbacGrantDefinition(final RbacRoleDefinition subRoleDef, final RbacRoleDefinition superRoleDef, final CaseDef forCase) {
             this.userDef = null;
             this.subRoleDef = subRoleDef;
             this.superRoleDef = superRoleDef;
             this.permDef = null;
+            this.forCases = forCase != null ? hashSet(forCase) : null;
             register(this);
         }
 
@@ -537,7 +576,7 @@ public class RbacView {
 
         @NotNull
         GrantType grantType() {
-            return permDef != null ? GrantType.PERM_TO_ROLE
+            return permDef != null ? PERM_TO_ROLE
                     : userDef != null ? GrantType.ROLE_TO_USER
                     : GrantType.ROLE_TO_ROLE;
         }
@@ -546,6 +585,23 @@ public class RbacView {
             return assumed;
         }
 
+
+        RbacGrantDefinition forCase(final CaseDef processingCase) {
+            forCases.add(processingCase);
+            return this;
+        }
+
+        boolean isConditional() {
+            return forCases != null && !forCases.isEmpty() && forCases.size()<allCases.size();
+        }
+
+        boolean matchesCase(final ColumnValue requestedCase) {
+            final var noCasesDefined = forCases.isEmpty();
+            final var generateForAllCases = requestedCase == null;
+            final boolean isGrantedForRequestedCase = forCases.stream().anyMatch(c -> c.isCase(requestedCase));
+            return  noCasesDefined || generateForAllCases || isGrantedForRequestedCase;
+        }
+
         boolean isToCreate() {
             return toCreate;
         }
@@ -567,8 +623,9 @@ public class RbacView {
                     .orElse(false);
         }
 
-        public void unassumed() {
+        public RbacGrantDefinition unassumed() {
             this.assumed = false;
+            return this;
         }
 
         public enum GrantType {
@@ -794,7 +851,7 @@ public class RbacView {
 
     private RbacGrantDefinition findOrCreateGrantDef(final RbacPermissionDefinition permDef, final RbacRoleDefinition roleDef) {
         return grantDefs.stream()
-                .filter(g -> g.permDef == permDef && g.subRoleDef == roleDef)
+                .filter(g -> g.permDef == permDef && g.superRoleDef == roleDef)
                 .findFirst()
                 .orElseGet(() -> new RbacGrantDefinition(permDef, roleDef));
     }
@@ -802,10 +859,12 @@ public class RbacView {
     private RbacGrantDefinition findOrCreateGrantDef(
             final RbacRoleDefinition subRoleDefinition,
             final RbacRoleDefinition superRoleDefinition) {
-        return grantDefs.stream()
+        final var distinctGrantDef = grantDefs.stream()
                 .filter(g -> g.subRoleDef == subRoleDefinition && g.superRoleDef == superRoleDefinition)
                 .findFirst()
-                .orElseGet(() -> new RbacGrantDefinition(subRoleDefinition, superRoleDefinition));
+                .map(g -> g.forCase(processingCase))
+                .orElseGet(() -> new RbacGrantDefinition(subRoleDefinition, superRoleDefinition, processingCase));
+        return distinctGrantDef;
     }
 
     record EntityAlias(String aliasName, Class<? extends RbacObject> entityClass, SQL fetchSql, Column dependsOnColum, boolean isSubEntity, Nullable nullable) {
@@ -1022,6 +1081,23 @@ public class RbacView {
         }
     }
 
+    public static class ColumnValue {
+
+        public static ColumnValue usingDefaultCase() {
+            return new ColumnValue(null);
+        }
+
+        public static ColumnValue usingCase(final String value) {
+            return new ColumnValue(value);
+        }
+
+        public final String value;
+
+        private ColumnValue(final String value) {
+            this.value = value;
+        }
+    }
+
     private static class AliasNameMapper {
 
         private final RbacView importedRbacView;
@@ -1046,6 +1122,55 @@ public class RbacView {
         }
     }
 
+    public static class CaseDef extends ColumnValue {
+
+        final Consumer<RbacView> def;
+
+        private CaseDef(final String discriminatorColumnValue, final Consumer<RbacView> def) {
+            super(discriminatorColumnValue);
+            this.def = def;
+        }
+
+
+        public static CaseDef inCaseOf(final String discriminatorColumnValue, final Consumer<RbacView> def) {
+            return new CaseDef(discriminatorColumnValue, def);
+        }
+
+        public static CaseDef inOtherCases(final Consumer<RbacView> def) {
+            return new CaseDef(null, def);
+        }
+
+        @Override
+        public int hashCode() {
+            return ofNullable(value).map(String::hashCode).orElse(0);
+        }
+
+        @Override
+        public boolean equals(final Object other) {
+            if (this == other)
+                return true;
+            if (other == null || getClass() != other.getClass())
+                return false;
+            final CaseDef caseDef = (CaseDef) other;
+            return Objects.equals(value, caseDef.value);
+        }
+
+        boolean isDefaultCase() {
+            return value == null;
+        }
+
+        @Override
+        public String toString() {
+            return isDefaultCase()
+                ? "inOtherCases"
+                : "inCaseOf:" + value;
+        }
+
+        public boolean isCase(final ColumnValue requestedCase) {
+            return Objects.equals(requestedCase.value, this.value);
+        }
+    }
+
     private static void generateRbacView(final Class<? extends RbacObject> c) {
         final Method mainMethod = stream(c.getMethods()).filter(
                         m -> isStatic(m.getModifiers()) && m.getName().equals("main")
diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java
index c6e775c9..96a956e5 100644
--- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RbacViewMermaidFlowchartGenerator.java
@@ -1,6 +1,7 @@
 package net.hostsharing.hsadminng.rbac.rbacdef;
 
 import lombok.SneakyThrows;
+import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef;
 import org.apache.commons.lang3.StringUtils;
 
 import java.nio.file.*;
@@ -15,10 +16,13 @@ public class RbacViewMermaidFlowchartGenerator {
     public static final String HOSTSHARING_DARK_BLUE = "#274d6e";
     public static final String HOSTSHARING_LIGHT_BLUE = "#99bcdb";
     private final RbacView rbacDef;
+
+    private final CaseDef forCase;
     private final StringWriter flowchart = new StringWriter();
 
-    public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef) {
+    public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef, final CaseDef forCase) {
         this.rbacDef = rbacDef;
+        this.forCase = forCase;
         flowchart.writeLn("""
                 %%{init:{'flowchart':{'htmlLabels':false}}}%%
                 flowchart TB
@@ -26,6 +30,10 @@ public class RbacViewMermaidFlowchartGenerator {
         renderEntitySubgraphs();
         renderGrants();
     }
+
+    public RbacViewMermaidFlowchartGenerator(final RbacView rbacDef) {
+       this(rbacDef, null);
+    }
     private void renderEntitySubgraphs() {
         rbacDef.getEntityAliases().values().stream()
                 .filter(entityAlias -> !rbacDef.isEntityAliasProxy(entityAlias))
@@ -99,6 +107,7 @@ public class RbacViewMermaidFlowchartGenerator {
     private void renderGrants(final RbacView.RbacGrantDefinition.GrantType grantType, final String comment) {
         final var grantsOfRequestedType = rbacDef.getGrantDefs().stream()
                 .filter(g -> g.grantType() == grantType)
+                .filter(this::isToBeRenderedInThisGraph)
                 .toList();
         if ( !grantsOfRequestedType.isEmpty()) {
             flowchart.ensureSingleEmptyLine();
@@ -107,10 +116,19 @@ public class RbacViewMermaidFlowchartGenerator {
         }
     }
 
+    private boolean isToBeRenderedInThisGraph(final RbacView.RbacGrantDefinition g) {
+        if ( g.grantType() != ROLE_TO_ROLE )
+            return true;
+        if ( forCase == null && !g.isConditional() )
+            return true;
+        final var isToBeRenderedInThisGraph = g.getForCases() == null || g.getForCases().contains(forCase);
+        return isToBeRenderedInThisGraph;
+    }
+
     private String grantDef(final RbacView.RbacGrantDefinition grant) {
         final var arrow = (grant.isToCreate() ? " ==>" : " -.->")
                         + (grant.isAssumed() ? " " : "|XX| ");
-        return switch (grant.grantType()) {
+        final var grantDef = switch (grant.grantType()) {
             case ROLE_TO_USER ->
                 // TODO: other user types not implemented yet
                     "user:creator" + arrow + roleId(grant.getSubRoleDef());
@@ -118,6 +136,7 @@ public class RbacViewMermaidFlowchartGenerator {
                     roleId(grant.getSuperRoleDef()) + arrow + roleId(grant.getSubRoleDef());
             case PERM_TO_ROLE -> roleId(grant.getSuperRoleDef()) + arrow + permId(grant.getPermDef());
         };
+        return grantDef;
     }
 
     private String permDef(final RbacView.RbacPermissionDefinition perm) {
@@ -146,16 +165,17 @@ public class RbacViewMermaidFlowchartGenerator {
         Files.writeString(
                 path,
                 """
-                        ### rbac %{entityAlias}
-                        
-                        This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
-                                        
-                        ```mermaid
-                        %{flowchart}
-                        ```
-                        """
-                        .replace("%{entityAlias}", rbacDef.getRootEntityAlias().aliasName())
-                        .replace("%{flowchart}", flowchart.toString()),
+                    ### rbac %{entityAlias}%{case}
+    
+                    This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
+    
+                    ```mermaid
+                    %{flowchart}
+                    ```
+                    """
+                    .replace("%{entityAlias}", rbacDef.getRootEntityAlias().aliasName())
+                    .replace("%{flowchart}", flowchart.toString())
+                    .replace("%{case}", forCase == null ? "" : " " + forCase),
                 StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
         System.out.println("Markdown-File: " + path.toAbsolutePath());
     }
diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java
index 484415f2..2089d4d9 100644
--- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacdef/RolesGrantsAndPermissionsGenerator.java
@@ -1,10 +1,13 @@
 package net.hostsharing.hsadminng.rbac.rbacdef;
 
+import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.CaseDef;
+import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacGrantDefinition;
 import net.hostsharing.hsadminng.rbac.rbacdef.RbacView.RbacPermissionDefinition;
 
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.stream.Stream;
 
 import static java.util.Optional.ofNullable;
@@ -22,7 +25,7 @@ import static org.apache.commons.lang3.StringUtils.uncapitalize;
 class RolesGrantsAndPermissionsGenerator {
 
     private final RbacView rbacDef;
-    private final Set<RbacView.RbacGrantDefinition> rbacGrants = new HashSet<>();
+    private final Set<RbacGrantDefinition> rbacGrants = new HashSet<>();
     private final String liquibaseTagPrefix;
     private final String simpleEntityName;
     private final String simpleEntityVarName;
@@ -31,7 +34,7 @@ class RolesGrantsAndPermissionsGenerator {
     RolesGrantsAndPermissionsGenerator(final RbacView rbacDef, final String liquibaseTagPrefix) {
         this.rbacDef = rbacDef;
         this.rbacGrants.addAll(rbacDef.getGrantDefs().stream()
-                .filter(RbacView.RbacGrantDefinition::isToCreate)
+                .filter(RbacGrantDefinition::isToCreate)
                 .collect(toSet()));
         this.liquibaseTagPrefix = liquibaseTagPrefix;
 
@@ -67,13 +70,11 @@ class RolesGrantsAndPermissionsGenerator {
                     NEW ${rawTableName}
                 )
                     language plpgsql as $$
-
-                declare
                 """
                 .replace("${simpleEntityName}", simpleEntityName)
                 .replace("${rawTableName}", rawTableName));
 
-        plPgSql.chopEmptyLines();
+        plPgSql.writeLn("declare");
         plPgSql.indented(() -> {
             referencedEntityAliases()
                     .forEach((ea) -> plPgSql.writeLn(entityRefVar(NEW, ea) + " " + ea.getRawTableName() + ";"));
@@ -172,6 +173,10 @@ class RolesGrantsAndPermissionsGenerator {
                 .anyMatch(e -> true);
     }
 
+    private boolean hasAnyConditionalGrants() {
+        return rbacDef.getGrantDefs().stream().anyMatch(RbacGrantDefinition::isConditional);
+    }
+
     private void generateCreateRolesAndGrantsAfterInsert(final StringWriter plPgSql) {
         referencedEntityAliases()
                 .forEach((ea) -> {
@@ -186,7 +191,25 @@ class RolesGrantsAndPermissionsGenerator {
         createRolesWithGrantsSql(plPgSql, REFERRER);
 
         generateGrants(plPgSql, ROLE_TO_USER);
+
         generateGrants(plPgSql, ROLE_TO_ROLE);
+        if (!rbacDef.getAllCases().isEmpty()) {
+            plPgSql.writeLn();
+            final var ifOrElsIf = new AtomicReference<>("IF ");
+            rbacDef.getAllCases().forEach(caseDef -> {
+                if (caseDef.value != null) {
+                    plPgSql.writeLn(ifOrElsIf + "NEW." + rbacDef.getDiscriminatorColumName() + " = '" + caseDef.value + "' THEN");
+                } else {
+                    plPgSql.writeLn("ELSE");
+                }
+                plPgSql.indented(() -> {
+                    generateGrants(plPgSql, ROLE_TO_ROLE, caseDef);
+                });
+                ifOrElsIf.set("ELSIF ");
+            });
+            plPgSql.writeLn("END IF;");
+        }
+
         generateGrants(plPgSql, PERM_TO_ROLE);
     }
 
@@ -248,7 +271,7 @@ class RolesGrantsAndPermissionsGenerator {
 
     private void updateGrantsDependingOn(final StringWriter plPgSql, final String columnName) {
         rbacDef.getGrantDefs().stream()
-                .filter(RbacView.RbacGrantDefinition::isToCreate)
+                .filter(RbacGrantDefinition::isToCreate)
                 .filter(g -> g.dependsOnColumn(columnName))
                 .filter(g -> !isInsertPermissionGrant(g))
                 .forEach(g -> {
@@ -259,21 +282,31 @@ class RolesGrantsAndPermissionsGenerator {
                 });
     }
 
-    private static Boolean isInsertPermissionGrant(final RbacView.RbacGrantDefinition g) {
+    private static Boolean isInsertPermissionGrant(final RbacGrantDefinition g) {
         final var isInsertPermissionGrant = ofNullable(g.getPermDef()).map(RbacPermissionDefinition::getPermission).map(p -> p == INSERT).orElse(false);
         return isInsertPermissionGrant;
     }
 
-    private void generateGrants(final StringWriter plPgSql, final RbacView.RbacGrantDefinition.GrantType grantType) {
-        plPgSql.ensureSingleEmptyLine();
+    private void generateGrants(final StringWriter plPgSql, final RbacGrantDefinition.GrantType grantType, final CaseDef caseDef) {
         rbacGrants.stream()
+                .filter(g -> g.matchesCase(caseDef))
                 .filter(g -> g.grantType() == grantType)
                 .map(this::generateGrant)
                 .sorted()
-                .forEach(text -> plPgSql.writeLn(text));
+                .forEach(text -> plPgSql.writeLn(text, with("ref", NEW.name())));
     }
 
-    private String generateRevoke(RbacView.RbacGrantDefinition grantDef) {
+    private void generateGrants(final StringWriter plPgSql, final RbacGrantDefinition.GrantType grantType) {
+        plPgSql.ensureSingleEmptyLine();
+        rbacGrants.stream()
+                .filter(g -> !g.isConditional())
+                .filter(g -> g.grantType() == grantType)
+                .map(this::generateGrant)
+                .sorted()
+                .forEach(text -> plPgSql.writeLn(text, with("ref", NEW.name())));
+    }
+
+    private String generateRevoke(RbacGrantDefinition grantDef) {
         return switch (grantDef.grantType()) {
             case ROLE_TO_USER -> throw new IllegalArgumentException("unexpected grant");
             case ROLE_TO_ROLE -> "call revokeRoleFromRole(${subRoleRef}, ${superRoleRef});"
@@ -285,8 +318,8 @@ class RolesGrantsAndPermissionsGenerator {
         };
     }
 
-    private String generateGrant(RbacView.RbacGrantDefinition grantDef) {
-        return switch (grantDef.grantType()) {
+    private String generateGrant(RbacGrantDefinition grantDef) {
+        final var grantSql = switch (grantDef.grantType()) {
             case ROLE_TO_USER -> throw new IllegalArgumentException("unexpected grant");
             case ROLE_TO_ROLE -> "call grantRoleToRole(${subRoleRef}, ${superRoleRef}${assumed});"
                     .replace("${assumed}", grantDef.isAssumed() ? "" : ", unassumed()")
@@ -298,6 +331,7 @@ class RolesGrantsAndPermissionsGenerator {
                         .replace("${permRef}", createPerm(NEW, grantDef.getPermDef()))
                         .replace("${superRoleRef}", roleRef(NEW, grantDef.getSuperRoleDef()));
         };
+        return grantSql;
     }
 
     private String findPerm(final PostgresTriggerReference ref, final RbacPermissionDefinition permDef) {
@@ -362,11 +396,8 @@ class RolesGrantsAndPermissionsGenerator {
                     .replace("${roleSuffix}", capitalize(role.name())));
 
             generatePermissionsForRole(plPgSql, role);
-
             generateIncomingSuperRolesForRole(plPgSql, role);
-
             generateOutgoingSubRolesForRole(plPgSql, role);
-
             generateUserGrantsForRole(plPgSql, role);
 
             plPgSql.chopTail(",\n");
@@ -380,7 +411,7 @@ class RolesGrantsAndPermissionsGenerator {
         final var grantsToUsers = findGrantsToUserForRole(rbacDef.getRootEntityAlias(), role);
         if (!grantsToUsers.isEmpty()) {
             final var arrayElements = grantsToUsers.stream()
-                    .map(RbacView.RbacGrantDefinition::getUserDef)
+                    .map(RbacGrantDefinition::getUserDef)
                     .map(this::toPlPgSqlReference)
                     .toList();
             plPgSql.indented(() ->
@@ -393,7 +424,7 @@ class RolesGrantsAndPermissionsGenerator {
         final var permissionGrantsForRole = findPermissionsGrantsForRole(rbacDef.getRootEntityAlias(), role);
         if (!permissionGrantsForRole.isEmpty()) {
             final var arrayElements = permissionGrantsForRole.stream()
-                    .map(RbacView.RbacGrantDefinition::getPermDef)
+                    .map(RbacGrantDefinition::getPermDef)
                     .map(RbacPermissionDefinition::getPermission)
                     .map(RbacView.Permission::name)
                     .map(p -> "'" + p + "'")
@@ -406,26 +437,30 @@ class RolesGrantsAndPermissionsGenerator {
     }
 
     private void generateIncomingSuperRolesForRole(final StringWriter plPgSql, final RbacView.Role role) {
-        final var incomingGrants = findIncomingSuperRolesForRole(rbacDef.getRootEntityAlias(), role);
-        if (!incomingGrants.isEmpty()) {
-            final var arrayElements = incomingGrants.stream()
+        final var unconditionalIncomingGrants = findIncomingSuperRolesForRole(rbacDef.getRootEntityAlias(), role).stream()
+                .filter(g -> !g.isConditional())
+                .toList();
+        if (!unconditionalIncomingGrants.isEmpty()) {
+            final var arrayElements = unconditionalIncomingGrants.stream()
                     .map(g -> toPlPgSqlReference(NEW, g.getSuperRoleDef(), g.isAssumed()))
                     .sorted().toList();
             plPgSql.indented(() ->
                     plPgSql.writeLn("incomingSuperRoles => array[" + joinArrayElements(arrayElements, 1) + "],\n"));
-            rbacGrants.removeAll(incomingGrants);
+            rbacGrants.removeAll(unconditionalIncomingGrants);
         }
     }
 
     private void generateOutgoingSubRolesForRole(final StringWriter plPgSql, final RbacView.Role role) {
-        final var outgoingGrants = findOutgoingSuperRolesForRole(rbacDef.getRootEntityAlias(), role);
-        if (!outgoingGrants.isEmpty()) {
-            final var arrayElements = outgoingGrants.stream()
+        final var unconditionalOutgoingGrants = findOutgoingSuperRolesForRole(rbacDef.getRootEntityAlias(), role).stream()
+                .filter(g -> !g.isConditional())
+                .toList();
+        if (!unconditionalOutgoingGrants.isEmpty()) {
+            final var arrayElements = unconditionalOutgoingGrants.stream()
                     .map(g -> toPlPgSqlReference(NEW, g.getSubRoleDef(), g.isAssumed()))
                     .sorted().toList();
             plPgSql.indented(() ->
                     plPgSql.writeLn("outgoingSubRoles => array[" + joinArrayElements(arrayElements, 1) + "],\n"));
-            rbacGrants.removeAll(outgoingGrants);
+            rbacGrants.removeAll(unconditionalOutgoingGrants);
         }
     }
 
@@ -435,7 +470,7 @@ class RolesGrantsAndPermissionsGenerator {
                 : arrayElements.stream().collect(joining(",\n\t", "\n\t", ""));
     }
 
-    private Set<RbacView.RbacGrantDefinition> findPermissionsGrantsForRole(
+    private Set<RbacGrantDefinition> findPermissionsGrantsForRole(
             final RbacView.EntityAlias entityAlias,
             final RbacView.Role role) {
         final var roleDef = rbacDef.findRbacRole(entityAlias, role);
@@ -444,7 +479,7 @@ class RolesGrantsAndPermissionsGenerator {
                 .collect(toSet());
     }
 
-    private Set<RbacView.RbacGrantDefinition> findGrantsToUserForRole(
+    private Set<RbacGrantDefinition> findGrantsToUserForRole(
             final RbacView.EntityAlias entityAlias,
             final RbacView.Role role) {
         final var roleDef = rbacDef.findRbacRole(entityAlias, role);
@@ -453,7 +488,7 @@ class RolesGrantsAndPermissionsGenerator {
                 .collect(toSet());
     }
 
-    private Set<RbacView.RbacGrantDefinition> findIncomingSuperRolesForRole(
+    private Set<RbacGrantDefinition> findIncomingSuperRolesForRole(
             final RbacView.EntityAlias entityAlias,
             final RbacView.Role role) {
         final var roleDef = rbacDef.findRbacRole(entityAlias, role);
@@ -462,7 +497,7 @@ class RolesGrantsAndPermissionsGenerator {
                 .collect(toSet());
     }
 
-    private Set<RbacView.RbacGrantDefinition> findOutgoingSuperRolesForRole(
+    private Set<RbacGrantDefinition> findOutgoingSuperRolesForRole(
             final RbacView.EntityAlias entityAlias,
             final RbacView.Role role) {
         final var roleDef = rbacDef.findRbacRole(entityAlias, role);
@@ -506,7 +541,7 @@ class RolesGrantsAndPermissionsGenerator {
     private void generateUpdateTrigger(final StringWriter plPgSql) {
 
         generateHeader(plPgSql, "update");
-        if ( hasAnyUpdatableAndNullableEntityAliases() ) {
+        if ( hasAnyUpdatableAndNullableEntityAliases() || hasAnyConditionalGrants() ) {
             generateSimplifiedUpdateTriggerFunction(plPgSql);
         } else {
             generateUpdateTriggerFunction(plPgSql);
diff --git a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java
index f8746eb5..f4dc2167 100644
--- a/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java
+++ b/src/main/java/net/hostsharing/hsadminng/rbac/rbacgrant/RbacGrantsDiagramService.java
@@ -167,7 +167,7 @@ public class RbacGrantsDiagramService {
             return "users";
         }
         if (refType.equals("perm")) {
-            return node.idName().split(" ", 4)[3];
+            return node.idName().split(":", 3)[1];
         }
         if (refType.equals("role")) {
             final var withoutRolePrefix = node.idName().substring("role:".length());
@@ -209,7 +209,7 @@ public class RbacGrantsDiagramService {
     }
 
 
-    class LimitedHashSet<T> extends HashSet<T> {
+    static class LimitedHashSet<T> extends HashSet<T> {
 
         @Override
         public boolean add(final T t) {
diff --git a/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql b/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql
index 6a3387fb..2b3147c9 100644
--- a/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql
+++ b/src/main/resources/db/changelog/1-rbac/1050-rbac-base.sql
@@ -248,7 +248,7 @@ declare
     objectUuidOfRole          uuid;
     roleUuid                  uuid;
 begin
-    -- TODO.refact: extract function toRbacRoleDescriptor(roleIdName varchar) + find other occurrences
+    -- TODO.refa: extract function toRbacRoleDescriptor(roleIdName varchar) + find other occurrences
     roleParts = overlay(roleIdName placing '#' from length(roleIdName) + 1 - strpos(reverse(roleIdName), ':'));
     objectTableFromRoleIdName = split_part(roleParts, '#', 1);
     objectNameFromRoleIdName = split_part(roleParts, '#', 2);
@@ -356,16 +356,13 @@ create trigger deleteRbacRolesOfRbacObject_Trigger
 /*
 
  */
-create domain RbacOp as varchar(67) -- TODO: shorten to 8, once the deprecated values are gone
+create domain RbacOp as varchar(6)
     check (
                VALUE = 'DELETE'
             or VALUE = 'UPDATE'
             or VALUE = 'SELECT'
             or VALUE = 'INSERT'
             or VALUE = 'ASSUME'
-            -- TODO: all values below are deprecated, use insert with table
-            or VALUE ~ '^add-[a-z]+$'
-            or VALUE ~ '^new-[a-z-]+$'
         );
 
 create table RbacPermission
@@ -417,37 +414,6 @@ begin
     return permissionUuid;
 end; $$;
 
--- TODO: deprecated, remove and amend all usages to createPermission
-create or replace function createPermissions(forObjectUuid uuid, permitOps RbacOp[])
-    returns uuid[]
-    language plpgsql as $$
-declare
-    refId         uuid;
-    permissionIds uuid[] = array []::uuid[];
-begin
-    if (forObjectUuid is null) then
-        raise exception 'forObjectUuid must not be null';
-    end if;
-
-    for i in array_lower(permitOps, 1)..array_upper(permitOps, 1)
-        loop
-            refId = (select uuid from RbacPermission where objectUuid = forObjectUuid and op = permitOps[i]);
-            if (refId is null) then
-                insert
-                    into RbacReference ("type")
-                    values ('RbacPermission')
-                    returning uuid into refId;
-                insert
-                    into RbacPermission (uuid, objectUuid, op)
-                    values (refId, forObjectUuid, permitOps[i]);
-            end if;
-            permissionIds = permissionIds || refId;
-        end loop;
-
-    return permissionIds;
-end;
-$$;
-
 create or replace function findEffectivePermissionId(forObjectUuid uuid, forOp RbacOp, forOpTableName text = null)
     returns uuid
     returns null on null input
@@ -649,25 +615,6 @@ begin
 end;
 $$;
 
--- TODO: deprecated, remove and use grantPermissionToRole(...)
-create or replace procedure grantPermissionsToRole(roleUuid uuid, permissionIds uuid[])
-    language plpgsql as $$
-begin
-    if cardinality(permissionIds) = 0 then return; end if;
-
-    for i in array_lower(permissionIds, 1)..array_upper(permissionIds, 1)
-        loop
-            perform assertReferenceType('roleId (ascendant)', roleUuid, 'RbacRole');
-            perform assertReferenceType('permissionId (descendant)', permissionIds[i], 'RbacPermission');
-
-            insert
-                into RbacGrants (grantedByTriggerOf, ascendantUuid, descendantUuid, assumed)
-                values (currentTriggerObjectUuid(), roleUuid, permissionIds[i], true)
-            on conflict do nothing; -- allow granting multiple times
-        end loop;
-end;
-$$;
-
 create or replace procedure grantRoleToRole(subRoleId uuid, superRoleId uuid, doAssume bool = true)
     language plpgsql as $$
 begin
@@ -691,7 +638,7 @@ declare
     superRoleId uuid;
     subRoleId uuid;
 begin
-    -- TODO: maybe separate method grantRoleToRoleIfNotNull(...) for NULLABLE references
+    -- TODO.refa: maybe separate method grantRoleToRoleIfNotNull(...) for NULLABLE references
     if superRole.objectUuid is null or subRole.objectuuid is null then
         return;
     end if;
@@ -712,30 +659,6 @@ begin
     on conflict do nothing; -- allow granting multiple times
 end; $$;
 
-create or replace procedure grantRoleToRoleIfNotNull(subRole RbacRoleDescriptor, superRole RbacRoleDescriptor, doAssume bool = true)
-    language plpgsql as $$
-declare
-    superRoleId uuid;
-    subRoleId uuid;
-begin
-    if ( superRoleId is null ) then return; end if;
-    superRoleId := findRoleId(superRole);
-    if ( subRoleId is null ) then return; end if;
-    subRoleId := findRoleId(subRole);
-
-    perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
-    perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
-
-    if isGranted(subRoleId, superRoleId) then
-        call raiseDuplicateRoleGrantException(subRoleId, superRoleId);
-    end if;
-
-    insert
-        into RbacGrants (grantedByTriggerOf, ascendantuuid, descendantUuid, assumed)
-        values (currentTriggerObjectUuid(), superRoleId, subRoleId, doAssume)
-    on conflict do nothing; -- allow granting multiple times
-end; $$;
-
 create or replace procedure revokeRoleFromRole(subRole RbacRoleDescriptor, superRole RbacRoleDescriptor)
     language plpgsql as $$
 declare
diff --git a/src/main/resources/db/changelog/1-rbac/1051-rbac-user-grant.sql b/src/main/resources/db/changelog/1-rbac/1051-rbac-user-grant.sql
index a82865c8..17645ca3 100644
--- a/src/main/resources/db/changelog/1-rbac/1051-rbac-user-grant.sql
+++ b/src/main/resources/db/changelog/1-rbac/1051-rbac-user-grant.sql
@@ -20,19 +20,18 @@ begin
     return currentSubjectsUuids[1];
 end; $$;
 
-create or replace procedure grantRoleToUserUnchecked(grantedByRoleUuid uuid, roleUuid uuid, userUuid uuid, doAssume boolean = true)
+create or replace procedure grantRoleToUserUnchecked(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true)
     language plpgsql as $$
 begin
     perform assertReferenceType('grantingRoleUuid', grantedByRoleUuid, 'RbacRole');
-    perform assertReferenceType('roleId (descendant)', roleUuid, 'RbacRole');
+    perform assertReferenceType('roleId (descendant)', grantedRoleUuid, 'RbacRole');
     perform assertReferenceType('userId (ascendant)', userUuid, 'RbacUser');
 
     insert
         into RbacGrants (grantedByRoleUuid, ascendantUuid, descendantUuid, assumed)
-        values (grantedByRoleUuid, userUuid, roleUuid, doAssume);
-    -- TODO.spec: What should happen on multiple grants? What if options (doAssume) are not the same?
-    --      Most powerful or latest grant wins? What about managed?
-    -- on conflict do nothing; -- allow granting multiple times
+        values (grantedByRoleUuid, userUuid, grantedRoleUuid, doAssume)
+    -- TODO: check if grantedByRoleUuid+doAssume are the same, otherwise raise exception?
+    on conflict do nothing; -- allow granting multiple times
 end; $$;
 
 create or replace procedure grantRoleToUser(grantedByRoleUuid uuid, grantedRoleUuid uuid, userUuid uuid, doAssume boolean = true)
diff --git a/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql b/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql
index 57ba3cb7..1e9bd2bc 100644
--- a/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql
+++ b/src/main/resources/db/changelog/1-rbac/1057-rbac-role-builder.sql
@@ -6,6 +6,7 @@
 --changeset rbac-role-builder-create-role:1 endDelimiter:--//
 -- -----------------------------------------------------------------
 
+-- TODO: rename to defineRoleWithGrants because it does not complain if the role already exists
 create or replace function createRoleWithGrants(
     roleDescriptor RbacRoleDescriptor,
     permissions RbacOp[] = array[]::RbacOp[],
@@ -28,7 +29,7 @@ declare
     userUuid                uuid;
     userGrantsByRoleUuid    uuid;
 begin
-    roleUuid := createRole(roleDescriptor);
+    roleUuid := coalesce(findRoleId(roleDescriptor), createRole(roleDescriptor));
 
     foreach permission in array permissions
         loop
diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md
new file mode 100644
index 00000000..e5f608e8
--- /dev/null
+++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac-REPRESENTATIVE.md
@@ -0,0 +1,102 @@
+### rbac relation inCaseOf:REPRESENTATIVE
+
+This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
+
+```mermaid
+%%{init:{'flowchart':{'htmlLabels':false}}}%%
+flowchart TB
+
+subgraph holderPerson["`**holderPerson**`"]
+    direction TB
+    style holderPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
+
+    subgraph holderPerson:roles[ ]
+        style holderPerson:roles fill:#99bcdb,stroke:white
+
+        role:holderPerson:OWNER[[holderPerson:OWNER]]
+        role:holderPerson:ADMIN[[holderPerson:ADMIN]]
+        role:holderPerson:REFERRER[[holderPerson:REFERRER]]
+    end
+end
+
+subgraph anchorPerson["`**anchorPerson**`"]
+    direction TB
+    style anchorPerson fill:#99bcdb,stroke:#274d6e,stroke-width:8px
+
+    subgraph anchorPerson:roles[ ]
+        style anchorPerson:roles fill:#99bcdb,stroke:white
+
+        role:anchorPerson:OWNER[[anchorPerson:OWNER]]
+        role:anchorPerson:ADMIN[[anchorPerson:ADMIN]]
+        role:anchorPerson:REFERRER[[anchorPerson:REFERRER]]
+    end
+end
+
+subgraph contact["`**contact**`"]
+    direction TB
+    style contact fill:#99bcdb,stroke:#274d6e,stroke-width:8px
+
+    subgraph contact:roles[ ]
+        style contact:roles fill:#99bcdb,stroke:white
+
+        role:contact:OWNER[[contact:OWNER]]
+        role:contact:ADMIN[[contact:ADMIN]]
+        role:contact:REFERRER[[contact:REFERRER]]
+    end
+end
+
+subgraph relation["`**relation**`"]
+    direction TB
+    style relation fill:#dd4901,stroke:#274d6e,stroke-width:8px
+
+    subgraph relation:roles[ ]
+        style relation:roles fill:#dd4901,stroke:white
+
+        role:relation:OWNER[[relation:OWNER]]
+        role:relation:ADMIN[[relation:ADMIN]]
+        role:relation:AGENT[[relation:AGENT]]
+        role:relation:TENANT[[relation:TENANT]]
+    end
+
+    subgraph relation:permissions[ ]
+        style relation:permissions fill:#dd4901,stroke:white
+
+        perm:relation:DELETE{{relation:DELETE}}
+        perm:relation:UPDATE{{relation:UPDATE}}
+        perm:relation:SELECT{{relation:SELECT}}
+        perm:relation:INSERT{{relation:INSERT}}
+    end
+end
+
+%% granting roles to users
+user:creator ==> role:relation:OWNER
+
+%% granting roles to roles
+role:global:ADMIN -.-> role:anchorPerson:OWNER
+role:anchorPerson:OWNER -.-> role:anchorPerson:ADMIN
+role:anchorPerson:ADMIN -.-> role:anchorPerson:REFERRER
+role:global:ADMIN -.-> role:holderPerson:OWNER
+role:holderPerson:OWNER -.-> role:holderPerson:ADMIN
+role:holderPerson:ADMIN -.-> role:holderPerson:REFERRER
+role:global:ADMIN -.-> role:contact:OWNER
+role:contact:OWNER -.-> role:contact:ADMIN
+role:contact:ADMIN -.-> role:contact:REFERRER
+role:global:ADMIN ==> role:relation:OWNER
+role:holderPerson:ADMIN ==> role:relation:OWNER
+role:relation:OWNER ==> role:relation:ADMIN
+role:relation:ADMIN ==> role:anchorPerson:OWNER
+role:relation:ADMIN ==> role:relation:AGENT
+role:anchorPerson:ADMIN ==> role:relation:AGENT
+role:relation:AGENT ==> role:relation:TENANT
+role:contact:ADMIN ==> role:relation:TENANT
+role:relation:TENANT ==> role:anchorPerson:REFERRER
+role:relation:TENANT ==> role:holderPerson:REFERRER
+role:relation:TENANT ==> role:contact:REFERRER
+
+%% granting permissions to roles
+role:relation:OWNER ==> perm:relation:DELETE
+role:relation:ADMIN ==> perm:relation:UPDATE
+role:relation:TENANT ==> perm:relation:SELECT
+role:anchorPerson:ADMIN ==> perm:relation:INSERT
+
+```
diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md
index 8014cdaf..4ff19e79 100644
--- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md
+++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.md
@@ -1,4 +1,4 @@
-### rbac relation
+### rbac relation inOtherCases
 
 This code generated was by RbacViewMermaidFlowchartGenerator, do not amend manually.
 
@@ -83,15 +83,14 @@ role:contact:OWNER -.-> role:contact:ADMIN
 role:contact:ADMIN -.-> role:contact:REFERRER
 role:global:ADMIN ==> role:relation:OWNER
 role:relation:OWNER ==> role:relation:ADMIN
-role:anchorPerson:ADMIN ==> role:relation:ADMIN
 role:relation:ADMIN ==> role:relation:AGENT
-role:holderPerson:ADMIN ==> role:relation:AGENT
 role:relation:AGENT ==> role:relation:TENANT
-role:holderPerson:ADMIN ==> role:relation:TENANT
 role:contact:ADMIN ==> role:relation:TENANT
 role:relation:TENANT ==> role:anchorPerson:REFERRER
 role:relation:TENANT ==> role:holderPerson:REFERRER
 role:relation:TENANT ==> role:contact:REFERRER
+role:anchorPerson:ADMIN ==> role:relation:OWNER
+role:holderPerson:ADMIN ==> role:relation:AGENT
 
 %% granting permissions to roles
 role:relation:OWNER ==> perm:relation:DELETE
diff --git a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql
index ff890a59..15114d03 100644
--- a/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql
+++ b/src/main/resources/db/changelog/5-hs-office/503-relation/5033-hs-office-relation-rbac.sql
@@ -57,16 +57,12 @@ begin
     perform createRoleWithGrants(
         hsOfficeRelationADMIN(NEW),
             permissions => array['UPDATE'],
-            incomingSuperRoles => array[
-            	hsOfficePersonADMIN(newAnchorPerson),
-            	hsOfficeRelationOWNER(NEW)]
+            incomingSuperRoles => array[hsOfficeRelationOWNER(NEW)]
     );
 
     perform createRoleWithGrants(
         hsOfficeRelationAGENT(NEW),
-            incomingSuperRoles => array[
-            	hsOfficePersonADMIN(newHolderPerson),
-            	hsOfficeRelationADMIN(NEW)]
+            incomingSuperRoles => array[hsOfficeRelationADMIN(NEW)]
     );
 
     perform createRoleWithGrants(
@@ -74,7 +70,6 @@ begin
             permissions => array['SELECT'],
             incomingSuperRoles => array[
             	hsOfficeContactADMIN(newContact),
-            	hsOfficePersonADMIN(newHolderPerson),
             	hsOfficeRelationAGENT(NEW)],
             outgoingSubRoles => array[
             	hsOfficeContactREFERRER(newContact),
@@ -82,6 +77,15 @@ begin
             	hsOfficePersonREFERRER(newHolderPerson)]
     );
 
+    IF NEW.type = 'REPRESENTATIVE' THEN
+        call grantRoleToRole(hsOfficePersonOWNER(newAnchorPerson), hsOfficeRelationADMIN(NEW));
+        call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newAnchorPerson));
+        call grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newHolderPerson));
+    ELSE
+        call grantRoleToRole(hsOfficeRelationAGENT(NEW), hsOfficePersonADMIN(newHolderPerson));
+        call grantRoleToRole(hsOfficeRelationOWNER(NEW), hsOfficePersonADMIN(newAnchorPerson));
+    END IF;
+
     call leaveTriggerForObjectUuid(NEW.uuid);
 end; $$;
 
@@ -118,48 +122,12 @@ create or replace procedure updateRbacRulesForHsOfficeRelation(
     NEW hs_office_relation
 )
     language plpgsql as $$
-
-declare
-    oldHolderPerson hs_office_person;
-    newHolderPerson hs_office_person;
-    oldAnchorPerson hs_office_person;
-    newAnchorPerson hs_office_person;
-    oldContact hs_office_contact;
-    newContact hs_office_contact;
-
 begin
-    call enterTriggerForObjectUuid(NEW.uuid);
-
-    SELECT * FROM hs_office_person WHERE uuid = OLD.holderUuid    INTO oldHolderPerson;
-    assert oldHolderPerson.uuid is not null, format('oldHolderPerson must not be null for OLD.holderUuid = %s', OLD.holderUuid);
-
-    SELECT * FROM hs_office_person WHERE uuid = NEW.holderUuid    INTO newHolderPerson;
-    assert newHolderPerson.uuid is not null, format('newHolderPerson must not be null for NEW.holderUuid = %s', NEW.holderUuid);
-
-    SELECT * FROM hs_office_person WHERE uuid = OLD.anchorUuid    INTO oldAnchorPerson;
-    assert oldAnchorPerson.uuid is not null, format('oldAnchorPerson must not be null for OLD.anchorUuid = %s', OLD.anchorUuid);
-
-    SELECT * FROM hs_office_person WHERE uuid = NEW.anchorUuid    INTO newAnchorPerson;
-    assert newAnchorPerson.uuid is not null, format('newAnchorPerson must not be null for NEW.anchorUuid = %s', NEW.anchorUuid);
-
-    SELECT * FROM hs_office_contact WHERE uuid = OLD.contactUuid    INTO oldContact;
-    assert oldContact.uuid is not null, format('oldContact must not be null for OLD.contactUuid = %s', OLD.contactUuid);
-
-    SELECT * FROM hs_office_contact WHERE uuid = NEW.contactUuid    INTO newContact;
-    assert newContact.uuid is not null, format('newContact must not be null for NEW.contactUuid = %s', NEW.contactUuid);
-
-
-    if NEW.contactUuid <> OLD.contactUuid then
-
-        call revokeRoleFromRole(hsOfficeRelationTENANT(OLD), hsOfficeContactADMIN(oldContact));
-        call grantRoleToRole(hsOfficeRelationTENANT(NEW), hsOfficeContactADMIN(newContact));
-
-        call revokeRoleFromRole(hsOfficeContactREFERRER(oldContact), hsOfficeRelationTENANT(OLD));
-        call grantRoleToRole(hsOfficeContactREFERRER(newContact), hsOfficeRelationTENANT(NEW));
 
+    if NEW.contactUuid is distinct from OLD.contactUuid then
+        delete from rbacgrants g where g.grantedbytriggerof = OLD.uuid;
+        call buildRbacSystemForHsOfficeRelation(NEW);
     end if;
-
-    call leaveTriggerForObjectUuid(NEW.uuid);
 end; $$;
 
 /*
diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md
index a0caa074..3522b5a3 100644
--- a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md
+++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.md
@@ -98,22 +98,21 @@ role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN
 role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER
 role:global:ADMIN -.-> role:partnerRel:OWNER
 role:partnerRel:OWNER -.-> role:partnerRel:ADMIN
-role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN
 role:partnerRel:ADMIN -.-> role:partnerRel:AGENT
-role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
 role:partnerRel:AGENT -.-> role:partnerRel:TENANT
-role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT
 role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT
 role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER
 role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER
 role:partnerRel:TENANT -.-> role:partnerRel.contact:REFERRER
+role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:OWNER
+role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
 
 %% granting permissions to roles
 role:global:ADMIN ==> perm:partner:INSERT
-role:partnerRel:ADMIN ==> perm:partner:DELETE
-role:partnerRel:AGENT ==> perm:partner:UPDATE
+role:partnerRel:OWNER ==> perm:partner:DELETE
+role:partnerRel:ADMIN ==> perm:partner:UPDATE
 role:partnerRel:TENANT ==> perm:partner:SELECT
-role:partnerRel:ADMIN ==> perm:partnerDetails:DELETE
+role:partnerRel:OWNER ==> perm:partnerDetails:DELETE
 role:partnerRel:AGENT ==> perm:partnerDetails:UPDATE
 role:partnerRel:AGENT ==> perm:partnerDetails:SELECT
 
diff --git a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql
index b5510d8c..7d263dbd 100644
--- a/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql
+++ b/src/main/resources/db/changelog/5-hs-office/504-partner/5043-hs-office-partner-rbac.sql
@@ -42,10 +42,10 @@ begin
     SELECT * FROM hs_office_partner_details WHERE uuid = NEW.detailsUuid    INTO newPartnerDetails;
     assert newPartnerDetails.uuid is not null, format('newPartnerDetails must not be null for NEW.detailsUuid = %s', NEW.detailsUuid);
 
-    call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel));
+    call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
     call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel));
-    call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
-    call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel));
+    call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationADMIN(newPartnerRel));
+    call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
     call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'SELECT'), hsOfficeRelationAGENT(newPartnerRel));
     call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
 
@@ -110,17 +110,17 @@ begin
 
     if NEW.partnerRelUuid <> OLD.partnerRelUuid then
 
-        call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationADMIN(oldPartnerRel));
-        call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel));
+        call revokePermissionFromRole(getPermissionId(OLD.uuid, 'DELETE'), hsOfficeRelationOWNER(oldPartnerRel));
+        call grantPermissionToRole(createPermission(NEW.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
 
-        call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationAGENT(oldPartnerRel));
-        call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
+        call revokePermissionFromRole(getPermissionId(OLD.uuid, 'UPDATE'), hsOfficeRelationADMIN(oldPartnerRel));
+        call grantPermissionToRole(createPermission(NEW.uuid, 'UPDATE'), hsOfficeRelationADMIN(newPartnerRel));
 
         call revokePermissionFromRole(getPermissionId(OLD.uuid, 'SELECT'), hsOfficeRelationTENANT(oldPartnerRel));
         call grantPermissionToRole(createPermission(NEW.uuid, 'SELECT'), hsOfficeRelationTENANT(newPartnerRel));
 
-        call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(oldPartnerRel));
-        call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationADMIN(newPartnerRel));
+        call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(oldPartnerRel));
+        call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'DELETE'), hsOfficeRelationOWNER(newPartnerRel));
 
         call revokePermissionFromRole(getPermissionId(oldPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(oldPartnerRel));
         call grantPermissionToRole(createPermission(newPartnerDetails.uuid, 'UPDATE'), hsOfficeRelationAGENT(newPartnerRel));
diff --git a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md
index 5c43e03d..57ce3e73 100644
--- a/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md
+++ b/src/main/resources/db/changelog/5-hs-office/506-debitor/5063-hs-office-debitor-rbac.md
@@ -151,15 +151,14 @@ role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN
 role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER
 role:global:ADMIN -.-> role:debitorRel:OWNER
 role:debitorRel:OWNER -.-> role:debitorRel:ADMIN
-role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:ADMIN
 role:debitorRel:ADMIN -.-> role:debitorRel:AGENT
-role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT
 role:debitorRel:AGENT -.-> role:debitorRel:TENANT
-role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:TENANT
 role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT
 role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER
 role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER
 role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER
+role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:OWNER
+role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT
 role:global:ADMIN -.-> role:refundBankAccount:OWNER
 role:refundBankAccount:OWNER -.-> role:refundBankAccount:ADMIN
 role:refundBankAccount:ADMIN -.-> role:refundBankAccount:REFERRER
@@ -176,15 +175,14 @@ role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN
 role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER
 role:global:ADMIN -.-> role:partnerRel:OWNER
 role:partnerRel:OWNER -.-> role:partnerRel:ADMIN
-role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN
 role:partnerRel:ADMIN -.-> role:partnerRel:AGENT
-role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
 role:partnerRel:AGENT -.-> role:partnerRel:TENANT
-role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT
 role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT
 role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER
 role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER
 role:partnerRel:TENANT -.-> role:partnerRel.contact:REFERRER
+role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:OWNER
+role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
 role:partnerRel:ADMIN ==> role:debitorRel:ADMIN
 role:partnerRel:AGENT ==> role:debitorRel:AGENT
 role:debitorRel:AGENT ==> role:partnerRel:TENANT
diff --git a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md
index aa3059f9..e3528f7f 100644
--- a/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md
+++ b/src/main/resources/db/changelog/5-hs-office/507-sepamandate/5073-hs-office-sepamandate-rbac.md
@@ -110,15 +110,14 @@ role:debitorRel.contact:OWNER -.-> role:debitorRel.contact:ADMIN
 role:debitorRel.contact:ADMIN -.-> role:debitorRel.contact:REFERRER
 role:global:ADMIN -.-> role:debitorRel:OWNER
 role:debitorRel:OWNER -.-> role:debitorRel:ADMIN
-role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:ADMIN
 role:debitorRel:ADMIN -.-> role:debitorRel:AGENT
-role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT
 role:debitorRel:AGENT -.-> role:debitorRel:TENANT
-role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:TENANT
 role:debitorRel.contact:ADMIN -.-> role:debitorRel:TENANT
 role:debitorRel:TENANT -.-> role:debitorRel.anchorPerson:REFERRER
 role:debitorRel:TENANT -.-> role:debitorRel.holderPerson:REFERRER
 role:debitorRel:TENANT -.-> role:debitorRel.contact:REFERRER
+role:debitorRel.anchorPerson:ADMIN -.-> role:debitorRel:OWNER
+role:debitorRel.holderPerson:ADMIN -.-> role:debitorRel:AGENT
 role:global:ADMIN -.-> role:bankAccount:OWNER
 role:bankAccount:OWNER -.-> role:bankAccount:ADMIN
 role:bankAccount:ADMIN -.-> role:bankAccount:REFERRER
diff --git a/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md
index 3681b8e6..9e5752b8 100644
--- a/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md
+++ b/src/main/resources/db/changelog/5-hs-office/510-membership/5103-hs-office-membership-rbac.md
@@ -96,15 +96,14 @@ role:partnerRel.contact:OWNER -.-> role:partnerRel.contact:ADMIN
 role:partnerRel.contact:ADMIN -.-> role:partnerRel.contact:REFERRER
 role:global:ADMIN -.-> role:partnerRel:OWNER
 role:partnerRel:OWNER -.-> role:partnerRel:ADMIN
-role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:ADMIN
 role:partnerRel:ADMIN -.-> role:partnerRel:AGENT
-role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
 role:partnerRel:AGENT -.-> role:partnerRel:TENANT
-role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:TENANT
 role:partnerRel.contact:ADMIN -.-> role:partnerRel:TENANT
 role:partnerRel:TENANT -.-> role:partnerRel.anchorPerson:REFERRER
 role:partnerRel:TENANT -.-> role:partnerRel.holderPerson:REFERRER
 role:partnerRel:TENANT -.-> role:partnerRel.contact:REFERRER
+role:partnerRel.anchorPerson:ADMIN -.-> role:partnerRel:OWNER
+role:partnerRel.holderPerson:ADMIN -.-> role:partnerRel:AGENT
 role:membership:OWNER ==> role:membership:ADMIN
 role:partnerRel:ADMIN ==> role:membership:ADMIN
 role:membership:ADMIN ==> role:membership:AGENT
diff --git a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md
index 26ff3d5c..b38ad4a0 100644
--- a/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md
+++ b/src/main/resources/db/changelog/5-hs-office/511-coopshares/5113-hs-office-coopshares-rbac.md
@@ -97,15 +97,14 @@ role:membership.partnerRel.contact:OWNER -.-> role:membership.partnerRel.contact
 role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel.contact:REFERRER
 role:global:ADMIN -.-> role:membership.partnerRel:OWNER
 role:membership.partnerRel:OWNER -.-> role:membership.partnerRel:ADMIN
-role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:ADMIN
 role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel:AGENT
-role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT
 role:membership.partnerRel:AGENT -.-> role:membership.partnerRel:TENANT
-role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:TENANT
 role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel:TENANT
 role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.anchorPerson:REFERRER
 role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.holderPerson:REFERRER
 role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.contact:REFERRER
+role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:OWNER
+role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT
 role:membership:OWNER -.-> role:membership:ADMIN
 role:membership.partnerRel:ADMIN -.-> role:membership:ADMIN
 role:membership:ADMIN -.-> role:membership:AGENT
diff --git a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md
index d220a38c..77de3dc2 100644
--- a/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md
+++ b/src/main/resources/db/changelog/5-hs-office/512-coopassets/5123-hs-office-coopassets-rbac.md
@@ -97,15 +97,14 @@ role:membership.partnerRel.contact:OWNER -.-> role:membership.partnerRel.contact
 role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel.contact:REFERRER
 role:global:ADMIN -.-> role:membership.partnerRel:OWNER
 role:membership.partnerRel:OWNER -.-> role:membership.partnerRel:ADMIN
-role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:ADMIN
 role:membership.partnerRel:ADMIN -.-> role:membership.partnerRel:AGENT
-role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT
 role:membership.partnerRel:AGENT -.-> role:membership.partnerRel:TENANT
-role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:TENANT
 role:membership.partnerRel.contact:ADMIN -.-> role:membership.partnerRel:TENANT
 role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.anchorPerson:REFERRER
 role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.holderPerson:REFERRER
 role:membership.partnerRel:TENANT -.-> role:membership.partnerRel.contact:REFERRER
+role:membership.partnerRel.anchorPerson:ADMIN -.-> role:membership.partnerRel:OWNER
+role:membership.partnerRel.holderPerson:ADMIN -.-> role:membership.partnerRel:AGENT
 role:membership:OWNER -.-> role:membership:ADMIN
 role:membership.partnerRel:ADMIN -.-> role:membership:ADMIN
 role:membership:ADMIN -.-> role:membership:AGENT
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java
index 32f441af..3a4d4e16 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/debitor/HsOfficeDebitorRepositoryIntegrationTest.java
@@ -186,13 +186,13 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
                     "{ grant perm:debitor#D-1000122:DELETE                          to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }",
                     "{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:DELETE   to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }",
                     "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER    to role:global#global:ADMIN by system and assume }",
+                    "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER    to role:person#FirstGmbH:ADMIN by system and assume }",
                     "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER    to user:superuser-alex@hostsharing.net by relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER and assume }",
 
                     // admin
                     "{ grant perm:debitor#D-1000122:UPDATE                          to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }",
                     "{ grant perm:relation#FirstGmbH-with-DEBITOR-FourtheG:UPDATE   to role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN by system and assume }",
                     "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN    to role:relation#FirstGmbH-with-DEBITOR-FourtheG:OWNER by system and assume }",
-                    "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN    to role:person#FirstGmbH:ADMIN by system and assume }",
                     "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:ADMIN    to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:ADMIN by system and assume }",
 
                     // agent
@@ -208,7 +208,6 @@ class HsOfficeDebitorRepositoryIntegrationTest extends ContextBasedTestWithClean
                     "{ grant role:person#FirstGmbH:REFERRER                         to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }",
                     "{ grant role:person#FourtheG:REFERRER                          to role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT by system and assume }",
                     "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT   to role:contact#fourthcontact:ADMIN by system and assume }",
-                    "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT   to role:person#FourtheG:ADMIN by system and assume }",
                     "{ grant role:relation#FirstGmbH-with-DEBITOR-FourtheG:TENANT   to role:relation#FirstGmbH-with-DEBITOR-FourtheG:AGENT by system and assume }",
 
                     null));
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java
index 633278a0..a6da48c9 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/membership/HsOfficeMembershipRepositoryIntegrationTest.java
@@ -134,6 +134,7 @@ class HsOfficeMembershipRepositoryIntegrationTest extends ContextBasedTestWithCl
                             "{ grant perm:membership#M-1000117:SELECT to role:membership#M-1000117:AGENT by system and assume }",
                             "{ grant role:membership#M-1000117:AGENT to role:membership#M-1000117:ADMIN by system and assume }",
 
+                            // referrer
                             "{ grant role:membership#M-1000117:AGENT to role:relation#HostsharingeG-with-PARTNER-FirstGmbH:AGENT by system and assume }",
                             "{ grant role:relation#HostsharingeG-with-PARTNER-FirstGmbH:TENANT to role:membership#M-1000117:AGENT by system and assume }",
 
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java
index 8da1f12f..a763804a 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/migration/ImportOfficeData.java
@@ -218,23 +218,6 @@ public class ImportOfficeData extends ContextBasedTest {
         }
     }
 
-    @Test
-    @Order(1021)
-    void buildDebitorRelations() {
-        debitors.forEach( (id, debitor) -> {
-            final var debitorRel = HsOfficeRelationEntity.builder()
-                    .type(HsOfficeRelationType.DEBITOR)
-                    .anchor(debitor.getPartner().getPartnerRel().getHolder())
-                    .holder(debitor.getPartner().getPartnerRel().getHolder()) //  just 1 debitor/partner in legacy hsadmin
-                    // FIXME .contact()
-                    .build();
-            if (debitorRel.getAnchor() != null && debitorRel.getHolder() != null &&
-                    debitorRel.getContact() != null ) {
-                relations.put(relationId++, debitorRel);
-            }
-        });
-    }
-
     @Test
     @Order(1029)
     void verifyContacts() {
@@ -292,29 +275,25 @@ public class ImportOfficeData extends ContextBasedTest {
                 {
                     2000000=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
                     2000001=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
-                    2000002=rel(anchor='NP Mellies, Michael', type='DEBITOR', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
-                    2000003=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
-                    2000004=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
-                    2000005=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
-                    2000006=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
-                    2000007=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
-                    2000008=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
-                    2000009=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'),
-                    2000010=rel(anchor='null null, null', type='DEBITOR'),
-                    2000011=rel(anchor='null null, null', type='DEBITOR'),
-                    2000012=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
-                    2000013=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
-                    2000014=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'),
-                    2000015=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
-                    2000016=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
-                    2000017=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
-                    2000018=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
-                    2000019=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
-                    2000020=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
-                    2000021=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
-                    2000022=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
-                    2000023=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
-2000024=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ')
+                    2000002=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
+                    2000003=rel(anchor='LP JM GmbH', type='DEBITOR', holder='LP JM GmbH', contact='Frau Dr. Jenny Meyer-Billing , JM GmbH'),
+                    2000004=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
+                    2000005=rel(anchor='?? Test PS', type='DEBITOR', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
+                    2000006=rel(anchor='LP Hostsharing eG', type='PARTNER', holder='null null, null'),
+                    2000007=rel(anchor='null null, null', type='DEBITOR'),
+                    2000008=rel(anchor='NP Mellies, Michael', type='OPERATIONS', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
+                    2000009=rel(anchor='NP Mellies, Michael', type='REPRESENTATIVE', holder='NP Mellies, Michael', contact='Herr Michael Mellies '),
+                    2000010=rel(anchor='LP JM GmbH', type='EX_PARTNER', holder='LP JM e.K.', contact='JM e.K.'),
+                    2000011=rel(anchor='LP JM GmbH', type='OPERATIONS', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
+                    2000012=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
+                    2000013=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='operations-announce', holder='LP JM GmbH', contact='Herr Andrew Meyer-Operation , JM GmbH'),
+                    2000014=rel(anchor='LP JM GmbH', type='REPRESENTATIVE', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
+                    2000015=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='members-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
+                    2000016=rel(anchor='LP JM GmbH', type='SUBSCRIBER', mark='customers-announce', holder='LP JM GmbH', contact='Herr Philip Meyer-Contract , JM GmbH'),
+                    2000017=rel(anchor='LP JM GmbH', type='VIP_CONTACT', holder='LP JM GmbH', contact='Frau Tammy Meyer-VIP , JM GmbH'),
+                    2000018=rel(anchor='?? Test PS', type='OPERATIONS', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
+                    2000019=rel(anchor='?? Test PS', type='REPRESENTATIVE', holder='?? Test PS', contact='Petra Schmidt , Test PS'),
+                    2000020=rel(anchor='NP Mellies, Michael', type='SUBSCRIBER', mark='operations-announce', holder='NP Fanninga, Frauke', contact='Frau Frauke Fanninga ')
                 }
                 """);
     }
@@ -425,14 +404,33 @@ public class ImportOfficeData extends ContextBasedTest {
     }
 
     @Test
-    @Order(2009)
+    @Order(3001)
+    void removeSelfRepresentativeRelations() {
+        assumeThatWeAreImportingControlledTestData();
+
+        // this happens if a natural person is marked as 'contractual' for itself
+        final var idsToRemove = new HashSet<Integer>();
+        relations.forEach( (id, r) -> {
+            if (r.getHolder() == r.getAnchor() ) {
+                idsToRemove.add(id);
+            }
+        });
+
+        // remove self-representatives
+        idsToRemove.forEach(id -> {
+            System.out.println("removing self representative relation: " + relations.get(id).toString());
+            relations.remove(id);
+        });
+    }
+
+    @Test
+    @Order(3002)
     void removeEmptyRelations() {
         assumeThatWeAreImportingControlledTestData();
 
         // avoid a error when persisting the deliberately invalid partner entry #99
         final var idsToRemove = new HashSet<Integer>();
         relations.forEach( (id, r) -> {
-            // such a record
             if (r.getContact() == null || r.getContact().getLabel() == null ||
                r.getHolder() == null || r.getHolder().getPersonType() == null ) {
                 idsToRemove.add(id);
@@ -447,7 +445,7 @@ public class ImportOfficeData extends ContextBasedTest {
     }
 
     @Test
-    @Order(2002)
+    @Order(3003)
     void removeEmptyPartners() {
         assumeThatWeAreImportingControlledTestData();
 
@@ -471,7 +469,7 @@ public class ImportOfficeData extends ContextBasedTest {
     }
 
     @Test
-    @Order(2003)
+    @Order(3004)
     void removeEmptyDebitors() {
         assumeThatWeAreImportingControlledTestData();
 
@@ -490,7 +488,7 @@ public class ImportOfficeData extends ContextBasedTest {
     }
 
     @Test
-    @Order(3000)
+    @Order(9000)
     @Commit
     void persistEntities() {
 
@@ -516,6 +514,7 @@ public class ImportOfficeData extends ContextBasedTest {
             relations.forEach(this::persist);
         }).assertSuccessful();
 
+        System.out.println("persisting " + partners.size() + " partners");
         jpaAttempt.transacted(() -> {
             context(rbacSuperuser);
             partners.forEach((id, partner) -> {
@@ -533,7 +532,7 @@ public class ImportOfficeData extends ContextBasedTest {
             context(rbacSuperuser);
             debitors.forEach((id, debitor) -> {
                 debitor.setDebitorRel(em.merge(debitor.getDebitorRel()));
-                em.persist(debitor);
+                persist(id, debitor);
             });
         }).assertSuccessful();
 
@@ -721,7 +720,6 @@ public class ImportOfficeData extends ContextBasedTest {
                             null, // will be set in contacts import
                             null // will beset in contacts import
                     );
-                    relations.put(relationId++, debitorRel);
 
                     final var debitor = HsOfficeDebitorEntity.builder()
                             .debitorNumberSuffix("00")
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java
index 98bff812..c1d3fbc3 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/partner/HsOfficePartnerRepositoryIntegrationTest.java
@@ -10,7 +10,6 @@ import net.hostsharing.hsadminng.hs.office.test.ContextBasedTestWithCleanup;
 import net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantRepository;
 import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacObjectRepository;
 import net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleRepository;
-import net.hostsharing.test.Array;
 import net.hostsharing.test.JpaAttempt;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Nested;
@@ -25,13 +24,13 @@ import jakarta.persistence.EntityManager;
 import jakarta.persistence.PersistenceContext;
 import jakarta.servlet.http.HttpServletRequest;
 import java.util.Arrays;
-import java.util.HashSet;
 import java.util.List;
+import java.util.Objects;
 
 import static net.hostsharing.hsadminng.rbac.rbacgrant.RawRbacGrantEntity.distinctGrantDisplaysOf;
 import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacObjectEntity.objectDisplaysOf;
 import static net.hostsharing.hsadminng.rbac.rbacrole.RawRbacRoleEntity.distinctRoleNamesOf;
-import static net.hostsharing.test.Array.fromFormatted;
+import static net.hostsharing.test.Array.from;
 import static net.hostsharing.test.JpaAttempt.attempt;
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -130,7 +129,7 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
             }).assertSuccessful();
 
             // then
-            assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(Array.from(
+            assertThat(distinctRoleNamesOf(rawRoleRepo.findAll())).containsExactlyInAnyOrder(from(
                     initialRoleNames,
                     "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:OWNER",
                     "hs_office_relation#HostsharingeG-with-PARTNER-ErbenBesslerMelBessler:ADMIN",
@@ -140,44 +139,43 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
                     .map(s -> s.replace("ErbenBesslerMelBessler", "EBess"))
                     .map(s -> s.replace("fourthcontact", "4th"))
                     .map(s -> s.replace("hs_office_", ""))
-                    .containsExactlyInAnyOrder(distinct(fromFormatted(
+                    .containsExactlyInAnyOrder(distinct(from(
                             initialGrantNames,
-                            "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:INSERT>sepamandate  to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
+                            "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:INSERT>sepamandate to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
 
                             // permissions on partner
-                            "{ grant perm:partner#P-20032:DELETE                            to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
-                            "{ grant perm:partner#P-20032:UPDATE                            to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
-                            "{ grant perm:partner#P-20032:SELECT                            to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
+                            "{ grant perm:partner#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
+                            "{ grant perm:partner#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
+                            "{ grant perm:partner#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
 
                             // permissions on partner-details
-                            "{ grant perm:partner_details#P-20032:DELETE                    to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
-                            "{ grant perm:partner_details#P-20032:UPDATE                    to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
-                            "{ grant perm:partner_details#P-20032:SELECT                    to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
+                            "{ grant perm:partner_details#P-20032:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
+                            "{ grant perm:partner_details#P-20032:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
+                            "{ grant perm:partner_details#P-20032:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
 
                             // permissions on partner-relation
-                            "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:DELETE  to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
-                            "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:UPDATE  to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
-                            "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:SELECT  to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
+                            "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:DELETE to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
+                            "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:UPDATE to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
+                            "{ grant perm:relation#HostsharingeG-with-PARTNER-EBess:SELECT to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
 
                             // relation owner
-                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER   to role:global#global:ADMIN by system and assume }",
-                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER   to user:superuser-alex@hostsharing.net by relation#HostsharingeG-with-PARTNER-EBess:OWNER and assume }",
+                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to role:global#global:ADMIN by system and assume }",
+                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to user:superuser-alex@hostsharing.net by relation#HostsharingeG-with-PARTNER-EBess:OWNER and assume }",
 
                             // relation admin
-                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN   to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
-                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN   to role:person#HostsharingeG:ADMIN by system and assume }",
+                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN to role:relation#HostsharingeG-with-PARTNER-EBess:OWNER by system and assume }",
+                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:OWNER to role:person#HostsharingeG:ADMIN by system and assume }",
 
                             // relation agent
-                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT   to role:person#EBess:ADMIN by system and assume }",
-                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT   to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
+                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:person#EBess:ADMIN by system and assume }",
+                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:AGENT to role:relation#HostsharingeG-with-PARTNER-EBess:ADMIN by system and assume }",
 
                             // relation tenant
-                            "{ grant role:contact#4th:REFERRER                              to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
-                            "{ grant role:person#EBess:REFERRER                             to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
-                            "{ grant role:person#HostsharingeG:REFERRER                     to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
-                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT  to role:contact#4th:ADMIN by system and assume }",
-                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT  to role:person#EBess:ADMIN by system and assume }",
-                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT  to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
+                            "{ grant role:contact#4th:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
+                            "{ grant role:person#EBess:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
+                            "{ grant role:person#HostsharingeG:REFERRER to role:relation#HostsharingeG-with-PARTNER-EBess:TENANT by system and assume }",
+                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:contact#4th:ADMIN by system and assume }",
+                            "{ grant role:relation#HostsharingeG-with-PARTNER-EBess:TENANT to role:relation#HostsharingeG-with-PARTNER-EBess:AGENT by system and assume }",
                             null)));
         }
 
@@ -411,9 +409,9 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
         public void deletingAPartnerAlsoDeletesRelatedRolesAndGrants() {
             // given
             context("superuser-alex@hostsharing.net");
-            final var initialObjects = Array.from(objectDisplaysOf(rawObjectRepo.findAll()));
-            final var initialRoleNames = Array.from(distinctRoleNamesOf(rawRoleRepo.findAll()));
-            final var initialGrantNames = Array.from(distinctGrantDisplaysOf(rawGrantRepo.findAll()));
+            final var initialObjects = from(objectDisplaysOf(rawObjectRepo.findAll()));
+            final var initialRoleNames = from(distinctRoleNamesOf(rawRoleRepo.findAll()));
+            final var initialGrantNames = from(distinctGrantDisplaysOf(rawGrantRepo.findAll()));
             final var givenPartner = givenSomeTemporaryHostsharingPartner(20034, "Erben Bessler", "twelfth");
 
             // when
@@ -499,8 +497,6 @@ class HsOfficePartnerRepositoryIntegrationTest extends ContextBasedTestWithClean
 
     private String[] distinct(final String[] strings) {
         // TODO: alternatively cleanup all rbac objects in @AfterEach?
-        final var set = new HashSet<String>();
-        set.addAll(List.of(strings));
-        return set.toArray(new String[0]);
+        return Arrays.stream(strings).filter(Objects::nonNull).distinct().toList().toArray(new String[0]);
     }
 }
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationControllerAcceptanceTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationControllerAcceptanceTest.java
index 78d64e6a..54218b67 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationControllerAcceptanceTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationControllerAcceptanceTest.java
@@ -362,7 +362,7 @@ class HsOfficeRelationControllerAcceptanceTest extends ContextBasedTestWithClean
             assertThat(givenRelation.getContact().getLabel()).isEqualTo("seventh contact");
             final var givenContact = contactRepo.findContactByOptionalLabelLike("fourth").get(0);
 
-            final var location = RestAssured // @formatter:off
+            RestAssured // @formatter:off
                 .given()
                     .header("current-user", "superuser-alex@hostsharing.net")
                     .contentType(ContentType.JSON)
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java
index f474de0c..77342f0d 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/relation/HsOfficeRelationRepositoryIntegrationTest.java
@@ -140,9 +140,10 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
 
                     "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:UPDATE to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }",
                     "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER by system and assume }",
-                    "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }",
+                    "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:OWNER to role:hs_office_person#BesslerBert:ADMIN by system and assume }",
+                    "{ grant role:hs_office_person#ErbenBesslerMelBessler:OWNER to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }",
 
-                    "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_person#BesslerBert:ADMIN by system and assume }",
+                    "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_person#ErbenBesslerMelBessler:ADMIN by system and assume }",
                     "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:AGENT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:ADMIN by system and assume }",
 
                     "{ grant perm:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:SELECT to role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT by system and assume }",
@@ -153,8 +154,6 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
 
                     // REPRESENTATIVE holder person -> (represented) anchor person
                     "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_contact#fourthcontact:ADMIN by system and assume }",
-                    "{ grant role:hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerBert:TENANT to role:hs_office_person#BesslerBert:ADMIN by system and assume }",
-
                     null)
             );
         }
@@ -217,10 +216,10 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
             context("superuser-alex@hostsharing.net");
             final var givenRelation = givenSomeTemporaryRelationBessler(
                     "Bert", "fifth contact");
+            assertThatRelationActuallyInDatabase(givenRelation);
             assertThatRelationIsVisibleForUserWithRole(
                     givenRelation,
                     "hs_office_person#ErbenBesslerMelBessler:ADMIN");
-            assertThatRelationActuallyInDatabase(givenRelation);
             context("superuser-alex@hostsharing.net");
             final var givenContact = contactRepo.findContactByOptionalLabelLike("sixth contact").stream().findFirst().orElseThrow();
 
@@ -249,19 +248,19 @@ class HsOfficeRelationRepositoryIntegrationTest extends ContextBasedTestWithClea
         }
 
         @Test
-        public void holderAdmin_canNotUpdateRelatedRelation() {
+        public void relationAgent_canSelectButNotUpdateRelatedRelation() {
             // given
             context("superuser-alex@hostsharing.net");
             final var givenRelation = givenSomeTemporaryRelationBessler(
                     "Anita", "eighth");
             assertThatRelationIsVisibleForUserWithRole(
                     givenRelation,
-                    "hs_office_person#BesslerAnita:ADMIN");
+                    "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerAnita:AGENT");
             assertThatRelationActuallyInDatabase(givenRelation);
 
             // when
             final var result = jpaAttempt.transacted(() -> {
-                context("superuser-alex@hostsharing.net", "hs_office_person#BesslerAnita:ADMIN");
+                context("superuser-alex@hostsharing.net", "hs_office_relation#ErbenBesslerMelBessler-with-REPRESENTATIVE-BesslerAnita:AGENT");
                 givenRelation.setContact(null);
                 return relationRepo.save(givenRelation);
             });
diff --git a/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java b/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java
index fc0b81c3..64feda26 100644
--- a/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java
+++ b/src/test/java/net/hostsharing/hsadminng/hs/office/test/ContextBasedTestWithCleanup.java
@@ -17,7 +17,6 @@ import org.springframework.data.jpa.repository.Query;
 import org.springframework.data.repository.Repository;
 
 import jakarta.persistence.*;
-import java.lang.reflect.Method;
 import java.util.*;
 
 import static java.lang.System.out;
@@ -272,12 +271,11 @@ public abstract class ContextBasedTestWithCleanup extends ContextBasedTest {
     /**
      * Generates a diagram of the RBAC-Grants to the current subjects (user or assumed roles).
      */
-    protected void generateRbacDiagramForCurrentSubjects(final EnumSet<RbacGrantsDiagramService.Include> include) {
-        final var title = testInfo.getTestMethod().map(Method::getName).orElseThrow();
+    protected void generateRbacDiagramForCurrentSubjects(final EnumSet<RbacGrantsDiagramService.Include> include, final String name) {
         RbacGrantsDiagramService.writeToFile(
-                title,
+                name,
                 diagramService.allGrantsToCurrentUser(include),
-                "doc/" + title + ".md"
+                "doc/temp/" + name + ".md"
         );
     }