Vaksina - Vaksina COVID QR Validation Checker With Python

Overview

Vaksina COVID QR Validation Checker

Vaksina is a general purpose library intended to validate multiple COVID QR codes from multiple countries and issuers. It is intended to streamline and help make validation of codes from multiple sources easier for public venues and other event.

This was primarilly written because, at the time I started this project, there is still no comprehensive COVID checking platform in existence. While some exist for Canada's SMART Health Cards, and EU Digital COVID Pass, there is no framework that can handle them as a single source of truth.

Vaksina is the intended proof of concept to handle this, and is intended to work with a REST based API deployed on venue, but may be adopted for use in mobile applications and similar as a future goal, but the intent is implementation with a kiosk like system that is used in combination with a national ID card since none of COVID-19 QR codes are usable as an ID in and of themselves.

Version 0.1 Goals

Zero-Knowledge/Zero-Record Model

It is intended that no data submitting to vaksina is stored beyond the time it takes to parse the record. The only external data loaded and kept are PKI information from a set of "known good" trusted sources, that is covered by the next bullet point.

Creation of Public Trust Store

The creation of a "known good" set of sign keys will be provided ala Mozilla store

Creation of validation of SMART Health Card standard

There is no one specific standard for COVID-19 QR validation. Canada, and Japan have standarded on SMART, as have several states, pharmacies, hospitals and more within the United States. While vaxsina is intended as a general COVID-19 credential verification library, the initial MVP will only handle SMART Health Cards. Support for additional standards such as EU Digital COVID Pass, UK NHS Pass, and others like New York State EmpirePass will be added with time.

Implementation of VaccinePolicy Framework, to determine status

Given the ongoing needs of various venues, and other changes, it is planned that a given VaccinePolicy can coded for and changed. vaxshina is intended to have a "generic" frontend with current best practices, but is meant to be easily customized without having to fork the library.

Basic Front End for testing purposes

For purposes of testing and validation, a simple REST frontend + javascript page for testing on a local install is intended as part of the MVP

Full code coverage and unit tests

Because we don't want to have untested code paths

Comments
  • Why not use dict() instead of JSON for some code checks

    Why not use dict() instead of JSON for some code checks

    Hi,

    Good afternoon,

    A suggestion that comes to me to improve the code cleanliness and how to work with it.

        def get_vaccine_by_identifier(self, identifier):
            """Gets a vaccine by the identifier in the JSON file"""
            for vaccine in self._known_vaccine_list:
                if vaccine.vaccine_identifier == identifier:
                    return vaccine
    
            raise ValueError("Unknown vaccine")
    

    If we pass self._known_vaccine_list as a dict() we could just use

        def get_vaccine_by_identifier(self, identifier):
            """Gets a vaccine by the identifier in the JSON file"""
            if  vaccine.vaccine_identifier in VACCINE_DICTIONARY:
                    return True, vaccine
            else:
                    raise ValueError("Unknown vaccine")
    

    And dictionaries can be changed to JSON whenever we want, but we gain speed and stability when working with them.

    It's a suggestion, maybe it has a dark side that I don't see.

    Let's not forget that dictionaries can also be serialised, stored and loaded from main memory to persistent memory.

    Regards

    opened by peseoane 1
  • Fixed violations (MD, Python, JSON, XML and more)

    Fixed violations (MD, Python, JSON, XML and more)

    They have been corrected again, adapting the following to the new code generated by @NComannder:

    • Markdown syntax violations.
    • Python 3 syntax violations
      • In addition, the imports have been tidied up
      • The code, without altering its functionality, has been formatted for better readability, as this is the philosophical purpose of Python 3.
    • XML syntax violations
    • JSON syntax-structural violations

    The problem in merging the branches was the absence of a file that has been deleted. Now it's fixed.

    opened by peseoane 1
  • Revert

    Revert "Include metadata YAML in Markdown documentation"

    Reverts NCommander/vaksina#13

    Github displays a very ugly vertical table with this landed. Maybe we need to generate an AUTHORS file, but this isn't a solution.

    opened by NCommander 0
  • Include metadata YAML in Markdown documentation

    Include metadata YAML in Markdown documentation

    Include metadata in documentation

    On this occasion, if it seems relevant, I have added a YAML header (it is part of the accepted Markdown) in order to better format the document and add metadata to the README.md

    Also, whether you want to do the binding or not, at least it is now signed as requested. :)

    Regards.

    opened by peseoane 0
  • Possible solution to #16

    Possible solution to #16

    The result of running test.py:

    {
       "cards":{
          "card0":{
             "card_type":"smart_health_card",
             "issued_by":"https://spec.smarthealth.cards/examples/issuer",
             "persons":{
                "person0":{
                   "name":[
                      "Jane C. Anyperson"
                   ],
                   "dob":"1961-01-20",
                   "immunizations":[
                      {
                         "vaccine_administered":"PFIZER_COMIRNATY",
                         "date_given":"2021-01-01",
                         "lot_number":"0000002"
                      },
                      {
                         "vaccine_administered":"PFIZER_COMIRNATY",
                         "date_given":"2021-01-29",
                         "lot_number":"0000008"
                      }
                   ]
                }
             }
          }
       },
       "validations":[
          {
             "validation_method":"osha_1910_501",
             "results":{
                "Jane C. Anyperson":"success"
             }
          }
       ]
    }
    

    Note:

    In your example in #16 in results you refered to the person using their reference id (person0), however assuming several cards get passed to the validator, wouldn't this id be duplicated in every card? Since the id is assigned locally separately for each card:

    class Card(object):
        def __init__(self):
            ...
            self.persons = {}
            self._person_count = 0
    
        def add_person(self, card):
            person_key = "person" + str(self._person_count)
            self.persons[person_key] = card
            self._person_count = self._person_count + 1
    

    Thus, for now I am using the persons name(s) instead. However, this of course has the potential for trouble if several people share the same card and name (parent and child for example).

    opened by Guiorgy 1
  • Typos in code/comments, some cleanup and fixed parse_immunization_record?

    Typos in code/comments, some cleanup and fixed parse_immunization_record?

    • fixed typos in code
    • cleaned up some code (PyCharm linter errors/warnings)
    • fixed parse_immunization_record?

    On the last one (parse_immunization_record), the comment inside it states:

    It's possible that multiple vaccines can be given in single day. This isn't done for COVID per se, but because FHIR is a general purpose specification, we should handle this, especially if there are future multishot COVID vaccinations that are given at later point, because data structures are important

    If I understand this correctly, the method should handle multiple immunization records, store them in an list and return them all. If that is the intended behaviour, then I fixed it. If not then this should be reverted, and the method refactored, since before it created a list of imunizations that was filled but never used, and the method only ever returned the last parsed immunization, and if the received dictionarry was empty/had no immunizations, the method would return a variable before initialized (so my PyCharm linter was freaking out on that :P)

    opened by Guiorgy 0
  • Typos and small changes

    Typos and small changes

    • typos in docs
    • added some links (Alpine, Ubuntu Core and etc.) to the docs
    • typos in tests
    • fixed duplicate test names
    • changed file paths from relative to absolute. Otherwise, tests would raise FileNotFound in PyCharm (on Windows)
    opened by Guiorgy 0
  • Implement Proper Key Management + Revocation

    Implement Proper Key Management + Revocation

    So as of right now, Vaksina is using a very simplistic design which has a JSON file with all know keys from the VCI issuers list. This doesn't handle key revocation (which is a custom rolled thing in SHC and is semi-complex), but essentially, we need to do the following.

    Each SHC has a specific signing key in the iss field, but that doesn't specifically denote who actually issued a given card, and that should be available in plain text if possible (this will also be true for other card types later) through the API. For fully offline operation, we need to be able to generate a datafile that has all the information in a single go, and then load it as needed.

    In practice, the key management tool needs to do the following:

    • Download all known VCI key signers from (https://github.com/the-commons-project/vci-directory)'s metadata
      • The keys are specifically at VCI base path + /.well-known/jwks.json, and are represented as a JSON Web Keyset format
      • However, the CRL system is unique
    • Merge VCI metadata with the VCI signers in such a way that all key information is available in a single go
    • If CRL support is defined (aka crlRevision: 1 is present in the JWK object), then we need to do additional steps
      • CRLs are defined on a per key basis, and refer to the rid object on a given card.
      • We need to download `/.well-known/crls/kid.json to get a list of revoked keys
      • This file needs a validation check before incorporated in the dataset.
    • Have a local database of keys. As of last run, the key database is 210 kb JSON file. That may or may not be acceptable to load at library instance.

    While we could dynamically fetch a pubkey for an unknown issuer, I question if that's really a door I want to open ...

    The following tools need to be implemented:

    • Define a serialization type for the key signer database
    • Implement a tool to download the VCI list and serialize it
    • Tools to create a local test signing CA for development purposes

    We need to test the following scenarios to make sure we're handling this properly

    • Download and validate a JWS claim for a given key (this is coded, but not unit tested)
    • Ensure expiration and NBF (not valid before) is handled
    • Check revocation status (example03 of SHC data is a revoked example)
    • Model the issuer somewhere in Card information properly

    There's probably more I'm forgetting, but this is a relatively good baseline in which to start

    opened by NCommander 1
  • Should the API specifically handle multiple validation tests at once? (Validation Data Modelling)

    Should the API specifically handle multiple validation tests at once? (Validation Data Modelling)

    While I was beginning to refactor code to handle vaccinationresults, I had a thought. Currently, in API.md, we define an example result as such:

    {
        "card_validation_status": "good",
        "card_decoded_content": {
            "card_type": "smart_health_card",
            "persons": [
                {
                    "names" : [
                        "John A. Person"
                    ],
                    "dob": "01-05-1950",
                    "immunizations": [
                        {
                            "vaccine": "MODERNA",
                            "given_on": "01-01-2021",
                            "lot_number": "1"
                        },
                        {
                            "vaccine": "MODERNA",
                            "given_on": "01-29-2021",
                            "lot_number": "20"
                        }
                    ]
                }
            ],
            "issued_by": "Example Issuer"
        },
        "validation_error": ""
    }
    

    However, this doesn't work properly because a validation result needs to handle a person, and it is legal per FIRS/SHC for multiple persons/patients to be within one dataset, and when I brought this up on SHC (https://github.com/smart-on-fhir/health-cards/issues/223), this seems to be by design.

    As such, we refactored the card representation/results to look like this:

    {
      "card_type": "smart_health_card",
      "issued_by": "https://spec.smarthealth.cards/examples/issuer",
      "persons": {
        "person0": {
          "name": [
            "John B. Anyperson"
          ],
          "dob": "1951-01-20",
          "immunizations": [
            {
              "vaccine_administered": "MODERNA",
              "date_given": "2021-01-01",
              "lot_number": "0000001"
            },
            {
              "vaccine_administered": "MODERNA",
              "date_given": "2021-01-29",
              "lot_number": "0000007"
            }
          ]
        }
      }
    }
    

    with the expectation that the end result would look like this (abbreviated):

    {
        "cards": {
            "card0": {
                "persons": {
                    "person0": {
                        "person_object": "data goes here"
                    },
                }
            }
        },
        "validation": {
            "person0": "good"
        }
    }  
    

    This seemed fine at the time, but I don't think its flexible enough. For one, it makes the assumption that a given vaksina instance only has a single validator, and well, I can envision user stories where I can see multiple validators may need to be run (i.e., someone having to be checked for multiple criteria for different locations).

    I'm thinking we need to model this list so:

    {
        "cards": {
            "card0": {
                "persons": {
                    "person0": {
                        "person_object": "data goes here"
                    }
                }
            }
        },
        "validations": [
            {
                "validation_method": "osha2022",
                "results": {
                    "person0": "good"
                }
            }
        ]
    }
    

    This might be more a job for the API than the library itself, but I don't want to make this difficult to implement either. It may be worth having REST endpoints for different validations, but that doesn't handle cases where something is interfacing w/ the library directly. I'm undecided on how best to represent the validation results as of right now, or if I should handle it in the core library at all ...

    opened by NCommander 1
Owner
Michael Casadevall
Michael Casadevall
App and Python library for parsing, writing, and validation of the STAND013 file format.

python-stand013 python-stand013 is a Python app and library for parsing, writing, and validation of the STAND013 file format. Features The following i

Oda 3 Nov 9, 2022
validation for pre-commit.ci configuration

pre-commit-ci-config validation for pre-commit.ci configuration installation pip install pre-commit-ci-config api pre_commit_ci_config.SCHEMA a cfgv s

pre-commit.ci 17 Jul 11, 2022
Automation in socks label validation

This is a project for socks card label validation where the socks card is validated comparing with the correct socks card whose coordinates are stored in the database. When the test socks card is compared with the correct socks card(master socks card) the software checks whether both test and master socks card matches or not.

null 1 Jan 19, 2022
CDM Device Checker for python

CDM Device Checker for python

zackmark29 79 Dec 14, 2022
WMIC Serial Checker For Python

WMIC Serial Checker Follow me here: Discord | Github FR: A but éducatif seulement. EN: For educational purposes only. ❓ Informations FR: WMIC Serial C

AkaTool's 0 Apr 25, 2022
Excel cell checker with python

excel-cell-checker Description This tool checks a given .xlsx file has the struc

Paul Aumann 1 Jan 4, 2022
Lightweight Scheduled Blocks Checker for Current Epoch. No cardano-node Required, data is taken from blockfrost.io

ReLeaderLogs For Cardano Stakepool Operators: Lightweight Scheduled Blocks Checker for Current Epoch. No cardano-node Required, data is taken from blo

SNAKE (Cardano Stakepool) 2 Oct 19, 2021
With the initiation of the COVID vaccination drive across India for all individuals above the age of 18, I wrote a python script which alerts the user regarding open slots in the vicinity!

cowin_notifier With the initiation of the COVID vaccination drive across India for all individuals above the age of 18, I wrote a python script which

null 13 Aug 1, 2021
Simple and easy to use python API for the COVID registration booking system of the math department @ unipd (torre archimede)

Simple and easy to use python API for the COVID registration booking system of the math department @ unipd (torre archimede). This API creates an interface with the official browser, with more useful functionalities.

Guglielmo Camporese 4 Dec 24, 2021
Python NZ COVID Pass Verifier/Generator

Python NZ COVID Pass Verifier/Generator This is quick proof of concept verifier I coded up in a few hours using various libraries to parse and generat

NZ COVID Pass Community 12 Jan 3, 2023
🌍💉 Global COVID-19 vaccination data at the regional level.

COVID-19 vaccination data at subnational level. To ensure its officiality, the source data is carefully verified.

sociepy 61 Sep 21, 2022
To check my COVID-19 vaccine appointment, I wrote an infinite loop that sends me a Whatsapp message hourly using Twilio and Selenium. It works on my Raspberry Pi computer.

COVID-19_vaccine_appointment To check my COVID-19 vaccine appointment, I wrote an infinite loop that sends me a Whatsapp message hourly using Twilio a

Ayyuce Demirbas 24 Dec 17, 2022
Repositorio com arquivos processados da CPI da COVID para facilitar analise

cpi4all Repositorio com arquivos processados da CPI da COVID para facilitar analise Organização No site do senado é possivel encontrar a lista de todo

Breno Rodrigues Guimarães 12 Aug 16, 2021
Check COVID locations of interest against Google location history

Location of Interest Checker Script to compare COVID locations of interest to Google location history. The script produces a map plot (as shown below)

null 9 Mar 30, 2022
COVID-19 case tracker in Dash

covid_dashy_personal This is a personal project to build a simple COVID-19 tracker for Australia with Dash. Key functions of this dashy will be to Dis

Jansen Zhang 1 Nov 30, 2021
We are building an open database of COVID-19 cases with chest X-ray or CT images.

?? Note: please do not claim diagnostic performance of a model without a clinical study! This is not a kaggle competition dataset. Please read this pa

Joseph Paul Cohen 2.9k Dec 30, 2022
Howell County, Missouri, COVID-19 data and (unofficial) estimates

COVID-19 in Howell County, Missouri This repository contains the daily data files used to generate my COVID-19 dashboard for Howell County, Missouri,

Jonathan Thornton 0 Jun 18, 2022
🦠 A simple and fast (< 200ms) API for tracking the global coronavirus (COVID-19, SARS-CoV-2) outbreak.

?? A simple and fast (< 200ms) API for tracking the global coronavirus (COVID-19, SARS-CoV-2) outbreak. It's written in python using the ?? FastAPI framework. Supports multiple sources!

Marius 1.6k Jan 4, 2023