diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt
index 5eebce6b2d80266b23191aadf9bc2d6790a307bd..a6e180fa4c69bbb1d47f447603ee9412e26ef3e6 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt
@@ -332,9 +332,15 @@ class HomeFragmentViewModel @AssistedInject constructor(
                             )
                         }
                     )
-                    VaccinatedPerson.Status.IMMUNITY -> {
-                        throw NotImplementedError()
-                    }
+                    // TODO wrong card, just placeholder
+                    VaccinatedPerson.Status.IMMUNITY -> CompleteVaccinationHomeCard.Item(
+                        vaccinatedPerson = vaccinatedPerson,
+                        onClickAction = {
+                            popupEvents.postValue(
+                                HomeFragmentEvents.GoToVaccinationList(vaccinatedPerson.identifier.code)
+                            )
+                        }
+                    )
                 }
                 add(card)
             }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/VaccinatedPersonIdentifier.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/VaccinatedPersonIdentifier.kt
index 0663df8d042146b08b0fbf14a14ed1c9d9d69da0..aea20ab9b2e412ec1f7862b0bb8f12f8d1c710e3 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/VaccinatedPersonIdentifier.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/VaccinatedPersonIdentifier.kt
@@ -1,11 +1,12 @@
 package de.rki.coronawarnapp.vaccination.core
 
 import de.rki.coronawarnapp.util.HashExtensions.toSHA256
+import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException
+import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException.ErrorCode
 import de.rki.coronawarnapp.vaccination.core.certificate.VaccinationDGCV1
 import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateQRCode
-import de.rki.coronawarnapp.vaccination.core.repository.errors.VaccinationDateOfBirthMissmatchException
-import de.rki.coronawarnapp.vaccination.core.repository.errors.VaccinationNameMissmatchException
 import org.joda.time.LocalDate
+import timber.log.Timber
 
 data class VaccinatedPersonIdentifier(
     val dateOfBirth: LocalDate,
@@ -33,19 +34,16 @@ data class VaccinatedPersonIdentifier(
 
     fun requireMatch(other: VaccinatedPersonIdentifier) {
         if (lastNameStandardized != other.lastNameStandardized) {
-            throw VaccinationNameMissmatchException(
-                "Family name does not match, got ${other.lastNameStandardized}, expected $lastNameStandardized"
-            )
+            Timber.d("Family name does not match, got ${other.lastNameStandardized}, expected $lastNameStandardized")
+            throw InvalidHealthCertificateException(ErrorCode.VC_NAME_MISMATCH)
         }
         if (firstNameStandardized != other.firstNameStandardized) {
-            throw VaccinationNameMissmatchException(
-                "Given name does not match, got ${other.firstNameStandardized}, expected $firstNameStandardized"
-            )
+            Timber.d("Given name does not match, got ${other.firstNameStandardized}, expected $firstNameStandardized")
+            throw InvalidHealthCertificateException(ErrorCode.VC_NAME_MISMATCH)
         }
         if (dateOfBirth != other.dateOfBirth) {
-            throw VaccinationDateOfBirthMissmatchException(
-                "Date of birth does not match, got ${other.dateOfBirth}, expected $dateOfBirth"
-            )
+            Timber.d("Date of birth does not match, got ${other.dateOfBirth}, expected $dateOfBirth")
+            throw InvalidHealthCertificateException(ErrorCode.VC_DOB_MISMATCH)
         }
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepository.kt
index 1621f9eea96f84d4e1af2dcda9450efd73ab6fcc..ab3b35f4dfc2e3c48e4f5c94e586fcf66f7e6c6e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepository.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepository.kt
@@ -9,6 +9,8 @@ import de.rki.coronawarnapp.util.flow.combine
 import de.rki.coronawarnapp.vaccination.core.VaccinatedPerson
 import de.rki.coronawarnapp.vaccination.core.VaccinatedPersonIdentifier
 import de.rki.coronawarnapp.vaccination.core.VaccinationCertificate
+import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException
+import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException.ErrorCode
 import de.rki.coronawarnapp.vaccination.core.personIdentifier
 import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateQRCode
 import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationQRCodeExtractor
@@ -24,7 +26,6 @@ import kotlinx.coroutines.flow.catch
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.onStart
-import kotlinx.coroutines.launch
 import kotlinx.coroutines.plus
 import timber.log.Timber
 import javax.inject.Inject
@@ -93,13 +94,16 @@ class VaccinationRepository @Inject constructor(
                 }
             } else {
                 VaccinatedPerson(
-                    data = VaccinatedPersonData(
-                        vaccinations = emptySet()
-                    ),
+                    data = VaccinatedPersonData(),
                     valueSet = null,
                 )
             }
 
+            if (originalPerson.data.vaccinations.any { it.certificateId == qrCode.uniqueCertificateIdentifier }) {
+                Timber.tag(TAG).e("Certificate is already registered: %s", qrCode.uniqueCertificateIdentifier)
+                throw InvalidHealthCertificateException(ErrorCode.VC_ALREADY_REGISTERED)
+            }
+
             val newCertificate = qrCode.toVaccinationContainer(
                 scannedAt = timeStamper.nowUTC,
                 qrCodeExtractor = vaccinationQRCodeExtractor,
@@ -154,25 +158,25 @@ class VaccinationRepository @Inject constructor(
             )
 
             deletedVaccination = target.data.vaccinations.single {
-                it.certificateId != vaccinationCertificateId
+                it.certificateId == vaccinationCertificateId
             }
 
-            val newTarget = target.copy(
-                data = target.data.copy(
-                    vaccinations = target.data.vaccinations.filter {
-                        it.certificateId != vaccinationCertificateId
-                    }.toSet()
+            val newTarget = if (target.data.vaccinations.size > 1) {
+                target.copy(
+                    data = target.data.copy(
+                        vaccinations = target.data.vaccinations.filter { it != deletedVaccination }.toSet()
+                    )
                 )
-            )
+            } else {
+                Timber.tag(TAG).w("Person has no certificate after removal, removing person.")
+                null
+            }
 
-            this.map {
-                if (it != target) newTarget else it
-            }.toSet()
+            this.mapNotNull { if (it == target) newTarget else it }.toSet()
         }
 
         deletedVaccination?.let {
-            Timber.tag(TAG).i("Deleted vaccination was eligble for proof, refreshing: %s", deletedVaccination)
-            appScope.launch { refresh(it.personIdentifier) }
+            Timber.tag(TAG).i("Deleted vaccination certificate: %s", it.certificateId)
         }
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/errors/VaccinationDateOfBirthMissmatchException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/errors/VaccinationDateOfBirthMissmatchException.kt
deleted file mode 100644
index bedc695d22726250f93bcb4273b84dc17fc21430..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/errors/VaccinationDateOfBirthMissmatchException.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package de.rki.coronawarnapp.vaccination.core.repository.errors
-
-import de.rki.coronawarnapp.vaccination.core.VaccinationException
-
-class VaccinationDateOfBirthMissmatchException(
-    message: String
-) : VaccinationException(
-    message = message,
-    cause = null
-)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/errors/VaccinationNameMissmatchException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/errors/VaccinationNameMissmatchException.kt
deleted file mode 100644
index 3e27e652d6519f83fa9473c2a0e064c4b77e1411..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/errors/VaccinationNameMissmatchException.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package de.rki.coronawarnapp.vaccination.core.repository.errors
-
-import de.rki.coronawarnapp.vaccination.core.VaccinationException
-
-class VaccinationNameMissmatchException(
-    message: String
-) : VaccinationException(
-    message = message,
-    cause = null
-)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinatedPersonData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinatedPersonData.kt
index d5fea3bef653c4aef0e5b1670869a0fcd2ad50c3..06978d4907f11613336a3c1e85929a4228fa8021 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinatedPersonData.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinatedPersonData.kt
@@ -4,7 +4,7 @@ import com.google.gson.annotations.SerializedName
 import de.rki.coronawarnapp.vaccination.core.VaccinatedPersonIdentifier
 
 data class VaccinatedPersonData(
-    @SerializedName("vaccinationData") val vaccinations: Set<VaccinationContainer>
+    @SerializedName("vaccinationData") val vaccinations: Set<VaccinationContainer> = emptySet()
 ) {
     val identifier: VaccinatedPersonIdentifier
         get() = vaccinations.first().personIdentifier
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListVaccinationCardItemVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListVaccinationCardItemVH.kt
index 455beedf1b9a02a3b57d8c21ba385dd460c23542..e2f158b36e8772b596fdcff645e870006048a408 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListVaccinationCardItemVH.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/ui/list/adapter/viewholder/VaccinationListVaccinationCardItemVH.kt
@@ -57,7 +57,8 @@ class VaccinationListVaccinationCardItemVH(
                     }
                 }
                 IMMUNITY -> {
-                    throw NotImplementedError()
+                    // TODO
+                    R.drawable.ic_vaccination_complete_final
                 }
             }
             vaccinationIcon.setImageResource(iconRes)
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinatedPersonIdentifierTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinatedPersonIdentifierTest.kt
index 686426f4001791be9b32b9a9b141282c45a22ed4..5822f0e6951db3d730211a1a609c0c3d8c5fc608 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinatedPersonIdentifierTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinatedPersonIdentifierTest.kt
@@ -1,5 +1,9 @@
 package de.rki.coronawarnapp.vaccination.core
 
+import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException
+import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException.ErrorCode
+import io.kotest.assertions.throwables.shouldNotThrowAny
+import io.kotest.assertions.throwables.shouldThrow
 import io.kotest.matchers.shouldBe
 import org.joda.time.LocalDate
 import org.junit.jupiter.api.Test
@@ -43,4 +47,23 @@ class VaccinatedPersonIdentifierTest : BaseTest() {
         person1.code shouldBe person2.code
         person1.codeSHA256 shouldBe person2.codeSHA256
     }
+
+    @Test
+    fun `required matching`() {
+        shouldNotThrowAny {
+            testPersonMaxData.requireMatch(testPersonMaxData)
+        }
+
+        shouldThrow<InvalidHealthCertificateException> {
+            testPersonMaxData.requireMatch(testPersonMaxData.copy(firstNameStandardized = "nope"))
+        }.errorCode shouldBe ErrorCode.VC_NAME_MISMATCH
+
+        shouldThrow<InvalidHealthCertificateException> {
+            testPersonMaxData.requireMatch(testPersonMaxData.copy(lastNameStandardized = "nope"))
+        }.errorCode shouldBe ErrorCode.VC_NAME_MISMATCH
+
+        shouldThrow<InvalidHealthCertificateException> {
+            testPersonMaxData.requireMatch(testPersonMaxData.copy(dateOfBirth = LocalDate.parse("1900-12-31")))
+        }.errorCode shouldBe ErrorCode.VC_DOB_MISMATCH
+    }
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestComponent.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestComponent.kt
index 16b9d5cf00f6d1d5cb181993956c66a541d015cb..181970bd621adbbc1eb156126f6bd70dcbd01dd7 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestComponent.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestComponent.kt
@@ -4,6 +4,7 @@ import dagger.Component
 import dagger.Module
 import de.rki.coronawarnapp.util.serialization.SerializationModule
 import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationQRCodeExtractorTest
+import de.rki.coronawarnapp.vaccination.core.repository.VaccinationRepositoryTest
 import de.rki.coronawarnapp.vaccination.core.repository.storage.VaccinationContainerTest
 import de.rki.coronawarnapp.vaccination.core.repository.storage.VaccinationStorageTest
 import javax.inject.Singleton
@@ -21,6 +22,7 @@ interface VaccinationTestComponent {
     fun inject(testClass: VaccinationContainerTest)
     fun inject(testClass: VaccinationQRCodeExtractorTest)
     fun inject(testClass: VaccinatedPersonTest)
+    fun inject(testClass: VaccinationRepositoryTest)
 
     @Component.Factory
     interface Factory {
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestData.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestData.kt
index ed7422a60be963c8e4ea221ec058229b00887c31..0c5117d63094019d089ac68493a1edd962fda0cf 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestData.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/VaccinationTestData.kt
@@ -1,6 +1,9 @@
 package de.rki.coronawarnapp.vaccination.core
 
+import de.rki.coronawarnapp.vaccination.core.certificate.HealthCertificateHeader
 import de.rki.coronawarnapp.vaccination.core.certificate.VaccinationDGCV1
+import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateData
+import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationCertificateQRCode
 import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationQRCodeExtractor
 import de.rki.coronawarnapp.vaccination.core.repository.storage.VaccinatedPersonData
 import de.rki.coronawarnapp.vaccination.core.repository.storage.VaccinationContainer
@@ -12,7 +15,7 @@ class VaccinationTestData @Inject constructor(
 ) {
 
     // AndreasAstra1.pdf
-    val personAVac1QR =
+    val personAVac1QRCodeString =
         "HC1:6BFOXN*TS0BI\$ZD.P9UOL97O4-2HH77HRM3DSPTLRR+%3KXH9M9ESIGUBA KWML%6S5B9-+P70Q5VC9:BPCNYKMXEE1JAA/CXGG0JK1WL260X638J3-E3ND3DAJ-43TTTO3HK1H3QBCWNZ83UQJ:T0/8F7V0HKN:Q8.HBV+0SZ4GH00T9UKP0T9WC5PF6846A\$Q$76QW6%V98T5\$FQMI5DN9QZ5Y0Q\$UPE%5MZ5*T57ZA\$O7T6LEJOA+MZ55EII-EB1EKC422JBBD0D2K.EJJ14B2MP41WTRZPQEC5L64HX6IAS 8S8FT/MAMXP6QS03L0QIRR97I2HOAXL92L0. KOKG8VG5SI:TU+MMPZ55%PBT1YEGEA7IB65C94JBQ2NLEE:NQ% GC3MXHFLF9OIFN0IZ95LJL80P1FDLW452I8941:HH3M41GTNP8EFUNT$.FTD852IWKP/HLIJL8JF8JF172IMAS EDAHMXFBFBQSKJE72KV\$FHJ%3O%6:XM+1QD+T2/VKKER3L3%1THL7MGY.1S:T:GLOX6OCE7+RWYL3.C-L27WNV0G::M74O%K7C50AAEI4"
 
     val personAVac1Certificate = VaccinationDGCV1(
@@ -40,15 +43,31 @@ class VaccinationTestData @Inject constructor(
         )
     )
 
+    val personAVac1CertificateHeader = HealthCertificateHeader(
+        issuer = "DE",
+        issuedAt = Instant.parse("2021-05-11T09:25:00.000Z"),
+        expiresAt = Instant.parse("2022-05-11T09:25:00.000Z"),
+    )
+
+    val personAVac1CertificateData = VaccinationCertificateData(
+        certificate = personAVac1Certificate,
+        header = personAVac1CertificateHeader
+    )
+
+    val personAVac1QRCode = VaccinationCertificateQRCode(
+        qrCodeString = personAVac1QRCodeString,
+        parsedData = personAVac1CertificateData,
+    )
+
     val personAVac1Container = VaccinationContainer(
         scannedAt = Instant.ofEpochMilli(1620062834471),
-        vaccinationQrCode = personAVac1QR,
+        vaccinationQrCode = personAVac1QRCodeString,
     ).apply {
         qrCodeExtractor = this@VaccinationTestData.qrCodeExtractor
     }
 
     // AndreasAstra2.pdf
-    val personAVac2QR =
+    val personAVac2QRCodeString =
         "6BFOXN*TS0BI\$ZD.P9UOL97O4-2HH77HRM3DSPTLRR+%3D H9M9ESIGUBA KWMLYX1HXK 0DV:D5VC9:BPCNYKMXEE1JAA/CZIK0JK1WL260X638J3-E3ND3DAJ-43TTTMDF6S8:B73QN VNZ.0K6HYI3CNN96BPHNW*0I85V.499TXY9KK9%OC+G9QJPNF67J6QW67KQ9G66PPM4MLJE+.PDB9L6Q2+PFQ5DB96PP5/P-59A%N+892 7J235II3NJ7PK7SLQMIPUBN9CIZI.EJJ14B2MP41IZRZPQEC5L64HX6IAS 8SAFT/MAMXP6QS03L0QIRR97I2HOAXL92L0. KOKGGVG5SI:TU+MMPZ55%PBT1YEGEA7IB65C94JBQ2NLEE:NQ% GC3MXHFLF9OIFN0IZ95LJL80P1FDLW452I8941:HH3M41GTNP8EFUNT\$.FTD852IWKP/HLIJL8JF8JF172E2JA0K*WDQMPB8T3%KLUSR43M.F\$QBQDR\$VT7V01Y7J0BOZLH+D-QF6MO\$R3%XB+.4QI596GY\$SITJP5BS0DFROC.7B.2RTB*UNYSM$*00HIL+H"
 
     val personAVac2Certificate = VaccinationDGCV1(
@@ -76,18 +95,90 @@ class VaccinationTestData @Inject constructor(
         )
     )
 
+    val personAVac2CertificateHeader = HealthCertificateHeader(
+        issuer = "DE",
+        issuedAt = Instant.parse("2021-05-11T09:26:08.000Z"),
+        expiresAt = Instant.parse("2022-05-11T09:26:08.000Z"),
+    )
+
+    val personAVac2CertificateData = VaccinationCertificateData(
+        certificate = personAVac2Certificate,
+        header = personAVac2CertificateHeader
+    )
+
+    val personAVac2QRCode = VaccinationCertificateQRCode(
+        qrCodeString = personAVac2QRCodeString,
+        parsedData = personAVac2CertificateData,
+    )
+
     val personAVac2Container = VaccinationContainer(
         scannedAt = Instant.ofEpochMilli(1620069934471),
-        vaccinationQrCode = personAVac2QR,
+        vaccinationQrCode = personAVac2QRCodeString,
     ).apply {
         qrCodeExtractor = this@VaccinationTestData.qrCodeExtractor
     }
 
-    val personAData2Vac1Proof = VaccinatedPersonData(
+    val personAData2Vac = VaccinatedPersonData(
         vaccinations = setOf(personAVac1Container, personAVac2Container)
     )
 
-    val personWithoutCountryContainer = VaccinationContainer(
+    // BorisJohnson1.pdf
+    val personBVac1QRCodeString =
+        "HC1:6BFOXN*TS0BI\$ZD.P9UOL97O4-2HH77HRM3DSPTLRR+%3QVH9M9ESIGUBA KWML:SPHXK 0DMYF5VC9:BPCNYKMXEE1JAA/CZIK0JK1WL260X638J3-E3ND3DAJ-43 QTCPFFIJRF3O8H43HX37DUF GFE VMJJYC3SM74E5V.499TXY9KK9+OC+G9QJPNF67J6QW67KQ2G66PPM4MLJE+.PDB9L6Q2+PFQ5DB96PP5/P-59A%N+892 7J235II3NJ7PK7SLQMIPUBN9CIZI.EJJ14B2MP41AZRSEQEC5L64HX6IAS3DS2980IQ.DPUHLW\$GAHLW 70SO:GOLIROGO3T59YLQM14+OP\$I/XK\$M8CL6PZB*L8PK99Q9E\$BDZIF9J8-I\$GI0 J1ALL:F71APC9*KF6LF/NLR/FZ.COKEH-BB4OQ9OG4C5AO**HOELK2AZ7LBLEH-BHPLV5GK3DNKE\$JDVPLW1KD0KCZG.M1LUSB5BCQRJ\$DB5N9%V/GO4IHIBBJ-BI%NWRS%LR%\$KR46325NABFDDAFHD9PZP11COD5U*2KQXCA5W8HH/K51DQO8O0-SOSENFH9101U8$3"
+
+    val personBVac1Certificate = VaccinationDGCV1(
+        version = "1.0.0",
+        nameData = VaccinationDGCV1.NameData(
+            givenName = "Boris",
+            givenNameStandardized = "BORIS",
+            familyName = "Johnson Gültig",
+            familyNameStandardized = "JOHNSON<GUELTIG",
+        ),
+        dob = "1966-11-11",
+        vaccinationDatas = listOf(
+            VaccinationDGCV1.VaccinationData(
+                targetId = "840539006",
+                vaccineId = "1119305005",
+                medicalProductId = "EU/1/20/1525",
+                marketAuthorizationHolderId = "ORG-100001417",
+                doseNumber = 1,
+                totalSeriesOfDoses = 1,
+                dt = "2021-04-20",
+                countryOfVaccination = "DE",
+                certificateIssuer = "Bundesministerium für Gesundheit - Test01",
+                uniqueCertificateIdentifier = "01DE/00001/1119305005/3H24U2KVOTPCSINK7N64F2OB9#S",
+            )
+        )
+    )
+
+    val personBVac1CertificateHeader = HealthCertificateHeader(
+        issuer = "DE",
+        issuedAt = Instant.parse("2021-05-11T09:23:03.000Z"),
+        expiresAt = Instant.parse("2022-05-11T09:23:03.000Z"),
+    )
+
+    val personBVac1CertificateData = VaccinationCertificateData(
+        certificate = personBVac1Certificate,
+        header = personBVac1CertificateHeader
+    )
+
+    val personBVac1QRCode = VaccinationCertificateQRCode(
+        qrCodeString = personBVac1QRCodeString,
+        parsedData = personBVac1CertificateData,
+    )
+
+    val personBVac1Container = VaccinationContainer(
+        scannedAt = Instant.ofEpochMilli(1620069934471),
+        vaccinationQrCode = personBVac1QRCodeString,
+    ).apply {
+        qrCodeExtractor = this@VaccinationTestData.qrCodeExtractor
+    }
+
+    val personBData1Vac = VaccinatedPersonData(
+        vaccinations = setOf(personBVac1Container)
+    )
+
+    val personXVac1ContainerBadCountryData = VaccinationContainer(
         scannedAt = Instant.ofEpochMilli(1620062834471),
         vaccinationQrCode = VaccinationQrCodeTestData.qrCodeWithNonsenseCountry,
     ).apply {
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt
index b58dd524e24a8585a079d34e1f10283cb8dfd224..ef2d3bd05a7f431767e5bf92ce403b1a1f3b1100 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/qrcode/VaccinationQRCodeExtractorTest.kt
@@ -2,6 +2,7 @@ package de.rki.coronawarnapp.vaccination.core.qrcode
 
 import de.rki.coronawarnapp.vaccination.core.DaggerVaccinationTestComponent
 import de.rki.coronawarnapp.vaccination.core.VaccinationQrCodeTestData
+import de.rki.coronawarnapp.vaccination.core.VaccinationTestData
 import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException
 import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException.ErrorCode.HC_BASE45_DECODING_FAILED
 import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException.ErrorCode.HC_ZLIB_DECOMPRESSION_FAILED
@@ -19,6 +20,7 @@ import javax.inject.Inject
 class VaccinationQRCodeExtractorTest : BaseTest() {
 
     @Inject lateinit var extractor: VaccinationQRCodeExtractor
+    @Inject lateinit var vaccinationTestData: VaccinationTestData
 
     @BeforeEach
     fun setup() {
@@ -104,4 +106,16 @@ class VaccinationQRCodeExtractorTest : BaseTest() {
             extractor.extract(VaccinationQrCodeTestData.certificateMissing)
         }.errorCode shouldBe VC_NO_VACCINATION_ENTRY
     }
+
+    @Test
+    fun `test data person A check`() {
+        val extracted = extractor.extract(vaccinationTestData.personAVac1QRCodeString)
+        extracted shouldBe vaccinationTestData.personAVac1QRCode
+    }
+
+    @Test
+    fun `test data person B check`() {
+        val extracted = extractor.extract(vaccinationTestData.personBVac1QRCodeString)
+        extracted shouldBe vaccinationTestData.personBVac1QRCode
+    }
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepositoryTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepositoryTest.kt
index bcefa337179dab6e378ec59efcac4de629151b8c..f0703302cb0f92b034fdb75003771bfd254ef56e 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepositoryTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/VaccinationRepositoryTest.kt
@@ -1,14 +1,30 @@
 package de.rki.coronawarnapp.vaccination.core.repository
 
 import de.rki.coronawarnapp.util.TimeStamper
+import de.rki.coronawarnapp.vaccination.core.DaggerVaccinationTestComponent
+import de.rki.coronawarnapp.vaccination.core.VaccinationTestData
+import de.rki.coronawarnapp.vaccination.core.certificate.InvalidHealthCertificateException
+import de.rki.coronawarnapp.vaccination.core.qrcode.VaccinationQRCodeExtractor
+import de.rki.coronawarnapp.vaccination.core.repository.errors.VaccinationCertificateNotFoundException
 import de.rki.coronawarnapp.vaccination.core.repository.storage.VaccinatedPersonData
 import de.rki.coronawarnapp.vaccination.core.repository.storage.VaccinationStorage
 import de.rki.coronawarnapp.vaccination.core.server.valueset.VaccinationValueSet
+import io.kotest.assertions.throwables.shouldThrow
+import io.kotest.matchers.shouldBe
+import io.mockk.MockKAnnotations
+import io.mockk.every
 import io.mockk.impl.annotations.MockK
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.flowOf
 import org.joda.time.Instant
+import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
+import testhelpers.TestDispatcherProvider
 import testhelpers.coroutines.runBlockingTest2
+import timber.log.Timber
+import javax.inject.Inject
 
 class VaccinationRepositoryTest : BaseTest() {
 
@@ -17,107 +33,171 @@ class VaccinationRepositoryTest : BaseTest() {
     @MockK lateinit var storage: VaccinationStorage
     @MockK lateinit var valueSetsRepository: ValueSetsRepository
     @MockK lateinit var vaccinationValueSet: VaccinationValueSet
+    @MockK lateinit var qrCodeExtractor: VaccinationQRCodeExtractor
 
     private var testStorage: Set<VaccinatedPersonData> = emptySet()
 
-    private var nowUTC = Instant.ofEpochMilli(1234567890)
-
-//    @BeforeEach
-//    fun setup() {
-//        MockKAnnotations.init(this)
-//
-//        every { timeStamper.nowUTC } returns nowUTC
-//
-//        every { valueSetsRepository.latestValueSet } returns flowOf(vaccinationValueSet)
-//
-//        coEvery { vaccinationProofServer.getProofCertificate(any()) } returns VaccinationTestData.PERSON_A_PROOF_1_RESPONSE
-//
-//        storage.apply {
-//            every { personContainers } answers { testStorage }
-//            every { personContainers = any() } answers { testStorage = arg(0) }
-//        }
-//    }
-//
-//    private fun createInstance(scope: CoroutineScope) = VaccinationRepository(
-//        appScope = scope,
-//        dispatcherProvider = TestDispatcherProvider(),
-//        timeStamper = timeStamper,
-//        storage = storage,
-//        valueSetsRepository = valueSetsRepository,
-//        vaccinationProofServer = vaccinationProofServer,
-//    )
-//
-//    @Test
-//    fun `add new certificate - no prior data`() = runBlockingTest2(ignoreActive = true) {
-//        val instance = createInstance(this)
-//
-//        advanceUntilIdle()
-//
-//        instance.registerVaccination(VaccinationTestData.PERSON_A_VAC_1_QRCODE).apply {
-//            Timber.i("Returned cert is %s", this)
-//            this.personIdentifier shouldBe VaccinationTestData.PERSON_A_VAC_1_CONTAINER.personIdentifier
-//        }
-//    }
+    @Inject lateinit var vaccinationTestData: VaccinationTestData
+
+    // Few days after issued dates of person A in test data.
+    private var nowUTC = Instant.parse("2021-05-13T09:25:00.000Z")
+
+    @BeforeEach
+    fun setup() {
+        MockKAnnotations.init(this)
+
+        DaggerVaccinationTestComponent.factory().create().inject(this)
+
+        every { timeStamper.nowUTC } returns nowUTC
+
+        every { valueSetsRepository.latestValueSet } returns flowOf(vaccinationValueSet)
+
+        storage.apply {
+            every { personContainers } answers { testStorage }
+            every { personContainers = any() } answers { testStorage = arg(0) }
+        }
+    }
+
+    private fun createInstance(scope: CoroutineScope) = VaccinationRepository(
+        appScope = scope,
+        dispatcherProvider = TestDispatcherProvider(),
+        timeStamper = timeStamper,
+        storage = storage,
+        valueSetsRepository = valueSetsRepository,
+        vaccinationQRCodeExtractor = qrCodeExtractor,
+    )
 
     @Test
-    fun `add new certificate - existing data`() = runBlockingTest2(ignoreActive = true) {
-//        val dataBefore = VaccinationTestData.PERSON_A_DATA_2VAC_PROOF.copy(
-//            vaccinations = setOf(VaccinationTestData.PERSON_A_VAC_1_CONTAINER),
-//            proofs = emptySet()
-//        )
-//        val dataAfter = VaccinationTestData.PERSON_A_DATA_2VAC_PROOF.copy(
-//            vaccinations = setOf(
-//                VaccinationTestData.PERSON_A_VAC_1_CONTAINER,
-//                VaccinationTestData.PERSON_A_VAC_2_CONTAINER.copy(scannedAt = nowUTC)
-//            ),
-//            proofs = emptySet()
-//        )
-//        testStorage = setOf(dataBefore)
-//
-//        val instance = createInstance(this)
-//
-//        advanceUntilIdle()
-//
-//        instance.registerVaccination(VaccinationTestData.PERSON_A_VAC_2_QRCODE).apply {
-//            Timber.i("Returned cert is %s", this)
-//            this.personIdentifier shouldBe VaccinationTestData.PERSON_A_VAC_2_CONTAINER.personIdentifier
-//        }
-//
-//        testStorage.first() shouldBe dataAfter
+    fun `add new certificate - no prior data`() = runBlockingTest2(ignoreActive = true) {
+        val instance = createInstance(this)
+        advanceUntilIdle()
+
+        instance.registerVaccination(vaccinationTestData.personAVac1QRCode).apply {
+            Timber.i("Returned cert is %s", this)
+            this.personIdentifier shouldBe vaccinationTestData.personAVac1Container.personIdentifier
+        }
     }
 
     @Test
-    fun `add new certificate - if eligble for proof, start request`() = runBlockingTest2(ignoreActive = true) {
-//        TODO()
+    fun `add new certificate - existing data`() = runBlockingTest2(ignoreActive = true) {
+        val dataBefore = vaccinationTestData.personAData2Vac.copy(
+            vaccinations = setOf(vaccinationTestData.personAVac1Container),
+        )
+        val dataAfter = vaccinationTestData.personAData2Vac.copy(
+            vaccinations = setOf(
+                vaccinationTestData.personAVac1Container,
+                vaccinationTestData.personAVac2Container.copy(scannedAt = nowUTC)
+            ),
+        )
+        testStorage = setOf(dataBefore)
+
+        val instance = createInstance(this)
+        advanceUntilIdle()
+
+        instance.registerVaccination(vaccinationTestData.personAVac2QRCode).apply {
+            Timber.i("Returned cert is %s", this)
+            this.personIdentifier shouldBe vaccinationTestData.personAVac2Container.personIdentifier
+        }
+
+        testStorage.first() shouldBe dataAfter
     }
 
     @Test
-    fun `add new certificate - does not match existing person`() {
-//        TODO()
+    fun `add new certificate - does not match existing person`() = runBlockingTest2(ignoreActive = true) {
+        testStorage = setOf(vaccinationTestData.personAData2Vac)
+
+        val instance = createInstance(this)
+        advanceUntilIdle()
+
+        shouldThrow<InvalidHealthCertificateException> {
+            instance.registerVaccination(vaccinationTestData.personBVac1QRCode)
+        }.errorCode shouldBe InvalidHealthCertificateException.ErrorCode.VC_NAME_MISMATCH
+
+        testStorage shouldBe setOf(vaccinationTestData.personAData2Vac)
     }
 
     @Test
-    fun `add new certificate - duplicate certificate`() {
-//        TODO()
+    fun `add new certificate - duplicate certificate`() = runBlockingTest2(ignoreActive = true) {
+        val dataBefore = vaccinationTestData.personAData2Vac.copy(
+            vaccinations = setOf(vaccinationTestData.personAVac1Container),
+        )
+
+        testStorage = setOf(dataBefore)
+
+        val instance = createInstance(this)
+        advanceUntilIdle()
+
+        shouldThrow<InvalidHealthCertificateException> {
+            instance.registerVaccination(vaccinationTestData.personAVac1QRCode)
+        }.errorCode shouldBe InvalidHealthCertificateException.ErrorCode.VC_ALREADY_REGISTERED
+
+        testStorage.first() shouldBe dataBefore
     }
 
     @Test
-    fun `clear data`() {
-//        TODO()
+    fun `clear data`() = runBlockingTest2(ignoreActive = true) {
+        testStorage = setOf(vaccinationTestData.personAData2Vac)
+
+        val instance = createInstance(this)
+        advanceUntilIdle()
+
+        instance.vaccinationInfos.first().single().data shouldBe vaccinationTestData.personAData2Vac
+
+        instance.clear()
+
+        testStorage shouldBe emptySet()
+        instance.vaccinationInfos.first() shouldBe emptySet()
     }
 
     @Test
-    fun `remove certificate`() {
-//        TODO()
+    fun `remove certificate`() = runBlockingTest2(ignoreActive = true) {
+        val before = vaccinationTestData.personAData2Vac
+        val after = vaccinationTestData.personAData2Vac.copy(
+            vaccinations = setOf(vaccinationTestData.personAVac1Container)
+        )
+        val toRemove = vaccinationTestData.personAVac2Container
+
+        testStorage = setOf(before)
+
+        val instance = createInstance(this)
+        advanceUntilIdle()
+
+        instance.vaccinationInfos.first().single().data shouldBe vaccinationTestData.personAData2Vac
+
+        instance.deleteVaccinationCertificate(toRemove.certificateId)
+        advanceUntilIdle()
+
+        testStorage shouldBe setOf(after)
+        instance.vaccinationInfos.first().single().data shouldBe after
     }
 
     @Test
-    fun `remove certificate - starts proof check if we deleted a vaccination that was eligble for proof`() {
-//        TODO()
+    fun `remove certificate - unknown certificate`() = runBlockingTest2(ignoreActive = true) {
+        testStorage = setOf(vaccinationTestData.personAData2Vac)
+
+        val instance = createInstance(this)
+        advanceUntilIdle()
+
+        instance.vaccinationInfos.first().single().data shouldBe vaccinationTestData.personAData2Vac
+
+        shouldThrow<VaccinationCertificateNotFoundException> {
+            instance.deleteVaccinationCertificate(vaccinationTestData.personBVac1Container.certificateId)
+        }
     }
 
     @Test
-    fun `check for new proof certificate`() {
-//        TODO()
+    fun `remove certificate - last certificate for person`() = runBlockingTest2(ignoreActive = true) {
+        testStorage = setOf(vaccinationTestData.personBData1Vac)
+
+        val instance = createInstance(this)
+        advanceUntilIdle()
+
+        instance.vaccinationInfos.first().single().data shouldBe vaccinationTestData.personBData1Vac
+
+        instance.deleteVaccinationCertificate(vaccinationTestData.personBVac1Container.certificateId)
+        advanceUntilIdle()
+
+        instance.vaccinationInfos.first() shouldBe emptySet()
+        testStorage shouldBe emptySet()
     }
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainerTest.kt
index 4de4d70a1bc0e0c46e29a062df85c07f048a6a29..c362bebab70f4e7cfdccaa0e760174263e15374e 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainerTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationContainerTest.kt
@@ -138,7 +138,7 @@ class VaccinationContainerTest : BaseTest() {
 
     @Test
     fun `nonsense country code appears unchanged`() {
-        testData.personWithoutCountryContainer.toVaccinationCertificate(null).apply {
+        testData.personXVac1ContainerBadCountryData.toVaccinationCertificate(null).apply {
             certificateCountry shouldBe "YY"
         }
     }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorageTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorageTest.kt
index a888628a60455a202632c24e041d74366ce81758..9af9da65bd8172c743c89b1078d28416502a678b 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorageTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/repository/storage/VaccinationStorageTest.kt
@@ -61,7 +61,7 @@ class VaccinationStorageTest : BaseTest() {
     @Test
     fun `store one person`() {
         val instance = createInstance()
-        instance.personContainers = setOf(testData.personAData2Vac1Proof)
+        instance.personContainers = setOf(testData.personAData2Vac)
 
         val json =
             (mockPreferences.dataMapPeek["vaccination.person.1966-11-11#ASTRA<EINS#ANDREAS"] as String)
@@ -70,10 +70,10 @@ class VaccinationStorageTest : BaseTest() {
             {
                 "vaccinationData": [
                     {
-                        "vaccinationQrCode": "${testData.personAVac1QR}",
+                        "vaccinationQrCode": "${testData.personAVac1QRCodeString}",
                         "scannedAt": 1620062834471
                     }, {
-                        "vaccinationQrCode": "${testData.personAVac2QR}",
+                        "vaccinationQrCode": "${testData.personAVac2QRCodeString}",
                         "scannedAt": 1620069934471
                     }
                 ]
@@ -81,7 +81,7 @@ class VaccinationStorageTest : BaseTest() {
         """.toComparableJsonPretty()
 
         instance.personContainers.single().apply {
-            this shouldBe testData.personAData2Vac1Proof
+            this shouldBe testData.personAData2Vac
             this.vaccinations shouldBe setOf(
                 testData.personAVac1Container,
                 testData.personAVac2Container,