Skip to content

Tenants & identity

Darwin is multi-tenant by design. This page describes the identity model: what’s a tenant, how organizations sit under it, how users authenticate, and how DIDs anchor everything on-chain.

Tenant
├─ Organizations (multiple)
│ ├─ Members (users)
│ └─ Roles (Operator / Admin / Auditor / Compliance)
├─ Process maps (config: which events, which transformations)
├─ API keys (server-to-server)
└─ on-chain tenant contract + DID

A tenant is the commercial customer. One tenant per paying relationship (food cooperative, automotive supplier, textile brand, etc.). Each tenant has:

  • A DID (Decentralized Identifier, W3C). The on-chain anchor of the tenant’s identity.
  • A dedicated tenant smart contract. All on-chain events flowing through this tenant are gated through it.
  • A per-tenant configuration subtree: process map definitions, asset types, compliance frameworks toggled, branding.

Tenants are isolated for operational data. Raw events, photos, documents, and capture records are scoped per tenant in the operational database and storage layers. The on-chain layer stores hashes and references designed to be verifiable without exposing sensitive payloads, since the original payloads stay off-chain under tenant access control.

Inside a tenant, an organization is a legal entity that participates in the value chain: a cooperative, a tier-2 supplier, a tier-1 assembler, a retailer, an auditor. Multiple organizations under one tenant collaborate on a shared chain of custody.

Every organization has its own DID. Custody transfer events between organizations are signed by both DIDs and recorded on-chain.

A user is a person with credentials. They belong to one or more organizations within a tenant. Users have roles that determine which API surface they can use:

  • Operator: captures events via Captia (write-only against own org)
  • Admin: manages process maps, organizations, members
  • Auditor: read-only across the tenant
  • Compliance: read + sign-off on regulatory bundles

Roles map to scopes in the JWT. See Authentication for the wire format.

TypeFormatLifetimeUse
JWT bearerBearer <jwt>short (1h typical, refresh available)user-driven calls
API keyX-API-Key: <key>long-lived, rotatableserver-to-server
DIDdid:web:<domain> or did:ethr:<addr>permanent (rotation = new DID)on-chain anchoring
SIWESign-In with Ethereum nonceper-sessionwallet-based login

Process-scope grants extend role-based access with least-privilege per process:

Example: an Operator at the cooperative can only capture wool_shearing events. They can’t capture garment_assembly even if the role would technically allow writes. The grant is scoped to the processes they own.

This is the foundation for safely opening an organization to multiple collaborators without exposing the full process map.

The canonical permission semantics are anchored in the on-chain identity contracts and surfaced via the API reference.

Each tenant can customize their branding across operational interfaces and public-facing portals:

  • Logo (light + dark)
  • Color palette (primary / secondary / accents)
  • Custom domain (e.g. passport.<tenant>.com)
  • Language (es / en / fr / pt-BR, extensible)
  • Copy overrides

Branding is applied per tenant at runtime, with no code changes required to onboard a new whitelabel customer. New tenants pick their brand at provisioning.

This wiki documents the REST + GraphQL surface for integrators. Internal tenant provisioning and operational tooling are not part of the public API. Contact the team at tech@darwinevolution.io for provisioning flows or support.