From 2b379e1f0fc6f825b719e291edd2bff4fb3b8eba Mon Sep 17 00:00:00 2001 From: pixelplex Date: Thu, 5 Mar 2026 15:13:07 +0300 Subject: [PATCH 1/3] - profile credentials proposal --- .../cip-xxxx-profile-credentials.md | 317 ++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 cip-xxxx-profile-credentials/cip-xxxx-profile-credentials.md diff --git a/cip-xxxx-profile-credentials/cip-xxxx-profile-credentials.md b/cip-xxxx-profile-credentials/cip-xxxx-profile-credentials.md new file mode 100644 index 0000000..83a3a44 --- /dev/null +++ b/cip-xxxx-profile-credentials/cip-xxxx-profile-credentials.md @@ -0,0 +1,317 @@ +--- +Author: PixelPlex Inc. +CIP: TBD +Created: 2026-01-27 +License: CC0-1.0 +Status: Draft +Title: Canton Network Party Profile Credentials +Type: Standards Track +--- + +# Abstract + +This CIP standardizes a portable representation of **party profile +metadata** for user‑interface rendering on the Canton Network based on +the **Canton Network Credentials Standard**. + +It defines: + +- A set of **standard claim keys** for common party metadata such as + display name, avatar, website, and optional contact/social + information. +- An **application-side resolution method** for deriving a single + effective party profile from credentials issued across multiple + registries and issuers. + +The profile claims defined by this CIP are **informational only** and +**MUST NOT** be interpreted as verified identity attributes or used for +name or recipient resolution. + +# Motivation + +Party IDs serve as the primary identity anchors on the Canton Network. +While suitable for infrastructure-level identification, they are +difficult for humans to distinguish and remember. + +Applications interacting with Canton often need to display meaningful +information about the party behind a party ID, such as: + +- human-readable names +- avatars +- website references +- communication or social links + +Currently there is no standardized way to represent or resolve such +metadata across applications. + +This CIP introduces a **standardized profile metadata model** that +allows: + +- party owners to publish profile information +- applications to resolve party profiles consistently +- users to distinguish parties in wallets, explorers, and applications + +This improves **user experience and interoperability across Canton +ecosystem applications**. + +# Specification + +This CIP builds on the **Canton Network Credentials Standard** and uses +its claim encoding and lookup semantics. + +Profile metadata is expressed as **credential claims** under a dedicated +namespace: + +`cip-/` + +Where `` will be replaced by the assigned CIP number. + +# Party Profile Claim Keys + +## `cip-/displayName` + +Human-readable name used for UI display. + +Applications: + +- MUST treat the value as a display string +- MUST NOT treat it as an identifier +- SHOULD support up to **64 Unicode characters** +- SHOULD render the value as-is after applying UI escaping +- SHOULD gracefully truncate values longer than 64 characters + +## `cip-/avatar` + +Avatar reference for UI rendering. + +Applications: + +- MUST treat the value as a reference to an avatar resource +- MUST NOT interpret the value as identity verification +- SHOULD support `https://` URLs +- SHOULD support `ipfs://` URIs +- MAY ignore values that are not valid or supported URIs + +## `cip-/website` + +Website reference associated with the party. + +Applications: + +- MUST treat the value as informational metadata +- MUST NOT treat it as an authoritative identifier +- SHOULD expect an `https://` URL +- MAY display invalid URLs as plain text +- MUST NOT treat invalid values as trusted links + +## `cip-/email` + +Informational contact email. + +Applications: + +- MUST treat this value as informational metadata +- MUST NOT assume ownership or verification +- MAY perform basic email validation +- MAY render a `mailto:` link + +## `cip-/telegram` + +Telegram handle. + +Applications: + +- MUST treat the value as a Telegram username +- SHOULD store the value **without `@` prefix** +- MAY render the handle with a leading `@` + +## `cip-/x` + +X (Twitter) handle. + +Applications: + +- MUST treat the value as an X username +- SHOULD store it without a leading `@` +- MAY render it with `@` + +## `cip-/github` + +GitHub username or organization. + +Applications: + +- MUST treat the value as informational metadata +- MAY link to a GitHub profile URL + +## `cip-/discord` + +Discord handle or user ID. + +Applications: + +- MUST treat the value as informational metadata +- MAY display the value as provided + +# Party Profile Resolution + +Applications may obtain profile credentials for a party **P** from +multiple registries and issuers. + +To compute a single **effective profile**, applications use a configured +**ordered list of sources**. + +A source is defined as: + +`(registry, issuer)` + +Issuer may be: + +- a specific issuer party ID +- `self` (meaning issuer = holder party) + +## Resolution Algorithm + +### Step 1 --- Fetch credentials per source + +For each source in priority order: + +Fetch active credentials where: + +`holder = P` `issuer = resolved issuer` + +Only claims within the namespace `cip-/` are considered. + +### Step 2 --- Resolve duplicates within a source + +If multiple credentials from the same source define the same claim key: + +- Apply **last-write-wins semantics** +- Use the registry record timestamp to determine ordering + +### Step 3 --- Merge sources + +Construct the final profile **claim-by-claim**. + +For each claim key: + +1. Select the value from the **highest-priority source** that provides + it +2. Use lower-priority sources only when higher-priority ones do not + define the key + +### Output + +The result is an **effective profile map**: + +`profileClaimKey → (value, registry, issuer)` + +Applications MAY expose `(registry, issuer)` metadata in UI to show +claim provenance. + +# Rationale + +## Why Party-Centric Profiles + +Profiles are attached directly to the **party identity anchor**, +ensuring stability across applications and identity flows. + +## Why Namespaced Claim Keys + +Using namespaced keys `cip-/*`: + +- minimizes protocol changes +- preserves compatibility with existing credential infrastructure +- enables efficient querying +- allows extensibility + +Future profile attributes can be added under the same namespace. + +## Why Application-Side Resolution + +Different applications may have different trust policies, issuer +preferences, and registry priorities. + +This CIP standardizes: + +- claim namespace +- resolution semantics + +but leaves configurable: + +- registry selection +- issuer trust +- source priority ordering + +## Self-Published Profiles + +Self-published profiles provide a universal baseline. + +Applications may support the issuer alias: + +`self` + +which resolves to: + +`issuer = holder party` + +A common default configuration is: + +`[(dsoRegistry, self)]` + +# Examples + +## Example 1 --- Self-Published Profile + +Holder party: + +`P` + +Source list: + +`[(dsoRegistry, self)]` + +Profile is derived entirely from credentials where: + +`holder = P` `issuer = P` + +## Example 2 --- Preferred Issuer with Fallback + +Sources: + +`[(dsoRegistry, Ipreferred), (dsoRegistry, self)]` + +Preferred issuer values are used when available, otherwise fallback to +self-published values. + +## Example 3 --- Multiple Registries + +Sources: + +`[(registryA, Ipreferred), (registryB, Ipreferred), (registryA, self)]` + +Resolution priority: + +1. registryA preferred issuer +2. registryB preferred issuer +3. registryA self + +# Backwards Compatibility + +This CIP is **fully additive**. + +- No changes to Canton protocol +- No changes to Daml models +- No changes to registry contracts + +Applications not implementing this CIP will treat the claims as generic +key--value metadata. + +# Reference Implementation + +Not required. + +This CIP specifies only claim keys and application-side interpretation +rules. + + From 66ad5007d6988a616ebb7bbefab56258e23c2606 Mon Sep 17 00:00:00 2001 From: Vladislav Kokosh Date: Wed, 6 May 2026 15:56:28 +0300 Subject: [PATCH 2/3] Review fixes --- .DS_Store | Bin 6148 -> 22532 bytes .../cip-xxxx-profile-credentials.md | 163 +++++++----------- 2 files changed, 58 insertions(+), 105 deletions(-) diff --git a/.DS_Store b/.DS_Store index be50960cb4b350319874fdf6a98e13e389150896..d7c48ae107c191b920364c6b8dbd500a947dc1c0 100644 GIT binary patch literal 22532 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 delta 169 zcmZqKz}R9S!N9=4=v10w$iN@~WO4v8h-TrMSSU78Pja$B2#X|;&%gr2j9@tf1_K6D z1~d1d0E5kfOv{-WStcvkifrbw-NM9E7F?8DG61NT8%Vf< l%mzw*XP(R-VyOT$5{SSA6Nm-@AOqwKkjof0$Mei#1^|C*7f=8I diff --git a/cip-xxxx-profile-credentials/cip-xxxx-profile-credentials.md b/cip-xxxx-profile-credentials/cip-xxxx-profile-credentials.md index 83a3a44..89cf5c4 100644 --- a/cip-xxxx-profile-credentials/cip-xxxx-profile-credentials.md +++ b/cip-xxxx-profile-credentials/cip-xxxx-profile-credentials.md @@ -12,16 +12,15 @@ Type: Standards Track This CIP standardizes a portable representation of **party profile metadata** for user‑interface rendering on the Canton Network based on -the **Canton Network Credentials Standard**. +the [**Canton Network Credentials Standard**](https://github.com/canton-foundation/cips/pull/204). It defines: - A set of **standard claim keys** for common party metadata such as display name, avatar, website, and optional contact/social information. -- An **application-side resolution method** for deriving a single - effective party profile from credentials issued across multiple - registries and issuers. +- A clear **application-side interpretation model** for rendering these + claims consistently in user interfaces. The profile claims defined by this CIP are **informational only** and **MUST NOT** be interpreted as verified identity attributes or used for @@ -48,7 +47,7 @@ This CIP introduces a **standardized profile metadata model** that allows: - party owners to publish profile information -- applications to resolve party profiles consistently +- applications to interpret profile claims consistently - users to distinguish parties in wallets, explorers, and applications This improves **user experience and interoperability across Canton @@ -68,6 +67,11 @@ Where `` will be replaced by the assigned CIP number. # Party Profile Claim Keys +For social fields, this CIP uses grouped claim keys (for example, +`cip-/social:discord`) to align naming conventions with +[CPRP (CIP PR #171)](https://github.com/canton-foundation/cips/pull/171)-style +field organization while keeping this CIP namespace prefix. + ## `cip-/displayName` Human-readable name used for UI display. @@ -88,8 +92,8 @@ Applications: - MUST treat the value as a reference to an avatar resource - MUST NOT interpret the value as identity verification -- SHOULD support `https://` URLs -- SHOULD support `ipfs://` URIs +- SHOULD be a URI conforming to RFC 3986 +- SHOULD support `https://` URLs and `ipfs://` URIs - MAY ignore values that are not valid or supported URIs ## `cip-/website` @@ -100,7 +104,7 @@ Applications: - MUST treat the value as informational metadata - MUST NOT treat it as an authoritative identifier -- SHOULD expect an `https://` URL +- SHOULD be an absolute `https://` URL conforming to RFC 3986 - MAY display invalid URLs as plain text - MUST NOT treat invalid values as trusted links @@ -112,102 +116,63 @@ Applications: - MUST treat this value as informational metadata - MUST NOT assume ownership or verification +- SHOULD conform to RFC 5322 `addr-spec` syntax - MAY perform basic email validation - MAY render a `mailto:` link -## `cip-/telegram` +## `cip-/social:telegram` Telegram handle. Applications: - MUST treat the value as a Telegram username +- SHOULD conform to Telegram username format rules - SHOULD store the value **without `@` prefix** - MAY render the handle with a leading `@` -## `cip-/x` +## `cip-/social:x` X (Twitter) handle. Applications: - MUST treat the value as an X username +- SHOULD conform to X username format rules - SHOULD store it without a leading `@` - MAY render it with `@` -## `cip-/github` +## `cip-/social:github` GitHub username or organization. Applications: - MUST treat the value as informational metadata +- SHOULD conform to GitHub username or organization name format rules - MAY link to a GitHub profile URL -## `cip-/discord` +## `cip-/social:discord` Discord handle or user ID. Applications: - MUST treat the value as informational metadata +- SHOULD conform to Discord username or user ID format rules - MAY display the value as provided # Party Profile Resolution -Applications may obtain profile credentials for a party **P** from -multiple registries and issuers. - -To compute a single **effective profile**, applications use a configured -**ordered list of sources**. - -A source is defined as: - -`(registry, issuer)` - -Issuer may be: - -- a specific issuer party ID -- `self` (meaning issuer = holder party) - -## Resolution Algorithm - -### Step 1 --- Fetch credentials per source - -For each source in priority order: - -Fetch active credentials where: - -`holder = P` `issuer = resolved issuer` - -Only claims within the namespace `cip-/` are considered. - -### Step 2 --- Resolve duplicates within a source - -If multiple credentials from the same source define the same claim key: - -- Apply **last-write-wins semantics** -- Use the registry record timestamp to determine ordering - -### Step 3 --- Merge sources - -Construct the final profile **claim-by-claim**. +This CIP does not standardize a full cross-registry/cross-issuer profile +composition algorithm. -For each claim key: +Applications SHOULD rely on the resolution/composition flow defined in +[CPRP (CIP PR #171)](https://github.com/canton-foundation/cips/pull/171) +and apply this CIP only for: -1. Select the value from the **highest-priority source** that provides - it -2. Use lower-priority sources only when higher-priority ones do not - define the key - -### Output - -The result is an **effective profile map**: - -`profileClaimKey → (value, registry, issuer)` - -Applications MAY expose `(registry, issuer)` metadata in UI to show -claim provenance. +- profile claim key names under `cip-/...` +- per-key interpretation semantics for UI rendering # Rationale @@ -225,76 +190,64 @@ Using namespaced keys `cip-/*`: - enables efficient querying - allows extensibility -Future profile attributes can be added under the same namespace. +Future well-known profile attributes may be standardized via amendments +to this CIP (or a separate CIP where appropriate) while continuing to +use the `cip-/` namespace. + +This namespace design is primarily for forward compatibility: +applications may ignore unrecognized keys without breaking. ## Why Application-Side Resolution Different applications may have different trust policies, issuer preferences, and registry priorities. -This CIP standardizes: +Therefore this CIP standardizes only: - claim namespace -- resolution semantics +- claim interpretation semantics but leaves configurable: +- resolution/composition method - registry selection - issuer trust - source priority ordering -## Self-Published Profiles - -Self-published profiles provide a universal baseline. - -Applications may support the issuer alias: - -`self` - -which resolves to: - -`issuer = holder party` - -A common default configuration is: - -`[(dsoRegistry, self)]` - # Examples -## Example 1 --- Self-Published Profile - -Holder party: - -`P` - -Source list: - -`[(dsoRegistry, self)]` +## Example 1 --- Basic Profile Claims -Profile is derived entirely from credentials where: +A credential contains: -`holder = P` `issuer = P` +- `cip-/displayName = "PixelPlex"` +- `cip-/avatar = "https://cdn.example.com/profiles/pixelplex.png"` +- `cip-/website = "https://pixelplex.io"` +- `cip-/email = "info@pixelplex.io"` +- `cip-/social:github = "pixelplex"` -## Example 2 --- Preferred Issuer with Fallback +Applications should render these values as profile metadata only and +must not treat them as authoritative identity identifiers. -Sources: +## Example 2 --- Social Handle Rendering -`[(dsoRegistry, Ipreferred), (dsoRegistry, self)]` +A credential contains: -Preferred issuer values are used when available, otherwise fallback to -self-published values. +- `cip-/social:telegram = "Pixelplex"` +- `cip-/social:x = "pixelplexinc"` -## Example 3 --- Multiple Registries +Applications may render these in UI as `@Pixelplex` and +`@pixelplexinc` +while storing/interpreting the claim values without the leading `@`. -Sources: +## Example 3 --- Invalid Website Value -`[(registryA, Ipreferred), (registryB, Ipreferred), (registryA, self)]` +A credential contains: -Resolution priority: +- `cip-/website = "not-a-url"` -1. registryA preferred issuer -2. registryB preferred issuer -3. registryA self +Applications may display this value as plain text but must not treat it +as a trusted link. # Backwards Compatibility From a8f38ff628d3d3b4cb968dc5887c75fbf1ca1b5c Mon Sep 17 00:00:00 2001 From: Vladislav Kokosh Date: Wed, 6 May 2026 16:32:41 +0300 Subject: [PATCH 3/3] remove .DS_Store --- .DS_Store | Bin 22532 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index d7c48ae107c191b920364c6b8dbd500a947dc1c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22532 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