rip(casdoor): name the identity provider Hanzo IAM, and drop the dead manifest

main still called the provider Casdoor in ten places. hanzo.id is served by
github.com/hanzoai/iam, which its own LICENSE states is a clean-room
implementation carrying no third-party licensed source. The Casdoor-derived
server was hanzoai/iam-v1, retired and no part of this stack.

Every fact the text carried is kept. IAM really does stamp iss claims that
openid-client rejects, which is why the NextAuth provider is type: "oauth" and
why setting `issuer` breaks it; the applications really do live in the
iam-init-data configmap. Only the vendor name changed.

iam.py claimed a "Casdoor-compatible" flow. It is a standard flow — RFC 6749 and
OIDC Core — which is what HIP-0111 requires; naming a vendor for a capability
that has an RFC is what the standard exists to stop.

infra/k8s/cloud-deployment.yaml is deleted rather than edited. Its env block
named casdoorEndpoint / casdoorOrganization / casdoorApplication, and nothing
reads them: hanzoai/cloud configures IAM through IAM_URL, IAM_MINT_CLIENT_ID and
CLOUD_IAM_ISSUER, and ships no conf/. Renaming them to IAM_* would have produced
config that looks live and still does nothing. The file is unreferenced by
kustomization.yaml, duplicates declared state that belongs in universe
(infra/k8s/cloud/), pins registry.digitalocean.com instead of ghcr.io/hanzoai,
and pins a floating :latest tag that must never reach a cluster.

Landed directly on main via an isolated worktree. chore/use-datastore-fork is
139/137 divergent from a history rewrite; merging it would re-import that
lineage, and only two commit subjects there are genuinely absent from main.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
zooqueen
2026-07-28 17:45:19 -07:00
co-authored by Hanzo Dev
parent 135a4ede57
commit d022c3d860
3 changed files with 7 additions and 104 deletions
+6 -6
View File
@@ -416,7 +416,7 @@ All systems tested and operational:
### Active Services (Production)
| Service | URL | Status | Description |
|---------|-----|--------|-------------|
| IAM | https://hanzo.id | ✅ 200 | Hanzo Identity (Casdoor SSO) |
| IAM | https://hanzo.id | ✅ 200 | Hanzo Identity (SSO) |
| App Builder | https://hanzo.app | ✅ 200 | AI-powered app builder |
| KMS | kms.hanzo.ai (internal) | ✅ OK | Key Management Service (Infisical) |
| MinIO | internal | ✅ | Object storage |
@@ -1164,20 +1164,20 @@ HANZO_COMMERCE_WEBHOOK_SECRET=...
## Hanzo IAM / OAuth Configuration (2026-02-12)
### IAM Backend
- **Provider**: Casdoor (not Zitadel)
- **Provider**: Hanzo IAM (not Zitadel)
- **Backend URL**: `https://iam.hanzo.ai` (K8s service)
- **Frontend URL**: `https://hanzo.id` (Cloudflare Pages + middleware proxy)
- **Middleware**: `/Users/z/work/hanzo/hanzo.id/functions/_middleware.ts` proxies auth paths to IAM
### OAuth Flow for Console
- **Provider**: Custom `HanzoIamProvider` in `console/packages/shared/src/server/auth/hanzoIamProvider.ts`
- **Type**: `oauth` (NOT `oidc` — Casdoor JWT tokens have iss claims that openid-client rejects)
- **Type**: `oauth` (NOT `oidc` — IAM JWT tokens have iss claims that openid-client rejects)
- **Key settings**: `idToken: false`, `checks: ["state"]`, custom `token.request` function
- **Token endpoint**: `${serverUrl}/oauth/token`
- **Userinfo endpoint**: `${serverUrl}/api/userinfo`
- **Console env**: `IAM_SERVER_URL=https://hanzo.id`, `IAM_CLIENT_ID=hanzo-console-client-id`
### Casdoor Applications (in iam-init-data configmap)
### IAM Applications (in iam-init-data configmap)
| App | Display | Homepage |
|-----|---------|----------|
| app-console | Hanzo Console | console.hanzo.ai |
@@ -1186,7 +1186,7 @@ HANZO_COMMERCE_WEBHOOK_SECRET=...
| app-hanzo | Hanzo | hanzo.ai |
### Critical Lesson
Never set `issuer` on a `type: "oauth"` NextAuth provider pointing at Casdoor. This triggers OIDC discovery which overrides explicit endpoint URLs and causes JWT `iss` validation failures. Use a custom `token.request` function to bypass openid-client's JWT validation.
Never set `issuer` on a `type: "oauth"` NextAuth provider pointing at Hanzo IAM. This triggers OIDC discovery which overrides explicit endpoint URLs and causes JWT `iss` validation failures. Use a custom `token.request` function to bypass openid-client's JWT validation.
## Hanzo Bot Deployment (2026-02-12)
@@ -1210,7 +1210,7 @@ Never set `issuer` on a `type: "oauth"` NextAuth provider pointing at Casdoor. T
### Sites
- **hanzo.bot** → Landing page (hanzobot/site, Astro, K8s deploy)
- **app.hanzo.bot** → Bot dashboard
- **hanzo.id** → IAM/login (Casdoor via CF Pages middleware)
- **hanzo.id** → IAM/login (via CF Pages middleware)
## Hanzo Gateway Routes (2026-02-12)
+1 -1
View File
@@ -6,7 +6,7 @@ Supports login via:
- lux.id (Lux Network org)
- pars.id (Pars org)
Uses Casdoor-compatible OAuth2/OIDC flow.
Uses standard OAuth2/OIDC flow (RFC 6749, OIDC Core).
"""
import os
-97
View File
@@ -1,97 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: cloud
namespace: hanzo
labels:
app: cloud
spec:
replicas: 2
selector:
matchLabels:
app: cloud
template:
metadata:
labels:
app: cloud
spec:
containers:
- name: cloud
image: registry.digitalocean.com/hanzo/cloud:latest
imagePullPolicy: Always
ports:
- containerPort: 14000
env:
- name: RUNNING_IN_DOCKER
value: "true"
- name: httpport
value: "14000"
- name: driverName
value: "postgres"
- name: dataSourceName
valueFrom:
secretKeyRef:
name: cloud-secrets
key: database-url
- name: casdoorEndpoint
value: "https://hanzo.id"
- name: clientId
valueFrom:
secretKeyRef:
name: cloud-secrets
key: oauth-client-id
- name: clientSecret
valueFrom:
secretKeyRef:
name: cloud-secrets
key: oauth-client-secret
- name: casdoorOrganization
value: "hanzo"
- name: casdoorApplication
value: "app-cloud"
- name: redirectPath
value: "/callback"
- name: publicDomain
value: "https://cloud.hanzo.ai"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /api/health
port: 14000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /api/health
port: 14000
initialDelaySeconds: 5
periodSeconds: 5
imagePullSecrets:
- name: registry-hanzo
---
apiVersion: v1
kind: Service
metadata:
name: cloud
namespace: hanzo
labels:
app: cloud
spec:
selector:
app: cloud
ports:
- protocol: TCP
port: 80
targetPort: 14000
type: ClusterIP
# Note: cloud-secrets must be created separately with real OAuth credentials:
# kubectl create secret generic cloud-secrets -n hanzo \
# --from-literal=oauth-client-id="hanzo-cloud-client-id" \
# --from-literal=oauth-client-secret="<real-secret>" \
# --from-literal=database-url="postgres://hanzo:<password>@postgres:5432/hanzo_cloud?sslmode=disable"