Architecture overview
Vitni is a modular monolith with independently built web, API, and worker applications in one pnpm workspace.
Browser ── Nuxt web/BFF ── REST + OpenAPI ── NestJS API ── PostgreSQL │ │ ├── tenant data + RLS └── OIDC discovery ── configured provider └── encrypted email outbox │Cloudflare Worker ── Hyperdrive ── Neon ── Resend HTTPS APISelf-hosted Node worker ── PostgreSQL ── SMTP relayApplication responsibilities
Section titled “Application responsibilities”- Nuxt web app: customer and holder pages, sign-in session, and same-origin API proxy.
- NestJS API: organization, membership, issuer, achievement, pathway, credential, and public document routes.
- PostgreSQL: tenant records, migration-managed schema, row-level security, and the encrypted email outbox.
- Worker: hosted scheduled email delivery through an HTTPS provider; local and self-hosted SMTP delivery is optional and off by default.
- OIDC provider: local development uses Keycloak; hosted prelaunch uses ZITADEL; self-hosted operators can configure another OIDC-compatible issuer.
- Credential package: credential serialization, signing, status, and verification behavior shared by services.
Tenant boundary
Section titled “Tenant boundary”An organization is the tenant root. Tenant-owned records have an organization ID, and PostgreSQL row-level security is forced. The API sets the authenticated user and active organization in a transaction before tenant queries. The API, migration process, and worker use separate database roles. Public credential, issuer, and status-list reads are narrowly scoped to a requested public document.
Recipients do not become issuer-organization members by default. The holder claim flow is separate and requires sign-in with the verified email that received the claim link.
Signing and verification
Section titled “Signing and verification”Each organization receives one issuer profile and signing-key lifecycle. Publishing establishes its stable issuer identifier. Issuance stores an immutable signed credential; revocation updates a signed Bitstring Status List. Public verification checks proof, expiry, and revocation status.
Canonical design record
Section titled “Canonical design record”The repository’s canonical runtime and tenant-isolation note is docs/architecture.md. The implementation inventory and current delivery status are in docs/feature-inventory.md and docs/implementation-status.md. These records remain authoritative as the product evolves.