An open-source platform to demonstrate the capabilities of a Granular Certificate registry that conforms to the EnergyTag Standards and API specification.
The GC Registry is designed to be downloaded and operated locally either through a Docker container, or through manual package loading for development purposes. In addition, a persistent instance will be available on GCP for non-technical users to interact with the front end.
Dependency management is handled through Poetry - on first use, run poetry install
to initialise the required packages.
To get started interfacing with the GC Registry container, follow these steps to get started, using your IDE and API messenger of choice:
- Make sure you have the Docker daemon running, either through Docker desktop or the CLI.
- Create a
.env
file in the root directory and populate it with the example values in the.env.example
file provided. Make any configuration edits as required here. - On first use, from the root directory run
docker compose -f compose.override.yml up --build
to build the image and run the container cluster. The cluster is composed of four containers:gc_registry
- the FastAPI app and backend services for the registryeventsotre
- an open-source streaming database that sequentially records registry events immutablypostgres_db_write
- a Postgres database container using the official image that receives write operations from the registrypostgres_db_read
- the parallel read Postgres instance that is written to simultaneously to the write instance, in order to optimise the concurrent processing of read operations without being detrimental to the performance of write operations.
- By default, the container port mappings are:
- The
gc_registry
FastAPI app -8000
- The
eventstore
instance GUI -2113
- The Postgres write intance -
5436
- The Postgres read instance -
5438
- The
- Documentation comes in two flavours:
localhost:8000/docs
- Swagger-style schema and endpoint descriptions that allows basic interaction with APIlocalhost:8000/redoc
- alternative, non-interactive documentation from Redocly that is more human-readable than Swagger
- This repository uses a makefile for quick access to convenience functions that are common across both users and developers. For instance,
make dev
will quickly call Docker compose to load up the container cluster. - On first build, the database containers will not contain the schemas for the entities. We have used
alembic
to manage the schema migrations and for ease of setting up - usemake db.update
to load in the most recent schema to the database.- If during development you make any changes to the
sqlmodel
entity definitions, you can quickly reflect that change in the database by runningmake db.revision "NAME={name_your_revision}"
, with a suitably descriptive name for the intended changes in place ofname_your_revision
. - This will create a new migration file in
gc_registry/core/alembic/versions
, and we recommend double checking the contents of this auto-generated file before committing it to the database withmake db.update
. - The database can be fully reset using
make db.reset
; this will clear all entities in both database instances and reset the schema to the most recent iteration.
- If during development you make any changes to the
- Initially, the database instances will contain no elements. To get started quickly, we recommend seeding the database with some example User, Account, Device, and GC Bundle entities courtesy of Elexon (the UK aggregator of electricity system data) with the command
make db.seed
.
Each entity has the four basic crud operation endpoints accessible through the lower case singular name of the entity as the router and the operation or ID as the suffix. For example, either through Postman to localhost:8000
or through a notebook with client = httpx.Client("localhost:8000)
GET(account/1)
will return the account with ID 1, which in this case would be first account created on the registry as the integer ID primary keys are unique and serial across each entity.- Creating an entity is possible by passing jsons programmatically, or manually through the payload entry on Postman:
This will create an account with the name
import json account = {"account_name": "Example Account", "user_ids": [1], "account_whitelist": [1]} client.post("account/create", data=json.dumps(account))
Example Account
, belonging to the user with ID1
, and has whitelisted the account with ID1
to receive GC Bundles from. - Querying certificates is done through the
certificates/query
POST endpoint, and allows for advanced requests to be expressed through theCertificateQuery
object, the schema for which can be found in the docs. - To enforce a safe workflow whereby registry users do not unintentially apply certificate lifecycle actions such as
transfer
andcancel
to bundles using blind queries, these actions only accept lists of certificate bundle IDs (not to be confused with the bundle range IDs that identify the individual Wh within each bundle). This encourages users to first run aquery
, confirm that the GC Bundles returned are those that they wish to operate on, and then pass the bundle IDs to the mutation endpoint to perform the intended action on those GC bundles.
The registry contains numerous validation steps to ensure that double counting risk is mitigated. Some additional mechanisms that have been included to mirror the operation of existing registries include:
- Accounts can only transfer GC Bundles to another account if the target account has whitelisted the source account. This can be achieved through the
account/update_whitelist
endpoint.
The main technological choices for the application include:
- Language: Python
- Framework: FastAPI
- Database: PostgreSQL (Local instances)
- Models/types: Pydantic (As specified in the EnergyTag API specification code)
- ORM: SQLModel (abstraction of SQLAlchemy)
- Frontend: React/Node.js with Axios for HTTP requests to FastAPI backend
Development tools:
- Dependency/Environment management: Poetry
- Database migrations: Alembic
- Test runner: Pytest
- Code linting/formatting: Ruff
- CI/CD: GitHub Actions
- Versioning: Python Semantic release
- Deployment: Docker and Docker Compose
I want to know about... | |
---|---|
Development | Linting, formatting, testing etc |
Contributing | Our processes for contributors |
Change Log | Log of code changes |