This API is currently configured for template policies for DOVU IWA Policies Alpha - 0.1.0
To comply for 0.2.0, request validation classes need to be updated. mainly to use a flat JSON structure.
You can copy env.example
to get you going
cp env.example .env.local
Make sure to have the Guardian API running locally and then fill out the GUARDIAN_API_URL
with the correct URL in your .env.local
file.
For example:
GUARDIAN_API_URL=http://localhost:3000/api/v1
Run yarn and then start the development server. This will default to localhost:3000 but will increment if that port is already busy.
yarn install
yarn dev
We provide a Dockerfile for running the API in a container. You can use the provided docker-compose.yml file to run the API locally. Please note that this builds a production build without any debug information.
Environment variables you have set in .env.local
will be used in the container. This can be changed in the docker-compose.yml file.
Please be aware that in order to reference the Guardian API from within the container, you will need to use the host.docker.internal
hostname in your .env.local
file. This is a special hostname that resolves to the host machine from within the container.
Example:
GUARDIAN_API_URL=http://host.docker.internal:3000/api/v1
The following command will run the Guardian Middleware API on port 3001. You can change this in the docker-compose.yml file if required.
docker-compose up -d --build
yarn lint
yarn format
yarn test
yarn types
All the above can be run together using
yarn ci
If you want to run all the tests, including the e2e tests for your config use:
yarn test:all
A Postman collection is included at the root of the repositorty which will allow you to start testing endpoints. The Postman file includes autogenerated HMAC headers for all requests and will also store the Bearer JWT of the last created/logged in account. All requests will then use this JWT in their Authorization header.
The types for the API are autogenerated based on the Open API spec found at /src/spec/openapi.json
.
When adding a new route follow these steps:
- Update the Open API JSON spec to describe the new route
- Run
yarn codegen
( which uses openapi-typescript) to auto generate the Typescript definitions at/src/spec/openapi.ts
- Add the new route to
pages/api/
and supply the required middleware for the route - Add a new handler for the route in
src/handlers/
- If required, create a new validator for the input in
/src/validators/
This flow allows us to have a strong contract between the Open API spec and the API types. Typescript checks should avoid issues of the API moving out of sync with the documentation.
This OpenAPI extension provides linting and autocomplete tools for editing the Open API spec https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi
The OpenAPI documentation can be found at: http://localhost:3000/docs
The OpenAPI JSON definition can be found at: http://localhost:3000/api/docs
Every request apart from api/status
and api/docs
should include HMAC authentication. We follow Microsoft's HMAC implementation here with a couple of simplifications.
host
: string - "example.com"x-date
: ISO 8601 UTC - "2022-08-01T11:06:23:1234Z"x-content-sha256
: SHA256 string - The SHA256 string of the content bodyx-signature
: HMAC string - The HMAC authentication string as defined below
The Microsoft Docs do a good job explaining the details. The following describes the simplified implementation that we use which avoids dynamic complexities like requiring SignedHeaders
and Credential
headers. Also, since we require the Authorization
header for the Guardian JWT, we instead use an x-signature
header for passing the HMAC signed hash.
Here is an example of how to construct the required HMAC headers to make a successful request:
function signRequest(
host, // Often added to the header by default in HTTP clients - example.com
method, // GET, PUT, POST, DELETE
url, // path+query - /api/posts?order=asc
body, // request body (undefined if none)
secret // The private key used to sign the HMAC content
) {
var verb = method.toUpperCase()
var utcNow = new Date().toUTCString()
// If passing body data then generate a Base64 encoded SHA256 hash
var contentHash = Crypto.createHash('sha256')
.update(JSON.stringify(body))
.digest('base64')
//
// String to sign if including body data. We follow the `\n` and `;` delimiters inline with the Microsoft spec
var stringToSign = `${verb}\n${url}\n${utcNow};${host};${contentHash}`
//
// String to sign if not including body data
var stringToSign = `${verb}\n${url}\n${utcNow};${host}`
//
// Signature - Base64 encoded SHA256 HMAC signed with secret key
var signature = Crypto.createHmac('sha256', secret)
.update(stringToSign)
.digest('base64')
//
// Result request headers
return [
{ name: 'host', value: host },
{ name: 'x-date', value: utcNow },
{ name: 'x-content-sha256', value: contentHash }, // Omit if not including body data
{ name: 'x-signature', value: signature },
]
}
Assumes a Standard Registry account already exists which has published a policy.
- Create A New Registrant Account
- Create A New Verifier Account
- Assign The New Accounts To A Policy
- Login With The Registrant Account
- Submit An Application
- Login With The Standard Registry Account
- Approve The Application
- Login With The Registrant Account
- Submit An Ecological Project
- Login With The Standard Registry Account
- Approve The Ecological Project
- Login With The Registrant Account
- Submit A New MRV Request
- Login With The Verifier Account
- Approve The MRV Request
After the MRV request is approved, tokens will automatically be minted that represent the carbon described in the MRV for this Ecological Project.