Witness Service
The witness service is the OpenCredentials issuer, deployed at https://witness.credentials.org. It "witnesses" a claim, such as that a holder controls a mailbox, and signs a credential as did:web:issuer.credentials.org. Anyone, including the Node, can later verify that credential against the issuer's published key with no further contact with the witness.
Role
The witness is the trust anchor of OpenCredentials: a credential is only as good as its signer. Its identity and key custody are what a Node operator pins when it accepts credentials for credential-gated-delegation. The issuer's DID document is hosted separately, at issuer.credentials.org, so the identity resolves independently of the service that signs.
Mechanics
Acquisition protocol (tinycloud.credentials/acquisition/v1)
The routes TinyCloud uses live under /v1/acquisitions. Discovery is at /.well-known/opencredentials and /v1/credential-types.
- Create.
POST /v1/acquisitionswith aholderDidand a profile. The request lasts 10 minutes. - Interact. The user follows an interaction page on
credentials.org. For a mailbox, the witness emails an 8-digit, uniformly random code. A challenge lasts 5 minutes and allows at most 5 proof attempts. - Prove.
POST /v1/acquisitions/{id}/proof. - Holder signature.
POST /v1/acquisitions/{id}/holder-signature: the holder signs with the requesting DID's key;issuerefuses (holder_signature_required) until this succeeds. - Issue.
POST /v1/acquisitions/{id}/issue, thenGET …/result, returns avc+sd-jwtcredential whose subject andholderBinding.didare the requesting DID, with status freshness 300 s.
Two mailbox profiles back TinyCloud shares:
tinycloud.email-proof/v1: for one exact mailbox. It disclosesemailand itsemailDomain.tinycloud.email-domain-proof/v1: for shares addressed to a whole domain. The witness derivesemailDomainfrom the canonical form of the mailbox that passed the code. The acquisition input is only{email}, so a client cannot assert a domain. Domain-profile challenges are rate-limited.
Key custody: dstack TEE
In production the Ed25519 signing key is derived inside a dstack TEE: dstack::get_key("opencredentials/witness/signing-key"), selected by KEYS_TYPE=dstack. It is never handled as plaintext outside the enclave. This is the same confidential-compute basis as the Node's TEE.
Legacy routes
TinyCloud policy admission uses only the acquisition flow above.
Shape
- Issuer DID:
did:web:issuer.credentials.org; DID document atissuer.credentials.org. - Service host:
https://witness.credentials.org; interaction originhttps://credentials.org. - Signature: Ed25519 /
EdDSA, TEE-derived key. - Mailbox code: 8 digits; 5 attempts; 5-minute challenge; 10-minute request.
Relationships
The issuer half of OpenCredentials; signs SD-JWT VCs; its DID is the trusted issuer the Node pins for credential-gated-delegation in policy-v3-admission; feeds the policy engine; key protected by a dstack TEE; also the audience the Node names when it authorizes a Share email (see native-sharing); identified by a did:web.
Example
Bob's browser posts an acquisition for profile tinycloud.email-domain-proof/v1 and his did:key. The witness emails bob@example.com a code such as 48213906. Bob enters it on credentials.org, and the witness issues a credential with email and the derived emailDomain: example.com, signed by its TEE-held key. The Node later verifies it against its pinned copy of did:web:issuer.credentials.org's key.
Status & drift
shipped. The acquisition API and both mailbox profiles back production email and domain shares. Earlier versions of this page said the witness signs as did:web:issuer.tinycloud.xyz; that is wrong. The production issuer is did:web:issuer.credentials.org (OpenCredentials README; Node production trust-bundle contract). Other flows exist (X tinycloud.x-verification/v2, DNS, GitHub, …) but are not accepted by Node policy admission.
Sources
OpenCredentials(60364a9):rust/opencredentials_witness/src/credentials/mod.rs(constants :32-70 incl. 8-digit code :64 and profiles :38, 42; routes :856-883; domain derivation :2013-2024; issuance :1790-1950),rust/opencredentials_witness/src/main.rs(dstack key derivation),rust/opencredentials_witness/src/routes.rs:36-45(legacy routes),README.md:16-25(two-host architecture)tinycloud-node(05c6a93):deploy/share-email/production-trust-bundle-contract.md:42-45