iam

package
v1.801.458 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package iam is Hanzo's identity provider: users, organizations, applications, and the OIDC/OAuth2 endpoints every Hanzo service authenticates against.

It folds Hanzo IAM into the unified hanzoai/cloud binary as an in-process subsystem (HIP-0106) — the LAST binary-consolidation piece: "one Go binary (hanzoai/cloud) embeds IAM + KMS + o11y".

CLEAN IAM (v2). This subsystem embeds github.com/hanzoai/iam — the clean-room identity rewrite on the native Hanzo stack (zip + hanzoai/orm + hanzoai/sqlite). The retired Beego fork (github.com/hanzoai/iam-v1) is GONE from cloud's graph: there is no beego process-global to corrupt, no InitEmbed, no session-manager hook, no shared-AppConfig co-residence hazard with the sibling `ai` legacy fork. The whole IAM v2 surface (OIDC discovery/JWKS, oauth authorize/token/userinfo/introspect/revoke, get-app-login, signin, the v2 entity CRUD, and the legacy verb-alias compat layer) is GRAFTED in process (safeMount): zip.Graft composes iamserver.NewApp(db) so cloud's router learns IAM's route patterns AND its op registry, while IAM's own router keeps IAM's behaviour.

IT IS THEREFORE NOT OPAQUE ANY MORE, and that is the whole point of the change. It used to be: the surface was hung on five `app.All` wildcards through zip.AdaptNetHTTP, which takes an http.Handler and returns a closure — the App went in and a bare function came out, taking IAM's 94 typed ops with it. cloud published FIVE path keys and 35 placeholder operations where 78 real paths and 94 typed operations were, so not one of them had a schema, an MCP tool, a CLI command or an SDK method. The refusal apps/iam/typed_wire_test.go used to gate was a property of that SEAM, never of IAM, and the seam is gone.

The specific self-service routes layered in front (skills) still win, because zip matches the most specific pattern. The two addresses that were NOT specificity but SHADOWING — /v1/iam/keys and /v1/iam/onboard, where apps/account registered deprecated aliases at addresses IAM already owns and serves — are gone from apps/account: a graft refuses a duplicate address at compose time rather than letting registration order decide silently, and at api.hanzo.ai those two were already answered by IAM anyway (ingress routes /v1/iam/* there).

The store is embedded SQLite under {DataDir}/iam (server.OpenSQLite, WAL) — this embed owns its OWN orm.DB outright, so the old fork's "ai bootstrap unable to open database file (14)" crash is gone. Config (orgs/apps/providers/signing certs) is seeded from the same init_data.json the deployment already provides (server.Seed, new-only + idempotent), so hanzo.id's OAuth/OIDC semantics are preserved.

IN-PROCESS STORE ACCESS. DB() exposes the opened orm.DB to sibling subsystems that REFLECT the IAM-owned Project resource in-process (clients/platform, clients/deploy) via github.com/hanzoai/iam/pkg/store — no HTTP hop to /v1/iam. It is nil until Mount runs (the same lifecycle the retired iam-v1 object-store global ormer had), so those callers guard a nil DB and degrade to a clean 503 until IAM is mounted.

FAIL-CLOSED, NOT FAIL-LOUD. A broken/misconfigured IAM does NOT crash the consolidated binary: an open/seed/mount failure degrades THIS subsystem to a 503 fail-closed on every IAM prefix (mountFailClosed) while every co-resident subsystem (KMS, o11y, …) stays up — the blast-radius isolation the whole consolidation exists for, mirroring the KMS "no master key → health-only" pattern.

Grafted in process (the whole IAM v2 surface, at its canonical paths — every pattern IAM's own router declares, and nothing else):

/v1/iam/…      OIDC/OAuth2 (/v1/iam/oauth/{authorize,token,userinfo,introspect,
               revoke,...}) + OIDC discovery (/v1/iam/.well-known/*) + signin +
               get-app-login + the v2 entity CRUD + the legacy verb-alias compat
/login/oauth/… browser authorize surface (the /v1/iam/oauth/authorize 302 target)
/.well-known/… OIDC discovery + JWKS at the issuer root (RFC 8414)

STAGING (security-critical): activation is the standard enable-list gate — the operator adds "iam" to the cloud deployment's --enable only AFTER the v2 config (init_data + KMS signing keys) is present and the fold is verified (login/authorize/token/jwks + the operator SSO chain). Until then hanzo.id is served by the standalone iam pod via ingress. If a broken config slips through, the subsystem serves 503 fail-closed rather than crashing cloud.

Index

Constants

This section is empty.

Variables

View Source
var Prefixes = []string{
	"/v1/iam",
	"/login/oauth",
}

Prefixes are the canonical absolute prefixes the IAM identity surface owns — this subsystem's own list, from which patterns() derives every address it registers, both the real routes (safeMount) and the fail-closed 503 (mountFailClosed). Everything outside them belongs to cloud, so the console catch-all keeps serving the SPA.

The host has a SECOND list and that is deliberate, the same split apps/commerce documents: manifest.Apps' iam row states what the light host's ROUTER may hand this binary (manifest/apps.go), while this states what the binary itself serves and fail-closes. Importing one into the other would re-fatten the host, which links manifest and zip and nothing else. They are not required to be equal, and today are not: the router does not name /.well-known, which manifest/router_test.go records in its `unreachable` ledger.

The bare /healthz is deliberately excluded — it is a shared-liveness path, not an auth surface, so 503-ing it would mask the binary's own health rather than an identity outage. It is also why iam2 must not be co-mingled: iam2 serves its OWN /healthz, which silently took over the shared binary's.

Functions

func DB

func DB() orm.DB

DB returns the embedded IAM store's orm.DB for in-process readers (clients/platform, clients/deploy) that reflect the IAM-owned Project resource via github.com/hanzoai/iam/pkg/store. It is nil until Mount has run (IAM not enabled, or a boot failure that fail-closed the subsystem); callers MUST nil-guard and degrade to 503 rather than dereference it.

func Mount

func Mount(app cloud.Router, deps cloud.Deps) error

Mount opens IAM's embedded store, seeds config from the same init_data.json the deployment provides (non-fatal), and registers the whole IAM v2 surface at the prefixes identity owns (Prefixes). Called once by cloud.MountAll when "iam" is enabled.

func Shutdown added in v1.801.381

func Shutdown() error

Shutdown releases the embedded IAM store. Idempotent.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL