Vault Branding — Org Identity on Every Surface

What It Is

Every vault entity has a profile.branding record — the single source of truth for how an org appears across all Tawa surfaces. The Passport reads it at mint time, registry pages render it, Bio-ID applies it to consent screens.

Schema

interface VaultBranding {
  // Self-serve after claiming
  displayName: string          // shown on all surfaces
  tagline?: string             // "Colorado's largest commercial agency"
  logoUrl?: string             // primary logo — SVG or PNG
  logoMarkUrl?: string         // icon/mark for small surfaces (32x32)
  primaryColor: string         // hex — buttons, accents (default: '#0F172A')
  secondaryColor?: string      // hex
  websiteUrl?: string
  phone?: string
  email?: string

  // White-label approved only
  customDomain?: string        // auth.acmeagency.com
  hideEcoBranding: boolean     // remove "Powered by InsurEco"
  emailFromName?: string       // magic link sender name
  customCss?: string           // injected into consent page, max 10KB

  // Platform-managed
  verified: boolean
  whiteLabelApproved: boolean
}

Two Tiers

TierWhoWhat they can set
ClaimedAny entity after Bio-ID claim flowdisplayName, tagline, logoUrl, logoMarkUrl, colors, website, phone, email
White-Label ApprovedPlatform approval after verificationcustomDomain, hideEcoBranding, emailFromName, customCss

API

GET  /v1/branding/:orgSlug                    → 0 gas, public
GET  /v1/entities/:iecHash/branding           → 0 gas, public
PATCH /v1/entities/:iecHash/branding          → 2 gas, auth required (owner/admin)

Response always returns defaults for unset fields.

SDK

import { VaultClient } from '@insureco/bio-vault'
const vault = VaultClient.fromEnv()

// By orgSlug (most common — you have it from the JWT)
const branding = await vault.getBranding('acme-agency')

// By iecHash (for public entity pages)
const branding = await vault.getBrandingByHash('0x1a2b3c...')

// Update (owner/admin only)
await vault.updateBranding('0x1a2b3c...', {
  tagline: 'Updated tagline',
  primaryColor: '#1D3557',
})

Prefer Passport Over Direct Vault Calls

If the user is authenticated and passport.includeBranding: true is declared in catalog-info.yaml, branding is already in req.user.branding. Don't call vault — read the Passport.

// CORRECT — branding is in the Passport
const { logoUrl, primaryColor } = req.user.branding

// WRONG — unnecessary vault call when Passport has it
const branding = await vault.getBranding(req.user.orgSlug)

Only call vault directly for:

  • Public pages where no user is authenticated (entity profile pages)
  • Background jobs that don't have a user context

Gotchas

  • verified and whiteLabelApproved can only be set by platform services — PATCH from a regular service returns 403 for those fields
  • hideEcoBranding is ignored unless whiteLabelApproved: true
  • customCss max 10KB — Bio-ID rejects larger payloads
  • Branding in the Passport is cached for up to 1 hour (token TTL) — logo changes propagate on refresh
  • Vault branding takes precedence over manual Bio-ID admin panel white-label settings

Last updated: July 15, 2026