---
# System prepended metadata

title: Issuer Kit/Traction Integration

---

# Issuer Kit/Traction Integration

## Issuer Kit

https://github.com/bcgov/issuer-kit.git

Issuer Kit runs the following components:

- api - aca-py controller that can register a new issuer agent (including public did, schema and cred def, etc) and provides services to create an invite, issue credentials etc.
- admin app - UI for an administrator to create "invitations"
- mail server - demo server provides SMTP service for issuer kit
- issuer webapp - UI for holders to "redeem" their credential, connect their wallet to the issuer agent, and receive a credential

The workflow is as follows:

- on startup, the issuer api controller registers the issuer's DID, schema and credential definition
- the administrator - via the admin app - enters a holder's email address and credential data
- issuer kit sends the holder an email with connection info (in the demo scenario you can view this using the demo mail server)
- the holder clicks on the link in the email to connect to the issuer webapp to "redeem" their invitation
- once they confirm the credential data (a series of screens in a browser) they are presented with a QR code they can scan (using their mobile wallet) - this initiates the connection between the issuer agent and mobile wallet, and then automatically issues the credential

To deploy issuer kit, a separate github repo is maintained with the configuration information, for example:

https://github.com/bcgov/identity-kit-configurations.git

In this example, for example, the schema configurations are here:

https://github.com/bcgov/identity-kit-configurations/tree/main/openshift/templates/api/config

Another example - derived from Issuer Kit but adding support for multitenancy - is the Aries VCR (OrgBook) Issuer Agency:

https://github.com/bcgov/aries-vcr-issuer-agency.git

(Note this is not strictly an Issuer Kit example, but the code is derived from Issuer Kit and adds multitenancy support.)

## Traction

https://github.com/bcgov/traction.git

Traction is an aca-py multitenancy agency for business applications (i.e. it is expected that traction users are Line of Business (LOB) systems rather than individuals).

> In a physical wallet, you hold credentials issued by trusted organizations to verify things about you (e.g., your age, bank account balance etc.). Similarly, businesses and organizations interact with each other and individuals using credentials. For example, a company may need to present a mining permit or verify that a job applicant has a degree. Traction is a software agent that allows businesses and organizations to issue, hold, exchange and verify credentials in the digital world.
> 

Traction consists of the following components:

- admin api - provides the ability for an administrator (called an "InnKeeper") to create and manage tenants, including specifying which tenants can become "issuers"
- tenant api - provides the aca-py tenant user access to their aca-py agent to perform SSI functions (connect to other agents, issue credentials, ask for proofs, etc.)

The tenant api provides some "value add" services on top of aca-py (like some workflow services, for example) and provides a simplified set of webooks to notify the LOB about interesting events, but also provides a "wrapper" to the aca-py agent, so that the LOB can call aca-py functions that aren't necessarily exposed throug traction.  (For example the tenant may use this to call aca-py's ledger functions.)

The general workflow is as follows (although traction doesn't mandate any specific workflows, these are just examples):

- The "InnKeeper" creates a new tenant (or tenants) through the admin api; the InnKeeper then sends the tenant's `wallet_id` and `wallet_key` to the tenant "out of band"
- The tenant can connect to the tenant api and use their `wallet_id` and `wallet_key` to obtain a bearer token - the tenant can then use this token to access any traction (or aca-py, via the traction wrapper) endpoint
- The InnKeeper can "invite" a tenant to become an issuer
- The tenant can then "accept the issuer invitation" and update their tenant agent to be able to issue (this includes setting up a connection with an Endorser agent and creating a public DID for the tenant agent)
- The "issuer" tenant can then create any schemas and/or credential definitions for credentials they intend to issue
- Tenant agents can create and accept invitations to connect with other agents (including other traction tenants as well as any other Aries agent)
- "Issuer" tenant agents can issue credentials; any agent can be a holder and respond to credential offers
- Tenant agents can request and (if they are a holder) respond to credential presentations

# Issuer Kit + Traction

Traction could provide Issuer Kit with multi-tenant capabilities.  The main benefit of this would be to allow new issuers to be created without having to deploy anything new in OpenShift.  New issuers could be created within an Issuer Kit/Traction deployment just by creating a new issuer tenant (and configuring any related configuration) through a UI or api.

Issuer Kit provides a streamlined way to setup a new tenant agent to issue credentials - providing a configuration-based approach to setup a new issuer; providing an admin api/UI for an administrator to enter credential information and issue an "invitation"; providing an api/UI for a holder to accept the invitation and receive the credential.

There are two main options for doing this integration:

1. Removing Issuer Kit's embedded aca-py agent, and updating Issuer Kit to connect to a back-end Traction instance
2. Removing the Issuer Kit's back-end API (keep only the two UI's) and add the Issuer Kit back-end functionality to Traction

For option 2, there are 2 sub-options - add the functionality to traction directly, or add the function as a plug-in (so it could be optionally included in a Traction deployment).

In either scenario, Issuer Kit would need to be updated to include a mechanism to create a new issuer agent (via Traction's multitenancy support).

## Issuer Kit/Traction Option 1

Removing Issuer Kit's embedded aca-py agent, and updating Issuer Kit to connect to a back-end Traction instance:

```plantuml
artifact Issuer_Kit_Web_App {
  folder AgencyAdmin #Green
  folder IssuerAdmin
  folder Holder
}
artifact Issuer_Kit_API {
    folder Manage_Tenants #Green
    folder Initialize_Issuer
    folder Manage_Invitations
    folder Issue_Credentials
    database Issuer_DB
}
AgencyAdmin -down-> Manage_Tenants
IssuerAdmin -down-> Initialize_Issuer
IssuerAdmin -down-> Manage_Invitations
Holder -down-> Issue_Credentials
artifact Traction {
    folder InnKeeper
    folder Tenant
    database Traction_DB
}
Manage_Tenants -down-> InnKeeper
Initialize_Issuer -down-> Tenant
Manage_Invitations -down-> Tenant
Issue_Credentials -down-> Tenant
```

In the above diagram the `Green` components reflect the new additions to Issuer Kit - basically the functionality to add and maintain new tenant issuer agents.  The remaining Issuer Kit functionality would need to be updated to call Traction API's instead of Aca-py directly.  (There *may* be some additions required to Traction, and some modifications of Issuer Kit API functionality, but the basic architecture/implementation would remain the same.)

## Issuer Kit/Traction Option 2

Removing the Issuer Kit's back-end API (keep only the two UI's) and add the Issuer Kit back-end functionality to Traction:

```plantuml
artifact Issuer_Kit_Web_App {
  folder AgencyAdmin #Green
  folder IssuerAdmin
  folder Holder
}
artifact Issuer_Kit_API {
    folder Manage_Tenants #Green
    folder Initialize_Issuer #Red
    folder Manage_Invitations #Red
    folder Issue_Credentials #Red
    database Issuer_DB #Red
}
AgencyAdmin -down-> Manage_Tenants
IssuerAdmin -down-> Initialize_Issuer
IssuerAdmin -down-> Manage_Invitations
Holder -down-> Issue_Credentials
artifact Traction {
    folder InnKeeper
    folder Tenant {
        component Issuer_Workflow_New #Green
    }
    database Traction_DB
}
Manage_Tenants -down-> InnKeeper
Initialize_Issuer -down-> Tenant
Manage_Invitations -down-> Tenant
Issue_Credentials -down-> Tenant
```

In the above diagram the `Green` components reflect the new additions to Issuer Kit - basically the functionality to add and maintain new tenant issuer agents - and the `Red` components reflect components that will drastically change.

Traction will require a new workflow - and related API's - to implement the Issuer Kit invitation/credential issue process (and possibly some additional functionality to support the auto-provisioning of issuers).  Issuer Kit API functionality will be reduced, as they will be leveraging functionality in Traction rather than having to implement the functionality themselves.

Note that an Issuer Kit API component will *likely* still be required, as it will provide the interface required to support the Web UI's.  (Theoretically the Web UI's could call Traction API's directly, this can be decided during implementation.)

The new Traction workflow to support the invitation/credential issue process *could* be implemented as a plug-in - this would require a general plug-in architecture to be designed for Traction, and may be a suitable feature for a second phase of development.

## Issuer Kit Deployment

The current process for deploying a new instance of Issuer Kit involves creating a new configuration repository (examples are provided at the top of this document) that contains openshift plus Issuer Kit-specific configs.

With multi-tenant capabilities, Issuer Kit deployment *could* be simplified.  The existing deployment process *could* be maintained (i.e. use a common deployment for Traction, but many individual Issuer Kit deployments that each connect to a tenant in Traction), *or* a single multi-tenant Issuer Kit/Traction deployment could support multiple Issuer Kit "instances".  In the latter scenario, new Issuer instances would be added via API calls rather than new config repo's and deployments.

## Issuer Kit UI Security

Depending on the Issuer Kit deployment model, the Issuer Kit UI components will need to implement a security model, so that the UI can determine the tenant agent associated with the user.

If the current deployment model is maintained (i.e. Issuer Kit is deployed separately from Traction, and a separate deployment is used for each Issuer), then the Issuer Kit Web UI/API will have to maintain the Traction tenant information (`wallet_id` and `wallet_key`) in order to authenticate, however there will be no impact to the end-user.

However if a single multi-tenant Issuer Kit deployment is used, then the user will have to authenticate to identify their tenant wallet:

- For administrators (creating and maintaining invitations) this may involve a user id and password (or a VC-based authentication using a credential they are issued when their issuer is created).
- For holders, this information could be embedded in their invitation, so when they redeem the invitation (to connect and receive their credential) Issuer Kit could use infomation in their invitation to connect them to the appropriate tenant wallet.

# Recommended Approach

The recommendation (from ianco) is:

- update Issuer Kit to call Traction instead of Aca-py (adding functionality to Traction and re-factoring Issuer Kit could be a later phase)
- update Issuer Kit to support multi-tenancy
- update Issuer Kit so that a single deployment can support multiple issuers (i.e. new issuers can be added via admin functionality)
- add a new (third) Issuer Kit UI (Agency) to support adding new Issuers
- add security to each Issuer Kit UI (TODO review vs the existing KeyCloak functionality):
    - Agency UI - use a configured id/password
    - Tenant Issuer Admin UI - create an id/password for each tenant agent (note - alternative is to issue an identification credential and use VC auth to access the UI)
    - Holder UI - embed agent identification into the invitation

# Implemented Approach

## Phase 1 - Replace aca-py with traction (single tenant)

For the initial Traction integration, the dedicated aca-py instance was replaced with a Traction instance.  On startup, Issuer Kit creates a single Traction tenant, and then uses this tenant as the Issuer agent.  This is still a single-tenant installation (effectively) but it lays the foundation to start creating additional Issuer instances within the same Issuer Kit/Traction installation.

Isser Kit by default will still run in single-aca-py mode:

```
./manage start-demo
```

... however you can *also* run in "traction" mode:

```
ACAPY_AGENT_MODE=TRACTION ./manage start-demo
```

Internally, Issuer Kit will check which "mode" it is running and will format services requests for aca-py or traction respectively.  Internally, the `api/src/utils/aca-py.ts` utility class handles most of the "aca-py vs traction" logic, so for the rest of the code it's fairly transparent.

## Phase 2 - Add multi-tenant support (TODO)
