Skip to content
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
6 changes: 6 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## [Unreleased]

### [3.12.0]- 2026-07-03
### Added
- Added toggle for requesting fields for selective disclosure
### Fixed
- Fixed a bug where a section was removed from the consent screen.

### [3.11.1] - 2026-06-18
### Added
- Show tile for zkp
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.1",
"version": "3.12.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --mode production",
Expand Down
Binary file modified public/Entity_c.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified src/assets/Entity_full.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 4 additions & 3 deletions src/views/ServiceConfig.vue
Original file line number Diff line number Diff line change
Expand Up @@ -633,18 +633,19 @@ export default {
const isEditing = this.isEditing;
const isLogoChanged = isEditing && this.formData.logoUrl !== this.backupData?.logoUrl;
const isIssuerChanged = isEditing && this.formData.issuerDid !== this.backupData?.issuerDid;
const isVerificationMethodChanged = isEditing && this.formData.issuerVerificationMethodId !== this.backupData?.issuerVerificationMethodId;
const isAppNameChanged = isEditing && this.formData.appName !== this.backupData?.appName;
const isDomainChanged = isEditing && this.formData.domain !== this.backupData?.domain;
await this.updateAnAppOnServer({ ...this.formData })
if (!isLogoChanged && !isIssuerChanged && !isAppNameChanged && !isDomainChanged) {
if (!isLogoChanged && !isIssuerChanged && !isVerificationMethodChanged && !isAppNameChanged && !isDomainChanged) {
this.isEditing = false;
return this.notifySuccess("Service configuration updated successfully!");
}
// Sync logo, issuerDid and issuerVerificationMethodId into widget config
if (Object.keys(this.widgetConfig).length > 0) {
let shouldUpdateWidgetConfig = false;
let updatedWidgetConfig = { ...this.widgetConfig };
if (isIssuerChanged && this.formData.issuerDid) {
if ((isIssuerChanged || isVerificationMethodChanged) && this.formData.issuerDid) {
updatedWidgetConfig.issuerDID = this.formData.issuerDid;
updatedWidgetConfig.issuerVerificationMethodId =
this.formData.issuerVerificationMethodId ||
Expand Down Expand Up @@ -675,7 +676,7 @@ export default {
if(Object.keys(this.kybWidgetConfig).length > 0 ){
let updatedKybWidgetConfig = { ...this.kybWidgetConfig };
let shouldUpdateKybWidgetConfig = false;
if (isIssuerChanged && this.formData.issuerDid) {
if ((isIssuerChanged || isVerificationMethodChanged) && this.formData.issuerDid) {
updatedKybWidgetConfig.issuerDID = this.formData.issuerDid;
updatedKybWidgetConfig.issuerVerificationMethodId =
this.formData.issuerVerificationMethodId ||
Expand Down
170 changes: 165 additions & 5 deletions src/views/playground/WidgetConfig/Index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@ ul {
list-style-type: none;
}

.selective-field-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 8px 12px;
}

.selective-field-badge {
border: 1px solid #d8dee8;
color: #334155;
margin-right: 6px;
margin-bottom: 6px;
padding: 6px 8px;
}

/* .zkbadge {
background-color: lightblue;
margin-left: 3px;
Expand Down Expand Up @@ -182,7 +196,6 @@ ul {
</div>
</li>


<li class="list-group-item">
<div class="row">
<div class="col">
Expand Down Expand Up @@ -216,7 +229,7 @@ ul {

</div>
</div>
<!-- <div class="col">
<div class="col">
<div class="row">
<div class="col">
<div class="row">
Expand All @@ -230,7 +243,7 @@ ul {

</div>
</div>
</div> -->
</div>
</div>
</li>
<li class="list-group-item">
Expand All @@ -244,14 +257,39 @@ ul {
<div class="col">
<label for=""><strong>Choose Trusted Issuer(s): </strong></label>
<div style="max-height: 300px; overflow-y: scroll;" class="p-1">
<MarketplaceList @selectedServiceEvent="selectedServiceEventHandler" isSelection="true" />
<MarketplaceList @selectedServiceEvent="selectedServiceEventHandler" :isSelection="true" />
</div>
</div>
</div>
<!-- <TrustedIssuer @selectedServiceEventFromTrustedIssuer="selectedServiceEventHandler" /> -->
</li>


<li class="list-group-item">
<div class="row">
<div class="col-md-6">
<b-form-checkbox
switch
size="lg"
v-model="widgetConfigTemp.selectiveDisclosure.enabled"
:disabled="!widgetConfigTemp.idOcr.enabled"
>
{{ widgetConfigUI.selectiveDisclosure.label }} <HFBeta></HFBeta>
</b-form-checkbox>
<small v-html="widgetConfigUI.selectiveDisclosure.description"></small>
</div>
<div class="col" v-if="widgetConfigTemp.selectiveDisclosure.enabled">
<label for="selective-disclosure-fields"><strong>Selected Identity Attributes: </strong></label>
<b-form-checkbox-group
id="selective-disclosure-fields"
v-model="widgetConfigTemp.selectiveDisclosure.fields"
:options="selectiveDisclosureFieldOptions"
class="selective-field-grid"
></b-form-checkbox-group>
</div>
</div>
</li>

<li class="list-group-item">
<div class="row">
<div class="col-md-6">
Expand Down Expand Up @@ -400,10 +438,33 @@ export default {
this.widgetConfigTemp.zkProof.proofs = [];

this.widgetConfigTemp.onChainId.enabled = false;
this.widgetConfigTemp.onChainId.selectedOnChainKYCconfiguration = null;
this.widgetConfigTemp.onChainId.selectedOnChainKYCconfiguration = null;

this.widgetConfigTemp.selectiveDisclosure.enabled = false;
this.widgetConfigTemp.selectiveDisclosure.fields = [];
this.widgetConfigTemp.selectiveDisclosure.frame = null;

}
}
},

'widgetConfigTemp.selectiveDisclosure.enabled': {
handler(enabled) {
if (enabled && !this.widgetConfigTemp.idOcr.enabled) {
this.widgetConfigTemp.selectiveDisclosure.enabled = false;
return;
}

if (enabled && this.widgetConfigTemp.selectiveDisclosure.fields.length === 0) {
this.widgetConfigTemp.selectiveDisclosure.fields = [...this.defaultSelectiveDisclosureFields]
}

if (!enabled) {
this.widgetConfigTemp.selectiveDisclosure.fields = [];
this.widgetConfigTemp.selectiveDisclosure.frame = null;
}
}
},
'widgetConfigTemp.isWidgetLogin': {
handler(newValue) {
this.widgetConfigTemp.isVaultEnabled = newValue !== false
Expand Down Expand Up @@ -505,6 +566,7 @@ export default {

this.widgetConfigTemp.trustedIssuer = this.widgetConfigTemp.issuerDID ? true : false;

this.ensureSelectiveDisclosure()


if (!this.widgetConfigTemp.zkProof.proofs) {
Expand Down Expand Up @@ -552,6 +614,10 @@ export default {
description: "Enable users to prove they meet a minimum age requirement without sharing their exact date of birth. Read more <b><a href=\"https://docs.hypersign.id/hypersign-kyc/integrations/widget-configuration#id-document-verification\" target=\"_blank\">here</a></b>."
}
},
selectiveDisclosure: {
label: "Request only the information you need",
description: "Choose which verified identity attributes users will share with your application after completing identity verification. Attributes that are not selected remain private and are not included in the verification response."
},
emailNotification: {
label: "Enable Email Notifications",
description: "Notify users via email regarding the status of their ID verification. When enabled, users will receive automated updates upon the successful completion or rejection of their verification attempt."
Expand Down Expand Up @@ -588,6 +654,11 @@ export default {
enabled: false,
proofs: []
},
selectiveDisclosure: {
enabled: false,
fields: [],
frame: null,
},
trustedIssuer: true,
isWidgetLogin: true,
isVaultEnabled: true,
Expand All @@ -597,6 +668,15 @@ export default {
},
selectedIssuerDids: new Set(),
ageProofCriteria: '',
defaultSelectiveDisclosureFields: ['docModel', 'givenNames', 'surname', 'sex', 'nationality', 'dateOfBirth'],
selectiveDisclosureFieldOptions: [
{ value: 'docModel', text: 'Document Type' },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its quite confusing,

here we are using docModel as Document Type field but in backend we have two different fields docModel and docType. I suggest we sohuld align both frontend and backend

{ value: 'givenNames', text: 'Given Name(s)' },
{ value: 'surname', text: 'Surname' },
{ value: 'sex', text: 'Gender' },
{ value: 'nationality', text: 'Nationality' },
{ value: 'dateOfBirth', text: 'Date of Birth' },
],
documentTypeOptions: [
{
value: null,
Expand Down Expand Up @@ -642,6 +722,74 @@ export default {
.filter(did => !!did && !!did.trim())
.join(',')
},
ensureSelectiveDisclosure() {
if (!this.widgetConfigTemp.selectiveDisclosure) {
this.$set(this.widgetConfigTemp, 'selectiveDisclosure', {
enabled: false,
fields: [],
frame: null,
})
}

if (!Array.isArray(this.widgetConfigTemp.selectiveDisclosure.fields)) {
this.$set(this.widgetConfigTemp.selectiveDisclosure, 'fields', [])
}

if (!Object.prototype.hasOwnProperty.call(this.widgetConfigTemp.selectiveDisclosure, 'frame')) {
this.$set(this.widgetConfigTemp.selectiveDisclosure, 'frame', null)
}

if (
this.widgetConfigTemp.selectiveDisclosure.enabled &&
this.widgetConfigTemp.selectiveDisclosure.fields.length === 0
) {
const framedFields = Object.keys(this.widgetConfigTemp.selectiveDisclosure.frame?.credentialSubject || {})
.filter(field => field !== '@explicit' && this.defaultSelectiveDisclosureFields.includes(field))

this.widgetConfigTemp.selectiveDisclosure.fields = framedFields.length > 0
? framedFields
: [...this.defaultSelectiveDisclosureFields]
}
},
getSelectiveDisclosureFieldLabel(field) {
const option = this.selectiveDisclosureFieldOptions.find(item => item.value === field)
return option ? option.text : field
},
generateSelectiveDisclosureFrame(fields) {
const credentialSubject = fields.reduce((frame, field) => {
frame[field] = {}
return frame
}, {
'@explicit': true,
})

return {
'@context': [
'https://www.w3.org/2018/credentials/v1',
'https://raw.githubusercontent.com/hypersign-protocol/hypersign-contexts/main/BJJSignature2021.jsonld',
'https://schema.org'
],
type: [
'VerifiableCredential'
],
credentialSubject,
}
},
syncSelectiveDisclosure() {
this.ensureSelectiveDisclosure()

if (!this.widgetConfigTemp.selectiveDisclosure.enabled) {
this.widgetConfigTemp.selectiveDisclosure.fields = []
this.widgetConfigTemp.selectiveDisclosure.frame = null
return
}

const selectedFields = this.widgetConfigTemp.selectiveDisclosure.fields
.filter(field => this.defaultSelectiveDisclosureFields.includes(field))

this.widgetConfigTemp.selectiveDisclosure.fields = selectedFields
this.widgetConfigTemp.selectiveDisclosure.frame = this.generateSelectiveDisclosureFrame(selectedFields)
},
syncAgeProof() {
if (!this.widgetConfigTemp.zkProof.proofs) {
this.widgetConfigTemp.zkProof.proofs = []
Expand Down Expand Up @@ -671,6 +819,16 @@ export default {
}
}

if (this.widgetConfigTemp.selectiveDisclosure.enabled) {
if (!this.widgetConfigTemp.idOcr.enabled) {
throw new Error('Selective disclosure requires ID document verification. Please enable ID document verification to proceed.')
}

if (this.widgetConfigTemp.selectiveDisclosure.fields.length === 0) {
throw new Error('Kindly select information to request through selective disclosure')
}
}

if (!this.widgetConfigTemp.onChainId.enabled) {
this.widgetConfigTemp.onChainId.selectedOnChainKYCconfiguration = null
this.widgetConfigTemp.onChainId.enabled = false
Expand Down Expand Up @@ -702,6 +860,7 @@ export default {
//TODO validate all fields
this.isLoading = true;
this.syncAgeProof()
this.syncSelectiveDisclosure()
this.validateField()
this.setWidgetConfig(this.widgetConfigTemp)
await this.createAppsWidgetConfig()
Expand All @@ -722,6 +881,7 @@ export default {
//TODO validate all field
this.isLoading = true;
this.syncAgeProof()
this.syncSelectiveDisclosure()
this.validateField()

this.setWidgetConfig(this.widgetConfigTemp)
Expand Down
Loading