XID Services
January 31, 2026 · View on GitHub
envelope xid service --help
│ Work with a XID document's services
│
│ Usage: envelope xid service <COMMAND>
│
│ Commands:
│ add Add a service to the XID document
│ all Retrieve all the XID services
│ at Retrieve the XID Document's service at the given index
│ count Print the count of the XID document's services
│ find Find all XID services matching the given criteria
│ remove Remove the given service from the XID document
│ update Updates the permissions, delegates, keys, capability identifer, or name of a service in a XID document
│ help Print this message or the help of the given subcommand(s)
│
│ Options:
│ -h, --help Print help
│ -V, --version Print version
Services are URI endpoints along with the keys, delegates, and permissions that are allowed to use them.
The keys and delegates in a Service declaration are references to keys and delegates that must already exist in the XID document.
ALICE_PRVKEYS=ur:crypto-prvkeys/lftansgohdcxdntswmjerdqdoxhnguzsdrhfcmjsfewkhkvezohkeycpasdysrvdgypeoemtgywztansgehdcxisespmvlhflnweksvyfnmhvofysnhyztpyhlftluweaoemenurstreckoybbfroektnncyls
ALICE_PUBKEYS=`envelope generate pubkeys $ALICE_PRVKEYS`
BOB_PRVKEYS=ur:crypto-prvkeys/lftansgohdcxhnlyeyzccpldfhsbmekkhspsmonlonctptenpkhettluhpzmteldssmejtdwbakttansgehdcxrkvapykpvalucwkgsalnmndefsfxfefsbwlujycebafybdqdpddwswswlktyzerfbeylotmk
BOB_PUBKEYS=`envelope generate pubkeys $BOB_PRVKEYS`
CAROL_PRVKEYS="ur:crypto-prvkeys/lftansgohdcxmorsytadihzswmckyltauyolecmevychhlwmtylbhsmdptfdrtuewnjtdkmnmkretansgehdcxhentsejphsfwclylihbwroaoisptaskegrimyldebecsdrrtbdlrrslazeursspmldtkmdds"
CAROL_PUBKEYS=`envelope generate pubkeys $CAROL_PRVKEYS`
xid service add: Add a Service to a XID Document
Alice creates a basic XID document.
ALICE_XID_DOC=`envelope xid new --nickname 'Alice' $ALICE_PUBKEYS`
envelope format $ALICE_XID_DOC
│ XID(93a4d4e7) [
│ 'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│ 'allow': 'All'
│ 'nickname': "Alice"
│ ]
│ ]
Alice adds Bob as a delegate.
BOB_XID_DOC=`envelope xid new --nickname 'Bob' $BOB_PUBKEYS`
ALICE_XID_DOC=`envelope xid delegate add --allow 'sign' --allow 'encrypt' $BOB_XID_DOC $ALICE_XID_DOC`
envelope format $ALICE_XID_DOC
│ XID(93a4d4e7) [
│ 'delegate': {
│ XID(f1199a75) [
│ 'key': PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│ 'allow': 'All'
│ 'nickname': "Bob"
│ ]
│ ]
│ } [
│ 'allow': 'Encrypt'
│ 'allow': 'Sign'
│ ]
│ 'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│ 'allow': 'All'
│ 'nickname': "Alice"
│ ]
│ ]
Alice adds a secure messaging service.
- Alice named the service "Messaging".
- The service is at
https://messaging.example.com. - The service provides the capability
com.example.messaging. - People can use the service to contact Alice (or Bob acting on behalf of Alice).
- The permissions on the service limit Alice and Bob's public keys to encrypting to Alice, and verifying signatures.
- Alice and Bob, as the holders of the private keys, can decrypt messages sent to them and sign messages they send.
ALICE_XID_DOC_WITH_SERVICE=`envelope xid service add \
--name 'Messaging' \
--capability 'com.example.messaging' \
--allow 'sign' \
--allow 'encrypt' \
--key $ALICE_PUBKEYS \
--delegate $BOB_XID_DOC \
"https://messaging.example.com" \
$ALICE_XID_DOC`
envelope format $ALICE_XID_DOC_WITH_SERVICE
│ XID(93a4d4e7) [
│ 'delegate': {
│ XID(f1199a75) [
│ 'key': PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│ 'allow': 'All'
│ 'nickname': "Bob"
│ ]
│ ]
│ } [
│ 'allow': 'Encrypt'
│ 'allow': 'Sign'
│ ]
│ 'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│ 'allow': 'All'
│ 'nickname': "Alice"
│ ]
│ 'service': URI(https://messaging.example.com) [
│ 'allow': 'Encrypt'
│ 'allow': 'Sign'
│ 'capability': "com.example.messaging"
│ 'delegate': Reference(f1199a75)
│ 'key': Reference(cab108a0)
│ 'name': "Messaging"
│ ]
│ ]
Alice adds a second service for retrieving her status.
- Alice named the service "Status".
- The service is at
https://status.example.com/alice. - The service provides the capability
com.example.status. - The public key is the only one used to verify Alice's signatures.
- Alice, as the holder of the private key, can sign her status updates.
ALICE_XID_DOC_WITH_SERVICE=`envelope xid service add \
--name 'Status' \
--capability 'com.example.status' \
--allow 'sign' \
--key $ALICE_PUBKEYS \
"https://status.example.com/alice" \
$ALICE_XID_DOC_WITH_SERVICE`
envelope format $ALICE_XID_DOC_WITH_SERVICE
│ XID(93a4d4e7) [
│ 'delegate': {
│ XID(f1199a75) [
│ 'key': PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│ 'allow': 'All'
│ 'nickname': "Bob"
│ ]
│ ]
│ } [
│ 'allow': 'Encrypt'
│ 'allow': 'Sign'
│ ]
│ 'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│ 'allow': 'All'
│ 'nickname': "Alice"
│ ]
│ 'service': URI(https://messaging.example.com) [
│ 'allow': 'Encrypt'
│ 'allow': 'Sign'
│ 'capability': "com.example.messaging"
│ 'delegate': Reference(f1199a75)
│ 'key': Reference(cab108a0)
│ 'name': "Messaging"
│ ]
│ 'service': URI(https://status.example.com/alice) [
│ 'allow': 'Sign'
│ 'capability': "com.example.status"
│ 'key': Reference(cab108a0)
│ 'name': "Status"
│ ]
│ ]
xid service count: Count the Number of Services in a XID Document
envelope xid service count $ALICE_XID_DOC_WITH_SERVICE
2
xid service at: Return the Service at the Specified Index
The indexes are zero-based, and in the order the service assertions appear in the XID document's Gordian Envelope, which is not necessarily the order they appear via envelope format.
envelope xid service at 0 $ALICE_XID_DOC_WITH_SERVICE | envelope format
│ URI(https://messaging.example.com) [
│ 'allow': 'Encrypt'
│ 'allow': 'Sign'
│ 'capability': "com.example.messaging"
│ 'delegate': Reference(f1199a75)
│ 'key': Reference(cab108a0)
│ 'name': "Messaging"
│ ]
envelope xid service at 1 $ALICE_XID_DOC_WITH_SERVICE | envelope format
│ URI(https://status.example.com/alice) [
│ 'allow': 'Sign'
│ 'capability': "com.example.status"
│ 'key': Reference(cab108a0)
│ 'name': "Status"
│ ]
xid service all: List All Services in a XID Document
envelope xid service all $ALICE_XID_DOC_WITH_SERVICE
│ ur:envelope/lttpsotpcxkscaisjyjyjojkftdldljnihjkjkhsioinjtiodmihkshsjnjojzihdmiajljnoycsfhtpsotanshkhdcxwncfnykphhsekedagdsfqdihoysadpzmimrpgtrnlesansjtdshtkedyhlwdmngloybdtpsoingtihjkjkhsioinjtiooycsfxtpsokpiajljndmihkshsjnjojzihdmjnihjkjkhsioinjtiooyaytpsotanshkhdcxsgpaaynbpdrdlbmkloykidfzmdtonnlngrtyrkbwcpfnmntyoyamuoetwydaremwoycsfncsfdoycsfncsgagdvamume
│ ur:envelope/lptpsotpcxkscxisjyjyjojkftdldljkjyhsjykpjkdmihkshsjnjojzihdmiajljndlhsjziniaihoybdtpsoiygujyhsjykpjkoycsfxtpsojpiajljndmihkshsjnjojzihdmjkjyhsjykpjkoyaytpsotanshkhdcxsgpaaynbpdrdlbmkloykidfzmdtonnlngrtyrkbwcpfnmntyoyamuoetwydaremwoycsfncsfdglmhuenb
Example capturing the above envelopes into a shell array. Note that newer shells like zsh use one-based indexing by default, but can be configured to use zero-based indexing.
XID_SERVICES=($(envelope xid service all $ALICE_XID_DOC_WITH_SERVICE))
envelope format ${XID_SERVICES[1]}
│ URI(https://messaging.example.com) [
│ 'allow': 'Encrypt'
│ 'allow': 'Sign'
│ 'capability': "com.example.messaging"
│ 'delegate': Reference(f1199a75)
│ 'key': Reference(cab108a0)
│ 'name': "Messaging"
│ ]
envelope format ${XID_SERVICES[2]}
│ URI(https://status.example.com/alice) [
│ 'allow': 'Sign'
│ 'capability': "com.example.status"
│ 'key': Reference(cab108a0)
│ 'name': "Status"
│ ]
xid service find: Find a Service by its URI
xid service find uri: Find a Service by its URI
Returns at most one service envelope.
envelope xid service find uri 'https://status.example.com/alice' $ALICE_XID_DOC_WITH_SERVICE | envelope format
│ URI(https://status.example.com/alice) [
│ 'allow': 'Sign'
│ 'capability': "com.example.status"
│ 'key': Reference(cab108a0)
│ 'name': "Status"
│ ]
xid service find name: Find a Service by its Name
May return multiple service envelopes.
envelope xid service find name 'Messaging' $ALICE_XID_DOC_WITH_SERVICE | envelope format
│ URI(https://messaging.example.com) [
│ 'allow': 'Encrypt'
│ 'allow': 'Sign'
│ 'capability': "com.example.messaging"
│ 'delegate': Reference(f1199a75)
│ 'key': Reference(cab108a0)
│ 'name': "Messaging"
│ ]
xid service remove: Remove a Service from a XID Document
Alice removes the messaging service.
ALICE_XID_DOC_WITH_SERVICE_REMOVED=`envelope xid service remove 'https://messaging.example.com' $ALICE_XID_DOC_WITH_SERVICE`
envelope format $ALICE_XID_DOC_WITH_SERVICE_REMOVED
│ XID(93a4d4e7) [
│ 'delegate': {
│ XID(f1199a75) [
│ 'key': PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│ 'allow': 'All'
│ 'nickname': "Bob"
│ ]
│ ]
│ } [
│ 'allow': 'Encrypt'
│ 'allow': 'Sign'
│ ]
│ 'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│ 'allow': 'All'
│ 'nickname': "Alice"
│ ]
│ 'service': URI(https://status.example.com/alice) [
│ 'allow': 'Sign'
│ 'capability': "com.example.status"
│ 'key': Reference(cab108a0)
│ 'name': "Status"
│ ]
│ ]
xid service update: Update an Existing Service in an Existing XID Document
- To remove the name, use
--name ''. - To remove the capability, use
--capability ''. - Passing one or more
--keyoptions replaces the existing keys with the ones provided. - Passing one or more
--delegateoptions replaces the existing delegates with the ones provided. - Passing one or more
--allowoptions replaces the existing permissions with the ones provided.
Alice adds Bob as a delegate to the status service. This leaves Alices key and all other attributes of the service unchanged.
ALICE_XID_DOC_WITH_SERVICE_UPDATED=`envelope xid service update \
--delegate $BOB_XID_DOC \
'https://status.example.com/alice' \
$ALICE_XID_DOC_WITH_SERVICE_REMOVED`
envelope format $ALICE_XID_DOC_WITH_SERVICE_UPDATED
│ XID(93a4d4e7) [
│ 'delegate': {
│ XID(f1199a75) [
│ 'key': PublicKeys(e2c18423, SigningPublicKey(f1199a75, SchnorrPublicKey(f0638394)), EncapsulationPublicKey(4af6be52, X25519PublicKey(4af6be52))) [
│ 'allow': 'All'
│ 'nickname': "Bob"
│ ]
│ ]
│ } [
│ 'allow': 'Encrypt'
│ 'allow': 'Sign'
│ ]
│ 'key': PublicKeys(cab108a0, SigningPublicKey(93a4d4e7, SchnorrPublicKey(26712894)), EncapsulationPublicKey(00b42db3, X25519PublicKey(00b42db3))) [
│ 'allow': 'All'
│ 'nickname': "Alice"
│ ]
│ 'service': URI(https://status.example.com/alice) [
│ 'allow': 'All'
│ 'capability': "com.example.status"
│ 'delegate': Reference(f1199a75)
│ 'key': Reference(cab108a0)
│ 'name': "Status"
│ ]
│ ]
Removing a key or delegate from the XID that is referenced by a service is not allowed.
To remove a key or delegate that is referenced by a service, first remove the service.
envelope xid delegate remove $BOB_XID_DOC $ALICE_XID_DOC_WITH_SERVICE_UPDATED
│ Error: item is still referenced: delegate