zeekayandHanzo Dev 18756a8ce2 ci: retire deploy.yml and the dead .github lane — one build path
Second half of the migration, and deliberately a separate commit: the canonical
lane was landed first and watched green while deploy.yml was still in place, so
this repo was never left with zero delivery.

Three files out, one line changed.

.hanzo/workflows/deploy.yml — superseded. The canonical lane builds the same
Dockerfile, reads the same package.json version, pushes ghcr.io/hanzoai/id, and
proves the manifest resolves before going green. It also runs the 160 tests and
the typecheck that this file never did.

.github/workflows/docker.yml — a second image lane. It had already been reduced
to an echo, but it kept the SHAPE of a build lane alive in a directory this forge
cannot even read (Gitea takes the first of WORKFLOW_DIRS present, and
.hanzo/workflows has existed here for months). Two lanes for one image is how the
two drifted in the first place.

.github/workflows/workflow-sanity.yml — imports
hanzoai/.github/.github/workflows/workflow-sanity.yml@main, which returns 404:
the reusable it calls does not exist. It could only ever have failed. It also
triggers on `paths: ['.github/workflows/**']`, a directory that is now empty, so
even a live version of it would be guarding nothing.

sync-from-github.yml keeps its cron and its fast-forward-only rule, and its
build dispatch is repointed deploy.yml -> cicd.yml. That reference is BY
FILENAME. Left alone it would have 404'd against the `|| echo` that makes it
non-fatal, so the symptom would not have been a red sync — it would have been
commits arriving on the forge and nothing building, silently, which is the exact
failure this repo already survived once (four commits, zero images, no red).

Co-authored-by: Hanzo Dev <dev@hanzo.ai>
2026-08-04 17:28:44 -07:00
2026-02-14 05:26:48 -08:00
2026-08-04 11:22:27 -07:00
2026-06-28 20:06:13 -07:00

id

@hanzo/id

White-label login + identity verification portal. One Vite SPA, four hosts (hanzo.id, lux.id, zoo.id, pars.id), per-tenant brand resolved from the request hostname at runtime.

Layout

apps/
  web/                Vite + React 19 + @hanzo/gui — the actual SPA
    k8s/              Deployment + Service + Ingress (4 hosts, 4 TLS secrets)
pkgs/
  shared/             @hanzo/id-shared  — TenantConfig + brand resolver
  auth/               @hanzo/id-auth    — composable login/signup/OTP flows
                                          on top of @hanzo/iam SDK
  idv/                @hanzo/id-idv     — pluggable identity verification
                                          (Persona, Onfido, Veriff, stub)
legacy-nextjs/        Frozen — predecessor Next.js implementation. Kept
                     for reference until v0.1.0 ships to production.

Local dev

pnpm install
pnpm dev                 # http://localhost:5173 (defaults to hanzo brand)

To preview a different brand locally, edit /etc/hosts:

127.0.0.1  lux.id zoo.id pars.id

then visit http://lux.id:5173.

Build

pnpm build               # builds apps/web -> dist/
docker build -t ghcr.io/hanzoai/id:0.1.0 .

Adding a brand

  1. Publish or workspace-link the new per-org brand pkg (must ship brand.json at the package root and match the BrandContract shape in pkgs/shared/src/types.ts).
  2. Add a DEFAULT_TENANTS entry in pkgs/shared/src/tenant.ts OR put the override in the runtime catalog (IAM_TENANT_CONFIG_JSON env) so no rebuild is needed.
  3. Add the hostname to apps/web/vite.config.ts::BRAND_PACKAGES (lets dev + build serve /brand/<pkg>/brand.json).
  4. Add the hostname + TLS secret to apps/web/k8s/ingress.yaml.
  5. DNS: CNAME or A record → cluster ingress IP.

That's it — no per-brand Worker, no per-brand image, no per-brand deployment. One binary, four brands.

Plugging an IDV provider

import { registerProvider, createPersonaProvider } from '@hanzo/id-idv'
registerProvider(createPersonaProvider({
  templateId: import.meta.env.VITE_PERSONA_TEMPLATE_ID,
  apiKey: import.meta.env.VITE_PERSONA_API_KEY,
  environment: 'production',
}))

The portal stays unchanged — switching providers is a single registration call at boot.

S
Description
No description provided
Readme MIT
1.9 MiB
Languages
TypeScript 89.7%
JavaScript 5.5%
CSS 4.4%
Dockerfile 0.2%
HTML 0.1%