KeyService
KeyService manages the signing keys of the caller's namespace, and publishes the key history of any namespace.
An owner holds a keyring of Ed25519 keys. At most 10 keys are active at once. At most 1 active key is custodial, and the server holds it. Any other key is self-owned: the owner holds it and signs with it. While custodial signing is on, at most 9 keys are self-owned, so the custodial key always has a place.
Conventions and error codes: see common.proto.
A key-change credential that is missing, invalid, ended or refused by uno-api answers permission_denied, never unauthenticated. A client that refreshes its session on unauthenticated would revoke the credential that it holds. A credential that the server already used answers failed_precondition: call ListKeys to see whether the change happened.
Who may change keys:
- A guest that has never been claimed gives its control proof, as for every RPC. The control proof is the owner authorization.
- An account gives a key-change credential in key_change_token. The credential comes from KitCredentialService.IssueKeyChangeCredential, after a fresh passkey step-up for this exact change. It lives at most 120 seconds, and the server consumes it once.
- The control key of a guest that an account has claimed cannot change keys. An OAuth bearer or a delegation never changes keys.
GetKeyHistory is the one RPC here that needs no credential. See its comment.
A rotation, removal, revocation, or custody off raises the authority generation. The key leaves the active set at once. A write with a lease at the old generation may still land until the server completes the generation call. ListKeys shows the key as retiring or revoking until then.
These RPCs take no idempotency_key. Each change needs a fresh proof that the server consumes once. After an uncertain answer, call ListKeys.
CreateKeyChallenge
/rpc/uno.kit.v1.KeyService/CreateKeyChallengeIssues a challenge for the proof of possession of EnrollKey. The challenge is single use and lives 120 seconds.
Header Parameters
Request Body
application/jsonResponses
stringThe status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
canceledunknowninvalid_argumentdeadline_exceedednot_foundstringA developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
EnrollKey
/rpc/uno.kit.v1.KeyService/EnrollKeyAdds a self-owned key. The new key signs a statement to prove that the caller holds it. See EnrollKeyRequest.signature.
Header Parameters
Request Body
application/jsonstringThe Ed25519 public key to add: 64 lowercase hex characters. An owner holds a public key active once. A public key that was removed (retired) may enroll again as a new key. A revoked public key never returns.
stringThe Ed25519 signature of the new key, 128 lowercase hex characters, over
these lines joined with "\n", with no final newline:
uno-kit-key-possession-v1
<deployment origin, for example https://kit.uno.fun>
uno.kit.v1
Responses
stringThe status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
canceledunknowninvalid_argumentdeadline_exceedednot_foundstringA developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
Reads the public key history of a namespace: every key, and every change to its status, in the order that the server made them. Anyone may call it, with no credential. It is the evidence behind a verify answer: ownership of a namespace is Uno-attested, and this history is how a third party checks which keys the keyring held and when.
/rpc/uno.kit.v1.KeyService/GetKeyHistoryThe history holds only the key id, the public key, the kind and the times. It names no account, no owner, no custody setting and no device.
It is append-only. The server adds events and never changes or removes one, so a page that a client read stays true. history_version moves only forward.
How to read it. Order events by seq. Never order them by at: the at of a *_EFFECTIVE event is a bound, and it can be later than the at of an event with a higher seq. The status of a key is the last of its events:
- CREATED: active.
- RETIRED, with no RETIREMENT_EFFECTIVE after it: retiring. A write that held a lease at the old authority generation may still land.
- RETIREMENT_EFFECTIVE: retired. No write that the key signed lands from the at of that event.
- REVOKED, with no REVOCATION_EFFECTIVE after it: revoking.
- REVOCATION_EFFECTIVE: revoked. A signature that landed at or after revoked_from reports retroactive revocation. Raw validity stays intact. A key that was retired and then revoked has both pairs of events.
A namespace that no owner holds, and one with no key yet, answer the same: no events and history_version 0. A visitor cannot tell them apart. namespace must be an owner UUIDv7: lowercase, with dashes, no prefix. Any other value fails with invalid_argument.
The call costs a visitor the heavy bucket of the anonymous read limit.
Header Parameters
Request Body
Responses
string <int64>The seq of the last event of the namespace when the server read this page, or 0 with no event. It moves only forward: each change to the keyring adds an event and raises it. A client that holds a version V and reads a greater one asks again from the next_page_token of its last page. This page holds only events up to this version.
stringThe status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
canceledunknowninvalid_argumentdeadline_exceedednot_foundstringA developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
ListKeys
/rpc/uno.kit.v1.KeyService/ListKeysLists every key of the caller's namespace, active or not, in the order that the server made them.
Header Parameters
Request Body
Responses
stringThe status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
canceledunknowninvalid_argumentdeadline_exceedednot_foundstringA developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
RemoveKey
/rpc/uno.kit.v1.KeyService/RemoveKeyRetires a self-owned key. The key signs no more, and its history stays valid. The key id never returns. The same public key may enroll again, as a new key with a new key id.
Header Parameters
Request Body
Responses
stringThe status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
canceledunknowninvalid_argumentdeadline_exceedednot_foundstringA developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
RevokeKey
/rpc/uno.kit.v1.KeyService/RevokeKeyRevokes an active or retired key. Landings at or after the requested time report retroactive revocation. Raw signature validity stays intact. Custody off refuses the last active self-owned key. With custody on, the next write replaces a revoked custodial key.
Header Parameters
Request Body
application/jsonResponses
stringThe status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
canceledunknowninvalid_argumentdeadline_exceedednot_foundstringA developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
RotateCustodialKey
/rpc/uno.kit.v1.KeyService/RotateCustodialKeyReplaces the active custodial key and retires the old key. History stays valid. The request must name the current key. Call ListKeys after an uncertain answer.
Header Parameters
Request Body
Responses
stringThe status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
canceledunknowninvalid_argumentdeadline_exceedednot_foundstringA developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
SetCustody
/rpc/uno.kit.v1.KeyService/SetCustodyTurns custodial signing on or off. Off retires the custodial key and makes no new one. Off needs an active self-owned key. On needs room for the custodial key: at most 9 active self-owned keys.
Header Parameters
Request Body
Responses
stringThe status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
canceledunknowninvalid_argumentdeadline_exceedednot_foundstringA developer-facing error message, which should be in English. Any user-facing error message should be localized and sent in the [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.