Skip to content
Open
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
4 changes: 2 additions & 2 deletions plugins/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ghcr.io/openwallet-foundation/acapy-agent:py3.13-1.5.0rc0 AS base
FROM ghcr.io/openwallet-foundation/acapy-agent:py3.13-1.5.0 AS base

# Install and Configure Poetry
USER root
Expand All @@ -24,7 +24,7 @@ RUN poetry install --only main
RUN ln -s $(poetry env info -p)/lib/python3.6/site-packages site-packages


FROM ghcr.io/openwallet-foundation/acapy-agent:py3.13-1.5.0rc0
FROM ghcr.io/openwallet-foundation/acapy-agent:py3.13-1.5.0
COPY --from=base --chown=aries:aries /home/aries/.venv /home/aries/.venv
ENV PATH="/home/aries/.venv/bin:$PATH"

Expand Down
12 changes: 6 additions & 6 deletions plugins/traction_innkeeper/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion plugins/traction_innkeeper/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ packages = [{include = "traction_innkeeper"}]

[tool.poetry.dependencies]
python = "^3.13"
acapy-agent = { version = "1.5.0rc0" }
acapy-agent = { version = "1.5.0" }
python-dateutil = "^2.9.0"
bcrypt = "^4.2.1"
mergedeep = "^1.3.4"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,10 @@
EVENT_LISTENER_PATTERN as INDY_SCHEMA_EVENT_PATTERN,
)

# Try to import ANONCREDS_SCHEMA_FINISHED_EVENT, but handle the case where it doesn't exist
# (e.g., if using an older version of acapy that doesn't have this event yet)
try:
from acapy_agent.anoncreds.events import (
SCHEMA_FINISHED_EVENT as ANONCREDS_SCHEMA_FINISHED_EVENT,
)
except (ImportError, AttributeError):
# If the event doesn't exist, we'll only subscribe to Indy events
ANONCREDS_SCHEMA_FINISHED_EVENT = None
# Import the AnonCreds schema finished event
from acapy_agent.anoncreds.events import (
SCHEMA_FINISHED_EVENT as ANONCREDS_SCHEMA_FINISHED_EVENT,
)

LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -274,13 +269,12 @@ async def sync_created(self, profile: Profile):
def subscribe(bus: EventBus):
# Subscribe to Indy schema events
bus.subscribe(INDY_SCHEMA_EVENT_PATTERN, schemas_event_handler)
# Subscribe to AnonCreds schema events if available
# Explicitly compile as literal pattern to ensure it's a Pattern object, not a string
if ANONCREDS_SCHEMA_FINISHED_EVENT:
bus.subscribe(
re.compile(re.escape(ANONCREDS_SCHEMA_FINISHED_EVENT)),
schemas_event_handler,
)
# Subscribe to AnonCreds schema finished events
# Use exact match pattern - escape special chars and anchor to start/end
bus.subscribe(
re.compile(f"^{re.escape(ANONCREDS_SCHEMA_FINISHED_EVENT)}$"),
schemas_event_handler,
)


def _normalize_schema_event_payload(event: Event) -> dict:
Expand All @@ -292,10 +286,7 @@ def _normalize_schema_event_payload(event: Event) -> dict:
payload = event.payload

# Check event topic to determine if it's AnonCreds or Indy
if (
ANONCREDS_SCHEMA_FINISHED_EVENT
and event.topic == ANONCREDS_SCHEMA_FINISHED_EVENT
):
if event.topic == ANONCREDS_SCHEMA_FINISHED_EVENT:
# AnonCreds event: SchemaFinishedPayload NamedTuple
if hasattr(payload, "schema_id"):
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@
<template #body="{ data }">
<MessageConnection
:connection-id="data.connection_id"
:connection-name="data.alias"
:connection-name="data.alias || data.their_label || ''"
/>
<Button
title="Delete Connection"
icon="pi pi-trash"
class="p-button-rounded p-button-icon-only p-button-text"
:disabled="deleteDisabled(data.alias)"
:disabled="deleteDisabled(data.alias || data.their_label || '')"
@click="deleteConnection($event, data.connection_id)"
/>
<EditConnection :connection-id="data.connection_id" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,7 @@
<script setup lang="ts">
// Types
import { FormattedIssuedCredentialRecord } from '@/helpers/tableFormatters';
import {
RevokeRequest,
V20CredExRecordDetail,
} from '@/types/acapyApi/acapyInterface';
import { RevokeRequest } from '@/types/acapyApi/acapyInterface';

// Vue/State
import { reactive, ref } from 'vue';
Expand Down Expand Up @@ -109,52 +106,22 @@ const handleSubmit = async (isFormValid: boolean) => {
}

try {
// Use cred_ex_id if available (preferred), otherwise use rev_reg_id and cred_rev_id
const payload: RevokeRequest = {
comment: formFields.comment,
connection_id: props.credExchRecord.connection_id,
rev_reg_id: props.credExchRecord.rev_reg_id,
cred_rev_id: props.credExchRecord.cred_rev_id,
...(props.credExchRecord.credential_exchange_id
? { cred_ex_id: props.credExchRecord.credential_exchange_id }
: {
rev_reg_id: props.credExchRecord.rev_reg_id,
cred_rev_id: props.credExchRecord.cred_rev_id,
}),
publish: true,
notify: true,
};

// Determine if this is an AnonCreds credential by checking if anoncreds/indy fields exist
// FormattedIssuedCredentialRecord extends V20CredExRecordDetail which has indy/anoncreds fields
// If only anoncreds exists, it's an AnonCreds credential; if only indy exists, it's Indy
// If both or neither exist, pass undefined to let the store determine based on wallet type
const credRecord = props.credExchRecord as V20CredExRecordDetail;
const hasAnoncreds = !!credRecord.anoncreds;
const hasIndy = !!credRecord.indy;
const isAnonCredsCredential =
hasAnoncreds && !hasIndy
? true
: hasIndy && !hasAnoncreds
? false
: undefined;

console.log('Credential format detection:', {
hasAnoncreds,
hasIndy,
isAnonCredsCredential,
});

// Warn if credential format can't be detected - revocation might fail silently
if (isAnonCredsCredential === undefined) {
toast.warning(
'Credential format could not be detected. Please verify the revocation succeeded by checking the credential list.'
);
}

await issuerStore.revokeCredential(payload, isAnonCredsCredential);

// If format couldn't be detected, show a warning message instead of success
if (isAnonCredsCredential === undefined) {
toast.warning(
'Revocation request sent. Please verify the credential was actually revoked in the credential list.'
);
emit('closed');
return;
}
// The store now determines the endpoint based on wallet type
await issuerStore.revokeCredential(payload);

emit('success');
// close up on success
Expand Down
16 changes: 14 additions & 2 deletions services/tenant-ui/frontend/src/helpers/tableFormatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface FormattedIssuedCredentialRecord extends V20CredExRecordDetail {
created: string;
cred_rev_id?: string;
rev_reg_id?: string;
credential_exchange_id?: string;
state: V20CredExRecord['state'];
}

Expand Down Expand Up @@ -185,12 +186,23 @@ export const formatIssuedCredentials = (
}
}

const connectionId = ce.cred_ex_record?.connection_id ?? '';
// findConnectionName is a function that takes connectionId and returns the connection name
// It should use alias first, then their_label as fallback
const connectionName =
connectionId && findConnectionName
? findConnectionName(connectionId) || ''
: '';

return {
// Preserve the full V20CredExRecordDetail structure for format detection
...ce,
// Explicitly set all formatted values to ensure they override any spread properties
state: ce.cred_ex_record?.state,
cred_rev_id: credRevId,
rev_reg_id: revRegId,
connection_id: ce.cred_ex_record?.connection_id,
connection: findConnectionName(ce.cred_ex_record?.connection_id ?? ''),
connection_id: connectionId,
connection: connectionName,
credential_definition_id: credentialDefinitionDisplay,
credential_exchange_id: ce.cred_ex_record?.cred_ex_id,
created: formatDateLong(ce.cred_ex_record?.created_at),
Expand Down
7 changes: 5 additions & 2 deletions services/tenant-ui/frontend/src/store/connectionStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ export const useConnectionStore = defineStore('connection', () => {

const findConnectionName = computed(() => (connectionId: string) => {
if (loading.value) return undefined;
// Find the connection alias for an ID
// Find the connection alias for an ID, fallback to their_label
const connection = connections.value?.find((c: any) => {
return c.connection_id === connectionId;
});
return connection && connection.alias ? connection.alias : '';
if (connection) {
return connection.alias || connection.their_label || '';
}
return '';
});

// actions
Expand Down
42 changes: 5 additions & 37 deletions services/tenant-ui/frontend/src/store/governanceStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -589,46 +589,14 @@ export const useGovernanceStore = defineStore('governance', () => {
.then((res) => {
result = res.data;
console.log(result);
// Schema finished event will be handled by the backend event handler
// which will automatically add it to storage
})
.then(async () => {
// Extract schema_id from response
const schemaId = result?.schema_state?.schema_id;

if (!schemaId) {
console.warn('No schema_id found in response, cannot verify storage');
return;
}

// Wait a bit for event handler to complete (if it runs)
await new Promise((resolve) => setTimeout(resolve, 1500));

// Refresh the stored schema list
// Wait a moment for the backend event handler to process and store the schema
await new Promise((resolve) => setTimeout(resolve, 500));
// Refresh the schema list to show the newly created schema
await listStoredSchemas();

// Check if schema is in storage after refresh
const storedSchema = storedSchemas.value.find(
(s: any) => s.schema_id === schemaId
);

if (!storedSchema) {
// Schema not in storage, manually add it via storage endpoint
console.log(
`Schema ${schemaId} not found in storage after event handler, manually adding...`
);
try {
await addSchemaFromLedgerToStorage({ schema_id: schemaId });
// Refresh again after manual add
await listStoredSchemas();
} catch (err) {
console.error(
`Failed to manually add schema ${schemaId} to storage:`,
err
);
// Don't throw - schema was created successfully, just storage failed
}
} else {
console.log(`Schema ${schemaId} found in storage`);
}
})
.catch((err) => {
console.log(err);
Expand Down
Loading
Loading