52 Commits
Author SHA1 Message Date
zeekay 7b5f02793e The CRM is a module an org installs into its own Base
A module is a named import document, and installing one is a grow:
core.GrowCollections creates what is missing and adds the fields, select
values and indexes an existing collection lacks, in one transaction,
changing nothing that exists. A relation names its collection by name.
Installing twice changes nothing.

modules/crm carries the thirteen collections: people, companies,
opportunities, candidates, applications, lists, list_members, segments,
activities (one row per source id), notes, tasks, attachments and the
org's shared views. POST /v1/modules/{name} installs, GET /v1/modules
lists, both for a superuser or the org's admin, who can never reach a
collection only a superuser manages this way.

The _view* system collections are retired. Nothing read them, and team
views are the ordinary views collection now.
2026-10-18 21:02:29 -07:00
zeekayandHanzo Dev a37196d301 Declare operations on the group that serves them
zip's registration is a verb method on the group now, so an operation reads as
the group answering it rather than a function taking the group, and a route that
is not a typed operation says which method it answers with. The package-level
form is gone, along with the Router interface it existed to accept any target
through.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-17 05:50:27 -07:00
zeekayandHanzo Dev 887f93b7b0 The plugin runtime is its own module
Base is not the only thing that runs plugins. Cloud grew a second goja runtime
— its own shim, its own bundler, its own registry — because the loader and the
runners lived here and there was nothing to import. hanzoai/plugin is that
something, and it implements zip's Module and Loader rather than the private
copies of them that sat beside these runners.

extruntime, gojavm, pyvm and wasmvm move out. jsvm stays, because it is base's
own app scripting rather than a plugin runtime — the two were only ever adjacent.

Their one tie to base was a single call for an unguessable string, and
crypto/rand says that without a dependency.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 12:42:17 -07:00
zeekayandHanzo Dev 10f67d734c Org Bases open under the KMS master key or not at all
The base binary passes IAM_ORGANIZATION as IAMOrg, and plugins/org
reads base/MASTER_KEY_B64 beneath it at Register: 32 bytes, base64.
With KMS configured, Register fails when no org is set, when KMS does
not answer, or when the key is not 32 bytes. No key stored leaves org
Bases unencrypted and logs it; a 404 from the KMS HTTP door reads as a
missing secret.

An encrypted Base needs SQLite to encrypt pages as it writes them, which
only a linked SQLCipher codec does, so Register refuses a master key on a
build without one. Under a key, the connector refuses an org Base file
that is plaintext.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-11 13:58:52 -07:00
zeekayandHanzo Dev 2ceb430a12 Document how to run, extend and upgrade Base
The README quickstart, docs/versions.md, hooks.md, rules.md, config.md
and listeners.md, and examples/hooks-hybrid-search, each command run
against the binary built from examples/base. LLM.md is cut to a current
map with test commands and known problems; threat-model, NETWORK,
SECURITY and CONTRIBUTING are corrected to the code.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-11 10:52:05 -07:00
a6d4cd6491 fix(zap): listen on the HTTP host, not every interface (#52)
Adds --zap / ZAP_ADDR / --no-mdns; the quasar and tasks ZAP nodes bind where asked.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-10 20:03:21 -07:00
zeekayandHanzo Dev 8fab4b95db Base reads its master key from KMS, over the door KMS serves
There were two ways to hold one thing. PRINCIPAL_ENCRYPTION_KEY carried a
32-byte master key through the environment into a Secret beside the pod, and
KMSEndpoint named a KMS that was supposed to hold it. Only the first worked,
because the client spoke ZAP and refused an http endpoint at construction —
and no KMS in this estate serves ZAP. So the deployment set
KMS_URL=http://kms.hanzo.svc, Register returned that refusal, and the env key
was the only path left. A field named Deprecated sat beside it, read through a
two-branch accessor, which is a third spelling of the same value.

Now: one key, one coordinate, one credential.

- httpSecrets implements the existing secrets interface over /v1/kms. The
  transport is a detail behind that interface, which is why adding one is not
  adding a second way to read a secret.
- It authenticates as an IAM application using the client credentials this
  plugin already holds to talk to IAM. One identity per Base, not two.
- The org leads the path on the ZAP side because that segment is the base
  boundary. Over HTTP the org comes from the credential and another tenant's
  secret is unnameable, so the prefix is dropped rather than composed twice.
- PrincipalEncryptionKey, its Deprecated twin and principalKey() are gone. The
  master key is read at Register from base/MASTER_KEY_B64 under the org.
- Absent stays non-fatal: no KMS, or no key stored, runs with encryption off
  exactly as an unset variable did.

Also dropped the default endpoint zap.kms.svc.cluster.local:9999. Nothing
answers there, so it turned "this deployment has no KMS" — which callers handle
— into a transport error on every read. Unset now means unset.

The HTTP-rejection test asserted the belief that caused this; it now asserts
what is true, that the door needs a credential. Added a coordinate test for the
org-segment drop.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-08 11:46:12 -07:00
zeekay d97d3d6276 cloud sql answers where a deployment configured it
Every address the plugin publishes hands out, or acts on, the connection
string that opens a database, and that string carries the PostgreSQL
password the plugin holds. Register now returns on a Config that is not
Enabled, so /v1/cloud-sql and /v1/meta are addresses an unconfigured
process does not answer at rather than addresses it refuses at.

Opt in with CLOUD_SQL_ENABLED=true, the way bootnode and calendar opt in:
an Enabled field, a ConfigFromEnv that reads it, and a Register that
returns early without it.
2026-08-24 05:49:02 -07:00
zeekay 8ef5f14055 functions reach the admin, and the binary can run them
The admin served 22 routes and none was functions, so a Base kept and
served functions nobody could see. /functions is now a page: list,
author, edit, delete, and run one against a JSON payload. It reads
/v1/functions, which is the record path, so the collection's own rules
decide who may write one and who may call one.

The binary could not run them either. apis/functions.go looks a runtime
up by language at call time and examples/base/main.go linked none, so
every call answered "No runtime is linked for js functions" while
apis/functions_test.go passed — that file blank-imports plugins/gojavm
and the shipped binary did not. Measured on the built binary: before,
invoke 500s; after, handler returns its value and base.list reads rows
as its caller. TestBinaryRunsFunctions asks the same question where the
binary is assembled, so a dropped import fails in CI rather than in
production.

The page says what the server said. A function that throws reads as the
500 it is, and base.start answers that this deployment has nowhere to
run work — which is true: the Sandboxes seam is defined and nothing
installs one.
2026-08-21 11:28:19 -07:00
zeekay 146bbe5747 functions: land the half a sandbox reference was already compiled against
49b2d5633 committed apis/functions.go reading Store().Get(StoreKeySandboxes)
and the const it names never landed, so main did not build: the definition and
the plugins/functions retirement were sitting uncommitted beside it. examples
still imported the retired package for the same reason.

This is that half, unchanged from where it was written — the const, the example's
import, and the deletion that was already staged. Nothing about the sandbox
design is decided here; a commit that cannot compile is decided against by the
compiler.
2026-08-13 22:57:33 -07:00
zeekayandHanzo Dev 046526b72a a brand is not an address, so reading takes the shorter one
Minting a token has to address the brand, because IAM stamps the issuer from
the host it was asked on and a relying party that discovered through one brand
refuses a token issued by another. Reading answers about the credential
presented and does not depend on which brand was addressed.

They were one value, so a deployment could only have the brand — every read
left the cluster, crossed the public edge and came back to a pod one hop away,
and naming the pod instead broke minting.

They are two now. The brand stays where it was; the service is named when it
answers somewhere else, and reads take it. A bare address is ZAP.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-13 19:10:13 -07:00
zeekayandHanzo Dev 2be914ad49 one Base needs no upstream, so serving one asks for none
The org plugin is what scopes a Base per organization, and an org is resolved
from identity. So it registers when an IAM endpoint is configured — the same
value the plugin itself requires, rather than a switch beside it. Where no
identity provider is configured there is nothing for a Base to be scoped to,
and this binary serves ONE Base needing no upstream at all.

`make dev` is that path: go run, loopback, ./pb_data. One command to a running
Base for the studio and the /rest/v1 clients to point at.

Multi-tenant deployments are unchanged: they set IAM_ENDPOINT (or IAM_URL)
already, so the plugin registers exactly as before, and cloud links this
package rather than this binary.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-13 13:38:42 -07:00
zeekay d46f495b7b a request reaches the Base of the org its token carries
Every read landed on the shared platform Base whatever org was named. The
per-org files existed and were written by nothing.

Three things were wrong, stacked. The org was taken from the `owner` claim,
which IAM stamps with the org of the APPLICATION a token was minted through, so
a token carrying alpha resolved to whichever org owned the sign-in app. It then
travelled over X-Org-Id, a header the client also sets and this overwrote. And
whichever org it landed on, the resolver opened a dbx pool, set it on the
request as "orgDB", and nothing anywhere read that key — every handler kept
using e.App. Provisioning ran, directories appeared, and the request went to
data.db regardless.

The org is now resolved once, in loadAuthToken, from the membership set
authz.Claims carries, and RequestEvent.App is pointed at that org's Base before
any handler runs. An org's Base is a Base: {DataDir}/orgs/{org}/data.db,
bootstrapped on first use, with its own collections and settings. apis.Bases is
the one lookup from an org to its Base; plugins/org registers it, and a
deployment that registers none has exactly one Base for everybody.

X-Org-Id and the rest of the identity headers are deleted on ingress, because
inbound they are a client asserting an identity. The header is read once first,
as the org a request says it means, and honored only where the token already
carries it — naming any other org answers 403 rather than quietly serving the
caller's own, which reads as an empty Base and is a different, false statement.

The reserved admin org's Base is the process's own, since _superusers, schema,
settings, backups and logs are process-wide. A token with no membership at all
is a machine and is refused rather than handed that Base: its org could only
come from `owner`, and reading that claim is the bug above.

PrincipalIsolation is gone. Registering the plugin is what gives an org a Base;
a deployment with orgs and one shared database is not a shape anyone wants. The
pool manager it gated went with it, having lost its only caller. The org's file
is data.db rather than org.db — the directory already says whose it is.
2026-08-11 11:57:25 -07:00
zeekay e4b1f3c75c a Base is addressed at /v1/bases, and Base stops running a second auth
Two things wore the name "platform" here, and neither is the PaaS at
platform.hanzo.ai. That collision is why "where are my Bases?" had no answer a
person could act on: one prefix, two products, and the one you reached was
whichever you happened to mean.

A Base is what an org gets — its own collections, its own files, its own key —
so the resource a client addresses is /v1/bases. Not /v1/orgs: the org is IAM's
noun and Base does not get a second one. Everything scoped to an org now hangs
off the Base it belongs to (/v1/bases/{id}/config, /creds, /customers), and
compliance moves to /v1/compliance, a sibling of /v1/iam rather than a child of
Base's own resource. The package is `org`, which seven of its files already
were. Nothing addressed the old prefix — no client, no UI, no manifest — so this
renames a surface rather than breaking one.

The auth proxy is DELETED, not renamed. Its five routes reshaped bodies and
forwarded to /v1/iam/login, /signup, /userinfo and /send-verification-code —
which the opaque /v1/iam/{path...} passthrough beside it already reaches. So
Base carried a hand-written login, signup and one-time-code flow whose only job
was to be a second way to reach IAM. Auth is IAM's, and one way is the whole
point of that rule.

The prefix test that already banned /api/ bans this too, so the name cannot come
back: it reads route LITERALS through go/ast, so a comment explaining the ban is
prose and a route is a route. Verified to fail on the exact regression.
2026-08-10 19:18:08 -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
zeekay f3173a023c feat(calendar): reshape scheduling plugin into the Cal.com API-v2 contract
Rename plugins/scheduling -> plugins/calendar and mount under /v1/calendar,
serving the Cal <Booker> atom's endpoint subset — public event, available
slots, advisory slot holds, booking create/read/reschedule/cancel and an
anonymous /me — so cal.hanzo.ai renders Cal's real Booker straight against
native Base.

The reviewed core is preserved verbatim: computeSlots, the isOpenSlot
availability gate, the transactional double-book guard + partial unique index,
and the per-IP/per-host rate limiter (slots_test + redverify_test still pass).

Security decisions live in cal.go: event types resolve by (owner, slug) so the
client-supplied numeric eventTypeId is never trusted for data access; the
public event and /me expose no host email and no raw meeting location (only
revealed to the booking uid holder post-booking); reserve/delete are advisory
holds that never gate the write path.
2026-07-22 13:31:38 -07:00
zeekay db0925bec2 feat(scheduling): booking API over the Base scheduling collections
The public booking backend a booking page (cal.hanzo.ai) talks to, IAM-native:
  GET  /v1/schedule/{owner}/{slug}          — the event type (public)
  GET  /v1/schedule/{owner}/{slug}/slots    — open slots from availability minus
                                              existing bookings + synced calendar
  POST /v1/schedule/{owner}/{slug}/book     — create a booking (conflict re-checked)
  GET  /v1/booking/{uid}                     — view a booking by its opaque uid
  POST /v1/booking/{uid}/cancel              — cancel by uid

Slot computation is pure + tested (weekly windows in the host's tz, buffers,
minimum-notice, conflict exclusion). Bookings are written by the endpoint after
validation. Opt-in via SCHEDULING_ENABLED=true; wired into examples/base.
Builds green; slot tests + boot-migration test pass.
2026-07-22 00:31:53 -07:00
zeekayandHanzo Dev 710ff15151 fix(base): accept IAM_ENDPOINT||IAM_URL alias; align modernc version guard
Docker / docker (push) Blocked by required conditions
Docker / test (push) Waiting to run
gitleaks / scan (push) Waiting to run
release / build (push) Waiting to run
The shipped base binary read only IAM_URL for the platform IAMEndpoint, while
the canonical env (docs, healthy deployments) is IAM_ENDPOINT — a deployment
setting only one spelling would silently misconfigure Base. Resolve both
(IAM_ENDPOINT then IAM_URL; likewise KMS_ENDPOINT then KMS_URL) via a small
envAny helper, matching plugins/platform/kms_helpers.go. One way to configure,
two accepted spellings — no per-deploy config drift.

Also align modernc_versions_check.go's expected constants to the pairing
actually in go.mod (sqlite v1.50.0 / libc v1.72.0) so the benign consistency
WARN stops firing. libc is not semver-stable, so both move in lockstep with
the sqlite tag's go.mod requirement (issue #6136).

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-03 11:41:25 -07:00
4f728e95a2 feat(waitlist): register the waitlist plugin in the shipped base binary + fix go.sum (#19)
Docker / test (push) Waiting to run
Docker / docker (push) Blocked by required conditions
release / build (push) Waiting to run
The waitlist plugin (POST /v1/waitlist/join etc.) existed in plugins/waitlist but
was never registered in examples/base/main.go — the binary that builds
ghcr.io/hanzoai/base. So /v1/waitlist/join 404'd, console2's WAITLIST_URL had
nothing to point at, and the UI showed 'the waitlist is not open on this
deployment yet'. Register it (Enabled:true; Turnstile/admin/rate-limit resolve
from env). It OnBootstrap-creates the waitlists + waitlist_entries collections.

Also fix go.sum: luxfi/[email protected] + luxfi/[email protected] still carried stale
direct-git hashes that mismatch the immutable public proxy the Dockerfile now
uses (finishing the retag-refresh the [email protected] commit started) → base CI was
red. Synced both to the canonical sum.golang.org hashes. Builds + vets clean via
proxy; waitlist route serves.

Co-authored-by: hanzo-dev <[email protected]>
2026-07-01 10:27:24 -07:00
zeekayandGitHub 7dcecb01c9 feat(bootnode): Go port foundation as a Base plugin (5 modules end-to-end) (#15)
Why: consolidate the Python bootnode backend (bootnode/api/, ~100 .py files)
onto Hanzo Base, leveraging Base's IAM client and per-org/per-user tenant
infrastructure instead of reimplementing auth, sessions, and multi-tenancy.
This is the structural foundation + the 5 most-important modules, not the whole
port.

What landed
- plugins/bootnode/: blockchain developer platform mounted under /v1.
  Five modules ported end-to-end:
    1. auth   — multi-network OAuth2 callback (lux/pars/zoo/hanzo share the
                lux-web3 IAM app; client id derived from redirect_uri) + bn_
                project API keys (salted SHA-256, raw key shown once, verified
                in constant time). Accepts IAM JWTs and pk-/sk-/hk- keys by
                reusing github.com/hanzoai/base/iam — no IAM logic duplicated.
    2. team   — org/member CRUD scoped to the caller's project; invited emails
                resolved against IAM (active) or held pending with an invite
                token.
    3. networks — applies bootno.de/v1 Network CRs (white-label brand, tier,
                region, validator fleet). Replaces the Python's kubectl + raw
                nginx-Ingress templating with a declarative CR for the
                bootno.de operator to reconcile.
    4. nodes  — applies bootno.de/v1 NodeFleet CRs (CRD-driven cloud path;
                the Python docker provider was a local-dev concern).
    5. keys   — applies bootno.de/v1 KMSSecret CRs by KMS path. NO plaintext
                key material ever touches this service; the request and
                response carry none, and a guard rejects any private-key field.
- plugins/bootnode/kube/: dependency-free Kubernetes REST client (net/http
  server-side apply). No client-go, no CGO. In-cluster SA or KUBE_APISERVER.
- plugins/commerce/: typed Hanzo Commerce (Square billing) client behind a
  Client interface. bootnode depends on the interface; commerce never depends
  on bootnode/iam.
- 11 SQLAlchemy models -> Base collections (models/collections.go). No `users`
  collection: IAM owns identity; bootnode references IAM user ids as text.
  OrgCluster is the canonical org->k8s-cluster mapping.
- examples/base/main.go: platform plugin now runs PrincipalIsolation="sqlite"
  (per-org + per-user encrypted SQLite); bootnode registered (BOOTNODE_ENABLED).

Modules pending (15, tracked in PR body): chat, zap, billing-http, bundler,
fleets, gas, infra, launch, lux, mpc, nfts, observability, rpc, tokens,
transfers, wallets, webhooks-http. (chains is also ported as a bonus 6th.)

Tests (20 functions, all green incl -race)
- auth: token classification, key gen/hash/verify (tamper + wrong-salt),
  redirect->clientId derivation.
- kube: server-side-apply shape (PATCH + apply-patch+yaml + fieldManager),
  error propagation, 404 get/delete idempotency.
- commerce: disabled no-op, get-or-create (create + existing), usage error
  propagation, immediate cancel.
- workers: HMAC-signed delivery, non-2xx-is-failure, unreachable-is-failure.
- bootnode: full end-to-end against a fake IAM + fake apiserver — /me 401 then
  200, project + bn_ key, team invite/list, Network + NodeFleet CR apply/get,
  KMSSecret plaintext-rejection + apply + status, public chains. Plus
  fail-fast on the insecure default salt against production IAM.

Verified: `go build ./...` exits 0; `go test -race ./plugins/bootnode/...
./plugins/commerce/...` passes; live binary serves /v1/chains (200) and gates
/v1/auth/me, /v1/networks (401); per-org SQLite isolation logged active; all
10 _bootnode_ collections created on boot.

Co-authored-by: zeekay <[email protected]>
2026-06-18 17:16:15 -07:00
zeekay 1e90d21b7c rename JWKS_URL → IAM_KEYS_URL + IAM_ENDPOINT → IAM_URL
Aligns base with the canonical IAM_* env set defined by
hanzoai/kms fe6aca7:
  IAM_URL       — where IAM lives
  IAM_KEYS_URL  — JWKS endpoint

The standalone example in examples/base/main.go now reads
IAM_URL / KMS_URL for endpoint config — drops the
IAM_ENDPOINT / KMS_ENDPOINT alias.

No back-compat fallbacks.
2026-05-11 02:36:22 -07:00
zeekay 955e04b442 infra: standardize ZAP duplex port to 9999
ZAP binary protocol duplex RPC standardizes on :9999 across every
service. Lux validator staking/RPC ports (9630/9631 mainnet, 9650/9651
devnet) are unchanged — those are luxd network protocol ports, not ZAP.

One ZAP port everywhere (was a mix of 9651/9652/9653/9633/9900).
2026-04-25 15:35:01 -07:00
zeekay 4641f13ae7 feat: Base platform — CRDT privacy, React admin, on-chain anchor SDK 2026-03-01 18:00:00 -08:00
zeekay 1d3fe4e9e7 feat: add zap plugin and update IAM integration 2026-03-02 10:09:58 -08:00
zeekay 42520800f8 feat(base): add OpenFaaS functions plugin
Per-tenant serverless function management via OpenFaaS gateway:
- CRUD at /api/functions (deploy, list, get, delete)
- Invocation at /api/functions/{name}/invoke (sync + async)
- Tenant isolation via t-{slug}-{name} namespacing
- _functions system collection for tracking
- Auto-injected env: IAM_URL, STORAGE_URL
2026-03-01 18:38:16 -08:00
zeekay 87701541f5 feat(base): add Cloud SQL plugin for serverless PostgreSQL
Adds plugins/cloudsql with per-tenant database provisioning via Neon,
postgres-meta reverse proxy for schema introspection, and REST API
at /api/cloud-sql/databases. Registers platform + cloudsql plugins
in examples/base/main.go.
2026-03-01 18:14:19 -08:00
zeekay 6759ac456c Rebrand PocketBase imports to Hanzo Base across all Go files
Replace github.com/pocketbase/pocketbase with github.com/hanzoai/base
in 106 Go source files. Keep pocketbase/dbx and pocketbase/tygoja as-is
(upstream dependencies). Add compiled binary to .gitignore. Include
realtime DX design document inspired by Convex patterns.
2026-02-27 09:43:39 -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
Gani Georgiev 0fc158d1c5 added osutils.IsProbablyGoRun 2025-09-06 19:52:51 +03:00
zeekay ef90d0c4c4 Use base 2025-02-10 11:58:49 -06:00
Gani Georgiev ccbd91e861 updated changelog and help texts 2025-01-30 17:35:16 +02:00
Gani Georgiev a327cda446 reduce the default prewarmed jsvm pool size to 15 2024-10-25 12:27:10 +03:00
Gani Georgiev ef46d53314 remind users to call e.Next() in the OnBootstrap hook if the app is still not initilized after the hook trigger 2024-10-06 22:51:39 +03:00
Gani Georgiev 1d4fa61617 merge v0.23.0-rc changes 2024-09-29 21:09:46 +03:00
Gani Georgiev 62ba9d8fb6 fixed graceful shutdown handling 2023-12-08 21:16:48 +02:00
Gani Georgiev c50cf2041d reduced the default prewarmed goja vms to 25 2023-08-22 22:09:33 +03:00
Gani Georgiev d939cf2aa7 updated cron jsvm bindings and generated types 2023-07-16 23:24:10 +03:00
Gani Georgiev 949671737a added jsvm bindings and updateing the workflow to generate the jsvm types 2023-07-11 18:09:55 +03:00
Gani Georgiev 1736f273a2 added hooksPool flag and updated doc comments 2023-07-08 20:02:03 +03:00
Gani Georgiev f453627673 merged jsvm migrations and hooks and updated the ambient TS types location 2023-06-27 14:45:04 +03:00
Gani Georgiev 5085be8f3d bind hooksWatch flag 2023-06-21 21:46:13 +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 48755302c2 added experimental update command 2023-05-17 21:14:12 +03:00
Gani Georgiev 94e68f3444 added --queryTimeout flag 2023-02-23 18:59:23 +02:00
Gani Georgiev 2e5e5f1136 added empty migrations template test and removed publicdir plugin 2022-12-02 12:36:57 +02:00
Gani Georgiev a0e1d08a06 removed git path lookups and updated examples/base .gitignore 2022-11-27 23:21:42 +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 292b500a40 added plugins subpackage and added basic support for js migrations 2022-11-26 09:06:09 +02:00
Gani Georgiev 943c47a441 initial v0.8 pre-release 2022-10-30 10:28:14 +02:00
Gani Georgiev cf6136cf41 [#470] added --pbPublic flag 2022-09-16 11:18:15 +03:00