# RS-KYA interop profile

This profile describes the exact shape of the credentials Rightshold issues today, so any implementer can read, check and verify one without asking. A field-correspondence note states only that a member carries a named value or uses a named member name — correspondence is not a statement that a document conforms to the specification the name comes from. What is not asserted is listed in full, in this same document, under not_asserted. Nothing here confers a level, a status or a link: those come only from the live RS-KYA record.

Machine form: https://www.rightshold.com/v1/interop · Profile check: POST https://www.rightshold.com/v1/interop/check · The credential: GET https://www.rightshold.com/v1/kya/{number|handle|agent_id}/credential · Trust decision: POST https://www.rightshold.com/v1/kya/verify

## The credential, field by field

| Member | What it carries | Correspondence note |
|---|---|---|
| `@context` | an array whose entry is "https://www.w3.org/ns/credentials/v2" | The context URL the W3C Verifiable Credentials Data Model 2.0 defines for its documents. Carrying the URL names the vocabulary the member names come from; it is not a conformance statement. |
| `type` | "VerifiableCredential" followed by "RightsholdKYACredential" | "VerifiableCredential" is the data model's base type name; the second entry is the Rightshold type. |
| `spec` | the RS-KYA spec id, rs-kya/0.1 | A Rightshold member with no counterpart in the data model; it names the issuing standard version. |
| `issuer` | an object whose id is the issuer's HTTPS URL, with the issuer name and id | The data model permits a URL as an issuer identifier. This platform's issuer identifier is a URL, not a DID — see not_asserted.issuer_did. |
| `key_id` | the id of the issuer signing key | A Rightshold member; the key itself is published at /.well-known/rightshold-issuer.json and in the JWKS. |
| `validFrom / validUntil` | the validity window as instants | The data model's member names for the start and end of a credential's validity. |
| `credentialSubject.id` | "rs:agent:" followed by the registration number, or the agent id when unregistered | A Rightshold identifier form for the subject. |
| `credentialSubject.did` | when the agent has a key, that key's did:key identifier | A did:key identifier is derived from the key itself (multicodec ed25519-pub, multibase base58btc), so it names the agent's key, not an account on this platform. |
| `credentialSubject` | level, level_name, status and the verified components the level rests on | The RS-KYA payload: which facts were verified, stated as data. |
| `credentialStatus` | type "RightsholdLiveStatus"; id is the live lookup URL for the subject | A Rightshold status type. Status is answered by re-reading the live record — see not_asserted.status_list. |
| `schema` | the URL of the published JSON Schema for this document | The schema is published at the URL it names and describes this exact shape. |
| `signature (response envelope, not a document member)` | base64 Ed25519 over the canonical JSON (sorted keys, no whitespace) of the credential document | The proof travels beside the document, not inside it — see not_asserted.embedded_proof. |

Every note asserts field correspondence only. The token format (kya+jwt) and its claim-by-claim mapping are in the machine form.

## The profile requirements (rs-kya-credential/1)

| Id | Requirement |
|---|---|
| P1 | @context is an array containing "https://www.w3.org/ns/credentials/v2". |
| P2 | type is an array containing both "VerifiableCredential" and "RightsholdKYACredential". |
| P3 | spec is the RS-KYA spec id (rs-kya/0.1). |
| P4 | issuer.id is an https URL and key_id names the signing key. |
| P5 | validFrom and validUntil are instants, validFrom before validUntil. |
| P6 | credentialSubject carries id (rs:agent:…), agent_id, a level (L0–L5), a status, and the components object. |
| P7 | credentialSubject.did, when present, is a did:key identifier for the agent's key. |
| P8 | credentialStatus.type is "RightsholdLiveStatus" and credentialStatus.id is an https URL. |
| P9 | schema names the published credential schema (…/schemas/kya-credential-v1.json). |

## Vectors

Positive: fetch a credential for any public agent and run it through the profile check — every requirement passes. Negative vectors (one alteration each; the requirement that must fail):

| Vector | Alteration | Must fail |
|---|---|---|
| context-removed | remove the @context member from a passing credential | P1 |
| rightshold-type-removed | remove "RightsholdKYACredential" from the type array | P2 |
| spec-replaced | set spec to a different spec id | P3 |
| validity-inverted | set validUntil before validFrom | P5 |
| level-removed | remove credentialSubject.level | P6 |
| status-type-replaced | set credentialStatus.type to any other value | P8 |

## What is not asserted

- **vc_conformance** — Rightshold makes no statement that its credential conforms to the W3C Verifiable Credentials Data Model or to any other external specification. The document uses that data model's member names and its context URL, and departs from strict serializations in the items below. Any conformance statement waits on an owner decision.
- **issuer_did** — The issuer is identified by its HTTPS URL only. No DID document for the issuer is published, and no DID identifier of any method is asserted for the issuer. Agent keys do carry did:key identifiers — those identify the agent's key, never the issuer.
- **embedded_proof** — The credential's signature travels beside the document in the response envelope, as a base64 Ed25519 signature over the document's canonical JSON — not as a proof member embedded in the document. A document on its own does not carry its proof; verification pairs it with the envelope signature or re-reads the live record.
- **status_list** — credentialStatus is the platform's own live-status type: status is answered by re-reading the live record at the status URL. No status list is published, and no status-list type from any external specification is used.
- **registry_listings** — Rightshold's issuer metadata is not submitted to, and is not listed in, any external trust registry.
- **erc8004_alias** — The ERC-8004 read bridge resolves an ERC-8004 registry identity into an evidence document, and no more: no ERC-8004 identifier is accepted as an alias in the RS-KYA lookup, and no link between an ERC-8004 identity and an RS-KYA record is asserted. The bridge asserts a link only under its countersign rule, which public records cannot satisfy today.
- **erc8004_write** — Rightshold writes nothing to the ERC-8004 registries. The posting half of the bridge is disabled in code and refuses every call, pending an owner decision.
