Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds Non-Asset based Events #25

Merged
merged 2 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 59 additions & 8 deletions server/links/datatrails/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

# Increment for any API/attribute changes
link_type = "DataTrails"
link_version = "0.2.0"
link_version = "0.3.0"

# NOTE: Once DataTrails removes the dependency for assets,
# "asset_attributes" will be removed
Expand All @@ -24,7 +24,7 @@
# Why droid_id: "these are not the droids your're looking for"

default_options = {
"api_url": "https://app.datatrails.ai/archivist/v2",
"api_url": "https://app.datatrails.ai/archivist",
"auth_url": "https://app.datatrails.ai/archivist/iam/v1/appidp/token",
"asset_attributes": {"arc_display_type": "vcon_droid", "conserver_link_version": link_version},
}
Expand Down Expand Up @@ -119,7 +119,7 @@ def get_asset_by_attributes(opts: dict, auth: DataTrailsAuth, attributes: dict)
for param in attributes:
params.update({f"attributes.{param}": f"{attributes[param]}"})

response = requests.get(f"{api_url}/assets", params=params, headers=headers)
response = requests.get(f"{api_url}/v2/assets", params=params, headers=headers)
response.raise_for_status()
return response.json()

Expand Down Expand Up @@ -159,18 +159,18 @@ def create_asset(opts: dict, auth: DataTrailsAuth, attributes: dict) -> dict:
}
payload = {
"behaviours": ["RecordEvidence"],
"attributes": {"arc_display_type": "Publish", **attributes},
"attributes": {**attributes},
"public": False,
}
response = requests.post(f"{api_url}/assets", headers=headers, json=payload)
response = requests.post(f"{api_url}/v2/assets", headers=headers, json=payload)
if response.status_code == 429:
logger.info(f"response.raw: {response.raw}")

response.raise_for_status()
return response.json()


def create_event(opts: dict, asset_id: str, auth: DataTrailsAuth, event_attributes: dict) -> dict:
def create_asset_event(opts: dict, asset_id: str, auth: DataTrailsAuth, event_attributes: dict) -> dict:
"""
Create a new DataTrails Event, mapping to a SCITT Envelope

Expand All @@ -197,7 +197,39 @@ def create_event(opts: dict, asset_id: str, auth: DataTrailsAuth, event_attribut
# a cose-meta-map draft (https://github.com/SteveLasker/draft-lasker-cose-meta-map)
payload = {"operation": "Record", "behaviour": "RecordEvidence", "event_attributes": {**event_attributes}}
# logger.info(f"payload: {payload}")
response = requests.post(f"{api_url}/{asset_id}/events", headers=headers, json=payload)
response = requests.post(f"{api_url}/v2/{asset_id}/events", headers=headers, json=payload)

response.raise_for_status()
return response.json()


def create_event(opts: dict, auth: DataTrailsAuth, attributes: dict, trails) -> dict:
"""
Create a new DataTrails Non-Asset based Event, mapping to a SCITT Envelope

Args:
opts (dict): Configuration, including the base URL for the DataTrails API.
auth (DataTrailsAuth): Authentication object for DataTrails API.
attributes (dict): Attributes of the event.
trails (array): A collection of strings used for trails

Returns:
dict: Data of the created Event

Raises:
requests.HTTPError: If the API request fails
"""
headers = {
"Authorization": f"Bearer {auth.get_token()}",
"DataTrails-User-Agent": "oss/conserverlink/" + link_version,
"DataTrails-Partner-ID": opts["partner_id"],
"Content-Type": "application/json",
}
api_url = opts["api_url"]
# event_attributes will map to SCITT headers and
# a cose-meta-map draft (https://github.com/SteveLasker/draft-lasker-cose-meta-map)
payload = {"attributes": {**attributes}, "trails": trails}
response = requests.post(f"{api_url}/v1/events", headers=headers, json=payload)

response.raise_for_status()
return response.json()
Expand Down Expand Up @@ -233,6 +265,7 @@ def run(vcon_uuid: str, link_name: str, opts: dict = default_options) -> str:
raise HTTPException(
status_code=HTTP_501_NOT_IMPLEMENTED, detail='Auth improperly configured. Unable to find opt["auth"]'
)

if auth_type.lower() == "oidc-client-credentials":
auth = DataTrailsAuth(opts["auth"]["token_endpoint"], opts["auth"]["client_id"], opts["auth"]["client_secret"])
else:
Expand Down Expand Up @@ -318,6 +351,7 @@ def run(vcon_uuid: str, link_name: str, opts: dict = default_options) -> str:

event_attributes = {
"arc_display_type": vcon_operation,
"arc_event_type": vcon_operation,
"conserver_link": link_type,
"conserver_link_name": link_name,
"conserver_link_version": link_version,
Expand All @@ -329,6 +363,11 @@ def run(vcon_uuid: str, link_name: str, opts: dict = default_options) -> str:
"vcon_draft_version": "01",
"vcon_operation": vcon_operation,
}
# Asset-Free Events support a collection of Trails for indexing
# Add the primary paths by which a vCon consumer would need to index
trails = [
subject
]

# TODO: Should we set the public url for the vCon
# from https://datatracker.ietf.org/doc/draft-steele-cose-hash-envelope
Expand All @@ -339,10 +378,22 @@ def run(vcon_uuid: str, link_name: str, opts: dict = default_options) -> str:
# }
# )

event = create_event(opts, asset_id, auth, event_attributes)
event = create_asset_event(opts, asset_id, auth, event_attributes)
event_id = event["identity"]
logger.info(f"DataTrails: Event Created: {event_id}")

# Asset Free Events
try:
# during preview, Asset-free events are for DataTrails testing
# wrapped in a try/catch to avoid errors bubbling up to the conserver

event = create_event(opts, auth, event_attributes, trails)
event_id = event["identity"]
logger.info(f"DataTrails: New Event Created: {event_id}")
except:
logger.info(f"DataTrails: New Event Creation Failure")


# TODO: may want to store the receipt/transparent statement in the vCon, in the future

return vcon_uuid
26 changes: 22 additions & 4 deletions server/links/datatrails/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,11 @@ For each chain completion, the hash of the vCon will be placed on the ledger, wi

For each vCon Chain:

1. A [DataTrails Event]() will be recorded, integrity protecting each vCon, setting the `subject` to `vcon://<vcon_uuid>` for correlation of events to each vCon
1. A [DataTrails Event](https://docs.datatrails.ai/developers/api-reference/events-api/) will be recorded, integrity protecting each vCon, setting the `subject` to `vcon://<vcon_uuid>` for correlation of events to each vCon.
1. If no DataTrails Asset exists for the vCon, a new asset will be created.
_**Note:** this is a temporary solution as Assets are being deprecated._
_**Note:** this is a temporary solution as Assets are being deprecated._
In this latest version `0.3.0`, an early preview of Asset-Free events has been added.
This workflow is additional, and non-blocking for parallel testing by the DataTrails platform.

## Configuration

Expand All @@ -118,7 +120,7 @@ links:
datatrails-created:
module: links.datatrails
options:
api_url: "https://app.datatrails.ai/archivist/v2"
api_url: "https://app.datatrails.ai/archivist"
vcon_operation: "vcon_created"
auth:
type: "OIDC-client-credentials"
Expand All @@ -128,7 +130,7 @@ links:
datatrails_consent_revoked:
module: links.datatrails
options:
api_url: "https://app.datatrails.ai/archivist/v2"
api_url: "https://app.datatrails.ai/archivist"
vcon_operation: "vcon_consent_revoked"
auth:
type: "OIDC-client-credentials"
Expand Down Expand Up @@ -212,6 +214,22 @@ Please follow these steps:
- Check the conserver logs for any error messages related to the DataTrails Link.
- Verify that your vCons contain the expected data and tags.

## Version History

### `0.3.0`

_**Note: BREAKING CHANGE**_

- Configuration for DataTrails has changed
- This version adds a preview of [Asset-free Events](https://docs.datatrails.ai/developers/api-reference/events-api/), as a non-blocking addition for parallel testing in the DataTrails platform.
- Asset-free events uses version 1 `/v1/events` to differentiate from the `/v2/assets` APIs.
This change required a change to the `api_url` configuration.
Your configuration will have:
`api_url: "https://app.datatrails.ai/archivist/v2"`
**WHICH HAS BEEN CHANGED** to
`api_url: "https://app.datatrails.ai/archivist"`
moving `/v2` to the asset call, and uses `v1/events` for the new Asset Free events.

## Support

For issues, questions, or contributions, please open an issue in the GitHub repository or contact [DataTrails Support](https://support.datatrails.ai/)
Expand Down