56 Commits
Author SHA1 Message Date
zeekayandHanzo Dev 02731f68e9 the CLI's remote targeting points nowhere, and now the file says so
Two claims in the CLI section were wrong, both about how a host gets named.

EnvURLs over Env.DomainSuffix was described as "the one way the CLI names a
host". It names none — nothing calls it outside its own test — and it could not
name a real one if it did: DomainSuffix is hard-coded to example.com with no
env, config or flag behind it. Having no caller is the only reason a URL builder
that resolves to a domain nobody owns has never surfaced.

Env.K8sContext DOES have callers, eleven of them across operator, cluster and
status, and it returns the bare literals gke_mainnet / gke_testnet / gke_devnet
— not the gke_<project>-<env>_<region>_<suffix> map this section printed.
Neither shape exists here: Hanzo runs on DOKS, so kubectl --context gke_mainnet
finds nothing and every remote CLI command fails at its first call. Loudly, at
least. Local is unaffected: K8sContext returns "" and statuscmd keys on that to
skip the cluster.

Both are pinned now, so replacing the literals with real contexts is a
deliberate edit in two places rather than something discovered mid-incident.

Coverage while there: AddNetworkFlags was 0% and carries the property the skip
exists for — Base registers its own --dev, so re-registering would panic and
rebinding would leave Base's variable permanently false. Asserted by setting the
flag and checking the ORIGINAL variable receives it. cmd/cli 24.7% -> 25.8%.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-24 10:43:37 -07:00
zeekayandHanzo Dev 21c8030e02 a daemon's name is the daemon's, so the CLI reads it rather than spelling it
The CLI printed a fixed name in its examples and help text while already
taking that name as a parameter, so `operator` and `rpc` now interpolate what
they were handed, the way `cluster` already did.

The config file's per-env URL block goes with it. Nothing read it: EnvURLs
computes a service address from the environment's domain suffix, which is
what every command actually calls, so the block was a second unasked answer
to where a service lives. An older config still loads — an unknown key is
ignored — and its env block is dropped on the next write. The default org is
no longer a name.

The Tasks queue is named for this repo rather than written out three times.

Fixture hostnames follow the shape the operator emits, which one of those
files was already using.

crdt/privacy_fhe.go cited a PDF that is not in the tree; the two figures it
backed are in the design doc it already points at.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-13 14:16:11 -07:00
zeekay 054d65663a they are Bases, one per org — the word tenant is gone
Base's own registry was already org-native in every method — OrgDB(orgID),
HasOrg(orgID), orgDir(orgID) — and only the type names said tenant. So this is
the vocabulary catching up with the code, not a change of behaviour.

	TenantRegistry -> Bases          app.Bases().OrgDB(org)
	TenantConfig   -> BasesConfig
	MultiTenant    -> PerOrg         it enables per-org databases; say that
	MULTI_TENANT   -> MULTI_BASE
	core/tenant.go -> core/bases.go

Tenant was the wrong noun twice over: it is the multi-tenancy word, and this
product's unit is the thing a customer creates per org — a Base. Identity here
is org, user, project, and nothing else.

The UI never said it; this was Go-side only. 64 packages green.

One test was collateral and is fixed rather than renamed: TestToHTTPHeader
asserts a pure snake_case-to-Header-Case transform, so rewriting its EXPECTED
value while its input stayed "tenant_id" made it assert something false. The case
is dropped — org_id already covers that transform.
2026-08-10 18:23:40 -07:00
zeekayandHanzo Dev 4d5ad48ace chore: scrub upstream-fork brand mentions (Base-native naming only)
Co-authored-by: Hanzo Dev <[email protected]>
2026-06-30 13:32:06 -07:00
zeekay a8610147d2 fix(cli): brand-neutral K8s namespaces base-{main,test,dev}net (was liquid-* — Liquidity brand leak)
Docker / test (push) Waiting to run
Docker / docker (push) Blocked by required conditions
release / build (push) Waiting to run
2026-06-23 08:21:36 -07:00
zeekay e7df8c856e base: complete pocketbase→base rename; Base = pure IAM client
Rename / namespace:
- Finish github.com/pocketbase/* → github.com/hanzoai/base (+ /dbx) sweep
  across all Go sources; restore the renamed root launcher (Base, base.go).
- Drop the upstream-only surfaces ours doesn't ship (admin ui/, the
  password/OTP/oauth2/impersonate auth files, extensions) re-added by the
  upstream merge.
- Decomplect the on-disk layout to one base_/ namespace: data/, migrations/,
  hooks/, types.d.ts are siblings under base_/ (default data dir
  base_/data). Drop the hz_ prefix everywhere; collapse migratecmd's
  identical JS/Go branches to one path.
- Remove the accidentally-committed hz_data/ dev dir (db + iam.key) and
  gitignore the runtime namespace dirs.

Deps / build:
- kmsclient now imported from the light github.com/hanzoai/kms/sdk/go module
  (the root kms module zip exceeds Go's download limit); cloud/pkg/base
  Mount removed (lives in the fused daemon).
- replicate v0.4.0 → v0.8.0; metric.Counter.Get() (no prometheus dto);
  network/metrics.go import fix; auth gitlab/github tidy.

Tests / behavior:
- Wire registerNotifyWatcherHooks; debounce notify files past the kqueue
  rescan window so cross-instance settings/collections reload fires.
- migratecmd: exclude createdAt/updatedAt (not created/updated); regenerate
  Go+JS automigration goldens from canonical output.
- Convert the two stale archive red-probes to assert the landed defenses
  (backlog cap bounds memory; forged-segment signature is rejected).

IAM-native (Base = pure IAM client):
- Rip the ~1k-line home-grown embedded IAM (iam_embedded*.go) and the
  iam-user CLI. Base no longer reinvents identity as _iam_users/_superusers
  rows. IAM_ENDPOINT (hanzo.id, or an in-process iam.Embed in the fused
  daemon) is required; Base validates IAM JWTs via JWKS only — superuser is
  the IAM admin claim, resolved to an ephemeral unpersisted record.
- Extract the IDV reverse-proxy (/v1/idv/*) into idv_proxy.go — it was
  mis-colocated in the embedded onboarding file and is independent of IAM.
- Bind the SQL console (/v1/sql) and test it through real IAM JWTs against a
  JWKS stub (no hardcoded record tokens, no persisted rows).
2026-06-10 21:29:14 -07:00
zeekay 1bf4a1e5f4 chore: update 2026-06-10 13:59:55 -07:00
zeekay 04ef45baf3 merge: upstream/master (pocketbase, brand preserved with -X ours + accept-our-deletes)
Hanzo Base diverged from upstream pocketbase via:
- Replaced ui/ (Vue admin) with @hanzo/gui React shell
- Dropped legacy test fixtures
- Kept upstream Go backend changes (db, auth, hooks)

Conflicts resolved: UU/UA/AU → ours, UD/DD → drop (we deleted), DU → theirs (they restored).
2026-06-02 10:19:06 -07:00
zeekay cc7a65b5cb base: route convention /api/* -> /v1/*
One path: /v1/*. We do not use /api/ — that's Casdoor's path. The
BASE_API_PREFIX env knob is gone; the prefix is hard-coded in
apis/base.go and apis/serve.go banner.

Server-side mounts:
- apis: bindHealthApi, bindCollectionApi, bindRecordCrudApi, etc. all
  attach under r.Group("/v1") (was r.Group(BASE_API_PREFIX, default /api))
- platform plugin: /api/platform/* -> /v1/platform/* (including auth and
  org sub-groups)
- kms plugin: /api/kms/* -> /v1/kms/*
- functions plugin: /api/functions/* -> /v1/functions/*
- cloudsql plugin: /api/cloud-sql/*, /api/meta/* -> /v1/*
- superuser OIDC: /_/api/oidc/config -> /_/v1/oidc/config
- core settings: default RateLimitRule labels /api/batch, /api/ ->
  /v1/batch, /v1/
- apis/batch.go: ValidBatchActions regexes match /v1/collections/*;
  internal rewrite targets /v1/collections/* (was /v1/base/collections/*,
  a stale artifact)

Clients:
- sdk/base-js (BaseClient.collections, files, realtime, CRDT WS,
  signIn/refresh/health) targets /v1/*
- sdk/base-react (use-crdt WS path) targets /v1/crdt
- ui-react admin (lib/api.ts, settings.application copy) targets /v1/*
- cmd/cli (NewClient.APIPrefix) defaults to /v1; client_test.go and
  cmd/cli_test.go stubServer use /v1/*
- cmd/typegen calls /v1/collections

Upstream paths untouched: Casdoor IAM (/api/login, /api/userinfo,
/api/signup, /api/send-verification-code, /api/get-user), KMS Infisical
(/api/v1/auth/universal-auth/login, /api/v2/workspace/environments),
Kubernetes tasks (/api/v1/namespaces/...), IPFS (/api/v0/...), Gitea/
GitLab/Discord/Strava/Patreon/Box/Wakatime upstream APIs. Those are
their contracts, not ours.

Tests: all 437 prior /api/ test URLs across apis/*_test.go and
plugins/platform/auth_proxy_test.go updated to /v1/. Build + go vet
clean. ./apis ./core ./plugins/platform ./plugins/jsvm ./forms all
green. Pre-existing red probes (network/TestRedProbe_*,
migratecmd/TestAutomigrateCollection*) unchanged.
2026-05-15 14:41:26 -07:00
zeekay a2844392a1 platform: move embedded IAM mount to /v1/iam
Rename the in-process OIDC provider mount + proxy mount from /api/iam to
/v1/iam. One path. We do not use /api — this is not Casdoor.

- embeddedIAMMount constant -> /v1/iam
- iam_proxy registers /v1/iam/{path...} and trims that prefix
- HTML login form POSTs to /v1/iam/oauth/login
- iam_embedded_test.go: every test URL + issuer expectation -> /v1/iam
- doc strings across platform.go, iam_embedded.go, iam_proxy.go,
  record_auth.go, cmd/cli/login.go, apis/middlewares_test.go
- LLM.md + CHANGELOG.md docs updated to reflect /v1/iam
2026-05-15 14:30:28 -07:00
zeekay 37fdbe434f cmd: add iam-user create subcommand for embedded mode
Operators booting Base with IAM_MODE=embedded need a way to seed users
without going through HTTP. This adds a base iam-user create <email>
subcommand that prompts for a password (stdin) or honors
IAM_USER_PASSWORD for CI, then bcrypts at cost 12 and persists to
_iam_users.

Exposes EnsureIAMUsersCollection / CreateEmbeddedIAMUser /
AuthenticateEmbeddedIAMUser as the package-level public surface so the
CLI doesn't have to reach into plugin internals.

Tests cover both the env-driven happy path and the empty-password
guard.
2026-05-15 09:55:57 -07:00
zeekay ad764d9074 cmd: rip superuser CLI — local-password admin is dead
The superuser{,Upsert,Create,Update,Delete,OTP}Command tree managed
local bcrypt passwords and OTPs on _superusers. Hanzo IAM is the only
credential issuer now; the OIDC handler in apis/superuser_auth_oidc.go
auto-provisions a passwordless superuser record on first sign-in, so
there is nothing for a CLI subcommand to write. Drop the binary
sub-command and stop registering it in base.Start.
2026-05-15 03:17:53 -07:00
zeekay 2eb1ee2805 cmd: rip local-auth callers from base login + typegen
Two CLI tools were still POSTing to /collections/.../auth-with-password
that no longer exists:

  cmd/cli/login.go       — `base login --email --password`
  cmd/typegen/main.go    — `--admin-email --admin-password`

base login is reduced to an IAM-handoff stub: running it with no flags
prints the instructions and exits 0; running it with --email/--password
returns a non-zero exit with the same instructions. Tokens flow into
subsequent commands via the existing persistent `--token` flag,
$BASE_TOKEN, or ~/.config/base/token (see cmd/cli/config.go).

typegen swaps its --admin-email/--admin-password pair for a single
--token flag (also reads $BASE_TOKEN). The dead authenticate helper
and the bytes import go away.

cli_test.go: drops the auth-with-password stub and rewrites
TestCLILoginMissingFlags into TestCLILoginRejectsLocalCreds +
TestCLILoginNoArgsSucceeds matching the new contract.

Closes out the IAM-native rip's Go-build consumer sweep. Remaining
local-auth references (ui-react TypeScript, sdk/base-js, jsvm
typegen output) are non-Go and outside this commit's gate.
2026-05-14 17:19:01 -07:00
Gani Georgiev 1f98392548 added superuser ips whitelist 2026-05-05 13:04:06 +03:00
zeekay afa1ada328 fix: k8sNamespace() missing — add function, pass env param
daemon.go called k8sNamespace() with no args but it didn't exist.
Added k8sNamespace(env string) that resolves via parseEnv → Env.K8sNamespace().
All 4 call sites now pass the env string.
2026-04-17 11:40:35 -07:00
zeekay e540c65590 fix: remove hardcoded deployment URLs — use generic defaults, configurable via env 2026-04-16 22:08:04 -07:00
zeekay f2db679900 cli: first-class base CLI subcommands inherited by all Base daemons
Adds collection/record/login/whoami/crons + daemon lifecycle +
cluster (base-ha HA) + operator (K8s CRD) + config/status/self/rpc.
Lux/cli network flags (--mainnet/--testnet/--devnet/--dev).

All Base daemons (atsd-style binaries) get the full CLI for free
via base.Start() or manual cmd.AddCommand(cmd.NewCLICommand()).
2026-04-13 13:29:39 -07:00
zeekay 4641f13ae7 feat: Base platform — CRDT privacy, React admin, on-chain anchor SDK 2026-03-01 18:00:00 -08:00
zeekay 7f17d4b316 Add realtime DX platform: CRDT engine, WebSocket, SDKs, typegen, scheduler, multi-tenant
7-phase implementation of Convex-inspired realtime developer experience:

- crdt/: Go CRDT engine (GCounter, PNCounter, LWWRegister, ORSet, RGA text)
  with state-vector sync protocol and convergence-tested types (31 tests)
- apis/ws.go: Pure RFC 6455 WebSocket endpoint with JWT auth, CRDT sync,
  presence tracking, channel subscriptions
- apis/presence.go: Channel-based presence manager for collaborative awareness
- cmd/typegen/: CLI tool to generate TypeScript interfaces from Base schemas
  (4 tests, all 14 field types mapped)
- plugins/scheduler/: Scheduled functions with exactly-once semantics,
  retry with backoff, JSVM bindings (8 tests)
- plugins/platform/: Multi-tenant platform with IAM (hanzo.id) auth,
  KMS (kms.hanzo.ai) secrets, tenant isolation via collection prefixes,
  RBAC roles, API key management (7 tests)
- sdk/base-js/: @hanzoai/base TypeScript SDK with reactive queries,
  query deduplication, optimistic updates, state versioning, CRDT client
  (72 smoke tests passing)
- sdk/base-react/: @hanzoai/base-react React hooks (useQuery, useMutation,
  useAuth, useRealtime, useCRDT, usePresence) with useSyncExternalStore
2026-02-27 10:00:24 -08:00
zeekay 4b229fae5b Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	core/record_field_resolver_multi_match.go
#	ui/dist/assets/AuthMethodsDocs-ChShXLwE.js
#	ui/dist/assets/AuthMethodsDocs-Cqvl0T_l.js
#	ui/dist/assets/AuthMethodsDocs-DIqhS7qY.js
#	ui/dist/assets/AuthRefreshDocs-CHakkNnn.js
#	ui/dist/assets/AuthRefreshDocs-DLb1qree.js
#	ui/dist/assets/AuthRefreshDocs-DXgrlMdk.js
#	ui/dist/assets/AuthWithOAuth2Docs-Bl8VRxNv.js
#	ui/dist/assets/AuthWithOAuth2Docs-DVBOel22.js
#	ui/dist/assets/AuthWithOAuth2Docs-I213UiJ7.js
#	ui/dist/assets/AuthWithOtpDocs-B9tL6gIN.js
#	ui/dist/assets/AuthWithOtpDocs-C2PPm9-Z.js
#	ui/dist/assets/AuthWithOtpDocs-qEMoMG3D.js
#	ui/dist/assets/AuthWithPasswordDocs-B8JWDbPL.js
#	ui/dist/assets/AuthWithPasswordDocs-BTHeYJwE.js
#	ui/dist/assets/AuthWithPasswordDocs-D9rqgLpO.js
#	ui/dist/assets/BatchApiDocs-BV4PYYXn.js
#	ui/dist/assets/BatchApiDocs-DXa997am.js
#	ui/dist/assets/BatchApiDocs-Di2Qe2dV.js
#	ui/dist/assets/DeleteApiDocs-C3IINRwz.js
#	ui/dist/assets/DeleteApiDocs-LfmVp4Uf.js
#	ui/dist/assets/DeleteApiDocs-SU4XdGhJ.js
#	ui/dist/assets/EmailChangeDocs-COx1USU5.js
#	ui/dist/assets/EmailChangeDocs-D-qNHT_P.js
#	ui/dist/assets/EmailChangeDocs-DpfXIE_V.js
#	ui/dist/assets/FieldsQueryParam-BYe9ZK-G.js
#	ui/dist/assets/FieldsQueryParam-L8vpHeF4.js
#	ui/dist/assets/FieldsQueryParam-z0dGQ6uY.js
#	ui/dist/assets/ListApiDocs-BCTT-AOz.js
#	ui/dist/assets/ListApiDocs-C0_GwI7k.js
#	ui/dist/assets/ListApiDocs-T9_aO-pW.js
#	ui/dist/assets/PageInstaller-B22bivaN.js
#	ui/dist/assets/PageInstaller-C0BBhyBx.js
#	ui/dist/assets/PageInstaller-IYSwJhZW.js
#	ui/dist/assets/PageOAuth2RedirectFailure-BjbpqlFj.js
#	ui/dist/assets/PageOAuth2RedirectFailure-COyNF79R.js
#	ui/dist/assets/PageOAuth2RedirectFailure-DPmGG9zv.js
#	ui/dist/assets/PageOAuth2RedirectSuccess-6cMXLFAX.js
#	ui/dist/assets/PageOAuth2RedirectSuccess-CdkCarGH.js
#	ui/dist/assets/PageOAuth2RedirectSuccess-DSEIHeQL.js
#	ui/dist/assets/PageRecordConfirmEmailChange-BYW-6ASg.js
#	ui/dist/assets/PageRecordConfirmEmailChange-Bm1CIYvq.js
#	ui/dist/assets/PageRecordConfirmEmailChange-BpaqOT4u.js
#	ui/dist/assets/PageRecordConfirmPasswordReset--wx_u2lI.js
#	ui/dist/assets/PageRecordConfirmPasswordReset-CoeY2Z_C.js
#	ui/dist/assets/PageRecordConfirmPasswordReset-Ptya5bfe.js
#	ui/dist/assets/PageRecordConfirmVerification-6xjF3T0O.js
#	ui/dist/assets/PageRecordConfirmVerification-C1UTIIJh.js
#	ui/dist/assets/PageRecordConfirmVerification-C4LixXvA.js
#	ui/dist/assets/PageSuperuserConfirmPasswordReset-19z2IFg4.js
#	ui/dist/assets/PageSuperuserConfirmPasswordReset-DwNi0ugQ.js
#	ui/dist/assets/PageSuperuserConfirmPasswordReset-SMnDTRNi.js
#	ui/dist/assets/PageSuperuserRequestPasswordReset-BpDW217f.js
#	ui/dist/assets/PageSuperuserRequestPasswordReset-DK63qE6z.js
#	ui/dist/assets/PageSuperuserRequestPasswordReset-bG02qLIM.js
#	ui/dist/assets/PasswordResetDocs-CE67mLC0.js
#	ui/dist/assets/PasswordResetDocs-CHAK0vma.js
#	ui/dist/assets/PasswordResetDocs-Dap-N4rx.js
#	ui/dist/assets/RealtimeApiDocs-BooTSQCb.js
#	ui/dist/assets/RealtimeApiDocs-CoHmYVEx.js
#	ui/dist/assets/RealtimeApiDocs-D7ds3fHt.js
#	ui/dist/assets/VerificationDocs-B42AIoCQ.js
#	ui/dist/assets/VerificationDocs-BS7b11zH.js
#	ui/dist/assets/VerificationDocs-ZhkdFVIl.js
#	ui/dist/assets/ViewApiDocs-BXmRLHZ1.js
#	ui/dist/assets/ViewApiDocs-DM5JJQjh.js
#	ui/dist/assets/ViewApiDocs-DRpxcuJR.js
#	ui/public/fonts/source-sans-pro/source-sans-pro-v18-latin_cyrillic-700.woff2
#	ui/public/fonts/ubuntu-mono/ubuntu-mono-v17-cyrillic_latin-700.woff2
2026-02-22 01:17:16 -08:00
zeekay 86273e0e2c feat: rebrand to Hanzo Base with GeoPoint field support and token management 2026-02-13 22:12:10 -08:00
Gani Georgiev feae3fc76b updated dependencies and golangci-lint to v2 2025-04-12 20:05:21 +03:00
zeekay ef90d0c4c4 Use base 2025-02-10 11:58:49 -06:00
Gani Georgiev 48377c8736 removed the dynamic dashboard path option as it could complicate unnecessary too many things (oauth2 redirects, default email templates, etc.) 2024-11-12 12:32:26 +02:00
Gani Georgiev 7d448041c2 added superuser otp command 2024-11-08 18:04:22 +02:00
Gani Georgiev 9fe6eb31b8 updated comments and pass the dashboard path into the installer 2024-11-06 19:19:16 +02:00
Gani Georgiev 1d4fa61617 merge v0.23.0-rc changes 2024-09-29 21:09:46 +03:00
Gani Georgiev 0fa5c24521 fixed the error reporting of admin update/delete commands 2024-02-06 13:55:08 +02:00
Gani Georgiev ca7a803b2d updated serve command error reporting 2024-01-24 11:06:49 +02:00
Gani Georgiev 6496091cb3 fixed typos and some linter suggestions 2024-01-23 20:56:14 +02:00
Gani Georgiev f93c782f30 added helper admin cmd error message in case the migrations are not initialized yet 2024-01-23 20:13:30 +02:00
Gani Georgiev c66d5c946e updated CHANGELOG and added t.Parallel to some of the tests 2024-01-03 10:58:25 +02:00
Gani Georgiev 02459ae8ab added httpAddr default when domain name is missing 2023-08-25 12:06:24 +03:00
Gani Georgiev d5029fba26 poc of serve domain args 2023-08-25 11:16:31 +03:00
Gani Georgiev 8bbefafc78 return the http.Server instance to allow manual shutdowns 2023-07-16 23:13:15 +03:00
Gani Georgiev a065c35e83 restructered some of the internals and added basic js app hooks support 2023-06-08 17:59:08 +03:00
Gani Georgiev be9b2359f4 removed the legacy temp upgrade command 2023-05-17 18:39:15 +03:00
Gani Georgiev 9c256781b9 added admin console command tests 2023-04-20 23:39:48 +03:00
Gani Georgiev 693b319598 added admin console command 2023-04-20 17:20:56 +03:00
Gani Georgiev 35c0a084bf added apis.Serve helper 2023-04-20 05:06:22 +03:00
Gani Georgiev 39d65a9f9f [#1822] logged the current datetime on server start 2023-02-12 12:41:48 +02:00
Gani Georgiev 5a500692a6 filter enhancements 2023-01-07 22:27:11 +02:00
Gani Georgiev 3ce894b847 updated changelog and ui/dist 2022-12-06 00:32:10 +02:00
Gani Georgiev 472a5b86e3 tweaked automigrate to check for git status and extracted the base flags from the plugins 2022-11-26 22:33:27 +02:00
Gani Georgiev 943c47a441 initial v0.8 pre-release 2022-10-30 10:28:14 +02:00
Gani Georgiev c33d3d6dd7 [#375] fixed windows console color output 2022-09-02 14:42:22 +03:00
Gani Georgiev 5e2620332b updated test db and ui/dist 2022-08-10 20:37:41 +03:00
Gani Georgiev 6095158a51 test deleteMissing with schema changes 2022-08-10 13:22:27 +03:00
Gani Georgiev ae8b24c8d7 call transaction Dao events only after commit, added totalPages to the search response and updated the tests 2022-08-09 16:20:39 +03:00
Gani Georgiev 360e5e2389 updated tests 2022-08-08 19:16:33 +03:00