-
Notifications
You must be signed in to change notification settings - Fork 12
feat: add NFC Issuer Service documentation #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
9b0e33a
feat: add NFC Issuer Service documentation
andreyudentsovottofeller 2954c48
feat: introduce issuer credential (#79)
paolodamico 2501727
Update 9303.mdx
paolodamico 74222cd
Add minor updates
andreyudentsovottofeller 4c21070
Add quotes
andreyudentsovottofeller 0710481
Rename endpoint to
andreyudentsovottofeller cdc7dbf
Move a techincal details under the Technical reference link
andreyudentsovottofeller 29755d8
Improve html markup
andreyudentsovottofeller a65d299
Improve html markup
andreyudentsovottofeller 82a8da6
Fix html markup
andreyudentsovottofeller 1f29f2a
Merge branch 'main' into feat/nfc-credential-and-refresh-docs
Takaros999 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,221 @@ | ||
| /** | ||
| * Hero card for credential issuer documentation pages. | ||
| * Mintlify-safe: no hooks, no client-side state. | ||
| * | ||
| * IMPORTANT: Tailwind classes MUST be string literals in className | ||
| * props — Mintlify only prefixes classes it can statically analyze. | ||
| * Never use variables for className values. | ||
| * | ||
| * Props: | ||
| * - title: string — credential display name | ||
| * - description: string — one-sentence summary | ||
| * - image: string — path to thumbnail image | ||
| * - bgColor: string — hex color for the banner background | ||
| * - issuerName: string — who issues this credential | ||
| * - issuerHref: string — link to issuer (optional) | ||
| * - issuerVerified: boolean — show verified badge (optional) | ||
| * - status: "active" | "beta" | "deprecated" | ||
| * - id: number — credential schema ID | ||
| * - sybilResistance: boolean — whether uniqueness is enforced | ||
| * - sybilResistanceDescription: string — tooltip on the Yes tag | ||
| * - validityPeriod: string — e.g. "10 years or document expiry" | ||
| * - sourceCodeHref: string — GitHub URL, or "coming-soon" | ||
| */ | ||
| export const CredentialHero = ({ | ||
| title, | ||
| description, | ||
| image, | ||
| bgColor = "#1a1a2e", | ||
| issuerName, | ||
| issuerHref, | ||
| issuerVerified, | ||
| status, | ||
| id, | ||
| sybilResistance, | ||
| sybilResistanceDescription, | ||
| validityPeriod, | ||
| sourceCodeHref, | ||
| }) => { | ||
| return ( | ||
| <div className="not-prose rounded-3xl bg-zinc-100 dark:bg-zinc-900"> | ||
| {/* Banner */} | ||
| <div | ||
| className="relative overflow-hidden rounded-t-3xl px-6 py-8 md:px-8 md:py-10" | ||
| style={{ backgroundColor: bgColor }} | ||
| > | ||
| <div className="flex items-center justify-between gap-6"> | ||
| <div className="min-w-0"> | ||
| <h2 className="m-0 text-2xl font-semibold text-white sm:text-3xl"> | ||
| {title} | ||
| </h2> | ||
| {description && ( | ||
| <p className="m-0 mt-2 max-w-[420px] text-[15px] leading-relaxed text-white/75"> | ||
| {description} | ||
| </p> | ||
| )} | ||
| </div> | ||
| {image && ( | ||
| <img | ||
| src={image} | ||
| alt={title} | ||
| className="hidden h-28 w-auto rounded-xl object-contain shadow-lg shadow-black/30 sm:block" | ||
| /> | ||
| )} | ||
| </div> | ||
| </div> | ||
|
|
||
| {/* Metadata table */} | ||
| <div> | ||
| {issuerName && ( | ||
| <div className="flex items-center gap-3 border-b border-zinc-200 px-6 py-3.5 text-[14px] md:px-8 dark:border-zinc-800"> | ||
| <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-zinc-200/70 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"> | ||
| <Icon icon="building" size={16} /> | ||
| </span> | ||
| <span className="w-36 shrink-0 font-medium text-zinc-500 dark:text-zinc-400"> | ||
| Issued by | ||
| </span> | ||
| <span className="inline-flex items-center gap-1"> | ||
| {issuerVerified && ( | ||
| <Tooltip tip="Verified issuer"> | ||
| <span className="inline-flex items-center cursor-help" style={{ height: "20px" }}> | ||
| <Icon icon="circle-check" iconType="solid" size={14} color="#3b82f6" /> | ||
| </span> | ||
| </Tooltip> | ||
| )} | ||
| {issuerHref ? ( | ||
| <a | ||
| href={issuerHref} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="font-medium text-zinc-900 underline decoration-zinc-300 underline-offset-2 hover:decoration-zinc-500 dark:text-zinc-100 dark:decoration-zinc-600 dark:hover:decoration-zinc-400" | ||
| > | ||
| {issuerName} | ||
| </a> | ||
| ) : ( | ||
| <span className="font-medium text-zinc-900 dark:text-zinc-100"> | ||
| {issuerName} | ||
| </span> | ||
| )} | ||
| </span> | ||
| </div> | ||
| )} | ||
| {status && ( | ||
| <div className="flex items-center gap-3 border-b border-zinc-200 px-6 py-3.5 text-[14px] md:px-8 dark:border-zinc-800"> | ||
| <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-zinc-200/70 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"> | ||
| <Icon icon="signal" size={16} /> | ||
| </span> | ||
| <span className="w-36 shrink-0 font-medium text-zinc-500 dark:text-zinc-400"> | ||
| Status | ||
| </span> | ||
| {status === "active" && ( | ||
| <span className="inline-flex items-center rounded-md bg-green-50 px-2 py-0.5 text-xs font-semibold text-green-700 ring-1 ring-green-600/20 ring-inset dark:bg-green-500/10 dark:text-green-400 dark:ring-green-500/20"> | ||
| Active | ||
| </span> | ||
| )} | ||
| {status === "beta" && ( | ||
| <span className="inline-flex items-center rounded-md bg-blue-50 px-2 py-0.5 text-xs font-semibold text-blue-700 ring-1 ring-blue-600/20 ring-inset dark:bg-blue-500/10 dark:text-blue-400 dark:ring-blue-500/20"> | ||
| Beta | ||
| </span> | ||
| )} | ||
| {status === "deprecated" && ( | ||
| <span className="inline-flex items-center rounded-md bg-amber-50 px-2 py-0.5 text-xs font-semibold text-amber-700 ring-1 ring-amber-600/20 ring-inset dark:bg-amber-500/10 dark:text-amber-400 dark:ring-amber-500/20"> | ||
| Deprecated | ||
| </span> | ||
| )} | ||
| </div> | ||
| )} | ||
| {id != null && ( | ||
| <div className="flex items-center gap-3 border-b border-zinc-200 px-6 py-3.5 text-[14px] md:px-8 dark:border-zinc-800"> | ||
| <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-zinc-200/70 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"> | ||
| <Icon icon="hashtag" size={16} /> | ||
| </span> | ||
| <span className="w-36 shrink-0 font-medium text-zinc-500 dark:text-zinc-400"> | ||
| ID | ||
| </span> | ||
| <span className="font-mono font-medium text-zinc-900 dark:text-zinc-100"> | ||
| {id} | ||
| </span> | ||
| </div> | ||
| )} | ||
| {sybilResistance != null && ( | ||
| <div className="flex items-center gap-3 border-b border-zinc-200 px-6 py-3.5 text-[14px] md:px-8 dark:border-zinc-800"> | ||
| <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-zinc-200/70 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"> | ||
| <Icon icon="shield-check" size={16} /> | ||
| </span> | ||
| <span className="w-36 shrink-0 font-medium text-zinc-500 dark:text-zinc-400"> | ||
| Sybil resistance | ||
| </span> | ||
| {sybilResistance ? ( | ||
| <span className="inline-flex items-center gap-1.5"> | ||
| <span className="inline-flex items-center rounded-md bg-green-50 px-2 py-0.5 text-xs font-semibold text-green-700 ring-1 ring-green-600/20 ring-inset dark:bg-green-500/10 dark:text-green-400 dark:ring-green-500/20"> | ||
| Yes | ||
| </span> | ||
| {sybilResistanceDescription && ( | ||
| <Tooltip tip={sybilResistanceDescription}> | ||
| <span className="cursor-help text-zinc-400 dark:text-zinc-500"> | ||
| <Icon icon="circle-info" size={14} /> | ||
| </span> | ||
| </Tooltip> | ||
| )} | ||
| </span> | ||
| ) : ( | ||
| <span className="inline-flex items-center rounded-md bg-zinc-100 px-2 py-0.5 text-xs font-semibold text-zinc-500 ring-1 ring-zinc-500/20 ring-inset dark:bg-zinc-800 dark:text-zinc-400 dark:ring-zinc-500/20"> | ||
| No | ||
| </span> | ||
| )} | ||
| </div> | ||
| )} | ||
| {validityPeriod && ( | ||
| <div className="flex items-center gap-3 border-b border-zinc-200 px-6 py-3.5 text-[14px] md:px-8 dark:border-zinc-800"> | ||
| <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-zinc-200/70 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"> | ||
| <Icon icon="clock" size={16} /> | ||
| </span> | ||
| <span className="w-36 shrink-0 font-medium text-zinc-500 dark:text-zinc-400"> | ||
| <span className="inline-flex items-center gap-1"> | ||
| Validity period | ||
| <Tooltip tip="The default duration period of the credential. Generally the maximum recommended sybil resistance window."> | ||
| <span className="cursor-help text-zinc-400 dark:text-zinc-500"> | ||
| <Icon icon="circle-info" size={12} /> | ||
| </span> | ||
| </Tooltip> | ||
| </span> | ||
| </span> | ||
| <span className="font-medium text-zinc-900 dark:text-zinc-100"> | ||
| {validityPeriod} | ||
| </span> | ||
| </div> | ||
| )} | ||
| {sourceCodeHref && ( | ||
| <div className="flex items-center gap-3 px-6 py-3.5 text-[14px] md:px-8"> | ||
| <span className="flex h-7 w-7 shrink-0 items-center justify-center rounded-lg bg-zinc-200/70 text-zinc-500 dark:bg-zinc-800 dark:text-zinc-400"> | ||
| <Icon icon="code" size={16} /> | ||
| </span> | ||
| <span className="w-36 shrink-0 font-medium text-zinc-500 dark:text-zinc-400"> | ||
| SDK Reference | ||
| </span> | ||
| {sourceCodeHref === "coming-soon" ? ( | ||
| <span className="inline-flex items-center gap-1.5 rounded-md bg-blue-50 px-2 py-0.5 text-xs font-semibold text-blue-700 ring-1 ring-blue-600/20 ring-inset dark:bg-blue-500/10 dark:text-blue-400 dark:ring-blue-500/20"> | ||
| <Icon icon="lock" size={11} /> | ||
| Coming soon | ||
| </span> | ||
| ) : ( | ||
| <a | ||
| href={sourceCodeHref} | ||
| target="_blank" | ||
| rel="noopener noreferrer" | ||
| className="font-medium text-zinc-900 underline decoration-zinc-300 underline-offset-2 hover:decoration-zinc-500 dark:text-zinc-100 dark:decoration-zinc-600 dark:hover:decoration-zinc-400" | ||
| > | ||
| {sourceCodeHref.split("/").pop()} | ||
| </a> | ||
| )} | ||
| </div> | ||
| )} | ||
| </div> | ||
|
|
||
| {/* Bottom spacer */} | ||
| <div className="h-2" /> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default CredentialHero; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| --- | ||
| title: "NFC Credential" | ||
| icon: "passport" | ||
| iconType: "duotone" | ||
| description: "A unique government-issued document, such as a passport or eID." | ||
| "og:image": "https://docs.world.org/images/docs/docs-meta.png" | ||
| "twitter:image": "https://docs.world.org/images/docs/docs-meta.png" | ||
| --- | ||
|
|
||
| {/* cspell:ignore uniqueness NFC PCP eIDs */} | ||
|
|
||
| import { CredentialHero } from "/snippets/credential-hero.jsx"; | ||
|
|
||
| <CredentialHero | ||
| title="NFC Credential" | ||
| description="A unique government-issued document, such as a passport or eID." | ||
| image="/images/docs/id/issuers/9303/thumbnail.png" | ||
| bgColor="#4a1520" | ||
| issuerName="Tools for Humanity" | ||
| issuerHref="https://www.toolsforhumanity.com" | ||
| issuerVerified={true} | ||
| status="active" | ||
| id={9303} | ||
| sybilResistance={true} | ||
| sybilResistanceDescription="Each document can only be used with one World ID. Duplicate enrollments for the same document are rejected." | ||
| validityPeriod="Document expiry (max 10 years)" | ||
| sourceCodeHref="coming-soon" | ||
| /> | ||
|
|
||
| ## Introduction | ||
|
|
||
| The NFC Credential represents a unique government-issued document. It supports passports and eIDs. Availability varies by country and continues to expand over time. An NFC Credential is **guaranteed to be issued to a single World ID per unique document**. In addition to ICAO-9303 compliant documents (such as passports or eIDs), the Japanese [My Number Card](https://en.wikipedia.org/wiki/My_Number_Card) (MNC) is also supported. The MNC flow uses different enrollment handling internally, but it issues the same credential. | ||
|
|
||
| ## Use Cases | ||
|
|
||
| Use the NFC Credential when you need proof of a unique government document. This is useful for applications that need document-level Sybil resistance without requiring a proof of a unique human. | ||
|
|
||
| ## Credential Structure | ||
|
|
||
| This credential implements the following attributes beyond the defaults in the [Credential](https://docs.rs/world-id-primitives/latest/world_id_primitives/credential/struct.Credential.html). | ||
|
|
||
| <table> | ||
| <thead> | ||
| <tr> | ||
| <th className="whitespace-nowrap">Attribute</th> | ||
| <th>Description</th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr> | ||
| <td className="whitespace-nowrap"> | ||
| <code>genesis_issued_at</code> | ||
| </td> | ||
| <td>The timestamp of when the unique document was first verified.</td> | ||
| </tr> | ||
| <tr> | ||
| <td className="whitespace-nowrap"> | ||
| <code>expires_at</code> | ||
| </td> | ||
| <td>The expiration of the document with a maximum of 10 years.</td> | ||
| </tr> | ||
| <tr> | ||
| <td className="whitespace-nowrap"> | ||
| <code>associated_data_commitment</code> | ||
| </td> | ||
| <td> | ||
| A commitment to the user's Associated Data (see{" "} | ||
| <a href="/world-id/reference/nfc-issuer#associated-data"> | ||
| NFC Issuer implementation notes | ||
| </a> | ||
| ). | ||
| </td> | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
|
|
||
| In addition, the credential implements the following claims: | ||
|
|
||
| ### Claim 0 - Authentication Claim | ||
|
|
||
| Identifies the type of authentication performed when enrolling a document. This helps determine the state of the document at enrollment time. For example, documents that only undergo Passive Authentication have no guarantee that the data isn't cloned from an original document. Please note that not all authentications are supported for all documents, and it usually varies per country. The strongest authentication available is always selected. | ||
|
|
||
| | Value | Claim | Description | | ||
| | ----- | --------------------- | -------------------------------------------------------------------------------------------------- | | ||
| | `1` | None | Passive authentication only (document signature verification). | | ||
| | `2` | Chip Authentication | Document passed Chip Authentication (CA) per ICAO 9303. Proves the chip is genuine and not cloned. | | ||
| | `3` | Active Authentication | Document passed Active Authentication (AA) per ICAO 9303. Proves the chip holds a private key. | | ||
| | `4` | MNC Authentication | Document was verified via the MNC (My Number Card) SD-JWT flow. | | ||
|
|
||
| ### Claim 1 - SOD Signature | ||
|
|
||
| Contains a hash of the document's signature from the issuing authority. For passports and other ICAO-9303 compliant documents, the signature is retrieved from `SignedData.SignerInfos[0].Signature` in the `EF.SOD` (Security Object Document) (see [Section 4.6.2.1 from ICAO-9303 Part 10](https://www.icao.int/sites/default/files/publications/DocSeries/9303_p10_cons_en.pdf)). The raw signature bytes are then hashed with blake3 and converted to a field element with modulo reduction. Please note that this claim is not set for credentials from My Number Cards. | ||
|
|
||
| ## Credential Renewal | ||
|
|
||
| Renewal is not supported for this credential. A document can only be enrolled once. From a user standpoint, they will generally obtain a new document from their issuing authority (e.g. a new passport) and register it as a new credential. | ||
|
|
||
| ## Technical Reference | ||
|
|
||
| For issuer endpoints, migration payloads, and implementation-specific details, see the [NFC Issuer reference](/world-id/reference/nfc-issuer). |
8 changes: 7 additions & 1 deletion
8
world-id/credentials/legacy-presets.mdx → world-id/credentials/index.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,15 @@ | ||
| --- | ||
| title: "Legacy Presets" | ||
| title: "About Credentials" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wouldn't rename this. This is developer facing we want to keep it explicit we're talking about Presets here an IDKit concept |
||
| sidebarTitle: "About" | ||
| "og:image": "https://raw.githubusercontent.com/worldcoin/developer-docs/main/images/docs/docs-meta.png" | ||
| "twitter:image": "https://raw.githubusercontent.com/worldcoin/developer-docs/main/images/docs/docs-meta.png" | ||
| --- | ||
|
|
||
| A [Credential](https://docs.rs/world-id-primitives/latest/world_id_primitives/credential/struct.Credential.html) is a statement an issuer makes about a World ID holder. Fundamentally, when you as an RP request a proof, the choice of Credential matters significantly to fulfill your use case. For example, if you want to protect an action that should only be done once per human, you probably want to use the Proof of Human credential. | ||
|
|
||
|
|
||
| # Legacy Presets | ||
|
|
||
| Legacy presets only return World ID 3.0 proofs. These function the same as `VerificationLevel` from previous IDKit versions. | ||
|
|
||
| ## `orbLegacy` | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rename the page back