Architecture & Security
Layered Architecture
Section titled “Layered Architecture”TCS is organized into five architectural layers, each with dedicated services:

System Architecture
Section titled “System Architecture”TCS is a microservices platform composed of seven services and a set of shared libraries. Each service is independently deployable and communicates over HTTP. The shared libraries provide common functionality including configuration, validation, error handling, and database access.
Service Responsibilities
Section titled “Service Responsibilities”| Service | Purpose |
|---|---|
| Authorization Server | OAuth 2.0 token issuance, DPoP validation, PAR sessions, authorization code flow |
| Credential Issuer | SD-JWT VC issuance, credential offer management, issuer metadata |
| Holder Service | Custodial wallet, DID management, OID4VCI/OID4VP client operations |
| Verifier Service | OID4VP verification, JAR request objects, VP Token validation |
| Trust Registry | Issuer/verifier registration, API key management, DID creation and import |
| Schema Registry | VCT (Verifiable Credential Type) metadata definitions and discovery |
| Scheduler | Background job runner for scheduled maintenance tasks |
Security Model
Section titled “Security Model”TCS implements defense-in-depth through four complementary security layers, each addressing a distinct threat vector.
Layer 1: DPoP (Demonstrating Proof-of-Possession) — RFC 9449
Section titled “Layer 1: DPoP (Demonstrating Proof-of-Possession) — RFC 9449”DPoP binds access tokens to the client that requested them. Every token request can include a DPoP proof JWT signed by the client’s private key. The server validates the proof and records the JWK thumbprint (jkt). Subsequent requests using that token must include a fresh DPoP proof from the same key pair, preventing token theft and replay.
- Supported algorithms: EdDSA, ES256
- JTI replay protection with database-backed tracking
- Server-issued DPoP nonces (required per HAIP v1)
- Nonce, JTI, and IAT expiry: 300 seconds each
Layer 2: PKCE (Proof Key for Code Exchange) — RFC 7636
Section titled “Layer 2: PKCE (Proof Key for Code Exchange) — RFC 7636”The authorization code flow requires PKCE with the S256 challenge method. The client generates a random code verifier, computes a SHA-256 challenge, and sends the challenge during the PAR request. At token exchange, the client sends the original verifier, and the server validates it against the stored challenge. This prevents authorization code interception attacks.
Layer 3: Signing Trust Anchor
Section titled “Layer 3: Signing Trust Anchor”TCS supports two credential signing paths, selected automatically based on key material supplied at issuance time:
- EdDSA DID path — Ed25519 key with a DID identifier; the
kidheader references the issuer’s DID key. Used whenissuerDidandissuerPrivateKeyare both present. - ES256 X.509 path — P-256 key with a certificate chain; the
x5cheader carries the full chain. Used when no DID key material is present. Required for HAIP v1 conformance.
If only one of the two required fields is present, the request is rejected as an inconsistent signing configuration. Credentials issued via the X.509 path can be verified without DID resolution, providing a trust anchor rooted in the traditional PKI hierarchy.
Layer 4: HMAC Nonces
Section titled “Layer 4: HMAC Nonces”The nonce endpoint issues HMAC-signed nonces that are validated at credential request time without requiring database lookups. The nonce value encodes an expiry timestamp and is signed with a server-side secret. This provides stateless nonce validation while maintaining the security guarantee that nonces cannot be forged.
Multi-Tenancy
Section titled “Multi-Tenancy”TCS uses path-based routing to isolate tenants. Each registered organization receives a unique tenant identifier (e.g., turing, ntu) that appears in issuer URLs and metadata discovery endpoints.
Tenant URL Structure
Section titled “Tenant URL Structure”| Resource | URL Pattern |
|---|---|
| Credential Issuer identifier | https://issuer.turingspace.co/{tenant} |
| Issuer Metadata | https://issuer.turingspace.co/.well-known/openid-credential-issuer/{tenant} |
| DID Configuration | https://trust-registry.turingspace.co/.well-known/did-configuration.json/{tenant} |
| Tenant landing page | https://issuer.turingspace.co/{tenant} |
Isolation Model
Section titled “Isolation Model”- Data isolation: The
tenantfield on theUsermodel is unique and serves as a foreign key for credential offers. Each tenant’s offers, credential configurations, and DIDs are scoped to their user account. - API key scoping: API keys are tied to individual user accounts. Operations validate that the API key owner has access to the requested tenant resources.
- Metadata isolation: Each tenant’s issuer metadata (credential configurations, display properties, supported types) is generated independently from their registered schemas.
Security Practices
Section titled “Security Practices”- Pre-authorized codes and API keys are stored as SHA-256 hashes only; plaintext values are never persisted.
- Holder passwords use bcrypt hashing.
- Issuer private keys for credential signing are stored encrypted at rest (Cloud SQL encryption).
- All models include
createdAtandupdatedAtaudit timestamps.
Enterprise Readiness
Section titled “Enterprise Readiness”| Capability | Status |
|---|---|
| OIDF conformance testing (OID4VCI, OID4VP, HAIP) | OID4VCI passing; OID4VP processing |
| Multi-tenant architecture | Supported — per-tenant trust anchors and isolation |
| Schema governance | Built-in Schema Registry with VCT discovery |
| API key authentication | Supported via Trust Registry registration |
| DPoP token binding (RFC 9449) | Supported |
| ISO 27001 / 27701 | Architecture aligned; organization-stated |
| Custodial wallet | Supported via Holder Service |
| Credential revocation | Internal — issuer-side status tracked on each credential record. Spec-aligned IETF Token Status List is on the roadmap; no public revocation endpoint is exposed today. |
| Dual signing (EdDSA + ES256) | Supported |
| Pre-authorized code flow | Supported (OID4VCI) |
| Selective disclosure | Supported (SD-JWT _sd mechanism) |
Compliance & Data Handling
Section titled “Compliance & Data Handling”For procurement and compliance reviews — especially in regulated sectors (banking, healthcare, government) — TCS’s data-handling posture is stated honestly below. Items not yet shipped are listed as such rather than left ambiguous; items that are handled out of band are flagged so reviewers know the right channel.
| Topic | Current posture |
|---|---|
| Infrastructure region | TCS production runs on Google Cloud Platform asia-east1 (Taiwan). Single-region deployment today. |
| Data residency | Credential and tenant data in TCS-managed Cloud SQL stays in the deployment region above; cross-region replication is not enabled. Treat this as the residency baseline and confirm log / backup pipeline residency with the TCS team for individual flows. |
| PDPA / GDPR role | In a typical custodial deployment TCS acts as a data processor under the integrating organisation (the data controller). Contact us to request a reference Data Processing Agreement for review. |
| Right to erasure | The credential delete endpoint is a soft delete — see Holder · Manage Wallets · Delete a credential. For hard-purge requests (PDPA / GDPR right-to-erasure), contact the TCS team with the affected uuid / credential_id. |
| Audit log access | Application-layer logs cover credential issuance (POST /v1/offers, POST /credential), DID lifecycle (POST /v1/did, /v1/did/import), API-key authentication, login attempts, and verification sessions — each with timestamp, tenant, request ID, and outcome. A self-serve audit-log export API is not yet exposed and logs are not currently signed / WORM-backed (procurement teams should plan for SIEM-side tamper-evidence). For incident reviews or procurement evidence requests, reach out for a log extract. |
| Self-host / data portability | Standard self-hosted deployments are not currently offered. Data portability on service termination (Postgres dump + IOTA chain references for issued DIDs) is handled out of band — contact us for the procedure. |
| Penetration test posture | TCS does not currently publish a public pentest report. Engagements requiring evidence of independent security review can request the current posture under NDA. |
This table is the procurement-question source of truth. If something you need is not listed, contact us — we will answer honestly, including “not yet.”
Operability — Health, Observability, Runbook Posture
Section titled “Operability — Health, Observability, Runbook Posture”A separate honest table for the SRE and on-call lens. The same “state it, even if it’s not yet” rule applies.
| Topic | Current posture |
|---|---|
| Health endpoint | Each service exposes GET /health returning 200 OK with { status: "ok", service, version }. The check is process-liveness only today — it does not probe the DB or IOTA dependency. Treat it as a Kubernetes liveness signal, not a readiness gate; layer your own dependency probes if you need that distinction. |
| Logging | Pino structured JSON logs across all services; per-request request_id, tenant, service, and OTel trace_id / span_id when telemetry is enabled. Slow query logging at >200 ms is built into PrismaService. |
| Tracing / OTel | OpenTelemetry boots when OTEL_ENABLED=true. Default exporter targets Google Cloud Trace; HTTP, Pino, Postgres, and Prisma instrumentations are pre-wired. The library used is @tcs/telemetry, side-effect entry @tcs/telemetry/register. Operators integrating with their own backend should set OTEL_TRACES_EXPORTER / endpoint env vars and verify trace propagation end-to-end. |
| Rate limiting | Trust Registry login is rate-limited to 5 attempts / 60 s per UUID. Other endpoints have no documented per-tenant rate limit today; conformance-suite or load-test runs should rate-limit on the caller side. A documented platform-wide policy is not yet published — flag intended cadence to the TCS team for sustained tests. |
| IOTA Tangle dependency | DID creation (POST /v1/did) and on-chain notarization (notarize_on_iota: true) require IOTA reachability. During a Tangle outage these calls return 503 while signed credential issuance with notarize_on_iota: false remains available — set notarize_on_iota: false as the incident mitigation. Recovery and retry behaviour after the network returns is not yet a published SLO; for production rollouts confirm exact retry and queueing semantics with the TCS team. |
| Schema migrations | Prisma migrations are coordinated centrally; services share a single Cloud SQL backend and migration order is run by the TCS team during each release. Self-hosted operators should follow the migrate-first deployment pattern (run migrations to completion, then roll services). Backward-incompatible migrations are avoided by policy; if one is necessary it ships behind a feature flag with explicit operator notes. |
For deeper on-call collaboration (alerting templates, dashboard exports, capacity guidance), contact us — these are tailored per deployment rather than published as boilerplate.
What’s Next
Section titled “What’s Next”- Standards Compliance — Review the standards TCS implements and conformance testing results
- API Reference — Explore the complete endpoint surface across all services
- Authentication — Understand API Key, JWT, and DPoP authentication patterns