diff --git a/main/search/search_index.json b/main/search/search_index.json
index 528b1f081..f143dcba7 100644
--- a/main/search/search_index.json
+++ b/main/search/search_index.json
@@ -1 +1 @@
-{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Aries Cloud Agent Python Plugins","text":"This repository contains approved and tested plugins for Aries Cloud Agent Python (ACA-Py). This is to encourage collaboration and sharing of useful features not directly included in ACA-Py.
"},{"location":"#developer-notes","title":"Developer Notes","text":"The easiest way to develop and test ACA-Py plugins is to use the DevContainer configured in this repository.
- Open devcontainer in VS Code
- Python and all dependencies will be loaded
- Poetry will be loaded and configured, dependencies will be installed
- Docker and Docker Compose will be available
"},{"location":"#repo-management-script","title":"Repo Management Script","text":"A script was developed to help with maintenance of the repo called repo_manager.py
. To run it you need a current version of poetry and python available.
Run python repo_manager.py
and you will be met with a number of options. Run the options as needed.
- (1) Is used for starting or adding a new plugin. It will generate all the common scaffolding for a plugin which has the expected format.
- (2) Is used for updating and changing common poetry dependencies and configurations. It takes the poetry sections in the
pyproject.toml
files from the plugin_globals
directory and combines them with the local plugin poetry sections. For the dependencies the common will be overridden by the globals. The other config sections will be replaced by the global configs. Then the lock files will be removed and re-installed. - (3) Is used for updating the plugin versions in the
plugin_globals
directory. It will update the versions of the plugins in the plugin_globals
directory to the latest version on the main branch of the plugin repo. It will also update the plugin_globals
directory to the latest version on the main branch of the plugin repo. - (4) This option is used by the CI/CD release pipeline. It updates the release notes and the individual plugins with a new version of ACA-Py.
- (5) This option is also used by the CI/CD release pipeline. It gets any plugins that have succeeded the tests after a new version of ACA-Py has been released if their changes were not reverted than the plugin has been updated to the new version of ACA-Py.
- (6) This option will run a general update for all poetry lock files in all plugins.
- (7) This option is used for upgrading a particular library for all plugins. It's useful for when you don't want to do a general upgrade for every library.
"},{"location":"#lite-plugins","title":"Lite plugins","text":"Sometimes is desirable to have a plugin that doesn't need integration tests or extra scaffolding. However, we need a way to avoid these plugins running integration tests in the CI/CD pipeline. To do this, we can simply add the plugin name to the lite_plugins
file, a line-separated list of plugin names.
"},{"location":"#plugin-documentation","title":"Plugin Documentation","text":"Plugin developers SHOULD describe what the plugin does, any limitations (ex only in multitenant mode), any known issues interacting with other plugins, etc. Full documentation including a plugin_config sample should be provided.
This documentation should be provided in your plugin root as a README.md file, with at least a Description
and Configuration
section.
"},{"location":"#build-and-run","title":"Build and Run","text":"Each plugin (that is not a Lite Plugin) MUST include a Dockerfile (such as Dockerfile) to run integration tests. This image is not intended for production as it copies the plugin source and loads its dependencies (including ACA-Py) along with a simplistic ACA-Py configuration file, (such as default.yml).
"},{"location":"#run-and-debug","title":"Run and Debug","text":"In the devcontainer, we can run an ACA-Py instance with our plugin source loaded and set breakpoints for debug (see launch.json
).
To run your ACA-Py code in debug mode, go to the Run and Debug
view, select \"Run/Debug Plugin\" and click Start Debugging (F5)
. Using the default.yml
for the plugin (such as default.yml), your agent swagger is available at http://localhost:3001/api/doc.
"},{"location":"#testing","title":"Testing","text":"For the plugin to be accepted into this repo it must have adequate testing.
"},{"location":"#unit-testing","title":"Unit Testing:","text":" - There should be adequate unit testing coverage. A coverage report is created when
poetry run pytest .
in ran from the devcontainer. A good mark to aim for is 90% but the quality of the tests on critical sections is more important than coverage percentage. - Mocking can be challenging. Study the existing plugins in this repo and ACA-Py in general for good examples of mocks and fixtures.
- Put your unit tests in a tests folder in your plugin version path and name all files and test with the
test_
prefix.
"},{"location":"#integration-testing","title":"Integration Testing:","text":" - Plugins SHOULD have a suite of integration tests. The base suite will be created for your plugin after running the updater script. Plugins that don't have integrations must be flagged as being a Lite Plugin.
- An Integration
README
(such as integration tests) SHOULD describe the set of integration tests. When you generate a new plugin, you should have everything you need to start integration testing and a sample test will be provided.
"},{"location":"#deploy","title":"Deploy","text":"For production use, plugins should be installed as libraries to an ACA-Py image.
This requires having a Dockerfile and a config file for your agent.
Example Dockerfile:
FROM ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.11.0\n\nUSER root\n\n# install plugins as binaries\nRUN pip install git+https://github.com/hyperledger/aries-acapy-plugins@main#subdirectory=basicmessage_storage\nRUN pip install git+https://github.com/hyperledger/aries-acapy-plugins@main#subdirectory=connection_update\n\nUSER $user\nCOPY ./configs configs\n\nCMD [\"ACA-Py\"]\n
Example config file (local single tenant):
label: plugins-agent\n\nadmin-insecure-mode: true\nadmin: [0.0.0.0, 9061]\n\ninbound-transport:\n - [http, 0.0.0.0, 9060]\noutbound-transport: http\nendpoint: http://host.docker.internal:9060\n\ngenesis-url: http://test.bcovrin.vonx.io/genesis\n\nemit-new-didcomm-prefix: true\nwallet-type: askar\nwallet-storage-type: default\n\nauto-provision: true\ndebug-connections: true\nauto-accept-invites: true\nauto-accept-requests: true\nauto-ping-connection: true\nauto-respond-messages: true\n\nlog-level: info\n\nplugin:\n - basicmessage_storage.v1_0\n - connection_update.v1_0\n
Now you can deploy a agent with as many plugins as you want as long as they are declared in your build config file and installed.
docker build -f <Dockerfile> --tag acapy_plugins .\ndocker run -it -p 9060:9060 -p 9061:9061 --rm acapy_plugins start --arg-file=<config-file> -->\n
"},{"location":"CONTRIBUTING/","title":"How to Contribute","text":""},{"location":"CONTRIBUTING/#how-to-contribute","title":"How to contribute","text":"You are encouraged to contribute to the repository by forking and submitting a pull request.
For significant changes, please open an issue first to discuss the proposed changes to avoid re-work.
"},{"location":"DOCSITE/","title":"ACA-Py Plugins Documentation","text":"The documentation site for the ACA-Py plugins can be found at: https://hyperledger.github.io/aries-acapy-plugins.
"},{"location":"DOCSITE/#managing-the-documentation-site","title":"Managing the Documentation Site","text":"The documentation site is sourced from this repo and generated by the publish-docs
GitHub Action. That action:
- Checkouts out the repo at
main
- Installs Mkdocs Material
- Runs the script in the repo
setupDocs.sh
, which - Creates the
docs
folder - Populates the
docs
with all of the root level Markdown files - Creates a folder for each plugin and copies it's
README.md
- Generates a complete
mkdocs.yml
file with navigation
- Runs the
mkdocs
mike
extension to generate the site to thwe gh-pages
branch for deployment with GitHub pages
If you want to change how the doc site looks, edit the setupDocs.sh
file and the mkdocs.yml
portion of the script for both look and feel and navigation. Most of the script is just redirect plain text into the mkdocs.yml
file, although there is a little bash script to, for example, generate the navigation for all of the plugins. If you want to edit the content displayed on the site, edit the markdown files in this repo.
"},{"location":"DOCSITE/#testing-the-documentation-site","title":"Testing the Documentation Site","text":"To test the documentation site locally, follow the instructions on the Mkdocs Material to install mkdocs
locally and run it. When you are ready, run:
./setupDocs.sh\nmkdocs\n
You should have the site up at http://localhost:8000/
.
The /docs
folder and mkdocs.yml
file are .gitignore
d in this repo, but if you want to get rid of them, you can use the following to clean them up.
./setupDocs.sh clean\n
"},{"location":"LICENSE/","title":"License","text":" Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
Definitions.
\"License\" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
\"Licensor\" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
\"Legal Entity\" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, \"control\" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising permissions granted by this License.
\"Source\" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
\"Object\" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
\"Work\" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
\"Derivative Works\" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
\"Contribution\" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, \"submitted\" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as \"Not a Contribution.\"
\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
-
Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
-
Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
-
Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
\u00a9 You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a \"NOTICE\" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
-
Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
-
Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
-
Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
-
Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
-
Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0\n
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
"},{"location":"MAINTAINERS/","title":"Maintainers","text":""},{"location":"MAINTAINERS/#maintainer-scopes-github-roles-and-github-teams","title":"Maintainer Scopes, GitHub Roles and GitHub Teams","text":"Maintainers are assigned the following scopes in this repository:
Scope Definition GitHub Role GitHub Team Admin Admin aries-admins Maintainer The GitHub Maintain role Maintain aries-cloudagent-python committers Triage The GitHub Triage role Triage aries triage Read The GitHub Read role Read Aries Contributors"},{"location":"MAINTAINERS/#active-maintainers","title":"Active Maintainers","text":"GitHub ID Name Scope LFID Discord ID Email Company Affiliation amanji Akiff Manji Maintainer BC Gov andrewwhitehead Andrew Whitehead Maintainer BC Gov chumbert Clement Humbert Maintainer SICPA dbluhm Daniel Bluhm Indicio PBC dhh1128 Daniel Hardman Maintainer Provenant ianco Ian Costanzo Anonymous Systems jamshale Jamie Hale Maintainer BC Gov Jsyro Jason Syrotuck BC Gov shaangill025 Shaanjot Gill BC Gov swcurran Stephen Curran Maintainer BC Gov TelegramSam Sam Curren Maintainer Indicio PBC TimoGlastra Timo Glastra Animo Solutions WadeBarnes Wade Barnes Maintainer BC Gov usingtechnology Jason Sherman BC Gov"},{"location":"MAINTAINERS/#the-duties-of-a-maintainer","title":"The Duties of a Maintainer","text":"Maintainers are expected to perform the following duties for this repository. The duties are listed in more or less priority order:
- Review, respond, and act on any security vulnerabilities reported against the repository.
- Review, provide feedback on, and merge or reject GitHub Pull Requests from Contributors.
- Review, triage, comment on, and close GitHub Issues submitted by Contributors.
- When appropriate, lead/facilitate architectural discussions in the community.
- When appropriate, lead/facilitate the creation of a product roadmap.
- Create, clarify, and label issues to be worked on by Contributors.
- Ensure that there is a well defined (and ideally automated) product test and release pipeline, including the publication of release artifacts.
- When appropriate, execute the product release process.
- Maintain the repository CONTRIBUTING.md file and getting started documents to give guidance and encouragement to those wanting to contribute to the product, and those wanting to become maintainers.
- Contribute to the product via GitHub Pull Requests.
- Monitor requests from the Hyperledger Technical Oversight Committee about the contents and management of Hyperledger repositories, such as branch handling, required files in repositories and so on.
- Contribute to the Hyperledger Project's Quarterly Report.
"},{"location":"MAINTAINERS/#becoming-a-maintainer","title":"Becoming a Maintainer","text":"This community welcomes contributions. Interested contributors are encouraged to progress to become maintainers. To become a maintainer the following steps occur, roughly in order.
- The proposed maintainer establishes their reputation in the community, including authoring five (5) significant merged pull requests, and expresses an interest in becoming a maintainer for the repository.
- A PR is created to update this file to add the proposed maintainer to the list of active maintainers.
- The PR is authored by an existing maintainer or has a comment on the PR from an existing maintainer supporting the proposal.
- The PR is authored by the proposed maintainer or has a comment on the PR from the proposed maintainer confirming their interest in being a maintainer.
- The PR or comment from the proposed maintainer must include their willingness to be a long-term (more than 6 month) maintainer.
- Once the PR and necessary comments have been received, an approval timeframe begins.
- The PR MUST be communicated on all appropriate communication channels, including relevant community calls, chat channels and mailing lists. Comments of support from the community are welcome.
- The PR is merged and the proposed maintainer becomes a maintainer if either:
- Two weeks have passed since at least three (3) Maintainer PR approvals have been recorded, OR
- An absolute majority of maintainers have approved the PR.
- If the PR does not get the requisite PR approvals, it may be closed.
- Once the add maintainer PR has been merged, any necessary updates to the GitHub Teams are made.
"},{"location":"MAINTAINERS/#removing-maintainers","title":"Removing Maintainers","text":"Being a maintainer is not a status symbol or a title to be carried indefinitely. It will occasionally be necessary and appropriate to move a maintainer to emeritus status. This can occur in the following situations:
- Resignation of a maintainer.
- Violation of the Code of Conduct warranting removal.
- Inactivity.
- A general measure of inactivity will be no commits or code review comments for one reporting quarter. This will not be strictly enforced if the maintainer expresses a reasonable intent to continue contributing.
- Reasonable exceptions to inactivity will be granted for known long term leave such as parental leave and medical leave.
- Other circumstances at the discretion of the other Maintainers.
The process to move a maintainer from active to emeritus status is comparable to the process for adding a maintainer, outlined above. In the case of voluntary resignation, the Pull Request can be merged following a maintainer PR approval. If the removal is for any other reason, the following steps SHOULD be followed:
- A PR is created to update this file to move the maintainer to the list of emeritus maintainers.
- The PR is authored by, or has a comment supporting the proposal from, an existing maintainer or Hyperledger GitHub organization administrator.
- Once the PR and necessary comments have been received, the approval timeframe begins.
- The PR MAY be communicated on appropriate communication channels, including relevant community calls, chat channels and mailing lists.
- The PR is merged and the maintainer transitions to maintainer emeritus if:
- The PR is approved by the maintainer to be transitioned, OR
- Two weeks have passed since at least three (3) Maintainer PR approvals have been recorded, OR
- An absolute majority of maintainers have approved the PR.
- If the PR does not get the requisite PR approvals, it may be closed.
Returning to active status from emeritus status uses the same steps as adding a new maintainer. Note that the emeritus maintainer already has the 5 required significant changes as there is no contribution time horizon for those.
"},{"location":"RELEASES/","title":"Plugin Release Status","text":""},{"location":"RELEASES/#aca-py-release-100","title":"ACA-Py Release 1.0.0","text":"Plugin Name Supported ACA-Py Release basicmessage_storage 1.0.0 connection_update 1.0.0 firebase_push_notifications 1.0.0 jwt_vc_json 1.0.0 kafka_events 0.12.2 mso_mdoc 1.0.0 multitenant_provider 1.0.0 oid4vci 1.0.0 redis_events 1.0.0 rpc 1.0.0"},{"location":"RELEASES/#plugins-upgraded-for-aca-py-release-100","title":"Plugins Upgraded For ACA-Py Release 1.0.0","text":" - basicmessage_storage
- connection_update
- firebase_push_notifications
- jwt_vc_json
- mso_mdoc
- multitenant_provider
- oid4vci
- redis_events
- rpc
"},{"location":"RELEASES/#aca-py-release-0122","title":"ACA-Py Release 0.12.2","text":"Plugin Name Supported ACA-Py Release basicmessage_storage 0.12.2 connection_update 0.12.2 firebase_push_notifications 0.12.2 jwt_vc_json 0.12.2 kafka_events 0.12.2 mso_mdoc 0.12.2 multitenant_provider 0.12.2 oid4vci 0.12.2 redis_events 0.12.2 rpc 0.12.2"},{"location":"RELEASES/#plugins-upgraded-for-aca-py-release-0122","title":"Plugins Upgraded For ACA-Py Release 0.12.2","text":" - basicmessage_storage
- connection_update
- firebase_push_notifications
- jwt_vc_json
- kafka_events
- mso_mdoc
- multitenant_provider
- oid4vci
- redis_events
- rpc
"},{"location":"RELEASES/#aca-py-release-0121","title":"ACA-Py Release 0.12.1","text":"Plugin Name Supported ACA-Py Release basicmessage_storage 0.12.1 connection_update 0.12.1 firebase_push_notifications 0.12.1 kafka_events 0.12.1 multitenant_provider 0.12.1 oid4vci 0.12.1 redis_events 0.12.1 rpc 0.12.1"},{"location":"RELEASES/#plugins-upgraded-for-aca-py-release-0121","title":"Plugins Upgraded For ACA-Py Release 0.12.1","text":" - basicmessage_storage
- connection_update
- firebase_push_notifications
- kafka_events
- multitenant_provider
- oid4vci
- redis_events
- rpc
"},{"location":"basicmessage_storage/","title":"Basic Message Storage","text":""},{"location":"basicmessage_storage/#description","title":"Description","text":" - v1_0:
- Uses a middleware wrapper around the existing basicmessage
connections/{id}/send-message
api, and will persist the sent message. - Messages between all agents/connections can be fetched via
GET /basicmessages
with optional query params for connection_id
and state
. - single messages can be deleted via
DELETE /basicmessages/{message_id}
- subwallets can disable message storages by setting
extra_settings:{\"basicmessage-storage\":{\"wallet_enabled\":false}}
in the body of /multitenancy/wallet/{wallet_id}
"},{"location":"basicmessage_storage/#configuration","title":"Configuration","text":" - No additional configuration required.
"},{"location":"connection_update/","title":"Connection Update","text":""},{"location":"connection_update/#description","title":"Description","text":" - v1_0
- Creates a new endpoint PUT /connections/{conn_id} that allows a controller to update the connection alias label.
"},{"location":"connection_update/#configuration","title":"Configuration","text":" - No additional configuration required.
"},{"location":"firebase_push_notifications/","title":"Firebase Push Notifications","text":""},{"location":"firebase_push_notifications/#description","title":"Description","text":"Only to be used with a mediator agent.
Allows mobile agents to send firebase tokens to the mediator service. The mediator service creates a connection with the firebase server and will relay push notifications to the mobile agent on mediator forwarding events on the event_bus.
"},{"location":"firebase_push_notifications/#initialization","title":"Initialization","text":"sequenceDiagram\nparticipant Mobile\nparticipant Mediator\nNote left of Mobile: Logs In\nNote left of Mobile: Checks if already registered\nMobile->>Mediator: Do you support firebase protocol?\nMediator->>Mobile: No\nNote left of Mobile: Do Nothing\nMediator->>Mobile: Yes\nNote left of Mobile: Open notification Permission Modal\nMobile->>Mobile: User says \"not now\"\nNote left of Mobile: Close Modal and set user denied to true\nMobile->>Mobile: User says \"Allow\"\nMobile->>Mediator: Send device token\nNote right of Mediator: Save device token for conenction\nMobile->>Mobile: OS permissions popup\nNote left of Mobile: Approve or deny OS level permission
"},{"location":"firebase_push_notifications/#new-message","title":"New Message","text":"sequenceDiagram\nparticipant Agent (Faber)\nparticipant Mediator\nparticipant Mobile (Alice)\nparticipant Firebase\nNote left of Agent (Faber): Wants to send message to Mobile (Alice)\nAgent (Faber)->>Mediator: Message\nMediator->>Mobile (Alice): Message\nMediator->>Mediator: Receives Forwarding event in aca-py\nNote right of Mediator: Get device token for connection\nMediator->>Mediator: token is blank or None\nNote right of Mediator: Do nothing\nMediator->>Mediator: message sent withing 'n' minutes\nNote right of Mediator: Do nothing\nMediator->>Mediator: Token exists\nMediator->>Firebase: Request: Send OS notification to token\nFirebase->>Mobile (Alice): Sends OS notification
"},{"location":"firebase_push_notifications/#disableenable","title":"Disable/Enable","text":"sequenceDiagram\nparticipant Mobile\nparticipant Mediator\nMobile->>Mediator: Sends blank token\nNote right of Mediator: Saves blank token (disabled)\nMobile->>Mediator: Sends device token\nNote right of Mediator: Saves device token (enabled)
"},{"location":"firebase_push_notifications/#configuration","title":"Configuration","text":"To use the push notification protocol plugin you must have a firebase project to send the notifications to and a service account json file with Firebase Service Management Service Agent
roles.
In the project .env file you need to supply the information in the Firebase Plugin Configuration
section.
USE_FIREBASE_PLUGIN=true\nFIREBASE_PROJECT_ID=287275049656\nFIREBASE_NOTIFICATION_TITLE=You have important information in your digital wallet\nFIREBASE_NOTIFICATION_BODY=Please open your wallet\nFIREBASE_SERVICE_ACCOUNT={ flattend service account json }\n
FIREBASE_PROJECT_ID
can be found in the firebase console FIREBASE_NOTIFICATION_TITLE
and FIREBASE_NOTIFICATION_BODY
is the information displayed in the push notification
"},{"location":"kafka_events/","title":"Kafka Events","text":"This plugin contains the components needed for ACA-Py to use Kafka for inbound and outbound message queuing and events.
"},{"location":"kafka_events/#installation-and-usage","title":"Installation and Usage","text":"When starting up ACA-Py, load the plugin along with any other startup parameters.
aca-py start --plugin kafka_events # ... the remainder of your startup arguments\n
"},{"location":"kafka_events/#plugin-configuration","title":"Plugin configuration","text":"This is an open door to configure the kafka client to produce and consume records. Kafka has several configuration beyond the URL of the service.
An example configuration for the plugin can be found in example-config.yml
.
"},{"location":"kafka_events/#running-with-configuration","title":"Running with configuration","text":"aca-py start \\\n --plugin kafka_events \\\n --plugin-config plugins-config.yaml \\\n # ... the remainder of your startup arguments\n
"},{"location":"kafka_events/#consuming-didcomm-messages","title":"Consuming DIDComm messages","text":"Messages produced by this plugin contain metadata in addition to the encrypted DIDComm message. Messages look like:
{\n \"service\": {\"url\": \"recipient url\"},\n \"metadata\": {...},\n \"payload\": \"encrypted_and_packed_didcomm_message\"\n}\n
Metadata contain, amongst other things, the plaintext version of the DIDComm message; be cautious and only send the payload
content over the wire to the DIDComm recipient.
"},{"location":"multitenant_provider/","title":"Multi-Tenant Provider","text":""},{"location":"multitenant_provider/#description","title":"Description","text":"Provides support for multiple tenants by creating jwt based authentication tokens for each tenant wallet.
This plugin requires that ACA-Py is running in multi-tenant mode. this plugin will load a new Profile Manager in place of the one loaded by ACA-Py, and subsequent calls for a Multi-tenant Profile Manager will use the class configured in this plugin.
The default manager classes provided in this plugin allow multiple tokens per wallet.
The class_name
is the fully qualified class name/path. The always_check_provided_wallet_key
indicates whether we should check provided wallet_key values (required or not) when creating a token.
"},{"location":"multitenant_provider/#configuation","title":"Configuation","text":"# Multi-tenancy\nmultitenant: true\njwt-secret: insecure-jwt-secret\nmultitenant-admin: true\n\nplugin:\n # load this plugin, note multitenant must be true\n - multitenant_provider.v1_0\n\nplugin-config-value:\n - multitenant_provider.manager.class_name=\"multitenant_provider.v1_0.manager.BasicMultitokenMultitenantManager\"\n - multitenant_provider.manager.always_check_provided_wallet_key=true\n
The expiry time for the token is also configurable. By default, a token is valid for 52 weeks. Possible units are weeks, days, hours, minutes. The following example will build tokens that expire in 30 minutes.
plugin-config-value:\n - multitenant_provider.token_expiry.units=days\n - multitenant_provider.token_expiry.amount=1\n
And we can configure whether to throw an error when a managed wallet passes in a wallet key when getting a token (default is true).
plugin-config-value:\n - multitenant_provider.errors.on_unneeded_wallet_key=true\n
"},{"location":"multitenant_provider/#askar-vs-indy-sdk-storage","title":"Askar vs Indy SDK Storage","text":"NOTE: The Indy SDK has been removed from ACA-Py and should not be used.
There are 2 multitoken manager classes provided in this plugin: one for indy wallet types, one for askar wallet types. If there is no specific configuration provided for multitenant_provider.manager.class_name
, we will look at the wallet_type
(not multitenancy-config.wallet_type
). If wallet_type=askar
then we will load multitenant_provider.v1_0.manager.AskarMultitokenMultitenantManager
else we will load multitenant_provider.v1_0.manager.BasicMultitokenMultitenantManager
.
"},{"location":"multitenant_provider/#build-and-run","title":"Build and Run","text":"cd docker\ndocker build -f ./Dockerfile --tag multitenant_provider ..\ndocker run -it -p 3000:3000 -p 3001:3001 --rm multitenant_provider\n
"},{"location":"oid4vc/","title":"OpenID4VCI Plugin for ACA-Py","text":"This plugin implements OpenID4VCI (Draft 11). The OpenID4VCI specification is in active development, as is this plugin. Consider this plugin experimental; endpoints and records may change to reflect upstream changes in the specification.
"},{"location":"oid4vc/#openid4vci-plugin-demo-with-sphereon-wallet","title":"OpenID4VCI Plugin Demo with Sphereon Wallet","text":""},{"location":"oid4vc/#demo-overview","title":"Demo Overview","text":"This repository showcases a simplified demonstration of the OID4VCI (OpenID for Verifiable Credential Issuers) integration with the Sphereon Wallet app. Follow the steps below to run the demo successfully.
"},{"location":"oid4vc/#prerequisites","title":"Prerequisites","text":" - Sphereon Wallet App on your mobile device
- Docker + Docker Compose
- Ngrok Account (free tier is okay)
"},{"location":"oid4vc/#steps-to-run-the-demo","title":"Steps to Run the Demo","text":"First, you'll have to get your authtoken from ngrok. Note this value down.
cd oid4vc/demo\ndocker-compose build\necho \"NGROK_AUTHTOKEN=<PASTE YOUR AUTHTOKEN HERE>\" > .env\ndocker-compose up\ndocker-compose down -v # Clean up\n
If you're using Apple Silicon, you may have to separately build the image with the appropriate platform flag (from the demo
directory):
DOCKER_DEFAULT_PLATFORM=linux/amd64 docker build -f ../docker/Dockerfile --tag oid4vc ..\n
"},{"location":"oid4vc/#demo-flow","title":"Demo Flow","text":"Navigate to http://localhost:3002
in your browser. You will start at the landing page. The sidebar has buttons to take you to the issuance and presentation pages.
-
Issue Credential
-
This page generates a simple UniversityCredential
for issuance
- The demo obscures and automates the necessary
credential-supported/create
call, which is what defines the type and values of a credential that can be issued
-
Preparing a credential offer is simple:
- Enter your name and email, or use the test value provided, and hit
Register
- Once you hit
Register
, you'll be automatically taken to the Credential Offer Page
-
Credential Offer Page
- Presents a credential offer in the form of a QR code.
- Scan the QR code using the Sphereon Wallet app.
- The Sphereon Wallet follows the OID4VC flow, requesting an authentication token and using it to obtain a credential.
- The OID4VC plugin determines the credential subjects based on the exchange record.
Now you have a UniversityCredential
in your Sphereon Wallet. To demonstrate the other half of the OID4VC plugin, click on the Present Credential
button on the sidebar.
- Present Credential
- The Present Credential page has a single button on it: Present Credential
- When you press that button, the demo will prepare a QR code that contains a presentation request
- Again, the demo obscures and automates some of the necessary calls to prepare the request, but you can see the calls being made in the logs
- Scan this QR code with your Sphereon Wallet app
- Follow the steps on the app, which will prompt you to select a University Credential from your wallet
As mentioned, the demo automatically takes care of a lot of the setup calls necessary to prepare credential definitions, presentation requests, and so forth. You can see what calls are being made, and with what values, both in the container logs and on the page.
"},{"location":"oid4vc/#note","title":"Note","text":"In a production environment, the described processes would be more dynamic and involve additional security measures. This demo provides a streamlined representation for clarity and ease of understanding.
"},{"location":"oid4vc/#architecture","title":"Architecture","text":""},{"location":"oid4vc/#public-routes","title":"Public Routes","text":"ACA-Py provides a pluggable mechanism for registering routes for consumption by the controller, the Admin API. This Admin Server makes it trivial to extend the controller from plugins. ACA-Py does not, however, provide a similar mechanism for publicly accessible HTTP Endpoints. Generally speaking, the only public endpoint ACA-Py provides is the DIDComm Messaging endpoint. The OpenID4VCI protocol requires endpoints that are publicly accessible to present and exchange tokens for credentials. This Plugin accomplishes this by starting a separate aiohttp server (similar to how the Admin server is separate from the DIDComm messaging server) and publishes the OpenID4VCI endpoints through this separate server.
Details of the endpoints can be found at /api/docs
or in the OpenId4VCI Specification.
"},{"location":"oid4vc/#admin-routes","title":"Admin Routes","text":"The plugin exposes Admin API routes for consumption by the Controller to facilitate Credential Issuance over OpenID4VCI. The Admin API Routes can be found under /api/docs
of the Admin Server in the oid4vci
section.
"},{"location":"oid4vc/#records","title":"Records","text":"The plugin adds two records to ACA-Py, OID4VCIExchangeRecord
and SupportedCredential
. The exchange record keeps track of user data use during the exchange. The supported credential record keeps track of information a issuer needs to issue a credential.
"},{"location":"oid4vc/#how-it-works","title":"How it works","text":"It is the Controller's responsibility to prepare Credential Issuer Metadata, collect and record details about the credential subject, (optionally) generate and deliver a User PIN to the holder out of band, and to generate and present the credential offer to the holder.
"},{"location":"oid4vc/#credential-issuance","title":"Credential Issuance","text":"sequenceDiagram\nautonumber\n\nactor alice as Alice\nparticipant holder as Wallet\nparticipant controller as Controller\nbox OpenID4VCI Plugin\nparticipant public as Public Routes\nparticipant admin as Admin Routes\nend\nparticipant acapy as ACA-Py Core\n\ncontroller ->> admin: POST /oid4vci/credential-supported/create\nadmin -->> controller: created (supported_cred_id)\ncontroller ->> admin: POST /wallet/did/create\nadmin -->> controller: created (did)\nalice -> controller: Open URL in browser with form\nalice ->> controller: Submit form\nactivate controller\ncontroller ->> admin: POST /oid4vci/exchange/create (did, supported_cred_id, credential subject)\nadmin -->> controller: created (record)\nalt PIN required\ncontroller -->> alice: Deliver PIN Out of Band (email, sms, etc.)\nend\ncontroller ->> admin: GET /oid4vci/credential-offer (exchange id, pin)\nadmin -->> controller: credential offer\ncontroller ->> alice: redirects alice to a page with cred offer\ndeactivate controller\nalice ->> holder: Scan cred offer\nholder --> controller: scanned cred offer (pre-auth code)\nholder ->> holder: reads offer, extracts issuer\nholder ->> public: Retrieve issuer metadata\npublic -->> holder: issuer metadata\nholder ->> public: token request (pre-auth code)\npublic ->> holder: token response (access token)\nholder ->> public: credential request (access token)\nactivate public\npublic ->> acapy: Verify Proof of Possession\nacapy -->> public: Verified\npublic ->> acapy: Recall cred values\npublic ->> acapy: jwt sign\nacapy -->> public: signed cred\npublic ->> acapy: store exchange result\npublic ->> holder: credential response\ndeactivate public\nadmin ->> controller: POST /topic/oid4vci (issued)\nloop alice polling for exchange status\nalice ->> controller: get exchange status\ncontroller -->> alice: status\nalt complete\ncontroller ->> alice: redirect to success page\nend\nend
"},{"location":"oid4vc/#credential-presentation","title":"Credential Presentation","text":"sequenceDiagram\nautonumber\n\nactor alice as Alice\nparticipant holder as Wallet\nparticipant controller as Controller\nbox OpenID4VCI Plugin\nparticipant public as Public Routes\nparticipant admin as Admin Routes\nend\nparticipant acapy as ACA-Py Core\n\ncontroller ->> admin: POST /oid4vp/presentation-definition\nadmin ->> acapy: store presentation definition\nadmin -->> controller: created presentation definition\nalice ->> controller: Hits web page initiating presentation\ncontroller ->> admin: POST /oid4vp/request\nadmin ->> acapy: save request record associated <br/>with a particular pres def \nadmin -->> controller: request URI\ncontroller ->> alice: QR Code\nalice ->> holder: Scan QR Code\nholder ->> public: GET /oid4vp/request/{request_id} (request uri in QR code)\npublic -> acapy: retrieve stored request\npublic -->> holder: request \nholder ->> public: POST /oid4vp/response/{presentation_id}\nacapy ->> controller: POST /topic/oid4vp <br/>(state: presentation-valid/invalid)\ncontroller ->> holder: result
"},{"location":"oid4vc/#usage","title":"Usage","text":""},{"location":"oid4vc/#configuration","title":"Configuration","text":"The Plugin expects the following configuration options. These options can either be set by environment variable (OID4VCI_*
) or by plugin config value (-o oid4vci.*
).
OID4VCI_HOST
or oid4vci.host
- Host used for the OpenID4VCI public server
OID4VCI_PORT
or oid4vci.port
- Port used for the OpenID4VCI public server
OID4VCI_ENDPOINT
or oid4vci.endpoint
credential_issuer
endpoint, seen in the Credential Offer
OID4VCI_CRED_HANDLER
or oid4vci.cred_handler
- Dict of credential handlers. e.g.
{\"jwt_vc_json\": \"jwt_vc_json\"}
"},{"location":"oid4vc/#creating-supported-credential-records","title":"Creating Supported Credential Records","text":"To issue a credential using OpenID4VCI, the Issuer must first prepare credential issuer metadata including which credentials the Issuer can issue. Below is an example payload to the POST /oid4vci/credential-supported/create
endpoint:
{\n \"cryptographic_binding_methods_supported\": [\n \"did\"\n ],\n \"cryptographic_suites_supported\": [\n \"ES256K\"\n ],\n \"display\": [\n {\n \"name\": \"University Credential\",\n \"locale\": \"en-US\",\n \"logo\": {\n \"url\": \"https://w3c-ccg.github.io/vc-ed/plugfest-1-2022/images/JFF_LogoLockup.png\",\n \"alt_text\": \"a square logo of a university\"\n },\n \"background_color\": \"#12107C\",\n \"text_color\": \"#FFFFFF\"\n }\n ],\n \"format\": \"jwt_vc_json\",\n \"format_data\": {\n \"credentialSubject\": {\n \"degree\": {},\n \"given_name\": {\n \"display\": [\n {\n \"name\": \"Given Name\",\n \"locale\": \"en-US\"\n }\n ]\n },\n \"gpa\": {\n \"display\": [\n {\n \"name\": \"GPA\"\n }\n ]\n },\n \"last_name\": {\n \"display\": [\n {\n \"name\": \"Surname\",\n \"locale\": \"en-US\"\n }\n ]\n }\n },\n \"types\": [\n \"VerifiableCredential\",\n \"UniversityDegreeCredential\"\n ]\n },\n \"id\": \"UniversityDegreeCredential\",\n \"vc_additional_data\": {\n \"@context\": [\n \"https://www.w3.org/2018/credentials/v1\",\n \"https://www.w3.org/2018/credentials/examples/v1\"\n ],\n \"type\": [\n \"VerifiableCredential\",\n \"UniversityDegreeCredential\"\n ]\n }\n}\n
For the id
, format
, cryptographic_binding_supported
, cryptographic_suites_supported
, and display
attributes, see the OpenID4VCI Specification, Section 10.2.3.
format_data
: This attribute represents data specific to a given credential format. In this Supported Credential, which is of format jwt_vc_json
, this includes types
(required for JWT-VC) and credentialSubject
(which represents display characteristics of the credential only and is not an exhaustive list of the credential attributes). These values are reported in the credential issuer metadata. vc_additional_data
: This attribute represents data that is included in all credentials of this type. In this Supported Credential, this includes the @context
of credential to be issued as well as the type
. These values are NOT reported in the credential issuer metadata.
When the Controller sets up a Supported Credential record using the Admin API, the holder, upon requesting Credential Issuer Metadata, will receive the following information in response:
{\n \"credential_issuer\": \"https://e116-198-91-62-58.ngrok.io/\",\n \"credential_endpoint\": \"https://e116-198-91-62-58.ngrok.io/credential\",\n \"credentials_supported\": [\n {\n \"format\": \"jwt_vc_json\",\n \"cryptographic_binding_methods_supported\": [\n \"did\"\n ],\n \"cryptographic_suites_supported\": [\n \"ES256K\"\n ],\n \"display\": [\n {\n \"name\": \"University Credential\",\n \"locale\": \"en-US\",\n \"logo\": {\n \"url\": \"https://w3c-ccg.github.io/vc-ed/plugfest-1-2022/images/JFF_LogoLockup.png\",\n \"alt_text\": \"a square logo of a university\"\n },\n \"background_color\": \"#12107c\",\n \"text_color\": \"#FFFFFF\"\n }\n ],\n \"id\": \"UniversityDegreeCredential\",\n \"credentialSubject\": {\n \"degree\": {},\n \"given_name\": {\n \"display\": [\n {\n \"name\": \"Given Name\",\n \"locale\": \"en-US\"\n }\n ]\n },\n \"gpa\": {\n \"display\": [\n {\n \"name\": \"GPA\"\n }\n ]\n },\n \"last_name\": {\n \"display\": [\n {\n \"name\": \"Surname\",\n \"locale\": \"en-US\"\n }\n ]\n }\n },\n \"types\": [\n \"VerifiableCredential\",\n \"UniversityDegreeCredential\"\n ]\n }\n ]\n}\n
"},{"location":"oid4vc/#contributing","title":"Contributing","text":"This project is managed using Poetry. To get started:
poetry install\npoetry run pre-commit install\npoetry run pre-commit install --hook-type commit-msg\n
TODO: Pre-commit should move to the repo root
"},{"location":"oid4vc/#unit-tests","title":"Unit Tests","text":"To run unit tests:
# Run only unit tests; leaving off the directory will attempt to run integration tests\npoetry run pytest tests/\n
"},{"location":"oid4vc/#integration-tests","title":"Integration Tests","text":"This plugin includes two sets of integration tests:
- Tests against a minimal OpenID4VCI Client written in Python
- Tests against AFJ + OpenID4VCI Client Package (not complete!)
AFJ has an active PR working on adding support for Draft 11 version of the OpenID4VCI specification. Until that PR is in and available in a release, these tests are incomplete and ignored.
To run the integration tests:
cd oid4vc/integration\ndocker compose build\ndocker compose run tests\ndocker compose down -v # Clean up\n
For Apple Silicon, the DOCKER_DEFAULT_PLATFORM=linux/amd64
environment variable will be required.
"},{"location":"oid4vc/#not-implemented","title":"Not Implemented","text":" ldp_vc
, sd_jwt_vc
- Authorization Code Flow
- Only signature suite supported by ACA-Py for jwt-vc right now is
EdDSA
- GET /.well-known/openid-configuration
- GET /.well-known/oauth-authorization-server
- Batch Credential Issuance
- We're limited to DID Methods that ACA-Py supports for issuance (more can be added by Plugin, e.g. DID Web);
did:sov
, did:key
"},{"location":"redis_events/","title":"Redis Events","text":""},{"location":"redis_events/#description","title":"Description","text":"This plugin provides mechanism to persist both inbound and outbound messages, deliver messages and webhooks, and dispatch events.
For receiving inbound messages, you have an option to either setup a mediator or a relay [supports direct response].
flowchart LR;\n InboundMsg([Inbound Msg])-->Mediator;\n Mediator-->InboundQueue[(Inbound Queue)];\n InboundQueue-->YourAgent{{Your Agent}};
For the relay scenario:
flowchart LR;\n InboundMsg([Inbound Msg])-->Relay;\n Relay-->InboundQueue[(Inbound Queue)];\n InboundQueue-->YourAgent{{Your Agent}};
The deliverer
service dispatches the outbound messages and webhooks. For the events
, the payload is pushed to the relevant Redis LIST [for the topic name, refer to event.event_topic_maps] and further action is delegated to the controllers.
For the outbound scenario:
flowchart LR;\n YourAgent{{Your Agent}}-->OutboundQueue[(Outbound Queue)];\n OutboundQueue-->Deliverer;\n Deliverer-->OutboundMsg([Outbound Msg]);
The code for the Deliverer and Relay processes are in the redis_events.v1_0.services.deliverer
and redis_events.v1_0.services.redis_relay
directories, respectively. The redis_events.v1_0.status_endpoint
directory contains code for health endpoints that is used by both of these processes.
The docker
directory contains a dockerfile (and instructions) for running ACA-Py with the redis plugin.
"},{"location":"redis_events/#configuration","title":"Configuration","text":"The redis events plugin is configured using an external yaml file. An example yaml configuration is:
redis_queue:\n connection:\n connection_url: \"redis://default:test1234@172.28.0.103:6379\"\n\n ### For Inbound ###\n inbound:\n acapy_inbound_topic: \"acapy_inbound\"\n acapy_direct_resp_topic: \"acapy_inbound_direct_resp\"\n\n ### For Outbound ###\n outbound:\n acapy_outbound_topic: \"acapy_outbound\"\n mediator_mode: false\n\n ### For Event ###\n event:\n event_topic_maps:\n ^acapy::webhook::(.*)$: acapy-webhook-$wallet_id\n ^acapy::record::([^:]*)::([^:]*)$: acapy-record-with-state-$wallet_id\n ^acapy::record::([^:])?: acapy-record-$wallet_id\n acapy::basicmessage::received: acapy-basicmessage-received\n acapy::problem_report: acapy-problem_report\n acapy::ping::received: acapy-ping-received\n acapy::ping::response_received: acapy-ping-response_received\n acapy::actionmenu::received: acapy-actionmenu-received\n acapy::actionmenu::get-active-menu: acapy-actionmenu-get-active-menu\n acapy::actionmenu::perform-menu-action: acapy-actionmenu-perform-menu-action\n acapy::keylist::updated: acapy-keylist-updated\n acapy::revocation-notification::received: acapy-revocation-notification-received\n acapy::revocation-notification-v2::received: acapy-revocation-notification-v2-received\n acapy::forward::received: acapy-forward-received\n event_webhook_topic_maps:\n acapy::basicmessage::received: basicmessages\n acapy::problem_report: problem_report\n acapy::ping::received: ping\n acapy::ping::response_received: ping\n acapy::actionmenu::received: actionmenu\n acapy::actionmenu::get-active-menu: get-active-menu\n acapy::actionmenu::perform-menu-action: perform-menu-action\n acapy::keylist::updated: keylist\n deliver_webhook: true\n
The configuration parameters in the above example are:
Connection:
redis_queue.connection.connection_url
: This is required and is expected in redis://{username}:{password}@{host}:{port}
format.
Inbound:
redis_queue.inbound.acapy_inbound_topic
: This is the topic prefix for the inbound message queues. Recipient key of the message are also included in the complete topic name. The final topic will be in the following format acapy_inbound_{recip_key}
redis_queue.inbound.acapy_direct_resp_topic
: Queue topic name for direct responses to inbound message.
Outbound:
redis_queue.outbound.acapy_outbound_topic
: Queue topic name for the outbound messages. Used by Deliverer service to deliver the payloads to specified endpoint. redis_queue.outbound.mediator_mode
: Set to true, if using Redis as a http bridge when setting up a mediator agent. By default, it is set to false.
Events:
event.event_topic_maps
: Event topic map event.event_webhook_topic_maps
: Event to webhook topic map event.deliver_webhook
: When set to true, this will deliver webhooks to endpoints specified in admin.webhook_urls
. By default, set to true.
"},{"location":"redis_events/#plugin-deployment","title":"Plugin deployment","text":"Once the plugin config is defined, it is possible to deploy the plugin inside ACA-Py.
aca-py start \\\n --plugin redis_events.v1_0.redis_queue.events \\\n --plugin-config plugins-config.yaml \\\n -it redis_events.v1_0.redis_queue.inbound redis 0 -ot redis_events.v1_0.redis_queue.outbound\n # ... the remainder of your startup arguments\n
"},{"location":"redis_events/#status-endpoints","title":"Status Endpoints","text":"Relay
and Deliverer
service have the following service endpoints available:
GET
http://{STATUS_ENDPOINT_HOST}:{STATUS_ENDPOINT_PORT}/status/ready
GET
http://{STATUS_ENDPOINT_HOST}:{STATUS_ENDPOINT_PORT}/status/live
The configuration for the endpoint service can be provided as following for relay
and deliverer
. The API KEY should be provided in the header with access_token
as key name.
environment:\n - STATUS_ENDPOINT_HOST=0.0.0.0\n - STATUS_ENDPOINT_PORT=7001\n - STATUS_ENDPOINT_API_KEY=test_api_key_1\n
"},{"location":"redis_events/#basic-flow-diagrams","title":"Basic Flow Diagrams","text":"Relay:
sequenceDiagram\n box Alice\n participant A as Alice\n end\n box Bob\n participant R as Relay\n participant IRQ as Inbound [Redis Queue]\n participant ACA as ACA-PY Agent\n participant ORQ as Outbound [Redis Queue]\n participant D as Deliverer\n end\n A->>R: \n R->>IRQ: \n ACA->>IRQ: consume \n ACA->>ACA: process \n ACA->>ORQ: \n D->>ORQ: consume \n D->>A:
Mediator:
sequenceDiagram\n box Alice\n participant A as Alice\n participant ACAM as ACA-PY Mediator\n end\n box Bob\n participant IRQ as Inbound [Redis Queue]\n participant ACA as ACA-PY Agent\n participant ORQ as Outbound [Redis Queue]\n participant D as Deliverer\n end\n A->>ACAM: \n ACAM->>IRQ: \n ACA->>IRQ: consume\n ACA->>ACA: process\n ACA->>ORQ: \n D->>ORQ: consume\n D->>A:
Relay - Direct Response:
sequenceDiagram\n box Alice\n participant A as Alice\n end\n box Bob\n participant R as Relay\n participant IRQ as Inbound [Redis Queue]\n participant ACA as ACA-PY Agent\n participant ORQ as Outbound [Redis Queue]\n participant D as Deliverer\n end\n A->>R: \n R->>IRQ: \n ACA->>IRQ: consume \n ACA->>ACA: process \n ACA->>IRQ: inbound response \n R->>IRQ: consume \n R->>A:
"},{"location":"rpc/","title":"DIDComm RPC","text":""},{"location":"rpc/#description","title":"Description","text":"DIDComm RPC (DRPC) allows Aries agents to remotely execute methods on each others controllers using JSON-RPC over DIDComm.
- v1_0:
- Introduces
/drpc/{conn_id}/request
and /drpc/{conn_id}/response
POST endpoints for sending RPC request and response/error message(s), respectively, according to the specification of RPC request and and response/error objects as defined by JSON-RPC. - Introduces
/drpc/records
and /drpc/records/{record_id}
GET endpoints for querying DRPC records stored in Aries agent wallets.
"},{"location":"rpc/#configuration","title":"Configuration","text":"No additional configuration required.
"},{"location":"rpc/#sequence","title":"Sequence","text":"The basic sequence of events in a DRPC interaction are as follows (starting with Alice making a request to Bob and Bob responding accordingly):
sequenceDiagram\n box Alice\n participant AC as AliceController\n participant AA as AliceAgent\n end\n\n box Bob\n participant BA as BobAgent\n participant BC as BobController\n end\n\n AC->>AA: POST /drpc/{conn_id}/request\n AA->>BA: outbound\n BA->>BC: acapy::webhook::drpc_request\n\n BC->>BA: POST /drpc/{conn_id}/response\n BA->>AA: inbound\n AA->>AC: acapy::webhook::drpc_response\n
Convenience endpoints are also included to retrieve DRPC record information, in case webhook messages somehow don't make it to controllers and the interaction ends up in an incomplete state.
sequenceDiagram\n box\n participant C as Controller\n participant A as Agent\n end\n\n C->>A: GET /drpc/records\n A->>C: Array<DRPCRecord>\n\n C->>A: GET /drpc/records/{record_id}\n A->>C: DRPCRecord
"},{"location":"rpc/#additional-information","title":"Additional information","text":"See Aries RFC 0804 for more information about the DRPC protocol.
"}]}
\ No newline at end of file
+{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"Aries Cloud Agent Python Plugins","text":"This repository contains approved and tested plugins for Aries Cloud Agent Python (ACA-Py). This is to encourage collaboration and sharing of useful features not directly included in ACA-Py.
"},{"location":"#developer-notes","title":"Developer Notes","text":"The easiest way to develop and test ACA-Py plugins is to use the DevContainer configured in this repository.
- Open devcontainer in VS Code
- Python and all dependencies will be loaded
- Poetry will be loaded and configured, dependencies will be installed
- Docker and Docker Compose will be available
"},{"location":"#repo-management-script","title":"Repo Management Script","text":"A script was developed to help with maintenance of the repo called repo_manager.py
. To run it you need a current version of poetry and python available.
Run python repo_manager.py
and you will be met with a number of options. Run the options as needed.
- (1) Is used for starting or adding a new plugin. It will generate all the common scaffolding for a plugin which has the expected format.
- (2) Is used for updating and changing common poetry dependencies and configurations. It takes the poetry sections in the
pyproject.toml
files from the plugin_globals
directory and combines them with the local plugin poetry sections. For the dependencies the common will be overridden by the globals. The other config sections will be replaced by the global configs. Then the lock files will be removed and re-installed. - (3) Is used for updating the plugin versions in the
plugin_globals
directory. It will update the versions of the plugins in the plugin_globals
directory to the latest version on the main branch of the plugin repo. It will also update the plugin_globals
directory to the latest version on the main branch of the plugin repo. - (4) This option is used by the CI/CD release pipeline. It updates the release notes and the individual plugins with a new version of ACA-Py.
- (5) This option is also used by the CI/CD release pipeline. It gets any plugins that have succeeded the tests after a new version of ACA-Py has been released if their changes were not reverted than the plugin has been updated to the new version of ACA-Py.
- (6) This option will run a general update for all poetry lock files in all plugins.
- (7) This option is used for upgrading a particular library for all plugins. It's useful for when you don't want to do a general upgrade for every library.
"},{"location":"#lite-plugins","title":"Lite plugins","text":"Sometimes is desirable to have a plugin that doesn't need integration tests or extra scaffolding. However, we need a way to avoid these plugins running integration tests in the CI/CD pipeline. To do this, we can simply add the plugin name to the lite_plugins
file, a line-separated list of plugin names.
"},{"location":"#plugin-documentation","title":"Plugin Documentation","text":"Plugin developers SHOULD describe what the plugin does, any limitations (ex only in multitenant mode), any known issues interacting with other plugins, etc. Full documentation including a plugin_config sample should be provided.
This documentation should be provided in your plugin root as a README.md file, with at least a Description
and Configuration
section.
"},{"location":"#build-and-run","title":"Build and Run","text":"Each plugin (that is not a Lite Plugin) MUST include a Dockerfile (such as Dockerfile) to run integration tests. This image is not intended for production as it copies the plugin source and loads its dependencies (including ACA-Py) along with a simplistic ACA-Py configuration file, (such as default.yml).
"},{"location":"#run-and-debug","title":"Run and Debug","text":"In the devcontainer, we can run an ACA-Py instance with our plugin source loaded and set breakpoints for debug (see launch.json
).
To run your ACA-Py code in debug mode, go to the Run and Debug
view, select \"Run/Debug Plugin\" and click Start Debugging (F5)
. Using the default.yml
for the plugin (such as default.yml), your agent swagger is available at http://localhost:3001/api/doc.
"},{"location":"#testing","title":"Testing","text":"For the plugin to be accepted into this repo it must have adequate testing.
"},{"location":"#unit-testing","title":"Unit Testing:","text":" - There should be adequate unit testing coverage. A coverage report is created when
poetry run pytest .
in ran from the devcontainer. A good mark to aim for is 90% but the quality of the tests on critical sections is more important than coverage percentage. - Mocking can be challenging. Study the existing plugins in this repo and ACA-Py in general for good examples of mocks and fixtures.
- Put your unit tests in a tests folder in your plugin version path and name all files and test with the
test_
prefix.
"},{"location":"#integration-testing","title":"Integration Testing:","text":" - Plugins SHOULD have a suite of integration tests. The base suite will be created for your plugin after running the updater script. Plugins that don't have integrations must be flagged as being a Lite Plugin.
- An Integration
README
(such as integration tests) SHOULD describe the set of integration tests. When you generate a new plugin, you should have everything you need to start integration testing and a sample test will be provided.
"},{"location":"#deploy","title":"Deploy","text":"For production use, plugins should be installed as libraries to an ACA-Py image.
This requires having a Dockerfile and a config file for your agent.
Example Dockerfile:
FROM ghcr.io/hyperledger/aries-cloudagent-python:py3.9-0.11.0\n\nUSER root\n\n# install plugins as binaries\nRUN pip install git+https://github.com/hyperledger/aries-acapy-plugins@main#subdirectory=basicmessage_storage\nRUN pip install git+https://github.com/hyperledger/aries-acapy-plugins@main#subdirectory=connection_update\n\nUSER $user\nCOPY ./configs configs\n\nCMD [\"ACA-Py\"]\n
Example config file (local single tenant):
label: plugins-agent\n\nadmin-insecure-mode: true\nadmin: [0.0.0.0, 9061]\n\ninbound-transport:\n - [http, 0.0.0.0, 9060]\noutbound-transport: http\nendpoint: http://host.docker.internal:9060\n\ngenesis-url: http://test.bcovrin.vonx.io/genesis\n\nemit-new-didcomm-prefix: true\nwallet-type: askar\nwallet-storage-type: default\n\nauto-provision: true\ndebug-connections: true\nauto-accept-invites: true\nauto-accept-requests: true\nauto-ping-connection: true\nauto-respond-messages: true\n\nlog-level: info\n\nplugin:\n - basicmessage_storage.v1_0\n - connection_update.v1_0\n
Now you can deploy a agent with as many plugins as you want as long as they are declared in your build config file and installed.
docker build -f <Dockerfile> --tag acapy_plugins .\ndocker run -it -p 9060:9060 -p 9061:9061 --rm acapy_plugins start --arg-file=<config-file> -->\n
"},{"location":"CONTRIBUTING/","title":"How to Contribute","text":""},{"location":"CONTRIBUTING/#how-to-contribute","title":"How to contribute","text":"You are encouraged to contribute to the repository by forking and submitting a pull request.
For significant changes, please open an issue first to discuss the proposed changes to avoid re-work.
"},{"location":"DOCSITE/","title":"ACA-Py Plugins Documentation","text":"The documentation site for the ACA-Py plugins can be found at: https://hyperledger.github.io/aries-acapy-plugins.
"},{"location":"DOCSITE/#managing-the-documentation-site","title":"Managing the Documentation Site","text":"The documentation site is sourced from this repo and generated by the publish-docs
GitHub Action. That action:
- Checkouts out the repo at
main
- Installs Mkdocs Material
- Runs the script in the repo
setupDocs.sh
, which - Creates the
docs
folder - Populates the
docs
with all of the root level Markdown files - Creates a folder for each plugin and copies it's
README.md
- Generates a complete
mkdocs.yml
file with navigation
- Runs the
mkdocs
mike
extension to generate the site to thwe gh-pages
branch for deployment with GitHub pages
If you want to change how the doc site looks, edit the setupDocs.sh
file and the mkdocs.yml
portion of the script for both look and feel and navigation. Most of the script is just redirect plain text into the mkdocs.yml
file, although there is a little bash script to, for example, generate the navigation for all of the plugins. If you want to edit the content displayed on the site, edit the markdown files in this repo.
"},{"location":"DOCSITE/#testing-the-documentation-site","title":"Testing the Documentation Site","text":"To test the documentation site locally, follow the instructions on the Mkdocs Material to install mkdocs
locally and run it. When you are ready, run:
./setupDocs.sh\nmkdocs\n
You should have the site up at http://localhost:8000/
.
The /docs
folder and mkdocs.yml
file are .gitignore
d in this repo, but if you want to get rid of them, you can use the following to clean them up.
./setupDocs.sh clean\n
"},{"location":"LICENSE/","title":"License","text":" Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
Definitions.
\"License\" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
\"Licensor\" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
\"Legal Entity\" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, \"control\" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising permissions granted by this License.
\"Source\" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
\"Object\" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
\"Work\" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
\"Derivative Works\" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
\"Contribution\" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, \"submitted\" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as \"Not a Contribution.\"
\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
-
Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
-
Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
-
Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
\u00a9 You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
(d) If the Work includes a \"NOTICE\" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
-
Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
-
Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
-
Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
-
Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
-
Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following\n boilerplate notice, with the fields enclosed by brackets \"[]\"\n replaced with your own identifying information. (Don't include\n the brackets!) The text should be enclosed in the appropriate\n comment syntax for the file format. We also recommend that a\n file or class name and description of purpose be included on the\n same \"printed page\" as the copyright notice for easier\n identification within third-party archives.\n
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0\n
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
"},{"location":"MAINTAINERS/","title":"Maintainers","text":""},{"location":"MAINTAINERS/#maintainer-scopes-github-roles-and-github-teams","title":"Maintainer Scopes, GitHub Roles and GitHub Teams","text":"Maintainers are assigned the following scopes in this repository:
Scope Definition GitHub Role GitHub Team Admin Admin aries-admins Maintainer The GitHub Maintain role Maintain aries-cloudagent-python committers Triage The GitHub Triage role Triage aries triage Read The GitHub Read role Read Aries Contributors"},{"location":"MAINTAINERS/#active-maintainers","title":"Active Maintainers","text":"GitHub ID Name Scope LFID Discord ID Email Company Affiliation amanji Akiff Manji Maintainer BC Gov andrewwhitehead Andrew Whitehead Maintainer BC Gov chumbert Clement Humbert Maintainer SICPA dbluhm Daniel Bluhm Indicio PBC dhh1128 Daniel Hardman Maintainer Provenant ianco Ian Costanzo Anonymous Systems jamshale Jamie Hale Maintainer BC Gov Jsyro Jason Syrotuck BC Gov shaangill025 Shaanjot Gill BC Gov swcurran Stephen Curran Maintainer BC Gov TelegramSam Sam Curren Maintainer Indicio PBC TimoGlastra Timo Glastra Animo Solutions WadeBarnes Wade Barnes Maintainer BC Gov usingtechnology Jason Sherman BC Gov"},{"location":"MAINTAINERS/#the-duties-of-a-maintainer","title":"The Duties of a Maintainer","text":"Maintainers are expected to perform the following duties for this repository. The duties are listed in more or less priority order:
- Review, respond, and act on any security vulnerabilities reported against the repository.
- Review, provide feedback on, and merge or reject GitHub Pull Requests from Contributors.
- Review, triage, comment on, and close GitHub Issues submitted by Contributors.
- When appropriate, lead/facilitate architectural discussions in the community.
- When appropriate, lead/facilitate the creation of a product roadmap.
- Create, clarify, and label issues to be worked on by Contributors.
- Ensure that there is a well defined (and ideally automated) product test and release pipeline, including the publication of release artifacts.
- When appropriate, execute the product release process.
- Maintain the repository CONTRIBUTING.md file and getting started documents to give guidance and encouragement to those wanting to contribute to the product, and those wanting to become maintainers.
- Contribute to the product via GitHub Pull Requests.
- Monitor requests from the Hyperledger Technical Oversight Committee about the contents and management of Hyperledger repositories, such as branch handling, required files in repositories and so on.
- Contribute to the Hyperledger Project's Quarterly Report.
"},{"location":"MAINTAINERS/#becoming-a-maintainer","title":"Becoming a Maintainer","text":"This community welcomes contributions. Interested contributors are encouraged to progress to become maintainers. To become a maintainer the following steps occur, roughly in order.
- The proposed maintainer establishes their reputation in the community, including authoring five (5) significant merged pull requests, and expresses an interest in becoming a maintainer for the repository.
- A PR is created to update this file to add the proposed maintainer to the list of active maintainers.
- The PR is authored by an existing maintainer or has a comment on the PR from an existing maintainer supporting the proposal.
- The PR is authored by the proposed maintainer or has a comment on the PR from the proposed maintainer confirming their interest in being a maintainer.
- The PR or comment from the proposed maintainer must include their willingness to be a long-term (more than 6 month) maintainer.
- Once the PR and necessary comments have been received, an approval timeframe begins.
- The PR MUST be communicated on all appropriate communication channels, including relevant community calls, chat channels and mailing lists. Comments of support from the community are welcome.
- The PR is merged and the proposed maintainer becomes a maintainer if either:
- Two weeks have passed since at least three (3) Maintainer PR approvals have been recorded, OR
- An absolute majority of maintainers have approved the PR.
- If the PR does not get the requisite PR approvals, it may be closed.
- Once the add maintainer PR has been merged, any necessary updates to the GitHub Teams are made.
"},{"location":"MAINTAINERS/#removing-maintainers","title":"Removing Maintainers","text":"Being a maintainer is not a status symbol or a title to be carried indefinitely. It will occasionally be necessary and appropriate to move a maintainer to emeritus status. This can occur in the following situations:
- Resignation of a maintainer.
- Violation of the Code of Conduct warranting removal.
- Inactivity.
- A general measure of inactivity will be no commits or code review comments for one reporting quarter. This will not be strictly enforced if the maintainer expresses a reasonable intent to continue contributing.
- Reasonable exceptions to inactivity will be granted for known long term leave such as parental leave and medical leave.
- Other circumstances at the discretion of the other Maintainers.
The process to move a maintainer from active to emeritus status is comparable to the process for adding a maintainer, outlined above. In the case of voluntary resignation, the Pull Request can be merged following a maintainer PR approval. If the removal is for any other reason, the following steps SHOULD be followed:
- A PR is created to update this file to move the maintainer to the list of emeritus maintainers.
- The PR is authored by, or has a comment supporting the proposal from, an existing maintainer or Hyperledger GitHub organization administrator.
- Once the PR and necessary comments have been received, the approval timeframe begins.
- The PR MAY be communicated on appropriate communication channels, including relevant community calls, chat channels and mailing lists.
- The PR is merged and the maintainer transitions to maintainer emeritus if:
- The PR is approved by the maintainer to be transitioned, OR
- Two weeks have passed since at least three (3) Maintainer PR approvals have been recorded, OR
- An absolute majority of maintainers have approved the PR.
- If the PR does not get the requisite PR approvals, it may be closed.
Returning to active status from emeritus status uses the same steps as adding a new maintainer. Note that the emeritus maintainer already has the 5 required significant changes as there is no contribution time horizon for those.
"},{"location":"RELEASES/","title":"Plugin Release Status","text":""},{"location":"RELEASES/#aca-py-release-101","title":"ACA-Py Release 1.0.1","text":"Plugin Name Supported ACA-Py Release basicmessage_storage 1.0.1 connection_update 1.0.1 firebase_push_notifications 1.0.1 kafka_events 0.12.2 multitenant_provider 1.0.1 oid4vc 1.0.1 redis_events 1.0.1 rpc 1.0.1"},{"location":"RELEASES/#plugins-upgraded-for-aca-py-release-101","title":"Plugins Upgraded For ACA-Py Release 1.0.1","text":" - basicmessage_storage
- connection_update
- firebase_push_notifications
- multitenant_provider
- oid4vc
- redis_events
- rpc
"},{"location":"RELEASES/#aca-py-release-100","title":"ACA-Py Release 1.0.0","text":"Plugin Name Supported ACA-Py Release basicmessage_storage 1.0.0 connection_update 1.0.0 firebase_push_notifications 1.0.0 jwt_vc_json 1.0.0 kafka_events 0.12.2 mso_mdoc 1.0.0 multitenant_provider 1.0.0 oid4vci 1.0.0 redis_events 1.0.0 rpc 1.0.0"},{"location":"RELEASES/#plugins-upgraded-for-aca-py-release-100","title":"Plugins Upgraded For ACA-Py Release 1.0.0","text":" - basicmessage_storage
- connection_update
- firebase_push_notifications
- jwt_vc_json
- mso_mdoc
- multitenant_provider
- oid4vci
- redis_events
- rpc
"},{"location":"RELEASES/#aca-py-release-0122","title":"ACA-Py Release 0.12.2","text":"Plugin Name Supported ACA-Py Release basicmessage_storage 0.12.2 connection_update 0.12.2 firebase_push_notifications 0.12.2 jwt_vc_json 0.12.2 kafka_events 0.12.2 mso_mdoc 0.12.2 multitenant_provider 0.12.2 oid4vci 0.12.2 redis_events 0.12.2 rpc 0.12.2"},{"location":"RELEASES/#plugins-upgraded-for-aca-py-release-0122","title":"Plugins Upgraded For ACA-Py Release 0.12.2","text":" - basicmessage_storage
- connection_update
- firebase_push_notifications
- jwt_vc_json
- kafka_events
- mso_mdoc
- multitenant_provider
- oid4vci
- redis_events
- rpc
"},{"location":"RELEASES/#aca-py-release-0121","title":"ACA-Py Release 0.12.1","text":"Plugin Name Supported ACA-Py Release basicmessage_storage 0.12.1 connection_update 0.12.1 firebase_push_notifications 0.12.1 kafka_events 0.12.1 multitenant_provider 0.12.1 oid4vci 0.12.1 redis_events 0.12.1 rpc 0.12.1"},{"location":"RELEASES/#plugins-upgraded-for-aca-py-release-0121","title":"Plugins Upgraded For ACA-Py Release 0.12.1","text":" - basicmessage_storage
- connection_update
- firebase_push_notifications
- kafka_events
- multitenant_provider
- oid4vci
- redis_events
- rpc
"},{"location":"basicmessage_storage/","title":"Basic Message Storage","text":""},{"location":"basicmessage_storage/#description","title":"Description","text":" - v1_0:
- Uses a middleware wrapper around the existing basicmessage
connections/{id}/send-message
api, and will persist the sent message. - Messages between all agents/connections can be fetched via
GET /basicmessages
with optional query params for connection_id
and state
. - single messages can be deleted via
DELETE /basicmessages/{message_id}
- subwallets can disable message storages by setting
extra_settings:{\"basicmessage-storage\":{\"wallet_enabled\":false}}
in the body of /multitenancy/wallet/{wallet_id}
"},{"location":"basicmessage_storage/#configuration","title":"Configuration","text":" - No additional configuration required.
"},{"location":"connection_update/","title":"Connection Update","text":""},{"location":"connection_update/#description","title":"Description","text":" - v1_0
- Creates a new endpoint PUT /connections/{conn_id} that allows a controller to update the connection alias label.
"},{"location":"connection_update/#configuration","title":"Configuration","text":" - No additional configuration required.
"},{"location":"firebase_push_notifications/","title":"Firebase Push Notifications","text":""},{"location":"firebase_push_notifications/#description","title":"Description","text":"Only to be used with a mediator agent.
Allows mobile agents to send firebase tokens to the mediator service. The mediator service creates a connection with the firebase server and will relay push notifications to the mobile agent on mediator forwarding events on the event_bus.
"},{"location":"firebase_push_notifications/#initialization","title":"Initialization","text":"sequenceDiagram\nparticipant Mobile\nparticipant Mediator\nNote left of Mobile: Logs In\nNote left of Mobile: Checks if already registered\nMobile->>Mediator: Do you support firebase protocol?\nMediator->>Mobile: No\nNote left of Mobile: Do Nothing\nMediator->>Mobile: Yes\nNote left of Mobile: Open notification Permission Modal\nMobile->>Mobile: User says \"not now\"\nNote left of Mobile: Close Modal and set user denied to true\nMobile->>Mobile: User says \"Allow\"\nMobile->>Mediator: Send device token\nNote right of Mediator: Save device token for conenction\nMobile->>Mobile: OS permissions popup\nNote left of Mobile: Approve or deny OS level permission
"},{"location":"firebase_push_notifications/#new-message","title":"New Message","text":"sequenceDiagram\nparticipant Agent (Faber)\nparticipant Mediator\nparticipant Mobile (Alice)\nparticipant Firebase\nNote left of Agent (Faber): Wants to send message to Mobile (Alice)\nAgent (Faber)->>Mediator: Message\nMediator->>Mobile (Alice): Message\nMediator->>Mediator: Receives Forwarding event in aca-py\nNote right of Mediator: Get device token for connection\nMediator->>Mediator: token is blank or None\nNote right of Mediator: Do nothing\nMediator->>Mediator: message sent withing 'n' minutes\nNote right of Mediator: Do nothing\nMediator->>Mediator: Token exists\nMediator->>Firebase: Request: Send OS notification to token\nFirebase->>Mobile (Alice): Sends OS notification
"},{"location":"firebase_push_notifications/#disableenable","title":"Disable/Enable","text":"sequenceDiagram\nparticipant Mobile\nparticipant Mediator\nMobile->>Mediator: Sends blank token\nNote right of Mediator: Saves blank token (disabled)\nMobile->>Mediator: Sends device token\nNote right of Mediator: Saves device token (enabled)
"},{"location":"firebase_push_notifications/#configuration","title":"Configuration","text":"To use the push notification protocol plugin you must have a firebase project to send the notifications to and a service account json file with Firebase Service Management Service Agent
roles.
In the project .env file you need to supply the information in the Firebase Plugin Configuration
section.
USE_FIREBASE_PLUGIN=true\nFIREBASE_PROJECT_ID=287275049656\nFIREBASE_NOTIFICATION_TITLE=You have important information in your digital wallet\nFIREBASE_NOTIFICATION_BODY=Please open your wallet\nFIREBASE_SERVICE_ACCOUNT={ flattend service account json }\n
FIREBASE_PROJECT_ID
can be found in the firebase console FIREBASE_NOTIFICATION_TITLE
and FIREBASE_NOTIFICATION_BODY
is the information displayed in the push notification
"},{"location":"kafka_events/","title":"Kafka Events","text":"This plugin contains the components needed for ACA-Py to use Kafka for inbound and outbound message queuing and events.
"},{"location":"kafka_events/#installation-and-usage","title":"Installation and Usage","text":"When starting up ACA-Py, load the plugin along with any other startup parameters.
aca-py start --plugin kafka_events # ... the remainder of your startup arguments\n
"},{"location":"kafka_events/#plugin-configuration","title":"Plugin configuration","text":"This is an open door to configure the kafka client to produce and consume records. Kafka has several configuration beyond the URL of the service.
An example configuration for the plugin can be found in example-config.yml
.
"},{"location":"kafka_events/#running-with-configuration","title":"Running with configuration","text":"aca-py start \\\n --plugin kafka_events \\\n --plugin-config plugins-config.yaml \\\n # ... the remainder of your startup arguments\n
"},{"location":"kafka_events/#consuming-didcomm-messages","title":"Consuming DIDComm messages","text":"Messages produced by this plugin contain metadata in addition to the encrypted DIDComm message. Messages look like:
{\n \"service\": {\"url\": \"recipient url\"},\n \"metadata\": {...},\n \"payload\": \"encrypted_and_packed_didcomm_message\"\n}\n
Metadata contain, amongst other things, the plaintext version of the DIDComm message; be cautious and only send the payload
content over the wire to the DIDComm recipient.
"},{"location":"multitenant_provider/","title":"Multi-Tenant Provider","text":""},{"location":"multitenant_provider/#description","title":"Description","text":"Provides support for multiple tenants by creating jwt based authentication tokens for each tenant wallet.
This plugin requires that ACA-Py is running in multi-tenant mode. this plugin will load a new Profile Manager in place of the one loaded by ACA-Py, and subsequent calls for a Multi-tenant Profile Manager will use the class configured in this plugin.
The default manager classes provided in this plugin allow multiple tokens per wallet.
The class_name
is the fully qualified class name/path. The always_check_provided_wallet_key
indicates whether we should check provided wallet_key values (required or not) when creating a token.
"},{"location":"multitenant_provider/#configuation","title":"Configuation","text":"# Multi-tenancy\nmultitenant: true\njwt-secret: insecure-jwt-secret\nmultitenant-admin: true\n\nplugin:\n # load this plugin, note multitenant must be true\n - multitenant_provider.v1_0\n\nplugin-config-value:\n - multitenant_provider.manager.class_name=\"multitenant_provider.v1_0.manager.BasicMultitokenMultitenantManager\"\n - multitenant_provider.manager.always_check_provided_wallet_key=true\n
The expiry time for the token is also configurable. By default, a token is valid for 52 weeks. Possible units are weeks, days, hours, minutes. The following example will build tokens that expire in 30 minutes.
plugin-config-value:\n - multitenant_provider.token_expiry.units=days\n - multitenant_provider.token_expiry.amount=1\n
And we can configure whether to throw an error when a managed wallet passes in a wallet key when getting a token (default is true).
plugin-config-value:\n - multitenant_provider.errors.on_unneeded_wallet_key=true\n
"},{"location":"multitenant_provider/#askar-vs-indy-sdk-storage","title":"Askar vs Indy SDK Storage","text":"NOTE: The Indy SDK has been removed from ACA-Py and should not be used.
There are 2 multitoken manager classes provided in this plugin: one for indy wallet types, one for askar wallet types. If there is no specific configuration provided for multitenant_provider.manager.class_name
, we will look at the wallet_type
(not multitenancy-config.wallet_type
). If wallet_type=askar
then we will load multitenant_provider.v1_0.manager.AskarMultitokenMultitenantManager
else we will load multitenant_provider.v1_0.manager.BasicMultitokenMultitenantManager
.
"},{"location":"multitenant_provider/#build-and-run","title":"Build and Run","text":"cd docker\ndocker build -f ./Dockerfile --tag multitenant_provider ..\ndocker run -it -p 3000:3000 -p 3001:3001 --rm multitenant_provider\n
"},{"location":"oid4vc/","title":"OpenID4VCI Plugin for ACA-Py","text":"This plugin implements OpenID4VCI (Draft 11). The OpenID4VCI specification is in active development, as is this plugin. Consider this plugin experimental; endpoints and records may change to reflect upstream changes in the specification.
"},{"location":"oid4vc/#openid4vci-plugin-demo-with-sphereon-wallet","title":"OpenID4VCI Plugin Demo with Sphereon Wallet","text":""},{"location":"oid4vc/#demo-overview","title":"Demo Overview","text":"This repository showcases a simplified demonstration of the OID4VCI (OpenID for Verifiable Credential Issuers) integration with the Sphereon Wallet app. Follow the steps below to run the demo successfully.
"},{"location":"oid4vc/#prerequisites","title":"Prerequisites","text":" - Sphereon Wallet App on your mobile device
- Docker + Docker Compose
- Ngrok Account (free tier is okay)
"},{"location":"oid4vc/#steps-to-run-the-demo","title":"Steps to Run the Demo","text":"First, you'll have to get your authtoken from ngrok. Note this value down.
cd oid4vc/demo\ndocker-compose build\necho \"NGROK_AUTHTOKEN=<PASTE YOUR AUTHTOKEN HERE>\" > .env\ndocker-compose up\ndocker-compose down -v # Clean up\n
If you're using Apple Silicon, you may have to separately build the image with the appropriate platform flag (from the demo
directory):
DOCKER_DEFAULT_PLATFORM=linux/amd64 docker build -f ../docker/Dockerfile --tag oid4vc ..\n
"},{"location":"oid4vc/#demo-flow","title":"Demo Flow","text":"Navigate to http://localhost:3002
in your browser. You will start at the landing page. The sidebar has buttons to take you to the issuance and presentation pages.
-
Issue Credential
-
This page generates a simple UniversityCredential
for issuance
- The demo obscures and automates the necessary
credential-supported/create
call, which is what defines the type and values of a credential that can be issued
-
Preparing a credential offer is simple:
- Enter your name and email, or use the test value provided, and hit
Register
- Once you hit
Register
, you'll be automatically taken to the Credential Offer Page
-
Credential Offer Page
- Presents a credential offer in the form of a QR code.
- Scan the QR code using the Sphereon Wallet app.
- The Sphereon Wallet follows the OID4VC flow, requesting an authentication token and using it to obtain a credential.
- The OID4VC plugin determines the credential subjects based on the exchange record.
Now you have a UniversityCredential
in your Sphereon Wallet. To demonstrate the other half of the OID4VC plugin, click on the Present Credential
button on the sidebar.
- Present Credential
- The Present Credential page has a single button on it: Present Credential
- When you press that button, the demo will prepare a QR code that contains a presentation request
- Again, the demo obscures and automates some of the necessary calls to prepare the request, but you can see the calls being made in the logs
- Scan this QR code with your Sphereon Wallet app
- Follow the steps on the app, which will prompt you to select a University Credential from your wallet
As mentioned, the demo automatically takes care of a lot of the setup calls necessary to prepare credential definitions, presentation requests, and so forth. You can see what calls are being made, and with what values, both in the container logs and on the page.
"},{"location":"oid4vc/#note","title":"Note","text":"In a production environment, the described processes would be more dynamic and involve additional security measures. This demo provides a streamlined representation for clarity and ease of understanding.
"},{"location":"oid4vc/#architecture","title":"Architecture","text":""},{"location":"oid4vc/#public-routes","title":"Public Routes","text":"ACA-Py provides a pluggable mechanism for registering routes for consumption by the controller, the Admin API. This Admin Server makes it trivial to extend the controller from plugins. ACA-Py does not, however, provide a similar mechanism for publicly accessible HTTP Endpoints. Generally speaking, the only public endpoint ACA-Py provides is the DIDComm Messaging endpoint. The OpenID4VCI protocol requires endpoints that are publicly accessible to present and exchange tokens for credentials. This Plugin accomplishes this by starting a separate aiohttp server (similar to how the Admin server is separate from the DIDComm messaging server) and publishes the OpenID4VCI endpoints through this separate server.
Details of the endpoints can be found at /api/docs
or in the OpenId4VCI Specification.
"},{"location":"oid4vc/#admin-routes","title":"Admin Routes","text":"The plugin exposes Admin API routes for consumption by the Controller to facilitate Credential Issuance over OpenID4VCI. The Admin API Routes can be found under /api/docs
of the Admin Server in the oid4vci
section.
"},{"location":"oid4vc/#records","title":"Records","text":"The plugin adds two records to ACA-Py, OID4VCIExchangeRecord
and SupportedCredential
. The exchange record keeps track of user data use during the exchange. The supported credential record keeps track of information a issuer needs to issue a credential.
"},{"location":"oid4vc/#how-it-works","title":"How it works","text":"It is the Controller's responsibility to prepare Credential Issuer Metadata, collect and record details about the credential subject, (optionally) generate and deliver a User PIN to the holder out of band, and to generate and present the credential offer to the holder.
"},{"location":"oid4vc/#credential-issuance","title":"Credential Issuance","text":"sequenceDiagram\nautonumber\n\nactor alice as Alice\nparticipant holder as Wallet\nparticipant controller as Controller\nbox OpenID4VCI Plugin\nparticipant public as Public Routes\nparticipant admin as Admin Routes\nend\nparticipant acapy as ACA-Py Core\n\ncontroller ->> admin: POST /oid4vci/credential-supported/create\nadmin -->> controller: created (supported_cred_id)\ncontroller ->> admin: POST /wallet/did/create\nadmin -->> controller: created (did)\nalice -> controller: Open URL in browser with form\nalice ->> controller: Submit form\nactivate controller\ncontroller ->> admin: POST /oid4vci/exchange/create (did, supported_cred_id, credential subject)\nadmin -->> controller: created (record)\nalt PIN required\ncontroller -->> alice: Deliver PIN Out of Band (email, sms, etc.)\nend\ncontroller ->> admin: GET /oid4vci/credential-offer (exchange id, pin)\nadmin -->> controller: credential offer\ncontroller ->> alice: redirects alice to a page with cred offer\ndeactivate controller\nalice ->> holder: Scan cred offer\nholder --> controller: scanned cred offer (pre-auth code)\nholder ->> holder: reads offer, extracts issuer\nholder ->> public: Retrieve issuer metadata\npublic -->> holder: issuer metadata\nholder ->> public: token request (pre-auth code)\npublic ->> holder: token response (access token)\nholder ->> public: credential request (access token)\nactivate public\npublic ->> acapy: Verify Proof of Possession\nacapy -->> public: Verified\npublic ->> acapy: Recall cred values\npublic ->> acapy: jwt sign\nacapy -->> public: signed cred\npublic ->> acapy: store exchange result\npublic ->> holder: credential response\ndeactivate public\nadmin ->> controller: POST /topic/oid4vci (issued)\nloop alice polling for exchange status\nalice ->> controller: get exchange status\ncontroller -->> alice: status\nalt complete\ncontroller ->> alice: redirect to success page\nend\nend
"},{"location":"oid4vc/#credential-presentation","title":"Credential Presentation","text":"sequenceDiagram\nautonumber\n\nactor alice as Alice\nparticipant holder as Wallet\nparticipant controller as Controller\nbox OpenID4VCI Plugin\nparticipant public as Public Routes\nparticipant admin as Admin Routes\nend\nparticipant acapy as ACA-Py Core\n\ncontroller ->> admin: POST /oid4vp/presentation-definition\nadmin ->> acapy: store presentation definition\nadmin -->> controller: created presentation definition\nalice ->> controller: Hits web page initiating presentation\ncontroller ->> admin: POST /oid4vp/request\nadmin ->> acapy: save request record associated <br/>with a particular pres def \nadmin -->> controller: request URI\ncontroller ->> alice: QR Code\nalice ->> holder: Scan QR Code\nholder ->> public: GET /oid4vp/request/{request_id} (request uri in QR code)\npublic -> acapy: retrieve stored request\npublic -->> holder: request \nholder ->> public: POST /oid4vp/response/{presentation_id}\nacapy ->> controller: POST /topic/oid4vp <br/>(state: presentation-valid/invalid)\ncontroller ->> holder: result
"},{"location":"oid4vc/#usage","title":"Usage","text":""},{"location":"oid4vc/#configuration","title":"Configuration","text":"The Plugin expects the following configuration options. These options can either be set by environment variable (OID4VCI_*
) or by plugin config value (-o oid4vci.*
).
OID4VCI_HOST
or oid4vci.host
- Host used for the OpenID4VCI public server
OID4VCI_PORT
or oid4vci.port
- Port used for the OpenID4VCI public server
OID4VCI_ENDPOINT
or oid4vci.endpoint
credential_issuer
endpoint, seen in the Credential Offer
OID4VCI_CRED_HANDLER
or oid4vci.cred_handler
- Dict of credential handlers. e.g.
{\"jwt_vc_json\": \"jwt_vc_json\"}
"},{"location":"oid4vc/#creating-supported-credential-records","title":"Creating Supported Credential Records","text":"To issue a credential using OpenID4VCI, the Issuer must first prepare credential issuer metadata including which credentials the Issuer can issue. Below is an example payload to the POST /oid4vci/credential-supported/create
endpoint:
{\n \"cryptographic_binding_methods_supported\": [\n \"did\"\n ],\n \"cryptographic_suites_supported\": [\n \"ES256K\"\n ],\n \"display\": [\n {\n \"name\": \"University Credential\",\n \"locale\": \"en-US\",\n \"logo\": {\n \"url\": \"https://w3c-ccg.github.io/vc-ed/plugfest-1-2022/images/JFF_LogoLockup.png\",\n \"alt_text\": \"a square logo of a university\"\n },\n \"background_color\": \"#12107C\",\n \"text_color\": \"#FFFFFF\"\n }\n ],\n \"format\": \"jwt_vc_json\",\n \"format_data\": {\n \"credentialSubject\": {\n \"degree\": {},\n \"given_name\": {\n \"display\": [\n {\n \"name\": \"Given Name\",\n \"locale\": \"en-US\"\n }\n ]\n },\n \"gpa\": {\n \"display\": [\n {\n \"name\": \"GPA\"\n }\n ]\n },\n \"last_name\": {\n \"display\": [\n {\n \"name\": \"Surname\",\n \"locale\": \"en-US\"\n }\n ]\n }\n },\n \"types\": [\n \"VerifiableCredential\",\n \"UniversityDegreeCredential\"\n ]\n },\n \"id\": \"UniversityDegreeCredential\",\n \"vc_additional_data\": {\n \"@context\": [\n \"https://www.w3.org/2018/credentials/v1\",\n \"https://www.w3.org/2018/credentials/examples/v1\"\n ],\n \"type\": [\n \"VerifiableCredential\",\n \"UniversityDegreeCredential\"\n ]\n }\n}\n
For the id
, format
, cryptographic_binding_supported
, cryptographic_suites_supported
, and display
attributes, see the OpenID4VCI Specification, Section 10.2.3.
format_data
: This attribute represents data specific to a given credential format. In this Supported Credential, which is of format jwt_vc_json
, this includes types
(required for JWT-VC) and credentialSubject
(which represents display characteristics of the credential only and is not an exhaustive list of the credential attributes). These values are reported in the credential issuer metadata. vc_additional_data
: This attribute represents data that is included in all credentials of this type. In this Supported Credential, this includes the @context
of credential to be issued as well as the type
. These values are NOT reported in the credential issuer metadata.
When the Controller sets up a Supported Credential record using the Admin API, the holder, upon requesting Credential Issuer Metadata, will receive the following information in response:
{\n \"credential_issuer\": \"https://e116-198-91-62-58.ngrok.io/\",\n \"credential_endpoint\": \"https://e116-198-91-62-58.ngrok.io/credential\",\n \"credentials_supported\": [\n {\n \"format\": \"jwt_vc_json\",\n \"cryptographic_binding_methods_supported\": [\n \"did\"\n ],\n \"cryptographic_suites_supported\": [\n \"ES256K\"\n ],\n \"display\": [\n {\n \"name\": \"University Credential\",\n \"locale\": \"en-US\",\n \"logo\": {\n \"url\": \"https://w3c-ccg.github.io/vc-ed/plugfest-1-2022/images/JFF_LogoLockup.png\",\n \"alt_text\": \"a square logo of a university\"\n },\n \"background_color\": \"#12107c\",\n \"text_color\": \"#FFFFFF\"\n }\n ],\n \"id\": \"UniversityDegreeCredential\",\n \"credentialSubject\": {\n \"degree\": {},\n \"given_name\": {\n \"display\": [\n {\n \"name\": \"Given Name\",\n \"locale\": \"en-US\"\n }\n ]\n },\n \"gpa\": {\n \"display\": [\n {\n \"name\": \"GPA\"\n }\n ]\n },\n \"last_name\": {\n \"display\": [\n {\n \"name\": \"Surname\",\n \"locale\": \"en-US\"\n }\n ]\n }\n },\n \"types\": [\n \"VerifiableCredential\",\n \"UniversityDegreeCredential\"\n ]\n }\n ]\n}\n
"},{"location":"oid4vc/#contributing","title":"Contributing","text":"This project is managed using Poetry. To get started:
poetry install\npoetry run pre-commit install\npoetry run pre-commit install --hook-type commit-msg\n
TODO: Pre-commit should move to the repo root
"},{"location":"oid4vc/#unit-tests","title":"Unit Tests","text":"To run unit tests:
# Run only unit tests; leaving off the directory will attempt to run integration tests\npoetry run pytest tests/\n
"},{"location":"oid4vc/#integration-tests","title":"Integration Tests","text":"This plugin includes two sets of integration tests:
- Tests against a minimal OpenID4VCI Client written in Python
- Tests against AFJ + OpenID4VCI Client Package (not complete!)
AFJ has an active PR working on adding support for Draft 11 version of the OpenID4VCI specification. Until that PR is in and available in a release, these tests are incomplete and ignored.
To run the integration tests:
cd oid4vc/integration\ndocker compose build\ndocker compose run tests\ndocker compose down -v # Clean up\n
For Apple Silicon, the DOCKER_DEFAULT_PLATFORM=linux/amd64
environment variable will be required.
"},{"location":"oid4vc/#not-implemented","title":"Not Implemented","text":" ldp_vc
, sd_jwt_vc
- Authorization Code Flow
- Only signature suite supported by ACA-Py for jwt-vc right now is
EdDSA
- GET /.well-known/openid-configuration
- GET /.well-known/oauth-authorization-server
- Batch Credential Issuance
- We're limited to DID Methods that ACA-Py supports for issuance (more can be added by Plugin, e.g. DID Web);
did:sov
, did:key
"},{"location":"redis_events/","title":"Redis Events","text":""},{"location":"redis_events/#description","title":"Description","text":"This plugin provides mechanism to persist both inbound and outbound messages, deliver messages and webhooks, and dispatch events.
For receiving inbound messages, you have an option to either setup a mediator or a relay [supports direct response].
flowchart LR;\n InboundMsg([Inbound Msg])-->Mediator;\n Mediator-->InboundQueue[(Inbound Queue)];\n InboundQueue-->YourAgent{{Your Agent}};
For the relay scenario:
flowchart LR;\n InboundMsg([Inbound Msg])-->Relay;\n Relay-->InboundQueue[(Inbound Queue)];\n InboundQueue-->YourAgent{{Your Agent}};
The deliverer
service dispatches the outbound messages and webhooks. For the events
, the payload is pushed to the relevant Redis LIST [for the topic name, refer to event.event_topic_maps] and further action is delegated to the controllers.
For the outbound scenario:
flowchart LR;\n YourAgent{{Your Agent}}-->OutboundQueue[(Outbound Queue)];\n OutboundQueue-->Deliverer;\n Deliverer-->OutboundMsg([Outbound Msg]);
The code for the Deliverer and Relay processes are in the redis_events.v1_0.services.deliverer
and redis_events.v1_0.services.redis_relay
directories, respectively. The redis_events.v1_0.status_endpoint
directory contains code for health endpoints that is used by both of these processes.
The docker
directory contains a dockerfile (and instructions) for running ACA-Py with the redis plugin.
"},{"location":"redis_events/#configuration","title":"Configuration","text":"The redis events plugin is configured using an external yaml file. An example yaml configuration is:
redis_queue:\n connection:\n connection_url: \"redis://default:test1234@172.28.0.103:6379\"\n\n ### For Inbound ###\n inbound:\n acapy_inbound_topic: \"acapy_inbound\"\n acapy_direct_resp_topic: \"acapy_inbound_direct_resp\"\n\n ### For Outbound ###\n outbound:\n acapy_outbound_topic: \"acapy_outbound\"\n mediator_mode: false\n\n ### For Event ###\n event:\n event_topic_maps:\n ^acapy::webhook::(.*)$: acapy-webhook-$wallet_id\n ^acapy::record::([^:]*)::([^:]*)$: acapy-record-with-state-$wallet_id\n ^acapy::record::([^:])?: acapy-record-$wallet_id\n acapy::basicmessage::received: acapy-basicmessage-received\n acapy::problem_report: acapy-problem_report\n acapy::ping::received: acapy-ping-received\n acapy::ping::response_received: acapy-ping-response_received\n acapy::actionmenu::received: acapy-actionmenu-received\n acapy::actionmenu::get-active-menu: acapy-actionmenu-get-active-menu\n acapy::actionmenu::perform-menu-action: acapy-actionmenu-perform-menu-action\n acapy::keylist::updated: acapy-keylist-updated\n acapy::revocation-notification::received: acapy-revocation-notification-received\n acapy::revocation-notification-v2::received: acapy-revocation-notification-v2-received\n acapy::forward::received: acapy-forward-received\n event_webhook_topic_maps:\n acapy::basicmessage::received: basicmessages\n acapy::problem_report: problem_report\n acapy::ping::received: ping\n acapy::ping::response_received: ping\n acapy::actionmenu::received: actionmenu\n acapy::actionmenu::get-active-menu: get-active-menu\n acapy::actionmenu::perform-menu-action: perform-menu-action\n acapy::keylist::updated: keylist\n deliver_webhook: true\n
The configuration parameters in the above example are:
Connection:
redis_queue.connection.connection_url
: This is required and is expected in redis://{username}:{password}@{host}:{port}
format.
Inbound:
redis_queue.inbound.acapy_inbound_topic
: This is the topic prefix for the inbound message queues. Recipient key of the message are also included in the complete topic name. The final topic will be in the following format acapy_inbound_{recip_key}
redis_queue.inbound.acapy_direct_resp_topic
: Queue topic name for direct responses to inbound message.
Outbound:
redis_queue.outbound.acapy_outbound_topic
: Queue topic name for the outbound messages. Used by Deliverer service to deliver the payloads to specified endpoint. redis_queue.outbound.mediator_mode
: Set to true, if using Redis as a http bridge when setting up a mediator agent. By default, it is set to false.
Events:
event.event_topic_maps
: Event topic map event.event_webhook_topic_maps
: Event to webhook topic map event.deliver_webhook
: When set to true, this will deliver webhooks to endpoints specified in admin.webhook_urls
. By default, set to true.
"},{"location":"redis_events/#plugin-deployment","title":"Plugin deployment","text":"Once the plugin config is defined, it is possible to deploy the plugin inside ACA-Py.
aca-py start \\\n --plugin redis_events.v1_0.redis_queue.events \\\n --plugin-config plugins-config.yaml \\\n -it redis_events.v1_0.redis_queue.inbound redis 0 -ot redis_events.v1_0.redis_queue.outbound\n # ... the remainder of your startup arguments\n
"},{"location":"redis_events/#status-endpoints","title":"Status Endpoints","text":"Relay
and Deliverer
service have the following service endpoints available:
GET
http://{STATUS_ENDPOINT_HOST}:{STATUS_ENDPOINT_PORT}/status/ready
GET
http://{STATUS_ENDPOINT_HOST}:{STATUS_ENDPOINT_PORT}/status/live
The configuration for the endpoint service can be provided as following for relay
and deliverer
. The API KEY should be provided in the header with access_token
as key name.
environment:\n - STATUS_ENDPOINT_HOST=0.0.0.0\n - STATUS_ENDPOINT_PORT=7001\n - STATUS_ENDPOINT_API_KEY=test_api_key_1\n
"},{"location":"redis_events/#basic-flow-diagrams","title":"Basic Flow Diagrams","text":"Relay:
sequenceDiagram\n box Alice\n participant A as Alice\n end\n box Bob\n participant R as Relay\n participant IRQ as Inbound [Redis Queue]\n participant ACA as ACA-PY Agent\n participant ORQ as Outbound [Redis Queue]\n participant D as Deliverer\n end\n A->>R: \n R->>IRQ: \n ACA->>IRQ: consume \n ACA->>ACA: process \n ACA->>ORQ: \n D->>ORQ: consume \n D->>A:
Mediator:
sequenceDiagram\n box Alice\n participant A as Alice\n participant ACAM as ACA-PY Mediator\n end\n box Bob\n participant IRQ as Inbound [Redis Queue]\n participant ACA as ACA-PY Agent\n participant ORQ as Outbound [Redis Queue]\n participant D as Deliverer\n end\n A->>ACAM: \n ACAM->>IRQ: \n ACA->>IRQ: consume\n ACA->>ACA: process\n ACA->>ORQ: \n D->>ORQ: consume\n D->>A:
Relay - Direct Response:
sequenceDiagram\n box Alice\n participant A as Alice\n end\n box Bob\n participant R as Relay\n participant IRQ as Inbound [Redis Queue]\n participant ACA as ACA-PY Agent\n participant ORQ as Outbound [Redis Queue]\n participant D as Deliverer\n end\n A->>R: \n R->>IRQ: \n ACA->>IRQ: consume \n ACA->>ACA: process \n ACA->>IRQ: inbound response \n R->>IRQ: consume \n R->>A:
"},{"location":"rpc/","title":"DIDComm RPC","text":""},{"location":"rpc/#description","title":"Description","text":"DIDComm RPC (DRPC) allows Aries agents to remotely execute methods on each others controllers using JSON-RPC over DIDComm.
- v1_0:
- Introduces
/drpc/{conn_id}/request
and /drpc/{conn_id}/response
POST endpoints for sending RPC request and response/error message(s), respectively, according to the specification of RPC request and and response/error objects as defined by JSON-RPC. - Introduces
/drpc/records
and /drpc/records/{record_id}
GET endpoints for querying DRPC records stored in Aries agent wallets.
"},{"location":"rpc/#configuration","title":"Configuration","text":"No additional configuration required.
"},{"location":"rpc/#sequence","title":"Sequence","text":"The basic sequence of events in a DRPC interaction are as follows (starting with Alice making a request to Bob and Bob responding accordingly):
sequenceDiagram\n box Alice\n participant AC as AliceController\n participant AA as AliceAgent\n end\n\n box Bob\n participant BA as BobAgent\n participant BC as BobController\n end\n\n AC->>AA: POST /drpc/{conn_id}/request\n AA->>BA: outbound\n BA->>BC: acapy::webhook::drpc_request\n\n BC->>BA: POST /drpc/{conn_id}/response\n BA->>AA: inbound\n AA->>AC: acapy::webhook::drpc_response\n
Convenience endpoints are also included to retrieve DRPC record information, in case webhook messages somehow don't make it to controllers and the interaction ends up in an incomplete state.
sequenceDiagram\n box\n participant C as Controller\n participant A as Agent\n end\n\n C->>A: GET /drpc/records\n A->>C: Array<DRPCRecord>\n\n C->>A: GET /drpc/records/{record_id}\n A->>C: DRPCRecord
"},{"location":"rpc/#additional-information","title":"Additional information","text":"See Aries RFC 0804 for more information about the DRPC protocol.
"}]}
\ No newline at end of file