Witness Service
The witness service is the OpenCredentials issuer: an HTTP service (deployed at https://witness.tinycloud.xyz) that verifies a real-world fact about a subject and, on success, signs a credential as did:web:issuer.tinycloud.xyz. It "witnesses" a claim — that the subject controls an email address, a DNS record, a GitHub account — and converts that observation into a portable SD-JWT / W3C VC that anyone, including the policy engine, can later verify against the issuer's published DID document.
Role
The witness is the trust anchor of OpenCredentials within Layer 2. A credential is only as trustworthy as the entity that signed it, so the witness's identity (did:web:issuer.tinycloud.xyz) and key custody matter: it is the issuer a Policy names in authority.accepted_issuers when it gates a delegation on credential evidence. The verification logic lives off-chain (talking to email providers, DNS, GitHub APIs); the witness's signature is what makes the result self-verifying afterward.
Mechanics
The service is an axum Router (rust/opencredentials_witness/src/main.rs) exposing:
GET /.well-known/did.json— the issuer's DID document (Ed25519 verification key,JsonWebKey2020), generated from the issuer JWK with the privatedfield stripped (config::did_document).GET /capabilities— which verification flows + credential formats are enabled.POST /instructions→POST /statement→POST /witness_jwt | /witness_sd_jwt | /witness_ld— the three-step issuance handshake: the client gets flow instructions, submits a signed statement proving the fact, and receives the issued credential in the requested format.POST /verify— stateless verification of a presented VC.
Which flows are active is set per deployment by env vars (config::new_flow): no-API-key flows (DNS, GitHub, Reddit, same-controller assertion, attestation) default on; API-key flows (email via Resend, NFT via Alchemy, POAP, Twitter, SoundCloud) enable when their key is present.
Key custody — DStack TEE
The Ed25519 signing key is, in production, derived inside a DStack TEE (KEYS_TYPE=dstack): build_issuer_dstack calls dstack::get_key("opencredentials/witness/signing-key") to obtain a TEE-bound seed, so the issuer key is never handled as plaintext outside the enclave. Without dstack, the key comes from OPENCREDENTIALS_SK (development). This is the same DStack confidential-compute basis used elsewhere in TinyCloud.
Shape
- Issuer DID:
did:web:issuer.tinycloud.xyz(set viaDID_WEB). - Service host:
https://witness.tinycloud.xyz(the client'sDEFAULT_WITNESS_URL). - Signature: Ed25519 (
JsonWebKey2020/EdDSA), key derived in a DStack TEE. - Issuance handshake:
instructions → statement → witness_{jwt|sd_jwt|ld}.
Relationships
The issuer half of OpenCredentials; signs SD-JWT / W3C VCs; its DID did:web:issuer.tinycloud.xyz is the trusted issuer a Policy lists in accepted_issuers for credential-gated delegation; its key is protected by the same DStack TEE confidential-compute model; identified by a did:web; an L2 component.
Example
A client POSTs an email-verification statement to https://witness.tinycloud.xyz. The service runs the email flow, confirms the user controls sam@tinycloud.xyz, and returns from /witness_sd_jwt an SD-JWT credential signed by the TEE-held key of did:web:issuer.tinycloud.xyz. Months later the policy engine resolves that same DID's /.well-known/did.json, finds the verification key, and verifies the credential with no further contact with the witness.
Status & drift
in-progress. The axum service, the route set, the DStack-derived issuer key, and did.json generation are implemented. Many verification flows exist in config, but the only flow currently wired through to TinyCloud authorization is email (the policy engine's opencredentials.email/v1 verifier — see credential-gated-delegation). The did:web:issuer.tinycloud.xyz / witness.tinycloud.xyz hostnames reflect the intended deployment; treat exact operational endpoints as deployment config. See contradictions.
Sources
OpenCredentials:rust/opencredentials_witness/src/main.rs(axum routes, DStack key derivation),rust/opencredentials_witness/src/routes.rs(handler set),rust/opencredentials_witness/src/config.rs(new_flow,did_document,did:webissuer)