< Summary - Heimdall API

Line coverage
100%
Covered lines: 1076
Uncovered lines: 0
Coverable lines: 1076
Total lines: 1182
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage
100%
Covered methods: 3
Fully covered methods: 3
Total methods: 3
Method coverage: 100%
Full method coverage: 100%

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: Up(...)100%11100%
File 1: Down(...)100%11100%
File 2: BuildTargetModel(...)100%11100%

File(s)

/home/ci/agent/workspace/heimdall-api-docs_main/app/src/Infrastructure/ArturRios.Heimdall.Data/Migrations/20260909182313_AllowClearingAuditActor.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore.Migrations;
 2
 3#nullable disable
 4
 5namespace ArturRios.Heimdall.Data.Migrations
 6{
 7    /// <summary>
 8    ///     Narrows the audit log's append-only rule by exactly one permitted change: the actor
 9    ///     attribution may be cleared once it is due (NFR-21).
 10    /// </summary>
 11    /// <remarks>
 12    ///     <para>
 13    ///         `MakeAuditLogAppendOnly` refused every UPDATE, DELETE and TRUNCATE, which closed
 14    ///         Threat Model TH-18 and also made erasure impossible: `actor_person_id` holds a
 15    ///         person's `PublicId`, so an indefinitely retained, unalterable row naming an erased
 16    ///         person is personal data processed with no remaining basis.
 17    ///     </para>
 18    ///     <para>
 19    ///         Rather than dropping the guarantee, this narrows it. DELETE and TRUNCATE stay refused
 20    ///         outright. UPDATE becomes row-level and is permitted only when every column except
 21    ///         `actor_person_id` and `actor_role` is unchanged, the attribution is being set to
 22    ///         NULL rather than to somebody else, and the clearing is due. The resulting rule is
 23    ///         precise: <b>an action can never be denied, and who took it can never be reassigned —
 24    ///         only forgotten, on schedule or on erasure.</b>
 25    ///     </para>
 26    ///     <para>
 27    ///         "Due" means the entry is older than a thirty-day floor, or the identity it names has
 28    ///         been anonymised. The floor is an anti-tamper backstop rather than a retention policy:
 29    ///         the retention period is configuration and is far longer, and the floor exists so that
 30    ///         somebody who has just acted cannot immediately erase their own attribution. The
 31    ///         erasure branch carries no age condition, because a subject-requested erasure completes
 32    ///         thirty days after the request and their most recent entries must go with them.
 33    ///     </para>
 34    /// </remarks>
 35    public partial class AllowClearingAuditActor : Migration
 36    {
 37        /// <inheritdoc />
 38        protected override void Up(MigrationBuilder migrationBuilder)
 39        {
 1940            migrationBuilder.Sql(
 1941                """
 1942                CREATE OR REPLACE FUNCTION heimdall.audit_log_actor_clear_only()
 1943                RETURNS TRIGGER AS $$
 1944                DECLARE
 1945                    actor_erased boolean;
 1946                BEGIN
 1947                    -- Everything but the attribution is immutable. Checked first, so an attempt to
 1948                    -- rewrite what happened is refused with that reason rather than a later one.
 1949                    IF NEW.public_id IS DISTINCT FROM OLD.public_id
 1950                       OR NEW.action IS DISTINCT FROM OLD.action
 1951                       OR NEW.target_id IS DISTINCT FROM OLD.target_id
 1952                       OR NEW.succeeded IS DISTINCT FROM OLD.succeeded
 1953                       OR NEW.failure_reason IS DISTINCT FROM OLD.failure_reason
 1954                       OR NEW.created_at IS DISTINCT FROM OLD.created_at
 1955                    THEN
 1956                        RAISE EXCEPTION
 1957                            'heimdall.audit_log is append-only: only the actor attribution may be cleared'
 1958                            USING ERRCODE = 'restrict_violation';
 1959                    END IF;
 1960
 1961                    -- Cleared, never reassigned. Without this the trail could be made to say that
 1962                    -- somebody else took the action, which is worse than it not saying who did.
 1963                    IF NEW.actor_person_id IS NOT NULL OR NEW.actor_role IS NOT NULL THEN
 1964                        RAISE EXCEPTION
 1965                            'heimdall.audit_log actor attribution may be cleared but not reassigned'
 1966                            USING ERRCODE = 'restrict_violation';
 1967                    END IF;
 1968
 1969                    -- Already clear: a no-op write, permitted so a re-run is not an error.
 1970                    IF OLD.actor_person_id IS NULL AND OLD.actor_role IS NULL THEN
 1971                        RETURN NEW;
 1972                    END IF;
 1973
 1974                    SELECT EXISTS (
 1975                        SELECT 1 FROM heimdall.person p
 1976                        WHERE p.public_id = OLD.actor_person_id AND p.anonymised_at IS NOT NULL
 1977                        UNION ALL
 1978                        SELECT 1 FROM heimdall.google_user g
 1979                        WHERE g.public_id = OLD.actor_person_id AND g.anonymised_at IS NOT NULL
 1980                    ) INTO actor_erased;
 1981
 1982                    IF actor_erased OR OLD.created_at <= now() - interval '30 days' THEN
 1983                        RETURN NEW;
 1984                    END IF;
 1985
 1986                    RAISE EXCEPTION
 1987                        'heimdall.audit_log actor attribution is not yet due to be cleared'
 1988                        USING ERRCODE = 'restrict_violation';
 1989                END;
 1990                $$ LANGUAGE plpgsql;
 1991                """);
 92
 93            // The statement-level UPDATE trigger goes: the rule is now about which row-level change
 94            // is being made, which a statement-level trigger cannot see.
 1995            migrationBuilder.Sql("DROP TRIGGER IF EXISTS audit_log_no_update ON heimdall.audit_log;");
 96
 1997            migrationBuilder.Sql(
 1998                """
 1999                CREATE TRIGGER audit_log_actor_clear_only
 19100                BEFORE UPDATE ON heimdall.audit_log
 19101                FOR EACH ROW EXECUTE FUNCTION heimdall.audit_log_actor_clear_only();
 19102                """);
 19103        }
 104
 105        /// <inheritdoc />
 106        protected override void Down(MigrationBuilder migrationBuilder)
 107        {
 1108            migrationBuilder.Sql(
 1109                "DROP TRIGGER IF EXISTS audit_log_actor_clear_only ON heimdall.audit_log;");
 1110            migrationBuilder.Sql(
 1111                "DROP FUNCTION IF EXISTS heimdall.audit_log_actor_clear_only();");
 112
 113            // Back to refusing every UPDATE.
 1114            migrationBuilder.Sql(
 1115                """
 1116                CREATE TRIGGER audit_log_no_update
 1117                BEFORE UPDATE ON heimdall.audit_log
 1118                FOR EACH STATEMENT EXECUTE FUNCTION heimdall.audit_log_is_append_only();
 1119                """);
 1120        }
 121    }
 122}

/home/ci/agent/workspace/heimdall-api-docs_main/app/src/Infrastructure/ArturRios.Heimdall.Data/Migrations/20260909182313_AllowClearingAuditActor.Designer.cs

#LineLine coverage
 1// <auto-generated />
 2using System;
 3using ArturRios.Heimdall.Data.Configuration;
 4using Microsoft.EntityFrameworkCore;
 5using Microsoft.EntityFrameworkCore.Infrastructure;
 6using Microsoft.EntityFrameworkCore.Migrations;
 7using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
 8using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
 9
 10#nullable disable
 11
 12namespace ArturRios.Heimdall.Data.Migrations
 13{
 14    [DbContext(typeof(AppDbContext))]
 15    [Migration("20260909182313_AllowClearingAuditActor")]
 16    partial class AllowClearingAuditActor
 17    {
 18        /// <inheritdoc />
 19        protected override void BuildTargetModel(ModelBuilder modelBuilder)
 20        {
 21#pragma warning disable 612, 618
 1022            modelBuilder
 1023                .HasDefaultSchema("heimdall")
 1024                .HasAnnotation("ProductVersion", "10.0.11")
 1025                .HasAnnotation("Relational:MaxIdentifierLength", 63);
 26
 1027            NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
 28
 1029            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.Application", b =>
 1030                {
 1031                    b.Property<long>("Id")
 1032                        .ValueGeneratedOnAdd()
 1033                        .HasColumnType("bigint")
 1034                        .HasColumnName("id")
 1035                        .HasColumnOrder(1);
 1036
 1037                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 1038
 1039                    b.Property<DateTime>("CreatedAt")
 1040                        .ValueGeneratedOnAdd()
 1041                        .HasColumnType("timestamp with time zone")
 1042                        .HasColumnName("created_at")
 1043                        .HasDefaultValueSql("now()");
 1044
 1045                    b.Property<bool>("IsDeleted")
 1046                        .ValueGeneratedOnAdd()
 1047                        .HasColumnType("boolean")
 1048                        .HasDefaultValue(false)
 1049                        .HasColumnName("is_deleted");
 1050
 1051                    b.Property<string>("Name")
 1052                        .IsRequired()
 1053                        .HasMaxLength(200)
 1054                        .HasColumnType("character varying(200)")
 1055                        .HasColumnName("name");
 1056
 1057                    b.Property<long>("OwnerId")
 1058                        .HasColumnType("bigint")
 1059                        .HasColumnName("owner_id");
 1060
 1061                    b.Property<Guid>("PublicId")
 1062                        .HasColumnType("uuid")
 1063                        .HasColumnName("public_id");
 1064
 1065                    b.Property<long>("ScopeId")
 1066                        .HasColumnType("bigint")
 1067                        .HasColumnName("scope_id");
 1068
 1069                    b.Property<DateTime>("UpdatedAt")
 1070                        .ValueGeneratedOnAdd()
 1071                        .HasColumnType("timestamp with time zone")
 1072                        .HasColumnName("updated_at")
 1073                        .HasDefaultValueSql("now()");
 1074
 1075                    b.HasKey("Id")
 1076                        .HasName("pk_application");
 1077
 1078                    b.HasIndex("OwnerId")
 1079                        .HasDatabaseName("ix_application_owner_id");
 1080
 1081                    b.HasIndex("PublicId")
 1082                        .IsUnique()
 1083                        .HasDatabaseName("ix_application_public_id");
 1084
 1085                    b.HasIndex("ScopeId")
 1086                        .HasDatabaseName("ix_application_scope_id");
 1087
 1088                    b.ToTable("application", "heimdall");
 2089                });
 90
 1091            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.AuditLog", b =>
 1092                {
 1093                    b.Property<long>("Id")
 1094                        .ValueGeneratedOnAdd()
 1095                        .HasColumnType("bigint")
 1096                        .HasColumnName("id")
 1097                        .HasColumnOrder(1);
 1098
 1099                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 10100
 10101                    b.Property<string>("Action")
 10102                        .IsRequired()
 10103                        .HasMaxLength(200)
 10104                        .HasColumnType("character varying(200)")
 10105                        .HasColumnName("action");
 10106
 10107                    b.Property<Guid?>("ActorPersonId")
 10108                        .HasColumnType("uuid")
 10109                        .HasColumnName("actor_person_id");
 10110
 10111                    b.Property<int?>("ActorRole")
 10112                        .HasColumnType("integer")
 10113                        .HasColumnName("actor_role");
 10114
 10115                    b.Property<DateTime>("CreatedAt")
 10116                        .ValueGeneratedOnAdd()
 10117                        .HasColumnType("timestamp with time zone")
 10118                        .HasColumnName("created_at")
 10119                        .HasDefaultValueSql("now()");
 10120
 10121                    b.Property<string>("FailureReason")
 10122                        .HasMaxLength(500)
 10123                        .HasColumnType("character varying(500)")
 10124                        .HasColumnName("failure_reason");
 10125
 10126                    b.Property<Guid>("PublicId")
 10127                        .HasColumnType("uuid")
 10128                        .HasColumnName("public_id");
 10129
 10130                    b.Property<bool>("Succeeded")
 10131                        .HasColumnType("boolean")
 10132                        .HasColumnName("succeeded");
 10133
 10134                    b.Property<Guid?>("TargetId")
 10135                        .HasColumnType("uuid")
 10136                        .HasColumnName("target_id");
 10137
 10138                    b.HasKey("Id")
 10139                        .HasName("pk_audit_log");
 10140
 10141                    b.HasIndex("ActorPersonId")
 10142                        .HasDatabaseName("ix_audit_log_actor_person_id");
 10143
 10144                    b.HasIndex("CreatedAt")
 10145                        .HasDatabaseName("ix_audit_log_created_at");
 10146
 10147                    b.HasIndex("PublicId")
 10148                        .IsUnique()
 10149                        .HasDatabaseName("ix_audit_log_public_id");
 10150
 10151                    b.ToTable("audit_log", "heimdall");
 20152                });
 153
 10154            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.EmailVerificationToken", b =>
 10155                {
 10156                    b.Property<long>("Id")
 10157                        .ValueGeneratedOnAdd()
 10158                        .HasColumnType("bigint")
 10159                        .HasColumnName("id")
 10160                        .HasColumnOrder(1);
 10161
 10162                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 10163
 10164                    b.Property<DateTime>("ExpiresAt")
 10165                        .HasColumnType("timestamp with time zone")
 10166                        .HasColumnName("expires_at");
 10167
 10168                    b.Property<long>("PersonId")
 10169                        .HasColumnType("bigint")
 10170                        .HasColumnName("person_id");
 10171
 10172                    b.Property<string>("TokenHash")
 10173                        .IsRequired()
 10174                        .HasMaxLength(64)
 10175                        .HasColumnType("character varying(64)")
 10176                        .HasColumnName("token_hash");
 10177
 10178                    b.Property<bool>("Used")
 10179                        .ValueGeneratedOnAdd()
 10180                        .HasColumnType("boolean")
 10181                        .HasDefaultValue(false)
 10182                        .HasColumnName("used");
 10183
 10184                    b.HasKey("Id")
 10185                        .HasName("pk_email_verification_token");
 10186
 10187                    b.HasIndex("PersonId")
 10188                        .HasDatabaseName("ix_email_verification_token_person_id");
 10189
 10190                    b.HasIndex("TokenHash")
 10191                        .IsUnique()
 10192                        .HasDatabaseName("ix_email_verification_token_token_hash");
 10193
 10194                    b.ToTable("email_verification_token", "heimdall");
 20195                });
 196
 10197            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.GoogleUser", b =>
 10198                {
 10199                    b.Property<long>("Id")
 10200                        .ValueGeneratedOnAdd()
 10201                        .HasColumnType("bigint")
 10202                        .HasColumnName("id")
 10203                        .HasColumnOrder(1);
 10204
 10205                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 10206
 10207                    b.Property<DateTime?>("AnonymisedAt")
 10208                        .HasColumnType("timestamp with time zone")
 10209                        .HasColumnName("anonymised_at");
 10210
 10211                    b.Property<DateTime>("CreatedAt")
 10212                        .ValueGeneratedOnAdd()
 10213                        .HasColumnType("timestamp with time zone")
 10214                        .HasColumnName("created_at")
 10215                        .HasDefaultValueSql("now()");
 10216
 10217                    b.Property<DateTime?>("DeletedAt")
 10218                        .HasColumnType("timestamp with time zone")
 10219                        .HasColumnName("deleted_at");
 10220
 10221                    b.Property<int?>("DeletionKind")
 10222                        .HasColumnType("integer")
 10223                        .HasColumnName("deletion_kind");
 10224
 10225                    b.Property<string>("Email")
 10226                        .IsRequired()
 10227                        .HasMaxLength(256)
 10228                        .HasColumnType("character varying(256)")
 10229                        .HasColumnName("email");
 10230
 10231                    b.Property<bool>("EmailVerified")
 10232                        .ValueGeneratedOnAdd()
 10233                        .HasColumnType("boolean")
 10234                        .HasDefaultValue(false)
 10235                        .HasColumnName("email_verified");
 10236
 10237                    b.Property<string>("ErasureBlockedReason")
 10238                        .HasMaxLength(500)
 10239                        .HasColumnType("character varying(500)")
 10240                        .HasColumnName("erasure_blocked_reason");
 10241
 10242                    b.Property<DateTime?>("ErasureDueAt")
 10243                        .HasColumnType("timestamp with time zone")
 10244                        .HasColumnName("erasure_due_at");
 10245
 10246                    b.Property<DateTime?>("ErasureRequestedAt")
 10247                        .HasColumnType("timestamp with time zone")
 10248                        .HasColumnName("erasure_requested_at");
 10249
 10250                    b.Property<string>("GoogleId")
 10251                        .IsRequired()
 10252                        .HasMaxLength(255)
 10253                        .HasColumnType("character varying(255)")
 10254                        .HasColumnName("google_id");
 10255
 10256                    b.Property<bool>("IsDeleted")
 10257                        .ValueGeneratedOnAdd()
 10258                        .HasColumnType("boolean")
 10259                        .HasDefaultValue(false)
 10260                        .HasColumnName("is_deleted");
 10261
 10262                    b.Property<string>("Name")
 10263                        .IsRequired()
 10264                        .HasMaxLength(200)
 10265                        .HasColumnType("character varying(200)")
 10266                        .HasColumnName("name");
 10267
 10268                    b.Property<string>("ProfilePictureUrl")
 10269                        .HasMaxLength(2048)
 10270                        .HasColumnType("character varying(2048)")
 10271                        .HasColumnName("profile_picture_url");
 10272
 10273                    b.Property<Guid>("PublicId")
 10274                        .HasColumnType("uuid")
 10275                        .HasColumnName("public_id");
 10276
 10277                    b.Property<long>("ScopeId")
 10278                        .HasColumnType("bigint")
 10279                        .HasColumnName("scope_id");
 10280
 10281                    b.Property<DateTime>("UpdatedAt")
 10282                        .ValueGeneratedOnAdd()
 10283                        .HasColumnType("timestamp with time zone")
 10284                        .HasColumnName("updated_at")
 10285                        .HasDefaultValueSql("now()");
 10286
 10287                    b.HasKey("Id")
 10288                        .HasName("pk_google_user");
 10289
 10290                    b.HasIndex("DeletedAt")
 10291                        .HasDatabaseName("ix_google_user_deleted_at")
 10292                        .HasFilter("is_deleted = true AND anonymised_at IS NULL");
 10293
 10294                    b.HasIndex("PublicId")
 10295                        .IsUnique()
 10296                        .HasDatabaseName("ix_google_user_public_id");
 10297
 10298                    b.HasIndex("ScopeId", "Email")
 10299                        .IsUnique()
 10300                        .HasDatabaseName("ix_google_user_scope_id_email");
 10301
 10302                    b.HasIndex("ScopeId", "GoogleId")
 10303                        .IsUnique()
 10304                        .HasDatabaseName("ix_google_user_scope_id_google_id");
 10305
 10306                    b.ToTable("google_user", "heimdall");
 20307                });
 308
 10309            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.PasswordResetToken", b =>
 10310                {
 10311                    b.Property<long>("Id")
 10312                        .ValueGeneratedOnAdd()
 10313                        .HasColumnType("bigint")
 10314                        .HasColumnName("id")
 10315                        .HasColumnOrder(1);
 10316
 10317                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 10318
 10319                    b.Property<DateTime>("ExpiresAt")
 10320                        .HasColumnType("timestamp with time zone")
 10321                        .HasColumnName("expires_at");
 10322
 10323                    b.Property<long>("PersonId")
 10324                        .HasColumnType("bigint")
 10325                        .HasColumnName("person_id");
 10326
 10327                    b.Property<string>("TokenHash")
 10328                        .IsRequired()
 10329                        .HasMaxLength(64)
 10330                        .HasColumnType("character varying(64)")
 10331                        .HasColumnName("token_hash");
 10332
 10333                    b.Property<bool>("Used")
 10334                        .ValueGeneratedOnAdd()
 10335                        .HasColumnType("boolean")
 10336                        .HasDefaultValue(false)
 10337                        .HasColumnName("used");
 10338
 10339                    b.HasKey("Id")
 10340                        .HasName("pk_password_reset_token");
 10341
 10342                    b.HasIndex("PersonId")
 10343                        .HasDatabaseName("ix_password_reset_token_person_id");
 10344
 10345                    b.HasIndex("TokenHash")
 10346                        .IsUnique()
 10347                        .HasDatabaseName("ix_password_reset_token_token_hash");
 10348
 10349                    b.ToTable("password_reset_token", "heimdall");
 20350                });
 351
 10352            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.Person", b =>
 10353                {
 10354                    b.Property<long>("Id")
 10355                        .ValueGeneratedOnAdd()
 10356                        .HasColumnType("bigint")
 10357                        .HasColumnName("id")
 10358                        .HasColumnOrder(1);
 10359
 10360                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 10361
 10362                    b.Property<DateTime?>("AnonymisedAt")
 10363                        .HasColumnType("timestamp with time zone")
 10364                        .HasColumnName("anonymised_at");
 10365
 10366                    b.Property<DateTime>("CreatedAt")
 10367                        .ValueGeneratedOnAdd()
 10368                        .HasColumnType("timestamp with time zone")
 10369                        .HasColumnName("created_at")
 10370                        .HasDefaultValueSql("now()");
 10371
 10372                    b.Property<DateTime?>("DeletedAt")
 10373                        .HasColumnType("timestamp with time zone")
 10374                        .HasColumnName("deleted_at");
 10375
 10376                    b.Property<int?>("DeletionKind")
 10377                        .HasColumnType("integer")
 10378                        .HasColumnName("deletion_kind");
 10379
 10380                    b.Property<string>("Email")
 10381                        .IsRequired()
 10382                        .HasMaxLength(256)
 10383                        .HasColumnType("character varying(256)")
 10384                        .HasColumnName("email");
 10385
 10386                    b.Property<bool>("EmailVerified")
 10387                        .ValueGeneratedOnAdd()
 10388                        .HasColumnType("boolean")
 10389                        .HasDefaultValue(false)
 10390                        .HasColumnName("email_verified");
 10391
 10392                    b.Property<string>("ErasureBlockedReason")
 10393                        .HasMaxLength(500)
 10394                        .HasColumnType("character varying(500)")
 10395                        .HasColumnName("erasure_blocked_reason");
 10396
 10397                    b.Property<DateTime?>("ErasureDueAt")
 10398                        .HasColumnType("timestamp with time zone")
 10399                        .HasColumnName("erasure_due_at");
 10400
 10401                    b.Property<DateTime?>("ErasureRequestedAt")
 10402                        .HasColumnType("timestamp with time zone")
 10403                        .HasColumnName("erasure_requested_at");
 10404
 10405                    b.Property<int>("FailedLoginAttempts")
 10406                        .HasColumnType("integer")
 10407                        .HasColumnName("failed_login_attempts");
 10408
 10409                    b.Property<bool>("IsDeleted")
 10410                        .ValueGeneratedOnAdd()
 10411                        .HasColumnType("boolean")
 10412                        .HasDefaultValue(false)
 10413                        .HasColumnName("is_deleted");
 10414
 10415                    b.Property<DateTime?>("LockedOutUntil")
 10416                        .HasColumnType("timestamp with time zone")
 10417                        .HasColumnName("locked_out_until");
 10418
 10419                    b.Property<string>("Name")
 10420                        .IsRequired()
 10421                        .HasMaxLength(200)
 10422                        .HasColumnType("character varying(200)")
 10423                        .HasColumnName("name");
 10424
 10425                    b.Property<byte[]>("PasswordHash")
 10426                        .IsRequired()
 10427                        .HasColumnType("bytea")
 10428                        .HasColumnName("password_hash");
 10429
 10430                    b.Property<Guid>("PublicId")
 10431                        .HasColumnType("uuid")
 10432                        .HasColumnName("public_id");
 10433
 10434                    b.Property<long>("RoleId")
 10435                        .HasColumnType("bigint")
 10436                        .HasColumnName("role_id");
 10437
 10438                    b.Property<byte[]>("Salt")
 10439                        .IsRequired()
 10440                        .HasColumnType("bytea")
 10441                        .HasColumnName("salt");
 10442
 10443                    b.Property<long?>("ScopeId")
 10444                        .HasColumnType("bigint")
 10445                        .HasColumnName("scope_id");
 10446
 10447                    b.Property<DateTime>("UpdatedAt")
 10448                        .ValueGeneratedOnAdd()
 10449                        .HasColumnType("timestamp with time zone")
 10450                        .HasColumnName("updated_at")
 10451                        .HasDefaultValueSql("now()");
 10452
 10453                    b.HasKey("Id")
 10454                        .HasName("pk_person");
 10455
 10456                    b.HasIndex("DeletedAt")
 10457                        .HasDatabaseName("ix_person_deleted_at")
 10458                        .HasFilter("is_deleted = true AND anonymised_at IS NULL");
 10459
 10460                    b.HasIndex("Email")
 10461                        .HasDatabaseName("ix_person_email");
 10462
 10463                    b.HasIndex("PublicId")
 10464                        .IsUnique()
 10465                        .HasDatabaseName("ix_person_public_id");
 10466
 10467                    b.HasIndex("RoleId")
 10468                        .HasDatabaseName("ix_person_role_id");
 10469
 10470                    b.ToTable("person", "heimdall");
 20471                });
 472
 10473            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.Role", b =>
 10474                {
 10475                    b.Property<long>("Id")
 10476                        .HasColumnType("bigint")
 10477                        .HasColumnName("id")
 10478                        .HasColumnOrder(1);
 10479
 10480                    b.Property<string>("Description")
 10481                        .HasMaxLength(500)
 10482                        .HasColumnType("character varying(500)")
 10483                        .HasColumnName("description");
 10484
 10485                    b.Property<string>("Name")
 10486                        .IsRequired()
 10487                        .HasMaxLength(200)
 10488                        .HasColumnType("character varying(200)")
 10489                        .HasColumnName("name");
 10490
 10491                    b.Property<Guid>("PublicId")
 10492                        .HasColumnType("uuid")
 10493                        .HasColumnName("public_id");
 10494
 10495                    b.HasKey("Id")
 10496                        .HasName("pk_role");
 10497
 10498                    b.HasIndex("Name")
 10499                        .IsUnique()
 10500                        .HasDatabaseName("ix_role_name");
 10501
 10502                    b.HasIndex("PublicId")
 10503                        .IsUnique()
 10504                        .HasDatabaseName("ix_role_public_id");
 10505
 10506                    b.ToTable("role", "heimdall");
 20507                });
 508
 10509            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.Scope", b =>
 10510                {
 10511                    b.Property<long>("Id")
 10512                        .ValueGeneratedOnAdd()
 10513                        .HasColumnType("bigint")
 10514                        .HasColumnName("id")
 10515                        .HasColumnOrder(1);
 10516
 10517                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 10518
 10519                    b.Property<DateTime>("CreatedAt")
 10520                        .ValueGeneratedOnAdd()
 10521                        .HasColumnType("timestamp with time zone")
 10522                        .HasColumnName("created_at")
 10523                        .HasDefaultValueSql("now()");
 10524
 10525                    b.Property<string>("Description")
 10526                        .HasMaxLength(500)
 10527                        .HasColumnType("character varying(500)")
 10528                        .HasColumnName("description");
 10529
 10530                    b.Property<bool>("GoogleSignInEnabled")
 10531                        .ValueGeneratedOnAdd()
 10532                        .HasColumnType("boolean")
 10533                        .HasDefaultValue(false)
 10534                        .HasColumnName("google_sign_in_enabled");
 10535
 10536                    b.Property<bool>("IsDeleted")
 10537                        .ValueGeneratedOnAdd()
 10538                        .HasColumnType("boolean")
 10539                        .HasDefaultValue(false)
 10540                        .HasColumnName("is_deleted");
 10541
 10542                    b.Property<string>("Name")
 10543                        .IsRequired()
 10544                        .HasMaxLength(200)
 10545                        .HasColumnType("character varying(200)")
 10546                        .HasColumnName("name");
 10547
 10548                    b.Property<Guid>("PublicId")
 10549                        .HasColumnType("uuid")
 10550                        .HasColumnName("public_id");
 10551
 10552                    b.Property<DateTime>("UpdatedAt")
 10553                        .ValueGeneratedOnAdd()
 10554                        .HasColumnType("timestamp with time zone")
 10555                        .HasColumnName("updated_at")
 10556                        .HasDefaultValueSql("now()");
 10557
 10558                    b.HasKey("Id")
 10559                        .HasName("pk_scope");
 10560
 10561                    b.HasIndex("Name")
 10562                        .IsUnique()
 10563                        .HasDatabaseName("ix_scope_name");
 10564
 10565                    b.HasIndex("PublicId")
 10566                        .IsUnique()
 10567                        .HasDatabaseName("ix_scope_public_id");
 10568
 10569                    b.ToTable("scope", "heimdall");
 20570                });
 571
 10572            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.ScopeOwner", b =>
 10573                {
 10574                    b.Property<long>("ScopeId")
 10575                        .HasColumnType("bigint")
 10576                        .HasColumnName("scope_id");
 10577
 10578                    b.Property<long>("PersonId")
 10579                        .HasColumnType("bigint")
 10580                        .HasColumnName("person_id");
 10581
 10582                    b.HasKey("ScopeId", "PersonId")
 10583                        .HasName("pk_scope_owner");
 10584
 10585                    b.HasIndex("PersonId")
 10586                        .HasDatabaseName("ix_scope_owner_person_id");
 10587
 10588                    b.ToTable("scope_owner", "heimdall");
 20589                });
 590
 10591            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.ScopePermission", b =>
 10592                {
 10593                    b.Property<long>("Id")
 10594                        .ValueGeneratedOnAdd()
 10595                        .HasColumnType("bigint")
 10596                        .HasColumnName("id")
 10597                        .HasColumnOrder(1);
 10598
 10599                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 10600
 10601                    b.Property<DateTime>("CreatedAt")
 10602                        .ValueGeneratedOnAdd()
 10603                        .HasColumnType("timestamp with time zone")
 10604                        .HasColumnName("created_at")
 10605                        .HasDefaultValueSql("now()");
 10606
 10607                    b.Property<string>("Description")
 10608                        .HasMaxLength(500)
 10609                        .HasColumnType("character varying(500)")
 10610                        .HasColumnName("description");
 10611
 10612                    b.Property<bool>("IncludeAsJwtClaim")
 10613                        .ValueGeneratedOnAdd()
 10614                        .HasColumnType("boolean")
 10615                        .HasDefaultValue(false)
 10616                        .HasColumnName("include_as_jwt_claim");
 10617
 10618                    b.Property<bool>("IsDeleted")
 10619                        .ValueGeneratedOnAdd()
 10620                        .HasColumnType("boolean")
 10621                        .HasDefaultValue(false)
 10622                        .HasColumnName("is_deleted");
 10623
 10624                    b.Property<string>("Name")
 10625                        .IsRequired()
 10626                        .HasMaxLength(200)
 10627                        .HasColumnType("character varying(200)")
 10628                        .HasColumnName("name");
 10629
 10630                    b.Property<Guid>("PublicId")
 10631                        .HasColumnType("uuid")
 10632                        .HasColumnName("public_id");
 10633
 10634                    b.Property<long>("ScopeId")
 10635                        .HasColumnType("bigint")
 10636                        .HasColumnName("scope_id");
 10637
 10638                    b.Property<DateTime>("UpdatedAt")
 10639                        .ValueGeneratedOnAdd()
 10640                        .HasColumnType("timestamp with time zone")
 10641                        .HasColumnName("updated_at")
 10642                        .HasDefaultValueSql("now()");
 10643
 10644                    b.HasKey("Id")
 10645                        .HasName("pk_scope_permission");
 10646
 10647                    b.HasIndex("PublicId")
 10648                        .IsUnique()
 10649                        .HasDatabaseName("ix_scope_permission_public_id");
 10650
 10651                    b.HasIndex("ScopeId")
 10652                        .HasDatabaseName("ix_scope_permission_scope_id");
 10653
 10654                    b.ToTable("scope_permission", "heimdall");
 20655                });
 656
 10657            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.ScopeUser", b =>
 10658                {
 10659                    b.Property<long>("ScopeId")
 10660                        .HasColumnType("bigint")
 10661                        .HasColumnName("scope_id");
 10662
 10663                    b.Property<long>("PersonId")
 10664                        .HasColumnType("bigint")
 10665                        .HasColumnName("person_id");
 10666
 10667                    b.HasKey("ScopeId", "PersonId")
 10668                        .HasName("pk_scope_user");
 10669
 10670                    b.HasIndex("PersonId")
 10671                        .IsUnique()
 10672                        .HasDatabaseName("ix_scope_user_person_id");
 10673
 10674                    b.ToTable("scope_user", "heimdall");
 20675                });
 676
 10677            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.TwoFactorAuth", b =>
 10678                {
 10679                    b.Property<long>("Id")
 10680                        .ValueGeneratedOnAdd()
 10681                        .HasColumnType("bigint")
 10682                        .HasColumnName("id")
 10683                        .HasColumnOrder(1);
 10684
 10685                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 10686
 10687                    b.Property<bool>("AppEnabled")
 10688                        .ValueGeneratedOnAdd()
 10689                        .HasColumnType("boolean")
 10690                        .HasDefaultValue(false)
 10691                        .HasColumnName("app_enabled");
 10692
 10693                    b.Property<DateTime>("CreatedAt")
 10694                        .ValueGeneratedOnAdd()
 10695                        .HasColumnType("timestamp with time zone")
 10696                        .HasColumnName("created_at")
 10697                        .HasDefaultValueSql("now()");
 10698
 10699                    b.Property<bool>("EmailEnabled")
 10700                        .ValueGeneratedOnAdd()
 10701                        .HasColumnType("boolean")
 10702                        .HasDefaultValue(false)
 10703                        .HasColumnName("email_enabled");
 10704
 10705                    b.Property<bool>("IsActive")
 10706                        .ValueGeneratedOnAdd()
 10707                        .HasColumnType("boolean")
 10708                        .HasDefaultValue(false)
 10709                        .HasColumnName("is_active");
 10710
 10711                    b.Property<long?>("LastTotpTimeStepUsed")
 10712                        .HasColumnType("bigint")
 10713                        .HasColumnName("last_totp_time_step_used");
 10714
 10715                    b.Property<long>("PersonId")
 10716                        .HasColumnType("bigint")
 10717                        .HasColumnName("person_id");
 10718
 10719                    b.Property<byte[]>("TotpSecretEncrypted")
 10720                        .HasColumnType("bytea")
 10721                        .HasColumnName("totp_secret_encrypted");
 10722
 10723                    b.Property<DateTime>("UpdatedAt")
 10724                        .ValueGeneratedOnAdd()
 10725                        .HasColumnType("timestamp with time zone")
 10726                        .HasColumnName("updated_at")
 10727                        .HasDefaultValueSql("now()");
 10728
 10729                    b.HasKey("Id")
 10730                        .HasName("pk_two_factor_auth");
 10731
 10732                    b.HasIndex("PersonId")
 10733                        .IsUnique()
 10734                        .HasDatabaseName("ix_two_factor_auth_person_id");
 10735
 10736                    b.ToTable("two_factor_auth", "heimdall");
 20737                });
 738
 10739            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.TwoFactorEmailCode", b =>
 10740                {
 10741                    b.Property<long>("Id")
 10742                        .ValueGeneratedOnAdd()
 10743                        .HasColumnType("bigint")
 10744                        .HasColumnName("id")
 10745                        .HasColumnOrder(1);
 10746
 10747                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 10748
 10749                    b.Property<byte[]>("CodeHash")
 10750                        .IsRequired()
 10751                        .HasColumnType("bytea")
 10752                        .HasColumnName("code_hash");
 10753
 10754                    b.Property<DateTime>("CreatedAt")
 10755                        .ValueGeneratedOnAdd()
 10756                        .HasColumnType("timestamp with time zone")
 10757                        .HasColumnName("created_at")
 10758                        .HasDefaultValueSql("now()");
 10759
 10760                    b.Property<DateTime>("ExpiresAt")
 10761                        .HasColumnType("timestamp with time zone")
 10762                        .HasColumnName("expires_at");
 10763
 10764                    b.Property<int>("FailedAttempts")
 10765                        .HasColumnType("integer")
 10766                        .HasColumnName("failed_attempts");
 10767
 10768                    b.Property<byte[]>("Salt")
 10769                        .IsRequired()
 10770                        .HasColumnType("bytea")
 10771                        .HasColumnName("salt");
 10772
 10773                    b.Property<long>("TwoFactorAuthId")
 10774                        .HasColumnType("bigint")
 10775                        .HasColumnName("two_factor_auth_id");
 10776
 10777                    b.Property<bool>("Used")
 10778                        .ValueGeneratedOnAdd()
 10779                        .HasColumnType("boolean")
 10780                        .HasDefaultValue(false)
 10781                        .HasColumnName("used");
 10782
 10783                    b.HasKey("Id")
 10784                        .HasName("pk_two_factor_email_code");
 10785
 10786                    b.HasIndex("TwoFactorAuthId")
 10787                        .HasDatabaseName("ix_two_factor_email_code_two_factor_auth_id");
 10788
 10789                    b.ToTable("two_factor_email_code", "heimdall");
 20790                });
 791
 10792            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.TwoFactorRecoveryCode", b =>
 10793                {
 10794                    b.Property<long>("Id")
 10795                        .ValueGeneratedOnAdd()
 10796                        .HasColumnType("bigint")
 10797                        .HasColumnName("id")
 10798                        .HasColumnOrder(1);
 10799
 10800                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
 10801
 10802                    b.Property<byte[]>("CodeHash")
 10803                        .IsRequired()
 10804                        .HasColumnType("bytea")
 10805                        .HasColumnName("code_hash");
 10806
 10807                    b.Property<DateTime>("CreatedAt")
 10808                        .ValueGeneratedOnAdd()
 10809                        .HasColumnType("timestamp with time zone")
 10810                        .HasColumnName("created_at")
 10811                        .HasDefaultValueSql("now()");
 10812
 10813                    b.Property<long>("TwoFactorAuthId")
 10814                        .HasColumnType("bigint")
 10815                        .HasColumnName("two_factor_auth_id");
 10816
 10817                    b.Property<bool>("Used")
 10818                        .ValueGeneratedOnAdd()
 10819                        .HasColumnType("boolean")
 10820                        .HasDefaultValue(false)
 10821                        .HasColumnName("used");
 10822
 10823                    b.Property<DateTime?>("UsedAt")
 10824                        .HasColumnType("timestamp with time zone")
 10825                        .HasColumnName("used_at");
 10826
 10827                    b.HasKey("Id")
 10828                        .HasName("pk_two_factor_recovery_code");
 10829
 10830                    b.HasIndex("TwoFactorAuthId")
 10831                        .HasDatabaseName("ix_two_factor_recovery_code_two_factor_auth_id");
 10832
 10833                    b.ToTable("two_factor_recovery_code", "heimdall");
 20834                });
 835
 10836            modelBuilder.Entity("Microsoft.AspNetCore.DataProtection.EntityFrameworkCore.DataProtectionKey", b =>
 10837                {
 10838                    b.Property<int>("Id")
 10839                        .ValueGeneratedOnAdd()
 10840                        .HasColumnType("integer")
 10841                        .HasColumnName("id");
 10842
 10843                    NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
 10844
 10845                    b.Property<string>("FriendlyName")
 10846                        .HasColumnType("text")
 10847                        .HasColumnName("friendly_name");
 10848
 10849                    b.Property<string>("Xml")
 10850                        .HasColumnType("text")
 10851                        .HasColumnName("xml");
 10852
 10853                    b.HasKey("Id")
 10854                        .HasName("pk_data_protection_keys");
 10855
 10856                    b.ToTable("data_protection_keys", "heimdall");
 20857                });
 858
 10859            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.Application", b =>
 10860                {
 10861                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Person", "Owner")
 10862                        .WithMany("OwnedApplications")
 10863                        .HasForeignKey("OwnerId")
 10864                        .OnDelete(DeleteBehavior.Cascade)
 10865                        .IsRequired()
 10866                        .HasConstraintName("fk_application_person_owner_id");
 10867
 10868                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Scope", "Scope")
 10869                        .WithMany("Applications")
 10870                        .HasForeignKey("ScopeId")
 10871                        .OnDelete(DeleteBehavior.Cascade)
 10872                        .IsRequired()
 10873                        .HasConstraintName("fk_application_scope_scope_id");
 10874
 10875                    b.Navigation("Owner");
 10876
 10877                    b.Navigation("Scope");
 20878                });
 879
 10880            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.EmailVerificationToken", b =>
 10881                {
 10882                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Person", "Person")
 10883                        .WithMany("EmailVerificationTokens")
 10884                        .HasForeignKey("PersonId")
 10885                        .OnDelete(DeleteBehavior.Cascade)
 10886                        .IsRequired()
 10887                        .HasConstraintName("fk_email_verification_token_person_person_id");
 10888
 10889                    b.Navigation("Person");
 20890                });
 891
 10892            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.GoogleUser", b =>
 10893                {
 10894                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Scope", "Scope")
 10895                        .WithMany("GoogleUsers")
 10896                        .HasForeignKey("ScopeId")
 10897                        .OnDelete(DeleteBehavior.Cascade)
 10898                        .IsRequired()
 10899                        .HasConstraintName("fk_google_user_scope_scope_id");
 10900
 10901                    b.Navigation("Scope");
 20902                });
 903
 10904            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.PasswordResetToken", b =>
 10905                {
 10906                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Person", "Person")
 10907                        .WithMany("PasswordResetTokens")
 10908                        .HasForeignKey("PersonId")
 10909                        .OnDelete(DeleteBehavior.Cascade)
 10910                        .IsRequired()
 10911                        .HasConstraintName("fk_password_reset_token_person_person_id");
 10912
 10913                    b.Navigation("Person");
 20914                });
 915
 10916            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.Person", b =>
 10917                {
 10918                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Role", "Role")
 10919                        .WithMany("Persons")
 10920                        .HasForeignKey("RoleId")
 10921                        .OnDelete(DeleteBehavior.Restrict)
 10922                        .IsRequired()
 10923                        .HasConstraintName("fk_person_roles_role_id");
 10924
 10925                    b.Navigation("Role");
 20926                });
 927
 10928            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.ScopeOwner", b =>
 10929                {
 10930                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Person", "Person")
 10931                        .WithMany("ScopeOwnerships")
 10932                        .HasForeignKey("PersonId")
 10933                        .OnDelete(DeleteBehavior.Cascade)
 10934                        .IsRequired()
 10935                        .HasConstraintName("fk_scope_owner_person_person_id");
 10936
 10937                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Scope", "Scope")
 10938                        .WithMany("Owners")
 10939                        .HasForeignKey("ScopeId")
 10940                        .OnDelete(DeleteBehavior.Cascade)
 10941                        .IsRequired()
 10942                        .HasConstraintName("fk_scope_owner_scope_scope_id");
 10943
 10944                    b.Navigation("Person");
 10945
 10946                    b.Navigation("Scope");
 20947                });
 948
 10949            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.ScopePermission", b =>
 10950                {
 10951                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Scope", "Scope")
 10952                        .WithMany("ScopePermissions")
 10953                        .HasForeignKey("ScopeId")
 10954                        .OnDelete(DeleteBehavior.Cascade)
 10955                        .IsRequired()
 10956                        .HasConstraintName("fk_scope_permission_scope_scope_id");
 10957
 10958                    b.Navigation("Scope");
 20959                });
 960
 10961            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.ScopeUser", b =>
 10962                {
 10963                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Person", "Person")
 10964                        .WithOne("ScopeMembership")
 10965                        .HasForeignKey("ArturRios.Heimdall.Domain.Entities.ScopeUser", "PersonId")
 10966                        .OnDelete(DeleteBehavior.Cascade)
 10967                        .IsRequired()
 10968                        .HasConstraintName("fk_scope_user_person_person_id");
 10969
 10970                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Scope", "Scope")
 10971                        .WithMany("Users")
 10972                        .HasForeignKey("ScopeId")
 10973                        .OnDelete(DeleteBehavior.Cascade)
 10974                        .IsRequired()
 10975                        .HasConstraintName("fk_scope_user_scope_scope_id");
 10976
 10977                    b.Navigation("Person");
 10978
 10979                    b.Navigation("Scope");
 20980                });
 981
 10982            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.TwoFactorAuth", b =>
 10983                {
 10984                    b.HasOne("ArturRios.Heimdall.Domain.Entities.Person", "Person")
 10985                        .WithOne("TwoFactorAuth")
 10986                        .HasForeignKey("ArturRios.Heimdall.Domain.Entities.TwoFactorAuth", "PersonId")
 10987                        .OnDelete(DeleteBehavior.Cascade)
 10988                        .IsRequired()
 10989                        .HasConstraintName("fk_two_factor_auth_person_person_id");
 10990
 10991                    b.Navigation("Person");
 20992                });
 993
 10994            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.TwoFactorEmailCode", b =>
 10995                {
 10996                    b.HasOne("ArturRios.Heimdall.Domain.Entities.TwoFactorAuth", "TwoFactorAuth")
 10997                        .WithMany("EmailCodes")
 10998                        .HasForeignKey("TwoFactorAuthId")
 10999                        .OnDelete(DeleteBehavior.Cascade)
 101000                        .IsRequired()
 101001                        .HasConstraintName("fk_two_factor_email_code_two_factor_auth_two_factor_auth_id");
 101002
 101003                    b.Navigation("TwoFactorAuth");
 201004                });
 1005
 101006            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.TwoFactorRecoveryCode", b =>
 101007                {
 101008                    b.HasOne("ArturRios.Heimdall.Domain.Entities.TwoFactorAuth", "TwoFactorAuth")
 101009                        .WithMany("RecoveryCodes")
 101010                        .HasForeignKey("TwoFactorAuthId")
 101011                        .OnDelete(DeleteBehavior.Cascade)
 101012                        .IsRequired()
 101013                        .HasConstraintName("fk_two_factor_recovery_code_two_factor_auth_two_factor_auth_id");
 101014
 101015                    b.Navigation("TwoFactorAuth");
 201016                });
 1017
 101018            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.Person", b =>
 101019                {
 101020                    b.Navigation("EmailVerificationTokens");
 101021
 101022                    b.Navigation("OwnedApplications");
 101023
 101024                    b.Navigation("PasswordResetTokens");
 101025
 101026                    b.Navigation("ScopeMembership");
 101027
 101028                    b.Navigation("ScopeOwnerships");
 101029
 101030                    b.Navigation("TwoFactorAuth");
 201031                });
 1032
 101033            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.Role", b =>
 101034                {
 101035                    b.Navigation("Persons");
 201036                });
 1037
 101038            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.Scope", b =>
 101039                {
 101040                    b.Navigation("Applications");
 101041
 101042                    b.Navigation("GoogleUsers");
 101043
 101044                    b.Navigation("Owners");
 101045
 101046                    b.Navigation("ScopePermissions");
 101047
 101048                    b.Navigation("Users");
 201049                });
 1050
 101051            modelBuilder.Entity("ArturRios.Heimdall.Domain.Entities.TwoFactorAuth", b =>
 101052                {
 101053                    b.Navigation("EmailCodes");
 101054
 101055                    b.Navigation("RecoveryCodes");
 201056                });
 1057#pragma warning restore 612, 618
 101058        }
 1059    }
 1060}