Skip to content
14 changes: 13 additions & 1 deletion Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,27 @@

## [Unreleased]

### [3.11.1] - 2026-06-18
### Added
- Show tile for zkp
- show zkp error message
- change the zkp label to normal user readable text
- added toggle button for widget zkp configure
- Added toggel to disable widget login

### Added
- Added toggel to disable widget login
### [3.11.0] - 2026-06-18

### Added
- Added toggel to disable widget login
### [3.11.0] - 2026-06-18

### Added
- Added toggel to disable widget login

### [3.10.5] - 2026-06-11


### Fixed
- Fixed busines icon

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "entity-developer-dashboard",
"version": "3.11.0",
"version": "3.11.1",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --mode production",
Expand Down
1 change: 0 additions & 1 deletion src/views/GettingStarted.vue
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@
depressed
small
color="white"

class="text-none font-weight-bold"
:href="`#/studio/kyb-webpage-generator/${appId()}`"
>
Expand Down
5 changes: 5 additions & 0 deletions src/views/ServiceConfig.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<b-container fluid class="py-3">
<load-ing :active.sync="isLoading" :can-cancel="true" :is-full-page="fullPage"></load-ing>

<div class="d-flex justify-content-between align-items-center mb-4 flex-wrap">
<div>
Expand Down Expand Up @@ -332,11 +333,14 @@ import messages from "../mixins/messages";
import { mapGetters, mapActions, mapMutations, mapState } from 'vuex/dist/vuex.common.js';
import LogoUploader from "../components/element/LogoUploader.vue";
import CorsChipsInput from "../components/element/CorsChips.vue";
import LoadIng from "../components/element/LoadIng.vue";
import { normalizeCorsOrigin } from '../utils/utils.js';
export default {
name: "ServiceConfig",
data() {
return {
isLoading: false,
fullPage: true,
isEditing: false,
// allow editing domain independently of full-form edit
isEditingDomain: false,
Expand Down Expand Up @@ -385,6 +389,7 @@ export default {
HfPopUp,
LogoUploader,
CorsChipsInput,
LoadIng,
},
async created() {
this.formData = { ...this.getSelectedService };
Expand Down
25 changes: 24 additions & 1 deletion src/views/playground/Sessions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@
<template v-slot:activator="{ on, attrs }">
<v-icon v-bind="attrs" v-on="on" small color="red darken-1">mdi-alert-circle-outline</v-icon>
</template>
<span>{{ getFailureReason(row.failureInfo && row.failureInfo.failureReason, row.failureInfo && row.failureInfo.failureStep) }}</span>
<span>{{ getRowFailureReason(row) }}</span>
</v-tooltip>
</div>
</td>
Expand Down Expand Up @@ -330,6 +330,7 @@ export default {
{ field: 'step_start', icon: 'fa-flag', title: 'Started' },
{ field: 'step_liveliness', icon: 'fa-user', title: 'Liveliness Check' },
{ field: 'step_ocrIdVerification', icon: 'fa-address-card', title: 'Document Verification' },
// { field: 'step_zkProofVerification', icon: 'fa-user-check', title: 'Age Verification' },
{ field: 'step_mintSbt', icon: 'fa-address-book', title: 'Mint SBT' },
{ field: 'step_userConsent', icon: 'fa-thumbs-up', title: 'User Consent' },
{ field: 'step_finish', icon: 'fa-check', title: 'Finished' },
Expand Down Expand Up @@ -412,14 +413,36 @@ export default {
filteredSteps(row) {
return this.allSteps.filter(step => row[step.field] !== null && row[step.field] !== undefined);
},
getRowFailureReason(row) {
if (row.status !== 'Failed' || !row.failureInfo) {
return 'Unknown error';
}

return this.getFailureReason(row.failureInfo.failureReason, row.failureInfo.failureStep);
},
getFailureReason(errorCode, errorType = 'step_liveliness') {
if (typeof errorCode === 'string' && isNaN(Number(errorCode))) {
return errorCode;
}

if (errorType == 'step_liveliness') {
return Config['LivelinessError'][errorCode] || 'Unknown error';
}

if (errorType == 'step_ocrIdVerification') {
return Config['FaicalAuthenticationError'][errorCode] || 'Unknown error';
}

if (errorType == 'step_zkProofVerification') {
const zkpVerificationErrors = {
0: 'Age verification could not be performed',
1: 'Age verification failed',
2: 'Age verification uncertain',
};
return zkpVerificationErrors[errorCode] || 'Age verification failed';
}

return 'Unknown error';
},
getAvatarStyle() {
// const colors = ['#607d8b', '#3f51b5', '#009688', '#ff5722', '#795548', '#673ab7', '#e91e63'];
Expand Down
176 changes: 176 additions & 0 deletions src/views/playground/SessionsDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,47 @@
</div>
</v-col>

<!-- Age Verification -->
<v-col
cols="12"
md="6"
lg="4"
id="zkp-verification-info"
v-if="zkpVerificationDataFound"
>
<div class="detail-card p-4">
<div class="card-section-title">
<i class="fa fa-user-check mr-2"></i>Age Verification
</div>
<table class="data-table w-100">
<tbody>
<tr v-if="zkpVerificationResultFound">
<td>Status</td>
<td>
<span
v-if="zkpVerificationPassed"
style="color: #28a745; font-weight: 600"
>
<i class="fa fa-check-circle mr-1"></i>Passed
</span>
<span v-else style="color: #dc3545; font-weight: 600">
<i class="fa fa-times-circle mr-1"></i>Failed
</span>
</td>
</tr>
<!-- <tr v-if="zkpVerificationResultFound">
<td>Result</td>
<td>{{ zkpVerificationResultForDisplay }}</td>
</tr> -->
<tr v-if="session.zkpVerificationDetails.createdAt">
<td>Verified At</td>
<td>{{ formatDate(session.zkpVerificationDetails.createdAt) }}</td>
</tr>
</tbody>
</table>
</div>
</v-col>

<!-- Soul Bound Token -->
<v-col
cols="12"
Expand Down Expand Up @@ -834,6 +875,7 @@ const ServiceLivenessResultEnum = {
16: "Face is obstructed",
17: "No life detected",
18: "Eyes closed",
66: "Eye is obstructed"
};

const FaicalAuthenticationError = {
Expand All @@ -845,6 +887,13 @@ const FaicalAuthenticationError = {
6: "Duplicate document was used",
};

const ZkpVerificationResultEnum = {
0: "Age verification could not be performed",
1: "Age verification failed",
2: "Age verification uncertain",
3: "Age verification passed",
};

export default {
name: "sessionDetails",
components: {
Expand Down Expand Up @@ -963,6 +1012,21 @@ export default {
sbtDataFound() {
return this.session?.mintsbtsDetails && this.session.mintsbtsDetails.length > 0;
},
zkpVerificationDataFound() {
return this.hasObjectData(this.session?.zkpVerificationDetails);
},
zkpVerificationResultFound() {
return this.hasValue(
this.session?.zkpVerificationDetails?.serviceZkpVerificationResult
);
},
zkpVerificationPassed() {
return this.session?.zkpVerificationDetails?.serviceZkpVerificationResult == 3;
},
zkpVerificationResultForDisplay() {
const result = this.session?.zkpVerificationDetails?.serviceZkpVerificationResult;
return ZkpVerificationResultEnum[result] || `Result ${result}`;
},
startFinishDiffInSeconds() {
if (this.userConsentDataFound) {
const startDate = new Date(this.session.createdAt);
Expand Down Expand Up @@ -1184,9 +1248,23 @@ export default {
}
}

if (this.isZkpVerificationTimelineDetail(newItem)) {
newItem.stepName = "Age verification";
if (this.hasValue(newItem.result) && newItem.result != 3) {
newItem.error = newItem?.failureReason||"Age verification failed"
}
}

return newItem;
});
}

const zkpTimelineDetail = this.buildZkpVerificationTimelineDetail();
if (zkpTimelineDetail && !this.timeLineDetails.some(this.isZkpVerificationTimelineDetail)) {
this.timeLineDetails.push(zkpTimelineDetail);
}

this.applySessionFailureToTimeline();
} catch (e) {
this.notifyErr(e.message);
this.isLoading = false;
Expand All @@ -1205,6 +1283,104 @@ export default {
const d = new Date(date);
return d.toLocaleString(); // Customize formatting if needed
},
applySessionFailureToTimeline() {
if (this.session?.status !== "Failed") return;

const failureInfo = this.session?.failureInfo;
if (!failureInfo) {
return;
}

const failureReason = this.getFailureReason(
failureInfo.failureReason,
failureInfo.failureStep
);

this.timeLineDetails = this.timeLineDetails.map((item) => {
if (!this.isTimelineDetailForFailureStep(item, failureInfo.failureStep)) {
return item;
}

return {
...item,
error: failureReason,
};
});
},
isTimelineDetailForFailureStep(item, failureStep) {
const stepName = item?.step_name || item?.stepName;
const failureStepMap = {
step_liveliness: ["liveliness", "Selfie uploaded"],
step_ocrIdVerification: ["ocrIdDoc", "Document uploaded"],
step_zkProofVerification: [
"zkpVerification",
"zkProofVerification",
"Age verification",
],
step_zkpVerification: [
"zkpVerification",
"zkProofVerification",
"Age verification",
],
step_mintSbt: ["mintSbt", "Mint SBT", "Soul Bound Token"],
};

return (failureStepMap[failureStep] || []).includes(stepName);
},
getFailureReason(errorCode, errorType) {
if (typeof errorCode === "string" && isNaN(Number(errorCode))) {
return errorCode;
}

if (errorType === "step_liveliness") {
return ServiceLivenessResultEnum[errorCode] || "Liveliness check failed";
}

if (errorType === "step_ocrIdVerification") {
return FaicalAuthenticationError[errorCode] || "Document verification failed";
}

if (
errorType === "step_zkProofVerification" ||
errorType === "step_zkpVerification"
) {
return ZkpVerificationResultEnum[errorCode] || "Age verification failed";
}

if (errorType === "step_mintSbt") {
return "SBT minting failed";
}

return "Verification failed";
},
isZkpVerificationTimelineDetail(item) {
return (
item?.step_name === "zkpVerification" ||
item?.step_name === "zkProofVerification" ||
item?.stepName === "zkpVerification" ||
item?.stepName === "zkProofVerification" ||
item?.stepName === "Age verification"
);
},
buildZkpVerificationTimelineDetail() {
const details = this.session?.zkpVerificationDetails;
if (!details?.createdAt) return null;

const result = details.serviceZkpVerificationResult;
const timelineDetail = {
step_name: "zkpVerification",
stepName: "Age verification",
createdAt: details.createdAt,
result,
};

if (this.hasValue(result) && result != 3) {
timelineDetail.error =
ZkpVerificationResultEnum[result] || "Age verification failed";
}

return timelineDetail;
},
formatFieldValue(key, value) {
if (!value && value !== 0) return value;
const dateKeys = /date|dob|birth|expir|issued|valid/i;
Expand Down
Loading
Loading