├── rustfmt.toml ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── suggestion.yml │ ├── task.yml │ └── bug_report.yml ├── workflows │ ├── audit.yaml │ ├── format-lint-test.yaml │ ├── coverage.yaml │ ├── lint-pr-title.yaml │ └── release.yaml └── pull_request_template.md ├── agent_application ├── src │ ├── probes │ │ ├── mod.rs │ │ └── liveness.rs │ └── metadata │ │ ├── mod.rs │ │ ├── version.rs │ │ ├── config.rs │ │ └── info.rs ├── .gitignore ├── docker │ ├── .env.example │ ├── monitoring │ │ ├── grafana │ │ │ ├── datasources.yaml │ │ │ └── dashboards.yaml │ │ └── prometheus.yml │ ├── db │ │ └── pgadmin4 │ │ │ └── servers.json │ ├── Dockerfile │ └── compose.yaml ├── README.md ├── Cargo.toml └── build.rs ├── agent_issuance ├── src │ ├── utils │ │ ├── mod.rs │ │ └── generate_tx_code.rs │ ├── credential │ │ ├── application │ │ │ └── mod.rs │ │ ├── README.md │ │ ├── mod.rs │ │ ├── entity.rs │ │ ├── views │ │ │ ├── all_credentials.rs │ │ │ └── mod.rs │ │ ├── error.rs │ │ ├── command.rs │ │ └── event.rs │ ├── application │ │ ├── policies │ │ │ ├── mod.rs │ │ │ └── issuer_metadata_synchronization_policy.rs │ │ └── mod.rs │ ├── offer │ │ ├── mod.rs │ │ ├── README.md │ │ ├── views │ │ │ └── all_offers.rs │ │ ├── error.rs │ │ ├── command.rs │ │ └── event.rs │ ├── server_config │ │ ├── mod.rs │ │ ├── README.md │ │ ├── error.rs │ │ └── command.rs │ ├── services.rs │ └── lib.rs ├── res │ └── credential_format_templates │ │ └── openbadges_v3.json └── Cargo.toml ├── agent_library ├── src │ ├── lib.rs │ ├── template │ │ ├── error.rs │ │ ├── mod.rs │ │ ├── views │ │ │ └── all_templates.rs │ │ └── command.rs │ └── state.rs └── Cargo.toml ├── .dockerignore ├── CHANGELOG.md ├── agent_api_http ├── src │ ├── v0 │ │ ├── identity │ │ │ ├── well_known │ │ │ │ ├── mod.rs │ │ │ │ ├── did_configuration.rs │ │ │ │ └── did.rs │ │ │ ├── services │ │ │ │ └── mod.rs │ │ │ ├── error.rs │ │ │ ├── mod.rs │ │ │ └── documents │ │ │ │ └── mod.rs │ │ ├── verification │ │ │ ├── relying_party │ │ │ │ └── mod.rs │ │ │ └── mod.rs │ │ ├── holder │ │ │ ├── holder │ │ │ │ ├── mod.rs │ │ │ │ ├── offers │ │ │ │ │ ├── reject.rs │ │ │ │ │ └── mod.rs │ │ │ │ ├── presentations │ │ │ │ │ └── presentation_signed.rs │ │ │ │ └── credentials │ │ │ │ │ └── mod.rs │ │ │ ├── error.rs │ │ │ ├── openid4vci │ │ │ │ └── mod.rs │ │ │ └── mod.rs │ │ ├── issuance │ │ │ ├── credential_issuer │ │ │ │ ├── well_known │ │ │ │ │ └── mod.rs │ │ │ │ ├── mod.rs │ │ │ │ └── credential_offer.rs │ │ │ ├── credential_configurations.rs │ │ │ ├── offers │ │ │ │ └── send.rs │ │ │ └── mod.rs │ │ ├── authorization │ │ │ ├── authorization_server │ │ │ │ ├── mod.rs │ │ │ │ └── templates.rs │ │ │ ├── mod.rs │ │ │ └── error.rs │ │ ├── mod.rs │ │ └── library │ │ │ ├── error.rs │ │ │ └── mod.rs │ ├── handlers.rs │ └── metrics.rs ├── templates │ └── README.md ├── res │ ├── siopv2-authorization-request.json │ ├── open-badge-request.json │ └── open-badge-response.json └── tests │ └── response │ └── create-open-badge.json ├── commitlint.config.mjs ├── agent_authorization ├── src │ ├── lib.rs │ ├── domain │ │ ├── client │ │ │ ├── error.rs │ │ │ ├── mod.rs │ │ │ ├── README.md │ │ │ ├── views │ │ │ │ ├── all_clients.rs │ │ │ │ └── mod.rs │ │ │ ├── command.rs │ │ │ └── event.rs │ │ ├── access_token │ │ │ ├── error.rs │ │ │ ├── mod.rs │ │ │ ├── README.md │ │ │ ├── command.rs │ │ │ ├── event.rs │ │ │ └── views │ │ │ │ ├── all_tokens.rs │ │ │ │ └── mod.rs │ │ ├── authorization_code │ │ │ ├── mod.rs │ │ │ ├── README.md │ │ │ ├── error.rs │ │ │ ├── command.rs │ │ │ ├── views │ │ │ │ ├── all_authorization_codes.rs │ │ │ │ └── mod.rs │ │ │ └── event.rs │ │ ├── mod.rs │ │ └── oauth2_authorization_request │ │ │ ├── mod.rs │ │ │ ├── error.rs │ │ │ ├── README.md │ │ │ ├── command.rs │ │ │ ├── views │ │ │ └── all_oauth2_authorization_requests.rs │ │ │ └── event.rs │ ├── application │ │ ├── mod.rs │ │ ├── consent_query_service.rs │ │ └── consent_service.rs │ └── services.rs └── Cargo.toml ├── docs ├── res │ ├── unime-credential-offer.png │ └── unime-authorization-request.png ├── problem-details │ ├── conflict.md │ ├── unexpected.md │ └── persistence.md ├── README.md ├── configuration │ └── profiles.md └── deployment │ ├── monitoring.md │ └── domain-linkage.md ├── agent_holder ├── src │ ├── lib.rs │ ├── offer │ │ ├── mod.rs │ │ ├── README.md │ │ ├── command.rs │ │ ├── queries │ │ │ ├── all_offers.rs │ │ │ └── mod.rs │ │ ├── event.rs │ │ └── error.rs │ ├── credential │ │ ├── mod.rs │ │ ├── README.md │ │ ├── error.rs │ │ ├── command.rs │ │ ├── event.rs │ │ └── queries │ │ │ ├── all_credentials.rs │ │ │ └── mod.rs │ ├── presentation │ │ ├── mod.rs │ │ ├── README.md │ │ ├── command.rs │ │ ├── error.rs │ │ ├── event.rs │ │ └── views │ │ │ ├── mod.rs │ │ │ └── all_presentations.rs │ └── services.rs └── Cargo.toml ├── agent_identity ├── src │ ├── connection │ │ ├── error.rs │ │ ├── mod.rs │ │ ├── README.md │ │ ├── command.rs │ │ ├── event.rs │ │ └── views │ │ │ ├── all_connections.rs │ │ │ └── mod.rs │ ├── document │ │ ├── mod.rs │ │ ├── README.md │ │ ├── command.rs │ │ ├── views │ │ │ ├── all_documents.rs │ │ │ └── mod.rs │ │ ├── event.rs │ │ └── error.rs │ ├── profile │ │ ├── mod.rs │ │ ├── README.md │ │ ├── error.rs │ │ ├── command.rs │ │ ├── event.rs │ │ └── views │ │ │ └── mod.rs │ ├── service │ │ ├── mod.rs │ │ ├── README.md │ │ ├── command.rs │ │ ├── views │ │ │ ├── all_services.rs │ │ │ └── mod.rs │ │ ├── event.rs │ │ └── error.rs │ ├── lib.rs │ └── services.rs └── Cargo.toml ├── agent_verification ├── src │ ├── lib.rs │ ├── authorization_request │ │ ├── mod.rs │ │ ├── README.md │ │ ├── command.rs │ │ ├── error.rs │ │ ├── views │ │ │ ├── all_authorization_requests.rs │ │ │ └── mod.rs │ │ ├── event.rs │ │ └── queries.rs │ └── state.rs └── Cargo.toml ├── agent_secret_manager ├── tests │ └── res │ │ ├── test.stronghold │ │ ├── all_slots.stronghold │ │ └── test.stronghold.dat ├── README.md ├── src │ └── service.rs └── Cargo.toml ├── .releaserc.yaml ├── .gitignore ├── .env.example ├── agent_store ├── README.md └── Cargo.toml ├── agent_macros └── Cargo.toml ├── agent_shared ├── src │ ├── generic_query.rs │ ├── profile.rs │ ├── error.rs │ ├── application_state.rs │ ├── handlers.rs │ ├── lib.rs │ └── config │ │ └── provisioned.rs ├── tests │ ├── test_credential_configurations.json │ └── test.config.yaml └── Cargo.toml ├── agent_event_publisher_nats ├── Cargo.toml └── README.md └── agent_event_publisher_http └── Cargo.toml /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 120 2 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @nanderstabel @daniel-mader 2 | -------------------------------------------------------------------------------- /agent_application/src/probes/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod liveness; 2 | -------------------------------------------------------------------------------- /agent_issuance/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod generate_tx_code; 2 | -------------------------------------------------------------------------------- /agent_library/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod state; 2 | pub mod template; 3 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | **/Dockerfile 2 | **/target 3 | **/.git 4 | **/*.env 5 | -------------------------------------------------------------------------------- /agent_application/.gitignore: -------------------------------------------------------------------------------- 1 | *config.yaml 2 | !example.config.yaml 3 | -------------------------------------------------------------------------------- /agent_issuance/src/credential/application/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod token_status_list_service; 2 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Please check https://github.com/impierce/ssi-agent/releases for release notes. 2 | -------------------------------------------------------------------------------- /agent_api_http/src/v0/identity/well_known/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod did; 2 | pub mod did_configuration; 3 | -------------------------------------------------------------------------------- /agent_api_http/src/v0/verification/relying_party/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod redirect; 2 | pub mod request; 3 | -------------------------------------------------------------------------------- /agent_application/docker/.env.example: -------------------------------------------------------------------------------- 1 | UNICORE__APPLICATION_URL=${UNICORE__APPLICATION_URL} 2 | -------------------------------------------------------------------------------- /agent_issuance/src/application/policies/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod issuer_metadata_synchronization_policy; 2 | -------------------------------------------------------------------------------- /commitlint.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | extends: ["@commitlint/config-angular"], 3 | }; 4 | -------------------------------------------------------------------------------- /agent_issuance/src/application/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod access_token_validation_service; 2 | pub mod policies; 3 | -------------------------------------------------------------------------------- /agent_api_http/src/v0/holder/holder/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod credentials; 2 | pub mod offers; 3 | pub mod presentations; 4 | -------------------------------------------------------------------------------- /agent_authorization/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod application; 2 | pub mod domain; 3 | pub mod services; 4 | pub mod state; 5 | -------------------------------------------------------------------------------- /agent_library/src/template/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum TemplateError {} 5 | -------------------------------------------------------------------------------- /docs/res/unime-credential-offer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impierce/ssi-agent/HEAD/docs/res/unime-credential-offer.png -------------------------------------------------------------------------------- /agent_authorization/src/domain/client/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum ClientError {} 5 | -------------------------------------------------------------------------------- /agent_holder/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod credential; 2 | pub mod offer; 3 | pub mod presentation; 4 | pub mod services; 5 | pub mod state; 6 | -------------------------------------------------------------------------------- /agent_holder/src/offer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod queries; 6 | -------------------------------------------------------------------------------- /agent_identity/src/connection/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum ConnectionError {} 5 | -------------------------------------------------------------------------------- /agent_issuance/src/offer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_verification/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod authorization_request; 2 | pub mod generic_oid4vc; 3 | pub mod services; 4 | pub mod state; 5 | -------------------------------------------------------------------------------- /agent_holder/src/credential/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod queries; 6 | -------------------------------------------------------------------------------- /agent_holder/src/presentation/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_identity/src/connection/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_identity/src/document/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_identity/src/profile/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_identity/src/service/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_library/src/template/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /docs/res/unime-authorization-request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impierce/ssi-agent/HEAD/docs/res/unime-authorization-request.png -------------------------------------------------------------------------------- /agent_issuance/src/server_config/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_api_http/src/v0/issuance/credential_issuer/well_known/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod oauth_authorization_server; 2 | pub mod openid_credential_issuer; 3 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/access_token/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum AccessTokenError {} 5 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/client/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_secret_manager/tests/res/test.stronghold: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impierce/ssi-agent/HEAD/agent_secret_manager/tests/res/test.stronghold -------------------------------------------------------------------------------- /agent_authorization/src/domain/access_token/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_holder/src/credential/README.md: -------------------------------------------------------------------------------- 1 | # Credential 2 | 3 | This aggregate is defined by: 4 | 5 | - credential_id 6 | - offer_id 7 | - credential 8 | -------------------------------------------------------------------------------- /agent_identity/src/document/README.md: -------------------------------------------------------------------------------- 1 | # Document 2 | 3 | This aggregate holds everything related to a document: 4 | 5 | - document (DID document) 6 | -------------------------------------------------------------------------------- /agent_verification/src/authorization_request/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/authorization_code/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod access_token; 2 | pub mod authorization_code; 3 | pub mod client; 4 | pub mod oauth2_authorization_request; 5 | -------------------------------------------------------------------------------- /agent_secret_manager/tests/res/all_slots.stronghold: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impierce/ssi-agent/HEAD/agent_secret_manager/tests/res/all_slots.stronghold -------------------------------------------------------------------------------- /agent_secret_manager/tests/res/test.stronghold.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/impierce/ssi-agent/HEAD/agent_secret_manager/tests/res/test.stronghold.dat -------------------------------------------------------------------------------- /.releaserc.yaml: -------------------------------------------------------------------------------- 1 | plugins: 2 | - "@semantic-release/commit-analyzer" 3 | - "@semantic-release/release-notes-generator" 4 | - "@semantic-release/github" 5 | -------------------------------------------------------------------------------- /agent_api_http/src/v0/authorization/authorization_server/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod authorize; 2 | pub mod consent; 3 | pub mod par; 4 | pub mod templates; 5 | pub mod token; 6 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/oauth2_authorization_request/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod command; 3 | pub mod error; 4 | pub mod event; 5 | pub mod views; 6 | -------------------------------------------------------------------------------- /agent_issuance/src/credential/README.md: -------------------------------------------------------------------------------- 1 | # Credential 2 | 3 | This aggregate is defined by: 4 | 5 | - credential data 6 | - a format (such as: _Open Badge 3.0_) 7 | -------------------------------------------------------------------------------- /agent_identity/src/profile/README.md: -------------------------------------------------------------------------------- 1 | # Profile 2 | 3 | This aggregate holds everything related to a profile: 4 | - display_name 5 | - logo 6 | - source 7 | - country 8 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/oauth2_authorization_request/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum OAuth2AuthorizationRequestError {} 5 | -------------------------------------------------------------------------------- /agent_identity/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Aggregates 2 | pub mod connection; 3 | pub mod document; 4 | pub mod profile; 5 | pub mod service; 6 | 7 | pub mod services; 8 | pub mod state; 9 | -------------------------------------------------------------------------------- /agent_issuance/src/credential/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod aggregate; 2 | pub mod application; 3 | pub mod command; 4 | pub mod entity; 5 | pub mod error; 6 | pub mod event; 7 | pub mod views; 8 | -------------------------------------------------------------------------------- /agent_holder/src/presentation/README.md: -------------------------------------------------------------------------------- 1 | # Presentation 2 | 3 | This aggregate holds everything related to a presentation: 4 | - presentation_id 5 | - signed (the signed Presentation) 6 | -------------------------------------------------------------------------------- /agent_api_http/src/v0/issuance/credential_issuer/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod credential; 2 | pub mod credential_offer; 3 | pub mod notification; 4 | pub mod token_status_list; 5 | pub mod well_known; 6 | -------------------------------------------------------------------------------- /agent_api_http/src/v0/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod authorization; 2 | pub mod holder; 3 | pub mod identity; 4 | pub mod issuance; 5 | pub mod library; 6 | pub mod templates; 7 | pub mod verification; 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/target/ 2 | .cargo 3 | **/Cargo.lock 4 | !Cargo.lock 5 | 6 | debug/ 7 | 8 | **/*.env 9 | !**/.env.example 10 | 11 | .DS_Store 12 | 13 | **/stronghold.dat 14 | config.yaml 15 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | UNICORE__PROFILE=development 2 | 3 | UNICORE__LOG_FORMAT=text 4 | UNICORE__APPLICATION_URL="http://localhost:3033" 5 | UNICORE__SECRET_MANAGER__STRONGHOLD_PASSWORD="7Bs4IgCRaibbjd3of2pnoU7K" 6 | -------------------------------------------------------------------------------- /agent_application/src/metadata/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod config; 2 | pub mod info; 3 | pub mod version; 4 | 5 | #[derive(Clone)] 6 | pub struct MetadataState { 7 | pub startup_instant: std::time::Instant, 8 | } 9 | -------------------------------------------------------------------------------- /agent_store/README.md: -------------------------------------------------------------------------------- 1 | # agent_store 2 | 3 | The persistence layer sets up the CQRS framework and manages the application state. 4 | It will bind to some event store database to persist domain events. 5 | -------------------------------------------------------------------------------- /agent_application/README.md: -------------------------------------------------------------------------------- 1 | # agent_application 2 | 3 | The application crate combines individual modules and makes them executable. 4 | In most cases, it will simply spin up a webserver and serve the API. 5 | -------------------------------------------------------------------------------- /agent_identity/src/service/README.md: -------------------------------------------------------------------------------- 1 | # Service 2 | 3 | This aggregate holds everything related to a service: 4 | - id 5 | - service (DID Document Service) 6 | - resource (e.g. Domain Linkage resource) 7 | 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Company Website 4 | url: https://impierce.com/ 5 | about: "Contact us in the contact form for any questions." 6 | -------------------------------------------------------------------------------- /agent_holder/src/credential/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum CredentialError { 5 | #[error("Failed to decode Credential JWT")] 6 | CredentialDecodingError, 7 | } 8 | -------------------------------------------------------------------------------- /agent_issuance/src/server_config/README.md: -------------------------------------------------------------------------------- 1 | # Server Configuration 2 | 3 | This aggregate holds all things related to server configuration: 4 | 5 | - authorization_server_metadata 6 | - credential_issuer_metadata 7 | -------------------------------------------------------------------------------- /agent_issuance/src/credential/entity.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | 3 | #[derive(Debug, Clone, Serialize, Deserialize, Default, PartialEq)] 4 | pub struct Data { 5 | pub raw: serde_json::Value, 6 | } 7 | -------------------------------------------------------------------------------- /agent_authorization/src/application/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod consent_query_service; 2 | pub mod consent_service; 3 | pub mod oauth2_authorization_service; 4 | pub mod pushed_authorization_service; 5 | pub mod token_issuance_service; 6 | -------------------------------------------------------------------------------- /agent_holder/src/offer/README.md: -------------------------------------------------------------------------------- 1 | # Offer 2 | 3 | This aggregate holds everything related to a credential offer: 4 | 5 | - credential_offer 6 | - status 7 | - credential_configurations 8 | - token_response 9 | - credentials 10 | -------------------------------------------------------------------------------- /agent_identity/src/profile/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum ProfileError { 5 | #[error("The resource cannot be modified at runtime because it was provisioned")] 6 | ConfigurationConflict, 7 | } 8 | -------------------------------------------------------------------------------- /agent_application/docker/monitoring/grafana/datasources.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | datasources: 4 | - name: Prometheus 5 | type: prometheus 6 | access: proxy 7 | url: http://prometheus:9090 8 | isDefault: true 9 | editable: false 10 | -------------------------------------------------------------------------------- /agent_application/src/probes/liveness.rs: -------------------------------------------------------------------------------- 1 | use axum::http::StatusCode; 2 | use axum::response::IntoResponse; 3 | 4 | /// A simple liveness probe following application monitoring conventions. 5 | pub async fn healthz() -> impl IntoResponse { 6 | StatusCode::OK 7 | } 8 | -------------------------------------------------------------------------------- /agent_identity/src/connection/README.md: -------------------------------------------------------------------------------- 1 | # Connection 2 | 3 | This aggregate holds everything related to a connection: 4 | - connection_id 5 | - domain 6 | - dids (list of associated DIDs) 7 | - first_interacted 8 | - last_interacted 9 | - credential_offer_endpoint 10 | -------------------------------------------------------------------------------- /agent_api_http/templates/README.md: -------------------------------------------------------------------------------- 1 | # Templates 2 | 3 | This directory contains HTML templates used by the agent HTTP API service. The templates are rendered using the Askama templating engine, which allows for dynamic content generation based on the data provided by the backend. 4 | -------------------------------------------------------------------------------- /agent_application/docker/monitoring/grafana/dashboards.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: 1 2 | 3 | providers: 4 | - name: "Dashboard provider" 5 | disableDeletion: true 6 | updateIntervalSeconds: 10 7 | allowUiUpdates: false 8 | options: 9 | path: /var/lib/grafana/dashboards 10 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/access_token/README.md: -------------------------------------------------------------------------------- 1 | # Access Token 2 | 3 | This aggregate holds everything related to an access token: 4 | 5 | - user_id 6 | - client_id 7 | - scopes 8 | - issued_at 9 | - access_token_expires_at 10 | - refresh_token_expires_at 11 | - issuer_state 12 | -------------------------------------------------------------------------------- /agent_issuance/src/offer/README.md: -------------------------------------------------------------------------------- 1 | # Offer 2 | 3 | This aggregate holds everything related to an offer of a credential to a subject: 4 | 5 | - credential_ids 6 | - form_url_encoded_credential_offer 7 | - pre_authorized_code 8 | - token_response 9 | - access_token 10 | - credential_response 11 | -------------------------------------------------------------------------------- /agent_macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "agent_macros" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | 7 | [lib] 8 | proc-macro = true 9 | 10 | [dependencies] 11 | darling = "0.20" 12 | proc-macro2 = "1.0" 13 | quote = "1" 14 | syn = "2.0" 15 | -------------------------------------------------------------------------------- /agent_api_http/src/v0/library/error.rs: -------------------------------------------------------------------------------- 1 | use crate::error::IntoApiErrorExt; 2 | use agent_library::template::error::TemplateError; 3 | use http_api_problem::ApiError; 4 | 5 | impl IntoApiErrorExt for TemplateError { 6 | fn into_api_error(self) -> ApiError { 7 | match self {} 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/authorization_code/README.md: -------------------------------------------------------------------------------- 1 | # Authorization Code 2 | 3 | This aggregate holds everything related to an authorization code: 4 | 5 | - client_id 6 | - redirect_uri 7 | - code_challenge 8 | - code_challenge_method 9 | - issuer_state 10 | - expires_at 11 | - is_redeemed 12 | -------------------------------------------------------------------------------- /docs/problem-details/conflict.md: -------------------------------------------------------------------------------- 1 | ## Conflict Error 2 | 3 | ### Resource Provisioned by Configuration 4 | 5 | This resource was provisioned by a configuration file or environment variables and cannot be modified at runtime via the API. To make changes, please update the configuration and restart the service. 6 | -------------------------------------------------------------------------------- /agent_secret_manager/README.md: -------------------------------------------------------------------------------- 1 | # secret-manager 2 | 3 | Manages keys and secrets for the agent through easy-to-use interfaces. This module can either use an internal secret management solution (such as [Stronghold](https://github.com/iotaledger/stronghold.rs)) or rely on external solutions for signatures and encryption. 4 | -------------------------------------------------------------------------------- /agent_verification/src/authorization_request/README.md: -------------------------------------------------------------------------------- 1 | # Authorization Request 2 | 3 | This aggregate holds everything related to an Authorization Request: 4 | - authorization_request 5 | - form_url_encoded_authorization_request 6 | - signed_authorization_request_object 7 | - id_token 8 | - vp_token 9 | - state 10 | -------------------------------------------------------------------------------- /agent_holder/src/presentation/command.rs: -------------------------------------------------------------------------------- 1 | use identity_credential::credential::Jwt; 2 | use serde::Deserialize; 3 | 4 | #[derive(Debug, Deserialize)] 5 | #[serde(untagged)] 6 | pub enum PresentationCommand { 7 | CreatePresentation { 8 | presentation_id: String, 9 | signed_credentials: Vec, 10 | }, 11 | } 12 | -------------------------------------------------------------------------------- /agent_application/docker/db/pgadmin4/servers.json: -------------------------------------------------------------------------------- 1 | { 2 | "Servers": { 3 | "1": { 4 | "Name": "Local Development", 5 | "Group": "Servers", 6 | "Host": "cqrs-postgres-db", 7 | "Port": 5432, 8 | "MaintenanceDB": "demo", 9 | "Username": "demo_user", 10 | "SSLMode": "prefer" 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /agent_authorization/src/services.rs: -------------------------------------------------------------------------------- 1 | use agent_secret_manager::{service::Service, subject::SubjectExt}; 2 | use std::sync::Arc; 3 | 4 | pub struct AuthorizationServices { 5 | pub signer: Arc, 6 | } 7 | 8 | impl Service for AuthorizationServices { 9 | fn new(signer: Arc) -> Self { 10 | Self { signer } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /agent_holder/src/credential/command.rs: -------------------------------------------------------------------------------- 1 | use identity_credential::credential::Jwt; 2 | use serde::Deserialize; 3 | 4 | #[derive(Debug, Deserialize)] 5 | #[serde(untagged)] 6 | pub enum CredentialCommand { 7 | AddCredential { 8 | holder_credential_id: String, 9 | received_offer_id: Option, 10 | credential: Jwt, 11 | }, 12 | } 13 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/client/README.md: -------------------------------------------------------------------------------- 1 | # Client 2 | 3 | This aggregate holds everything related to a client: 4 | 5 | - client_secret 6 | - client_name 7 | - logo_uri 8 | - policy_uri 9 | - tos_uri 10 | - redirect_uris 11 | - grant_types 12 | - response_types 13 | - token_endpoint_auth_method 14 | - require_pkce 15 | - code_challenge_methods_supported 16 | - require_pushed_authorization_request 17 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/oauth2_authorization_request/README.md: -------------------------------------------------------------------------------- 1 | # OAuth2AuthorizationRequest 2 | 3 | This aggregate holds everything related to an OAuth2 authorization request: 4 | 5 | - response_type 6 | - state 7 | - client_id 8 | - redirect_uri 9 | - scope 10 | - issuer_state 11 | - authorization_details 12 | - code_challenge 13 | - code_challenge_method 14 | - expires_at 15 | - consent_status 16 | -------------------------------------------------------------------------------- /agent_issuance/src/server_config/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum ServerConfigError { 5 | #[error("Cannot update provisioned credential configuration during runtime")] 6 | UpdateProvisionedCredentialConfigurationError, 7 | #[error("Cannot remove provisioned credential configuration during runtime")] 8 | RemoveProvisionedCredentialConfigurationError, 9 | } 10 | -------------------------------------------------------------------------------- /agent_identity/src/connection/command.rs: -------------------------------------------------------------------------------- 1 | use identity_core::common::Url; 2 | use identity_did::DIDUrl; 3 | use serde::Deserialize; 4 | 5 | #[derive(Debug, Deserialize)] 6 | #[serde(untagged)] 7 | pub enum ConnectionCommand { 8 | AddConnection { 9 | connection_id: String, 10 | alias: Option, 11 | domain: Option, 12 | dids: Vec, 13 | credential_offer_endpoint: Option, 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /agent_issuance/src/services.rs: -------------------------------------------------------------------------------- 1 | use agent_secret_manager::{service::Service, subject::SubjectExt}; 2 | use std::sync::Arc; 3 | 4 | /// Issuance services. This struct is used to sign credentials and validate credential requests. 5 | pub struct IssuanceServices { 6 | pub issuer: Arc, 7 | } 8 | 9 | impl Service for IssuanceServices { 10 | fn new(issuer: Arc) -> Self { 11 | Self { issuer } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/access_token/command.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | 3 | #[derive(Debug, Deserialize)] 4 | #[serde(untagged)] 5 | pub enum AccessTokenCommand { 6 | IssueAccessToken { 7 | access_token_id: String, 8 | user_id: String, 9 | client_id: String, 10 | scopes: Option, 11 | access_token_expires_in: u64, 12 | refresh_token_expires_in: Option, 13 | issuer_state: Option, 14 | }, 15 | } 16 | -------------------------------------------------------------------------------- /agent_secret_manager/src/service.rs: -------------------------------------------------------------------------------- 1 | use crate::subject::SubjectExt; 2 | use std::sync::Arc; 3 | 4 | /// Convenience trait for Services like `IssuanceServices`, `HolderServices`, and `VerifierServices`. 5 | pub trait Service { 6 | fn new(subject: Arc) -> Self; 7 | 8 | #[cfg(feature = "test_utils")] 9 | fn default() -> Arc 10 | where 11 | Self: Sized, 12 | { 13 | Arc::new(Self::new(Arc::new(crate::subject::Subject::default()))) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /agent_holder/src/presentation/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum PresentationError { 5 | #[error("Failed to serialize presentation: {0}")] 6 | SerializationError(String), 7 | #[error("Failed to build presentation: {0}")] 8 | PresentationBuilderError(String), 9 | #[error("Invalid URL: {0}")] 10 | InvalidUrlError(String), 11 | #[error("Missing identifier: {0}")] 12 | MissingIdentifierError(String), 13 | #[error("Failed to sign presentation: {0}")] 14 | SigningError(String), 15 | } 16 | -------------------------------------------------------------------------------- /agent_shared/src/generic_query.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use cqrs_es::{ 4 | persist::{GenericQuery, ViewRepository}, 5 | Aggregate, View, 6 | }; 7 | 8 | /// Returns a new `GenericQuery` instance. 9 | pub fn generic_query(view_repository: Arc) -> GenericQuery 10 | where 11 | R: ViewRepository, 12 | A: Aggregate, 13 | V: View, 14 | { 15 | let mut generic_query = GenericQuery::new(view_repository); 16 | generic_query.use_error_handler(Box::new(|e| println!("{e}"))); 17 | 18 | generic_query 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/audit.yaml: -------------------------------------------------------------------------------- 1 | name: Audit dependencies 2 | 3 | on: 4 | schedule: 5 | - cron: "0 3 * * *" # run at 3 AM every day 6 | workflow_dispatch: 7 | pull_request: 8 | branches: 9 | - main 10 | - next 11 | - beta 12 | - alpha 13 | 14 | jobs: 15 | audit: 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | 21 | - uses: dtolnay/rust-toolchain@stable 22 | 23 | - uses: Swatinem/rust-cache@v2 24 | 25 | - run: cargo install cargo-audit 26 | 27 | - run: cargo audit 28 | -------------------------------------------------------------------------------- /agent_identity/src/service/command.rs: -------------------------------------------------------------------------------- 1 | use identity_iota::verification::VerificationMethod; 2 | use serde::Deserialize; 3 | 4 | #[derive(Debug, Deserialize)] 5 | #[serde(untagged)] 6 | pub enum ServiceCommand { 7 | CreateDomainLinkageService { 8 | service_id: String, 9 | verification_methods: Vec, 10 | }, 11 | DeleteDomainLinkageService { 12 | service_id: String, 13 | }, 14 | CreateLinkedVerifiablePresentationService { 15 | service_id: String, 16 | presentation_ids: Vec, 17 | }, 18 | } 19 | -------------------------------------------------------------------------------- /agent_issuance/res/credential_format_templates/openbadges_v3.json: -------------------------------------------------------------------------------- 1 | { 2 | "@context": [ 3 | "https://www.w3.org/2018/credentials/v1", 4 | "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json" 5 | ], 6 | "id": "http://example.com/credentials/3527", 7 | "type": ["VerifiableCredential", "OpenBadgeCredential"], 8 | "issuer": { 9 | "id": "https://example.com/issuers/876543", 10 | "type": "Profile", 11 | "name": "Example Corp" 12 | }, 13 | "issuanceDate": "2010-01-01T00:00:00Z", 14 | "name": "Teamwork Badge", 15 | "credentialSubject": {} 16 | } 17 | -------------------------------------------------------------------------------- /agent_holder/src/offer/command.rs: -------------------------------------------------------------------------------- 1 | use oid4vci::credential_offer::CredentialOffer; 2 | use serde::Deserialize; 3 | 4 | #[derive(Debug, Deserialize)] 5 | #[serde(untagged)] 6 | pub enum OfferCommand { 7 | ReceiveCredentialOffer { 8 | received_offer_id: String, 9 | credential_offer: CredentialOffer, 10 | }, 11 | AcceptCredentialOffer { 12 | received_offer_id: String, 13 | }, 14 | SendCredentialRequest { 15 | received_offer_id: String, 16 | }, 17 | RejectCredentialOffer { 18 | received_offer_id: String, 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/oauth2_authorization_request/command.rs: -------------------------------------------------------------------------------- 1 | use oid4vci::authorization_request::AuthorizationRequest; 2 | use serde::Deserialize; 3 | 4 | // TODO: remove this clippy allow 5 | #[allow(clippy::large_enum_variant)] 6 | #[derive(Debug, Deserialize)] 7 | #[serde(untagged)] 8 | pub enum OAuth2AuthorizationRequestCommand { 9 | CreateOAuth2AuthorizationRequest { 10 | oauth2_authorization_request_id: String, 11 | pushed_authorization_request: AuthorizationRequest, 12 | expires_at: i64, 13 | }, 14 | GrantConsent, 15 | RejectConsent, 16 | } 17 | -------------------------------------------------------------------------------- /agent_api_http/res/siopv2-authorization-request.json: -------------------------------------------------------------------------------- 1 | { 2 | "client_id": "did:key:z6MkiieyoLMSVsJAZv7Jje5wWSkDEymUgkyF8kbcrjZpX3qd", 3 | "redirect_uri": "http://192.168.1.127:3033/redirect", 4 | "state": "09d2c81651602a641a97b7fa6c08cc0d2435dde52729d37acc7597477a381361", 5 | "response_type": "id_token", 6 | "scope": "openid", 7 | "response_mode": "direct_post", 8 | "nonce": "0d520cbe176ab9e1f7888c70888020d84a69672a4baabd3ce1c6aaad8f6420c0", 9 | "client_metadata": { 10 | "subject_syntax_types_supported": [ 11 | "did:key" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /agent_application/docker/monitoring/prometheus.yml: -------------------------------------------------------------------------------- 1 | global: 2 | scrape_interval: 15s 3 | scrape_timeout: 10s 4 | evaluation_interval: 15s 5 | alerting: 6 | alertmanagers: 7 | - static_configs: 8 | - targets: [] 9 | scheme: http 10 | timeout: 10s 11 | api_version: v2 12 | scrape_configs: 13 | - job_name: ssi-agent 14 | scrape_interval: 5s 15 | static_configs: 16 | - targets: 17 | - ssi-agent:9091 18 | # Uncomment to scrape UniCore instance running on the host machine (macOS, Windows) 19 | # - host.docker.internal:9091 20 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # UniCore Documentation Source Files 2 | 3 | Welcome to the source repository for the official documentation of **UniCore**, our self-sovereign digital identity agent. 4 | 5 | ## About 6 | All the markdown (`.md`) files in this folder serve as the **source files** for the official UniCore documentation, which is hosted at: 7 | 8 | 👉 [UniCore Official Documentation (Beta)](https://beta.docs.impierce.com/unicore/) 9 | 10 | These markdown files are used as input for generating the official documentation site. Any changes to these files will reflect on the site after they are processed and deployed. 11 | -------------------------------------------------------------------------------- /agent_holder/src/presentation/event.rs: -------------------------------------------------------------------------------- 1 | use cqrs_es::DomainEvent; 2 | use identity_credential::credential::Jwt; 3 | use serde::{Deserialize, Serialize}; 4 | use strum::Display; 5 | 6 | #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Display)] 7 | pub enum PresentationEvent { 8 | PresentationCreated { 9 | presentation_id: String, 10 | signed_presentation: Jwt, 11 | }, 12 | } 13 | 14 | impl DomainEvent for PresentationEvent { 15 | fn event_type(&self) -> String { 16 | self.to_string() 17 | } 18 | 19 | fn event_version(&self) -> String { 20 | "1".to_string() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /agent_shared/src/profile.rs: -------------------------------------------------------------------------------- 1 | use serde::Serialize; 2 | use std::env; 3 | use std::str::FromStr; 4 | use strum::{Display, EnumString}; 5 | 6 | #[derive(Debug, Display, EnumString, Serialize)] 7 | #[serde(rename_all = "lowercase")] 8 | #[strum(serialize_all = "lowercase")] 9 | pub enum ApplicationProfile { 10 | Production, 11 | Development, 12 | } 13 | 14 | impl ApplicationProfile { 15 | pub fn load() -> Self { 16 | env::var("UNICORE__PROFILE") 17 | .ok() 18 | .and_then(|profile_str| ApplicationProfile::from_str(&profile_str).ok()) 19 | .unwrap_or(ApplicationProfile::Production) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /agent_identity/src/services.rs: -------------------------------------------------------------------------------- 1 | use agent_secret_manager::subject::Subject; 2 | use std::sync::Arc; 3 | 4 | /// Identity services. 5 | pub struct IdentityServices { 6 | pub subject: Arc, 7 | } 8 | 9 | impl IdentityServices { 10 | pub fn new(subject: Arc) -> Self { 11 | Self { subject } 12 | } 13 | 14 | #[cfg(feature = "test_utils")] 15 | #[allow(clippy::should_implement_trait)] 16 | pub fn default() -> Arc 17 | where 18 | Self: Sized, 19 | { 20 | Arc::new(Self::new(Arc::new(futures::executor::block_on(async { 21 | Subject::new().await 22 | })))) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/format-lint-test.yaml: -------------------------------------------------------------------------------- 1 | name: Format, Lint, Test 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | - next 8 | - beta 9 | - alpha 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - uses: dtolnay/rust-toolchain@stable 19 | with: 20 | components: rustfmt, clippy 21 | 22 | - name: Format 23 | run: cargo fmt --all -- --check 24 | 25 | - name: Lint 26 | run: cargo clippy --all-targets --all-features -- -D warnings 27 | 28 | - name: Test 29 | run: cargo test --workspace 30 | -------------------------------------------------------------------------------- /agent_shared/src/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum SharedError { 5 | #[error("Error while loading `{0}`: {1}")] 6 | GenericConfigurationError(String, String), 7 | // This error should always be unreachable since all configuration fields should have a default value in development mode 8 | #[error("Configuration parameter `{0}` is missing a default value")] 9 | MissingDefaultValueForDevelopment(String), 10 | #[error("Invalid configuration: {0}")] 11 | InvalidConfiguration(String), 12 | #[error("Configuration is not suitable for production: {0}")] 13 | ConfigurationNotSuitableForProduction(String), 14 | } 15 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/authorization_code/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum AuthorizationCodeError { 5 | #[error("Authorization code has already been redeemed")] 6 | RedeemedAuthorizationCodeError, 7 | #[error("Authorization code has expired")] 8 | ExpiredAuthorizationCodeError, 9 | #[error("Invalid client ID provided")] 10 | InvalidClientIdError, 11 | #[error("Invalid redirect URI provided")] 12 | InvalidRedirectUriError, 13 | #[error("Missing code verifier for PKCE")] 14 | MissingCodeVerifierError, 15 | #[error("Invalid code verifier provided for PKCE")] 16 | InvalidCodeVerifierError, 17 | } 18 | -------------------------------------------------------------------------------- /agent_shared/src/application_state.rs: -------------------------------------------------------------------------------- 1 | use std::{collections::HashMap, sync::Arc}; 2 | 3 | use async_trait::async_trait; 4 | use cqrs_es::Aggregate; 5 | 6 | /// The `Command` trait is used to define the command handlers for the aggregates. 7 | #[async_trait] 8 | pub trait Command 9 | where 10 | A: Aggregate, 11 | { 12 | async fn execute_with_metadata( 13 | &self, 14 | aggregate_id: &str, 15 | command: A::Command, 16 | metadata: HashMap, 17 | ) -> Result<(), cqrs_es::AggregateError> 18 | where 19 | A::Command: Send + Sync; 20 | } 21 | 22 | pub type CommandHandler = Arc + Send + Sync>; 23 | -------------------------------------------------------------------------------- /agent_verification/src/authorization_request/command.rs: -------------------------------------------------------------------------------- 1 | use oid4vp::dcql::dcql_query::DcqlQuery; 2 | use serde::Deserialize; 3 | 4 | use crate::generic_oid4vc::{GenericAuthorizationRequest, GenericAuthorizationResponse}; 5 | 6 | #[derive(Debug, Deserialize)] 7 | #[serde(untagged)] 8 | pub enum AuthorizationRequestCommand { 9 | CreateAuthorizationRequest { 10 | state: String, 11 | nonce: String, 12 | dcql_query: Option, 13 | }, 14 | SignAuthorizationRequestObject, 15 | VerifyAuthorizationResponse { 16 | authorization_request: GenericAuthorizationRequest, 17 | authorization_response: GenericAuthorizationResponse, 18 | }, 19 | } 20 | -------------------------------------------------------------------------------- /docs/configuration/profiles.md: -------------------------------------------------------------------------------- 1 | # Application Profiles 2 | 3 | UniCore can run with different application profiles. An application profile includes configuration defaults, changes runtime behavior and can enforce certain restrictions. 4 | Currently, UniCore supports the following application profiles: 5 | 6 | ### Production _(default)_ 7 | 8 | If nothing is further specified, UniCore will run in production mode by default. 9 | 10 | ### Development 11 | 12 | Can be enabled by setting the environment variable `UNICORE__PROFILE=development`. 13 | 14 | This profile is designed to be used for development purposes. It requires less initial configuration, enables a more verbose API and debugging information. 15 | -------------------------------------------------------------------------------- /docs/problem-details/unexpected.md: -------------------------------------------------------------------------------- 1 | ## Unexpected Error 2 | 3 | This error indicates that an unforeseen issue has occurred within the system. It serves as a catch-all for internal bugs or unhandled scenarios that fall outside the typical error categories. This error is not caused by external factors or transient issues, but rather signifies a flaw in UniCore's internal logic or configuration. 4 | 5 | ### Resolution 6 | 7 | Review the logs for additional context. Since this error represents an internal bug, please open a bug report at [https://github.com/impierce/ssi-agent/issues](https://github.com/impierce/ssi-agent/issues) with all relevant information so that the development team can promptly investigate and resolve the issue. 8 | -------------------------------------------------------------------------------- /agent_holder/src/credential/event.rs: -------------------------------------------------------------------------------- 1 | use cqrs_es::DomainEvent; 2 | use identity_credential::credential::Jwt; 3 | use serde::{Deserialize, Serialize}; 4 | use strum::Display; 5 | 6 | use super::aggregate::Data; 7 | 8 | #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Display)] 9 | pub enum CredentialEvent { 10 | CredentialAdded { 11 | holder_credential_id: String, 12 | received_offer_id: Option, 13 | credential: Jwt, 14 | data: Data, 15 | }, 16 | } 17 | 18 | impl DomainEvent for CredentialEvent { 19 | fn event_type(&self) -> String { 20 | self.to_string() 21 | } 22 | 23 | fn event_version(&self) -> String { 24 | "1".to_string() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /agent_api_http/res/open-badge-request.json: -------------------------------------------------------------------------------- 1 | { 2 | "offerId": "c86289fa-b105-4ec3-9326-a02436788f11", 3 | "credential": { 4 | "credentialSubject": { 5 | "id": "", 6 | "type": ["AchievementSubject"], 7 | "achievement": { 8 | "id": "https://example.com/achievements/21st-century-skills/teamwork", 9 | "type": ["Achievement"], 10 | "criteria": { 11 | "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management." 12 | }, 13 | "description": "This badge recognizes the development of the capacity to collaborate within a group environment.", 14 | "name": "Teamwork" 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /agent_api_http/src/v0/library/mod.rs: -------------------------------------------------------------------------------- 1 | // Endpoint handlers 2 | 3 | pub mod error; 4 | 5 | use agent_library::state::LibraryState; 6 | use axum::{routing::get, Router}; 7 | use std::sync::Arc; 8 | 9 | use crate::{ 10 | v0::templates::{get_template, get_templates, patch_template, post_templates}, 11 | API_VERSION, 12 | }; 13 | 14 | pub fn router(library_state: Arc) -> Router { 15 | Router::new() 16 | .nest( 17 | API_VERSION, 18 | Router::new() 19 | .route("/templates", get(get_templates).post(post_templates)) 20 | .route("/templates/{template_id}", get(get_template).patch(patch_template)), 21 | ) 22 | .with_state(library_state) 23 | } 24 | -------------------------------------------------------------------------------- /agent_issuance/src/lib.rs: -------------------------------------------------------------------------------- 1 | use async_trait::async_trait; 2 | use cqrs_es::{Aggregate, EventEnvelope, Query}; 3 | use tracing::info; 4 | 5 | // Aggregates 6 | pub mod credential; 7 | pub mod offer; 8 | pub mod server_config; 9 | pub mod utils; 10 | 11 | pub mod application; 12 | pub mod services; 13 | pub mod state; 14 | 15 | pub struct SimpleLoggingQuery {} 16 | 17 | #[async_trait] 18 | impl Query for SimpleLoggingQuery { 19 | async fn dispatch(&self, aggregate_id: &str, events: &[EventEnvelope]) { 20 | for event in events { 21 | let payload = serde_json::to_string_pretty(&event.payload).unwrap(); 22 | info!("{}-{} - {}", aggregate_id, event.sequence, payload); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/authorization_code/command.rs: -------------------------------------------------------------------------------- 1 | use oid4vci::authorization_request::CodeChallengeMethod; 2 | use serde::Deserialize; 3 | use url::Url; 4 | 5 | #[derive(Debug, Deserialize)] 6 | #[serde(untagged)] 7 | pub enum AuthorizationCodeCommand { 8 | CreateAuthorizationCode { 9 | authorization_code_id: String, 10 | client_id: String, 11 | redirect_uri: Url, 12 | code_challenge: Option, 13 | code_challenge_method: Option, 14 | issuer_state: Option, 15 | expires_in: i64, 16 | }, 17 | RedeemAuthorizationCode { 18 | client_id: String, 19 | redirect_uri: Option, 20 | code_verifier: Option, 21 | }, 22 | } 23 | -------------------------------------------------------------------------------- /agent_holder/src/presentation/views/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod all_presentations; 2 | 3 | use super::aggregate::Presentation; 4 | use cqrs_es::{EventEnvelope, View}; 5 | 6 | pub type PresentationView = Presentation; 7 | 8 | impl View for Presentation { 9 | fn update(&mut self, event: &EventEnvelope) { 10 | use crate::presentation::event::PresentationEvent::*; 11 | 12 | match &event.payload { 13 | PresentationCreated { 14 | presentation_id, 15 | signed_presentation, 16 | } => { 17 | self.presentation_id.clone_from(presentation_id); 18 | self.signed.replace(signed_presentation.clone()); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /agent_identity/src/connection/event.rs: -------------------------------------------------------------------------------- 1 | use cqrs_es::DomainEvent; 2 | use identity_core::common::Url; 3 | use identity_did::DIDUrl; 4 | use serde::{Deserialize, Serialize}; 5 | use strum::Display; 6 | 7 | #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Display)] 8 | pub enum ConnectionEvent { 9 | ConnectionAdded { 10 | connection_id: String, 11 | alias: Option, 12 | domain: Option, 13 | dids: Vec, 14 | credential_offer_endpoint: Option, 15 | }, 16 | } 17 | 18 | impl DomainEvent for ConnectionEvent { 19 | fn event_type(&self) -> String { 20 | self.to_string() 21 | } 22 | 23 | fn event_version(&self) -> String { 24 | "1".to_string() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /agent_verification/src/authorization_request/error.rs: -------------------------------------------------------------------------------- 1 | use thiserror::Error; 2 | 3 | #[derive(Error, Debug)] 4 | pub enum AuthorizationRequestError { 5 | #[error("Failed to create Authorization Request: {0}")] 6 | AuthorizationRequestBuilderError(#[source] anyhow::Error), 7 | #[error("Missing Authorization Request error")] 8 | MissingAuthorizationRequest, 9 | #[error("Failed to sign Authorization Request: {0}")] 10 | AuthorizationRequestSigningError(#[source] anyhow::Error), 11 | #[error("Invalid SIOPv2 Authorization Response: {0}")] 12 | InvalidSIOPv2AuthorizationResponse(#[source] anyhow::Error), 13 | #[error("Invalid OID4VP Authorization Response: {0}")] 14 | InvalidOID4VPAuthorizationResponse(#[source] anyhow::Error), 15 | } 16 | -------------------------------------------------------------------------------- /.github/workflows/coverage.yaml: -------------------------------------------------------------------------------- 1 | name: Coverage 2 | 3 | on: [pull_request, push] 4 | 5 | jobs: 6 | coverage: 7 | runs-on: ubuntu-latest 8 | env: 9 | CARGO_TERM_COLOR: always 10 | steps: 11 | - uses: actions/checkout@v4 12 | - name: Install Rust 13 | run: rustup update stable 14 | - name: Install cargo-llvm-cov 15 | uses: taiki-e/install-action@cargo-llvm-cov 16 | - name: Generate code coverage 17 | run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info --jobs 2 18 | - name: Upload coverage to Codecov 19 | uses: codecov/codecov-action@v5 20 | with: 21 | token: ${{ secrets.CODECOV_TOKEN }} 22 | files: lcov.info 23 | fail_ci_if_error: true 24 | -------------------------------------------------------------------------------- /agent_identity/src/profile/command.rs: -------------------------------------------------------------------------------- 1 | use agent_shared::config::Logo; 2 | use serde::Deserialize; 3 | 4 | use crate::profile::aggregate::Source; 5 | 6 | #[derive(Debug, Deserialize)] 7 | #[serde(untagged)] 8 | pub enum ProfileCommand { 9 | CreateProfile { 10 | profile_id: String, 11 | display_name: Option, 12 | logo: Option, 13 | country: Option, 14 | source: Source, 15 | }, 16 | UpdateDisplayName { 17 | display_name: String, 18 | source: Source, 19 | }, 20 | UpdateLogo { 21 | logo: Option, 22 | source: Source, 23 | }, 24 | UpdateCountry { 25 | country: Option, 26 | source: Source, 27 | }, 28 | UpdateSource { 29 | source: Source, 30 | }, 31 | } 32 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/access_token/event.rs: -------------------------------------------------------------------------------- 1 | use cqrs_es::DomainEvent; 2 | use serde::{Deserialize, Serialize}; 3 | use strum::Display; 4 | 5 | #[derive(Clone, Debug, Deserialize, PartialEq, Serialize, Display)] 6 | pub enum AccessTokenEvent { 7 | AccessTokenIssued { 8 | access_token_id: String, 9 | user_id: String, 10 | client_id: String, 11 | scopes: Option, 12 | issued_at: u64, 13 | access_token_expires_at: u64, 14 | refresh_token_expires_at: Option, 15 | issuer_state: Option, 16 | }, 17 | } 18 | 19 | impl DomainEvent for AccessTokenEvent { 20 | fn event_type(&self) -> String { 21 | self.to_string() 22 | } 23 | 24 | fn event_version(&self) -> String { 25 | "1".to_string() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /agent_issuance/src/offer/views/all_offers.rs: -------------------------------------------------------------------------------- 1 | use super::OfferView; 2 | use crate::offer::views::Offer; 3 | use cqrs_es::{EventEnvelope, View}; 4 | use serde::{Deserialize, Serialize}; 5 | use std::collections::HashMap; 6 | 7 | #[derive(Debug, Default, Serialize, Deserialize, Clone)] 8 | pub struct AllOffersView { 9 | #[serde(flatten)] 10 | pub offers: HashMap, 11 | } 12 | 13 | impl View for AllOffersView { 14 | fn update(&mut self, event: &EventEnvelope) { 15 | self.offers 16 | // Get the entry for the aggregate_id 17 | .entry(event.aggregate_id.clone()) 18 | // or insert a new one if it doesn't exist 19 | .or_default() 20 | // update the view with the event 21 | .update(event); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /agent_authorization/src/domain/client/views/all_clients.rs: -------------------------------------------------------------------------------- 1 | use super::Client; 2 | use super::ClientView; 3 | use cqrs_es::{EventEnvelope, View}; 4 | use serde::{Deserialize, Serialize}; 5 | use std::collections::HashMap; 6 | 7 | #[derive(Debug, Default, Serialize, Deserialize, Clone)] 8 | pub struct AllClientsView { 9 | #[serde(flatten)] 10 | pub clients: HashMap, 11 | } 12 | 13 | impl View for AllClientsView { 14 | fn update(&mut self, event: &EventEnvelope) { 15 | self.clients 16 | // Get the entry for the aggregate_id 17 | .entry(event.aggregate_id.clone()) 18 | // or insert a new one if it doesn't exist 19 | .or_default() 20 | // update the view with the event 21 | .update(event); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /agent_library/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "agent_library" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | 7 | [dependencies] 8 | agent_shared = { path = "../agent_shared" } 9 | 10 | async-trait.workspace = true 11 | chrono.workspace = true 12 | cqrs-es.workspace = true 13 | serde.workspace = true 14 | serde_json.workspace = true 15 | serde_with.workspace = true 16 | strum.workspace = true 17 | strum_macros.workspace = true 18 | thiserror.workspace = true 19 | tracing.workspace = true 20 | 21 | # `test_utils` dependencies 22 | rstest = { workspace = true, optional = true } 23 | 24 | [dev-dependencies] 25 | agent_library = { path = ".", features = ["test_utils"] } 26 | 27 | async-std.workspace = true 28 | serial_test = "3.0" 29 | 30 | [features] 31 | test_utils = ["dep:rstest"] 32 | -------------------------------------------------------------------------------- /agent_identity/src/document/command.rs: -------------------------------------------------------------------------------- 1 | use super::aggregate::Status; 2 | use agent_shared::config::SupportedDidMethod; 3 | use identity_document::service::Service as DocumentService; 4 | use identity_iota::verification::jwk::Jwk; 5 | use jsonwebtoken::Algorithm; 6 | use serde::Deserialize; 7 | 8 | #[derive(Debug, Deserialize)] 9 | #[serde(untagged)] 10 | pub enum DocumentCommand { 11 | CreateDocument { 12 | document_id: String, 13 | did_method: SupportedDidMethod, 14 | with_fixed_algorithm: Option, 15 | }, 16 | UpdateDocumentStatus { 17 | status: Status, 18 | }, 19 | UpdatePublicKeys { 20 | public_key_jwks: Vec, 21 | }, 22 | AddService { 23 | service_id: String, 24 | service: Box, 25 | }, 26 | PublishDocument, 27 | } 28 | -------------------------------------------------------------------------------- /agent_store/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "agent_store" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | 7 | [dependencies] 8 | agent_authorization = { path = "../agent_authorization" } 9 | agent_holder = { path = "../agent_holder" } 10 | agent_identity = { path = "../agent_identity" } 11 | agent_issuance = { path = "../agent_issuance" } 12 | agent_library = { path = "../agent_library" } 13 | agent_shared = { path = "../agent_shared" } 14 | agent_verification = { path = "../agent_verification" } 15 | 16 | async-trait.workspace = true 17 | cqrs-es.workspace = true 18 | mongo-es = "0.3" 19 | postgres-es = "0.4.12" 20 | serde_json.workspace = true 21 | sqlx = { version = "0.8", features = [ 22 | "postgres", 23 | "runtime-tokio-rustls", 24 | "json", 25 | ] } 26 | tokio.workspace = true 27 | -------------------------------------------------------------------------------- /agent_identity/src/service/views/all_services.rs: -------------------------------------------------------------------------------- 1 | use super::ServiceView; 2 | use crate::service::aggregate::Service; 3 | use cqrs_es::{EventEnvelope, View}; 4 | use serde::{Deserialize, Serialize}; 5 | use std::collections::HashMap; 6 | 7 | #[derive(Debug, Default, Serialize, Deserialize, Clone)] 8 | pub struct AllServicesView { 9 | #[serde(flatten)] 10 | pub services: HashMap, 11 | } 12 | 13 | impl View for AllServicesView { 14 | fn update(&mut self, event: &EventEnvelope) { 15 | self.services 16 | // Get the entry for the aggregate_id 17 | .entry(event.aggregate_id.clone()) 18 | // or insert a new one if it doesn't exist 19 | .or_default() 20 | // update the view with the event 21 | .update(event); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /agent_event_publisher_nats/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "agent_event_publisher_nats" 3 | version.workspace = true 4 | edition.workspace = true 5 | rust-version.workspace = true 6 | 7 | [dependencies] 8 | agent_issuance = { path = "../agent_issuance" } 9 | agent_shared = { path = "../agent_shared" } 10 | agent_store = { path = "../agent_store" } 11 | 12 | anyhow.workspace = true 13 | async-nats = "0.42" 14 | async-trait.workspace = true 15 | # TODO: Bump to next release after 0.8.0, where feature `async-nats` is available. 16 | cloudevents-sdk = { git = "https://github.com/cloudevents/sdk-rust", rev = "6f02d23", features = [ 17 | "nats", 18 | ] } 19 | cqrs-es.workspace = true 20 | futures.workspace = true 21 | serde.workspace = true 22 | serde_json.workspace = true 23 | tokio.workspace = true 24 | tracing.workspace = true 25 | uuid.workspace = true 26 | -------------------------------------------------------------------------------- /agent_library/src/template/views/all_templates.rs: -------------------------------------------------------------------------------- 1 | use super::TemplateView; 2 | use crate::template::views::Template; 3 | use cqrs_es::{EventEnvelope, View}; 4 | use serde::{Deserialize, Serialize}; 5 | use std::collections::HashMap; 6 | 7 | #[derive(Debug, Default, Serialize, Deserialize, Clone)] 8 | pub struct AllTemplatesView { 9 | #[serde(flatten)] 10 | pub templates: HashMap, 11 | } 12 | 13 | impl View