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
4 changes: 2 additions & 2 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
- Foundational support for modern AI & agentic economy use cases and protocols (AP2 + x402, ERC-8004, etc.)
- Continued prototyping and integration of identity solutions in Hiero ecosystem (Contributor Identity Verification mentorship program, Hiero-specific identity features and cross-project integrations)
- Support for enterprise adoption and use cases
- Advanced ZKP support (Longfellow ZKP, etc.)
- Advanced ZKP support (Longfellow ZK, etc.)

## Timeline

```mermaid
timeline
Q2 2026 : Platform and dependencies updates
: Documentation improvements
: Heka Identity Platform LFDT workshop
: Heka Identity Platform LFDT Meetup
: Hiero Contributor Identity Verification Prototype — LFDT mentorship kick-off
: Digital Credentials API (DC API) support
Q3 2026 : ERC-8004
Expand Down
14 changes: 7 additions & 7 deletions heka-identity-service-web-ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ steps before running or deploying the application:

The Web UI is configured via environment variables read by webpack at build time. Set them in the `.env` file at the package root.

| Variable | Default | Description |
|---|---|---|
| `REACT_APP_AGENCY_ENDPOINT` | `http://localhost:3000` | Heka Identity Service base URL. |
| `REACT_APP_AUTH_SERVICE_ENDPOINT` | `http://localhost:3004` | Heka Auth Service base URL. JWT login and token refresh go here. |
| `REACT_APP_DEMO_USER_DID` | _(empty)_ | DID of the pre-provisioned demo user. Filled in by `scripts/prepare-demo-user.ts` — see [Creation of Pre-Defined Demo User](#creation-of-pre-defined-demo-user). |
| `REACT_APP_DEMO_USER_ACCESS_TOKEN` | _(empty)_ | JWT access token for the demo user. Filled in by the script above. |
| `REACT_APP_DEMO_USER_REFRESH_TOKEN` | _(empty)_ | Refresh token for the demo user. Filled in by the script above. |
| Variable | Default | Description |
| ----------------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `REACT_APP_AGENCY_ENDPOINT` | `http://localhost:3000` | Heka Identity Service base URL. |
| `REACT_APP_AUTH_SERVICE_ENDPOINT` | `http://localhost:3004` | Heka Auth Service base URL. JWT login and token refresh go here. |
| `REACT_APP_DEMO_USER_DID` | _(empty)_ | DID of the pre-provisioned demo user. Filled in by `scripts/prepare-demo-user.ts` — see [Creation of Pre-Defined Demo User](#creation-of-pre-defined-demo-user). |
| `REACT_APP_DEMO_USER_ACCESS_TOKEN` | _(empty)_ | JWT access token for the demo user. Filled in by the script above. |
| `REACT_APP_DEMO_USER_REFRESH_TOKEN` | _(empty)_ | Refresh token for the demo user. Filled in by the script above. |

The Web UI authenticates against [Heka Auth Service](../heka-auth-service/README.md) for login and token refresh, and calls the [Heka Identity Service](../heka-identity-service/README.md) with the resulting JWT. Both services must be running and reachable from the browser at the configured endpoints.

Expand Down
9 changes: 8 additions & 1 deletion heka-identity-service-web-ui/scripts/prepare-demo-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,14 @@ async function main() {
const mdlSchema = {
name: 'mDL',
bgColor: '#1a3a5c',
fields: ['given_name', 'family_name', 'birth_date', 'age_over_18', 'document_number', 'expiry_date'],
fields: [
'given_name',
'family_name',
'birth_date',
'age_over_18',
'document_number',
'expiry_date',
],
registrations: [
{
network: 'key',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,12 @@ const UnauthenticatedLayout = () => {
/>
</DesktopView>
<Column className={cls.content}>
<Row
alignItems="center"
>
<Row alignItems="center">
<Button
onPress={onNavigateBack}
buttonType="text"
leftIcon="arrow-back"
alignment={"left"}
alignment={'left'}
>
<p>{t('Common.buttons.back')}</p>
</Button>
Expand All @@ -56,7 +54,6 @@ const UnauthenticatedLayout = () => {
/>
</Row>


<MobileView>
<TopPanel
title={title}
Expand Down
4 changes: 2 additions & 2 deletions heka-identity-service-web-ui/src/components/Logo/Logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export const Logo = ({ label, onClick }: LogoProps) => {
aria-label={label}
>
<HieroLogo
height={"100%"}
width={"100%"}
height={'100%'}
width={'100%'}
/>
</Button>
);
Expand Down
6 changes: 1 addition & 5 deletions heka-identity-service-web-ui/src/components/Panel/Panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,7 @@ export const PanelWithMenu = ({

return (
<Column className={cls.LeftPanel}>
<p
className={cls.titleWrapper}
>
{title}
</p>
<p className={cls.titleWrapper}>{title}</p>

<MobileView>
<Row
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,8 @@

.buttonGroup {
gap: var(--space-sm);

.textButton {
color: var(--color-light-high-emphasis);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,15 @@ export const CredentialSent = <T extends object>({
<Row className={cls.title}>{t('Flow.titles.credentialSent')}</Row>
<Column className={cls.buttonGroup}>
<Button
buttonType="outlined"
buttonType="filled"
onPress={() => onChangeStep(stepDetails.next?.name)}
>
{stepDetails.next?.title}
</Button>
{!context.useDemo && (
<Button
buttonType="text"
className={cls.textButton}
onPress={() => setTemplateModalOpen(true)}
>
{t('Template.titles.main')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
context,
onPrev,
onNext,
onSkip
onSkip,
}: FillCredentialDataProps) => {
const { t } = useTranslation();
const dispatch: AppDispatch = useDispatch();
Expand Down Expand Up @@ -75,7 +75,7 @@
);
navigate(ROUTES.ISSUE_CREDENTIAL_TEMPLATES);
},
[navigate, dispatch, context],

Check warning on line 78 in heka-identity-service-web-ui/src/components/Steps/FillCredentialData/FillCredentialData.tsx

View workflow job for this annotation

GitHub Actions / Build and check

React Hook useCallback has a missing dependency: 'getValues'. Either include it or remove the dependency array
);

const onUpdateTemplate = useCallback(async () => {
Expand Down Expand Up @@ -206,7 +206,7 @@
</Button>
)}

{(context.wizardType === 'demo') && (
{context.wizardType === 'demo' && (
<Button
buttonType="outlined"
onPress={onSkip}
Expand All @@ -215,7 +215,6 @@
</Button>
)}


{(context.wizardType === 'issue' || context.wizardType === 'demo') && (
<Button
type="submit"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,8 @@

.buttonGroup {
gap: var(--space-sm);

.textButton {
color: var(--color-light-high-emphasis);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,8 @@ export const PendingPresentation = ({
alignItems="flex-start"
className={cls.header}
>
<Row
className={cls.title}
>
{t('Flow.titles.verificationRequest')}
</Row>
<Row
className={cls.description}
>
<Row className={cls.title}>{t('Flow.titles.verificationRequest')}</Row>
<Row className={cls.description}>
<p>
{t('Common.titles.scanQR')}&nbsp;
<CopyLink value={value} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,15 @@ export const PresentationReceived = <T extends object>({
<Row className={cls.title}>{t('Flow.titles.presentationReceived')}</Row>
<Column className={cls.buttonGroup}>
<Button
buttonType="outlined"
buttonType="filled"
onPress={() => onChangeStep(stepDetails.next?.name)}
>
{stepDetails.next?.title}
</Button>
{!context.useDemo && (
<Button
buttonType="text"
className={cls.textButton}
onPress={() => setTemplateModalOpen(true)}
>
{t('Common.buttons.saveAsTemplate')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ export interface BuildCredentialParams {
namespace?: string;
}

export const buildCredential = (params: BuildCredentialParams): OpenIdCredential => {
export const buildCredential = (
params: BuildCredentialParams,
): OpenIdCredential => {
switch (params.format) {
case Openid4CredentialFormat.SdJwt:
return buildSdJwtCredential(params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,18 @@ export const buildJwtJsonPresentationRequest = ({
};
};

const MDL_DOCTYPE = 'org.iso.18013.5.1.mDL'
const MDL_NAMESPACE = 'org.iso.18013.5.1'
const MDL_ALG = ['ES256', 'ES384', 'ES512', 'EdDSA', 'ESB256', 'ESB320', 'ESB384', 'ESB512']
const MDL_DOCTYPE = 'org.iso.18013.5.1.mDL';
const MDL_NAMESPACE = 'org.iso.18013.5.1';
const MDL_ALG = [
'ES256',
'ES384',
'ES512',
'EdDSA',
'ESB256',
'ESB320',
'ESB384',
'ESB512',
];

export const buildMsoMdocPresentationRequest = ({
id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export const credentialFormatToCredentialRegistrationFormat = (
[Openid4CredentialFormat.JwtJsonLd]:
Openid4CredentialRegistrationFormat.JwtJsonLd,
[Openid4CredentialFormat.LdpVc]: Openid4CredentialRegistrationFormat.LdpVc,
[Openid4CredentialFormat.MsoMdoc]: Openid4CredentialRegistrationFormat.MsoMdoc,
[Openid4CredentialFormat.MsoMdoc]:
Openid4CredentialRegistrationFormat.MsoMdoc,
};
return map[format];
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
expiry_date: '2030-12-31',
};


interface AgeVerificationFieldsProps {
schema?: Schema;
onPrev: () => void;
Expand All @@ -59,20 +58,34 @@

return (
<div className={cls.resultView}>
<h2 className={cls.resultTitle}>{t('Flow.titles.presentationReceived')}</h2>
<h2 className={cls.resultTitle}>
{t('Flow.titles.presentationReceived')}
</h2>
<Column className={cls.resultAttributes}>
{revealedAttributes?.map((attr) => {
const displayValue = String(attr.value) === 'true' ? 'Yes' : String(attr.value) === 'false' ? 'No' : String(attr.value);
const displayValue =
String(attr.value) === 'true'
? 'Yes'
: String(attr.value) === 'false'
? 'No'
: String(attr.value);
const isAgeField = attr.name === AGE_FIELD;
const isVerified = isAgeField && String(attr.value) === 'true';

return (
<Row key={attr.name} className={cls.resultRow}>
<Row
key={attr.name}
className={cls.resultRow}
>
<span className={cls.resultLabel}>{attr.name}</span>
<span className={cls.resultValue}>
{displayValue}
{isAgeField && (
<span className={isVerified ? cls.ageBadgeSuccess : cls.ageBadgeFail}>
<span
className={
isVerified ? cls.ageBadgeSuccess : cls.ageBadgeFail
}
>
{isVerified
? t('AgeVerificationDemo.result.verified')
: t('AgeVerificationDemo.result.notVerified')}
Expand All @@ -96,9 +109,8 @@

const regularFields = useMemo(
() =>
schema?.fields
?.filter((f) => f.name !== AGE_FIELD)
.map((f) => f.name) ?? [],
schema?.fields?.filter((f) => f.name !== AGE_FIELD).map((f) => f.name) ??
[],
[schema?.fields],
);

Expand Down Expand Up @@ -165,7 +177,7 @@
};

const AgeVerificationDemo = () => {
const { t } = useTranslation();

Check warning on line 180 in heka-identity-service-web-ui/src/pages/AgeVerificationDemo/AgeVerificationDemo.tsx

View workflow job for this annotation

GitHub Actions / Build and check

't' is assigned a value but never used
const dispatch = useAppDispatch();
const schemas = useSelector(getSchemas);
const isPresentationCompleted = useSelector(getIsPresentationCompleted);
Expand Down Expand Up @@ -245,7 +257,10 @@
if (isPresentationCompleted) {
return (
<Row className={cls.AgeDemo}>
<BasicPanel title="Age Verification Demo" icon="car" />
<BasicPanel
title="Age Verification Demo"
icon="car"
/>
<AgeVerificationResultView />
</Row>
);
Expand Down
2 changes: 1 addition & 1 deletion heka-identity-service-web-ui/src/pages/SignUp/SignUp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const SignUpView: React.FC = () => {
}),
);
} catch (e) {
console.log(e.message);
console.error(e.message);
}
},
[dispatch],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,10 @@ export const VerificationFromTemplate = () => {
const supportSelectiveDisclosure = useMemo(
() =>
verificationTemplate?.protocol === ProtocolType.Aries ||
verificationTemplate?.credentialFormat === Openid4CredentialFormat.SdJwt ||
verificationTemplate?.credentialFormat === Openid4CredentialFormat.MsoMdoc,
verificationTemplate?.credentialFormat ===
Openid4CredentialFormat.SdJwt ||
verificationTemplate?.credentialFormat ===
Openid4CredentialFormat.MsoMdoc,
[verificationTemplate],
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

jest.mock('@/shared/assets/icons/visibility-off.svg', () => 'visibility-off.svg');
jest.mock(
'@/shared/assets/icons/visibility-off.svg',
() => 'visibility-off.svg',
);
jest.mock(
'@/shared/assets/icons/visibility-outline.svg',
() => 'visibility-outline.svg',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

jest.mock('@/shared/assets/icons/visibility-off.svg', () => 'visibility-off.svg');
jest.mock('@/shared/assets/icons/visibility-outline.svg', () => 'visibility-outline.svg');
jest.mock(
'@/shared/assets/icons/visibility-off.svg',
() => 'visibility-off.svg',
);
jest.mock(
'@/shared/assets/icons/visibility-outline.svg',
() => 'visibility-outline.svg',
);

import { TextInputUncontrolled } from './TextInput';

Expand Down
3 changes: 3 additions & 0 deletions heka-identity-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ The service is configured via environment variables. The full reference (~30 var
## Documentation

**Getting Started**

- [Setup and Configuration](docs/setup.md) — install, configure, and run the service locally or in Docker
- [Concepts and Glossary](docs/concepts.md) — roles, multi-tenancy, core abstractions, credential formats
- [Demo flow](docs/demo-flow.md) — end-to-end AnonCreds issuance and verification example

**How-To Guides**

- [How to Issue an SD-JWT VC](docs/how-to-issue-sd-jwt-vc.md) — Basic example flow for OID4VCI-based issuance with SD-JWT format
- [Local Configuration for Heka Wallet Integration](docs/local-config-for-heka-wallet-integration.md) — exposing a local instance to the mobile wallet

**Integration**

- [Hedera Integration](docs/hedera.md) — operator credentials, network selection, what gets written on-chain
- [Heka Identity Service API](docs/api.md) — REST API and webhook / WebSocket notifications

Expand Down
Loading
Loading