This repository contains a proof of concept for less-invasive personal-detail verification between two parties:
identity-consumer: creates an identity request and verifies a signed yes/no response against a DNS-published public key.identity-provider: evaluates the request against a local demo subject profile, shows the computed answer, and signs the response after consent.
apps/identity-consumer: Next.js consumer app on port3000apps/identity-provider: Next.js provider app on port3001packages/protocol: shared request/response schema, DSL, serialization, and evaluator helperspackages/crypto: Ed25519 signing, verification, and DNS TXT resolutiondocs/dns-setup.md: key generation and DNS publication guide
The request token is base64url-encoded JSON containing:
requestIdissuerDomaincreatedAtsubjectdisplayText
The POC implements a constrained subject expression:
bornOnOrBefore(subject.dateOfBirth, <cutoff-date>)
That allows the consumer to ask questions like:
- "Is the subject at least 18 years old?"
The response token is base64url-encoded JSON containing:
requestIdproviderDomaindnsRecordNamesubjectAnswerissuedAtdisplayTextsignatureAlgorithmsignature
The provider signs the canonical JSON payload using Ed25519. The consumer resolves the provider public key from DNS TXT and verifies that signature before accepting the response as proof.
Install dependencies for both apps:
cd apps/identity-consumer && npm install
cd ../identity-provider && npm installRun the apps in separate terminals:
cd apps/identity-consumer && npm run devcd apps/identity-provider && npm run devOr use Docker Compose after creating a .env file from .env.example:
docker compose up --buildBefore the provider can sign valid responses, generate a keypair:
npm run generate:provider-keysThen:
- Set
PROVIDER_PRIVATE_KEY_PKCS8_BASE64in.env. - Set
PROVIDER_DOMAINto the real domain that will publish the TXT record. - Publish the generated
DNS_TXT_VALUEat_kyuix-idp.<provider-domain>.
See DNS setup for the exact record format.
- Open the consumer app and create an age verification request.
- Copy the request token.
- Open the provider app and paste the request token.
- Review the computed answer and confirm consent.
- Copy the signed response token.
- Return to the consumer app and paste the response token.
- Verify the response. The consumer will:
- confirm the request ID is known,
- resolve
_kyuix-idp.<provider-domain>from DNS, - validate the Ed25519 signature,
- store the result in the local audit log.
COMPOSE_BUILD_CONTEXT=.
CONSUMER_DOMAIN=consumer.localtest.me
PROVIDER_DOMAIN=provider.example.com
PROVIDER_PRIVATE_KEY_PKCS8_BASE64=
DEMO_SUBJECT_DOB=1998-04-12If Dokploy checks out the repository into a code/ subdirectory but executes the
compose file from the parent deployment directory, set:
COMPOSE_BUILD_CONTEXT=./codeThis makes the compose build.context point at the cloned repository instead of
Dokploy's wrapper directory.
- The provider currently evaluates a single demo subject profile.
- The request DSL intentionally supports only one atomic age-related predicate.
- Audit persistence in the consumer is JSON-file based and intended only for the POC.
- The consumer performs real DNS TXT lookups, so full end-to-end verification requires a real public domain with the expected record.