Invia una richiesta firmata
Usa la chiave di un dispositivo autorizzato per modificare schede e organizzazioni.
Le letture pubbliche non richiedono una firma. Le modifiche usano una chiave attiva autorizzata e una richiesta firmata. Questi endpoint sono disponibili ai client locali o server. CORS non apre le scritture firmate a un altro sito. Non inviare mai una chiave privata a Veil.
Firma i byte della richiesta#
veil-rubrica:request:v1
POST /v1/identities/1/versions
<exact UTF-8 JSON body>Metti la chiave pubblica in X-Public-Key e la firma della richiesta in X-Signature. Il corpo JSON contiene un nonce nuovo e un timestamp in millisecondi Unix entro due minuti dall’orologio del server. Un nonce si usa una volta sola. La firma copre metodo, percorso esatto e corpo esatto.
Chiavi e firme Ed25519 usano l’esadecimale. Le chiavi e firme composite usano base64 e X-Signature-Alg impostato a mldsa65-ed25519. Per le GET firmate manda X-Nonce e X-Timestamp e firma il percorso esatto con query, nonce e timestamp separati da ritorni a capo.
veil-rubrica:request:v1
GET /v1/device-requests/PAIRING_CODE
<nonce>
<Unix milliseconds>Pubblica una versione in formato 2#
Il formato 2 è quello predefinito dal 28 ottobre 2026 e il registro in uso lo usa. Le quattro richieste di pubblicazione, POST /v1/identities, POST /v1/identities/{n}/versions, POST /v1/organizations e POST /v1/organizations/{n}/versions, mandano label, body, signature e, per un’immagine nuova, pictureData, con il nonce e il timestamp di sempre. La versione 1 manda anche clientSalt e saltTicket. Un record del formato 1 mandato a un registro in formato 2 riceve 400 wrong_format.
{
"label": "{\"auth\":[],\"body\":\"BODY_HASH\",\"identity\":\"CARD_TOKEN\",\"n\":2,\"prev\":\"PREVIOUS_LABEL_HASH\",\"state\":\"STATE_ROOT\",\"time\":1792960060,\"v\":2}",
"body": "{\"ops\":[{\"name\":\"Ada Brennan\",\"op\":\"name\"}],\"salt\":\"BODY_SALT\",\"v\":2}",
"signature": "LABEL_SIGNATURE",
"nonce": "FRESH_NONCE",
"timestamp": 1792960060000
}veil-rubrica:identity-version:v2
<canonical label>label e body sono testi JSON canonici, esattamente i byte di cui si calcola l’hash e che si firmano. Il server li codifica di nuovo e confronta, e non li riscrive mai. signature copre il prefisso qui sopra seguito dall’intestazione, in hex per Ed25519 e in base64 per una chiave composita. pictureData porta i byte di un’immagine nuova che il corpo nomina per hash, in base64 standard con padding.
- label.n è il numero della versione e label.prev l’hash dell’intestazione precedente, null per la versione 1. label.body è l’hash del corpo. label.state è la radice dello stato dopo le operazioni, salata con il sale del corpo. label.time sono secondi Unix entro cinque minuti dall’orologio del server.
- label.auth elenca, in ordine, le operazioni che cambiano chi può firmare: addKey e revokeKey per una persona, e invite, role e remove di un proprietario o di un amministratore per un’organizzazione. Nell’organizzazione Veil conta ogni ruolo dello staff. Ogni altra operazione va in body.ops, e un’operazione nel posto sbagliato riceve 422
invalid_op. - Per un’organizzazione, label.signer nomina la scheda del membro che firma e la sua versione corrente come
{identity, n}, e la chiave è una chiave attiva di quella versione. Il corpo non porta mai signer. - Ogni chiave che label.auth aggiunge vuole il suo nome in un’operazione
devicedello stesso corpo. - Una persona tiene al più 64 chiavi attive (
keys_limit) e un’organizzazione al più 1.024 membri nella sua autorità (authority_limit). Mentre una cancellazione della scheda aspetta, la scheda non pubblica (erase_pending).
Gli esempi con request.json presuppongono che il tuo client abbia già costruito e firmato il corpo. Una pubblicazione è pronta quando il suo impegno compare in un checkpoint controfirmato. Se una richiesta scade, controlla le versioni correnti prima di mandare un’altra modifica.
Una richiesta di cancellazione su un registro in formato 2 porta anche closing, la voce di chiusura firmata con la stessa chiave sul prefisso veil-rubrica:close-entry:v2 e un a capo seguiti dalla voce senza la firma. Senza, la risposta è 422 closing_required.
Il JSON canonico, per un’intestazione, un corpo o un record del formato 1, ordina le chiavi degli oggetti per unità UTF-16, conserva l’ordine degli array e non ha spazi fuori dalle stringhe. Ammette solo interi nell’intervallo sicuro di JavaScript, stringhe UTF-8, booleani e null. Non normalizzare o tagliare il testo firmato. Il corpo esterno della richiesta non deve essere canonico, ma la sua firma deve coprire esattamente i byte inviati.
Record del formato 1 su test-1#
Il formato 1 è fermo su log.veil.rip/test-1, che non prende versioni nuove. Solo un server il cui GET /v1/log non ha format prende il record firmato qui sotto, come record, signature e logoData facoltativo. Non firmare mai un record del formato 1 per una scheda che conosci in formato 2.
Il record ha una propria firma sul prefisso identity-version e il JSON canonico. La firma della richiesta e quella del record servono a controlli diversi. record.n è il numero della versione. Il numero permanente della scheda resta nel percorso dell’endpoint. Una nuova versione conserva l’impegno precedente in prev e la storia di chiavi e collegamenti.
- v vale 1. identity è il base64url di un token casuale di 16 byte per la prima versione e poi resta uguale. n parte da 1 e cresce di uno. prev è null alla versione 1 e poi l’impegno precedente in base64 standard.
- name è il nome mostrato. time usa secondi Unix entro cinque minuti dall’orologio del server. type è person o organization, e un record senza type è una persona. alias è facoltativo, minuscolo e segue le regole dell’endpoint di disponibilità.
- keys è la storia completa delle chiavi. Ogni elemento contiene key, alg, device, role, since e revoked. role è device o recovery. since e revoked sono numeri di versione, e revoked è null finché la chiave è attiva.
- links è la storia completa degli account. Ogni elemento contiene platform, subject, display, since, removed e il grant quando viene aggiunto. Gli elementi rimossi restano nei record successivi. Le API di collegamento danno il grant da pubblicare.
- Una persona può avere orgs per le appartenenze accettate, e un’organizzazione ha members con i ruoli. Conserva la storia e i grant di accettazione. Pubblicare un invito da solo non rende accettata l’appartenenza.
- logo è facoltativo per entrambi i tipi di scheda. Una versione nuova nomina l’immagine per hash: type, sha256 (il suo SHA-256 in 64 cifre esadecimali minuscole) e size (la sua lunghezza in byte, fino a 2 MiB). Quando l’immagine è nuova, mandala accanto al record come logoData, in base64 standard con padding. Usa image/svg+xml, image/png o image/gif. Le versioni pubblicate prima del 27 ottobre 2026 hanno invece type e data, e restano valide. L’API delle anteprime controlla l’immagine prima della pubblicazione.