Documentation
¶
Overview ¶
Copyright 2023-2025 Hanzo AI Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Package routers @APIVersion 1.70.0 @Title Hanzo Cloud RESTful API @Description Swagger Docs of Hanzo Cloud Backend API @Contact cloud@hanzo.ai @SecurityDefinition AccessToken apiKey Authorization header @Schemes https,http @ExternalDocs Find out more about Hanzo Cloud @ExternalDocsUrl https://hanzo.ai/cloud
Index ¶
- Variables
- func AfterRecordMessage(ctx *web.Context)
- func AssertOperationIDsUnique() error
- func AuthAvailableFilter(ctx *web.Context)
- func AuthzFilter(ctx *web.Context)
- func AutoSigninFilter(ctx *web.Context)
- func BalanceGateFilter(ctx *web.Context)
- func CacheControlFilter(ctx *web.Context)
- func CorsFilter(ctx *web.Context)
- func GetOrg(ctx *web.Context) string
- func GetSessionUser(ctx *web.Context) *iam.User
- func GetTenantOrgID(ctx *web.Context) string
- func GetTenantProjectID(ctx *web.Context) string
- func GetTenantUserID(ctx *web.Context) string
- func HstsFilter(ctx *web.Context)
- func InitBalanceGate()
- func InitTierCache()
- func InstallFilters()
- func OpenAPIPaths() map[string]any
- func OpenAPIPathsSorted() []string
- func PrometheusFilter(ctx *web.Context)
- func Prose() map[string]Doc
- func RateLimitFilter(ctx *web.Context)
- func RecordMessage(ctx *web.Context)
- func SecureCookieFilter(ctx *web.Context)
- func StaticFilter(ctx *web.Context)
- func TenantContextFilter(ctx *web.Context)
- func TrafficTapFilter(ctx *web.Context)
- type BalanceGate
- type Doc
- type RateLimiter
- type Response
- type Tier
- type TierCache
Constants ¶
This section is empty.
Variables ¶
var App = web.NewRouter()
App is the ai runtime's HTTP router: every /v1 route registers on it here, the filter chain is inserted at composition time, and the runtime serves it directly. Routes are explicit; there is no annotation-based registration.
Functions ¶
func AfterRecordMessage ¶
func AssertOperationIDsUnique ¶ added in v1.831.12
func AssertOperationIDsUnique() error
AssertOperationIDsUnique reports a duplicate operationId, which every code generator turns into a duplicate method name and most turn into a silent overwrite.
func AuthAvailableFilter ¶ added in v1.832.10
AuthAvailableFilter refuses every request while this process cannot validate a bearer token, and is the ONE place that decision is made.
It runs BEFORE any filter that reads a token (AutoSignin, Balance, Tenant, Authz), so no downstream code ever sees the difference between "this token is invalid" and "no cert was ever established". That difference is the whole point: the two look identical at a token-parsing call site, and treating the second as the first is what once left the service Running and answering 401 to everything, including free routes, with no crashloop and no alert to catch it.
503, not 401. A 401 says "your credential is wrong" to a caller whose credential is fine, invites a client to discard a good token and re-authenticate, and reads as normal traffic on every dashboard. 503 says the honest thing — the service cannot answer right now — and Retry-After tells a client when to come back.
It is deliberately NOT a readiness probe. A probe failure would take the pod out of service entirely; identity being briefly unreachable should cost the requests that need identity, not the process. Requests are refused while it is down and served again on the first attempt that succeeds, with no restart.
func AuthzFilter ¶
func AutoSigninFilter ¶
func BalanceGateFilter ¶
BalanceGateFilter is a Beego BeforeRouter filter that checks whether the requesting user has a positive Commerce balance before allowing paid API requests to proceed. It runs after AutoSigninFilter (which sets session users for legacy auth paths) and handles its own user resolution for JWT and IAM API key auth paths.
Posture: fail-CLOSED on balance, never on money. When billing is unconfigured (no gate) or the billing subject cannot be identified, the request passes to the downstream auth/controller layer, which re-checks (identity is that layer's job). When the subject IS identified, a positive spendable balance is REQUIRED: a known-insufficient balance is denied 402 (add credits), and a balance that cannot be verified is denied 503 (retry) — both deny. AI is prepaid; a billing-backend outage becomes a retryable 503, never free inference.
func CacheControlFilter ¶
CacheControlFilter adds Cache-Control headers to prevent caching of sensitive API endpoints This ensures that sensitive data (like passwords, user chats, messages) are not cached by intermediary proxies, SSL terminators, or browsers
func CorsFilter ¶
func GetOrg ¶ added in v1.804.1
GetOrg resolves the organization for data-scoping in filters from the VERIFIED request principal — never a raw client header.
On the direct (non-gateway) ingress the X-Org-Id header is fully client-controlled, so trusting it would let any caller act as any org (cross-tenant read/write + billing attribution). It is honored ONLY when it matches the authenticated principal's own org, or the principal is a global admin (cross-org platform access). A non-admin can never escape their own org via a header; an unauthenticated caller's header is ignored entirely.
Behind the gateway the injected X-Org-Id equals the JWT owner, so this resolves identically — the gateway path is unaffected.
func GetTenantOrgID ¶
GetTenantOrgID returns the org from IAM web.
func GetTenantProjectID ¶
GetTenantProjectID returns the project ID from IAM web.
func GetTenantUserID ¶
GetTenantUserID returns the user ID from IAM web.
func HstsFilter ¶
HstsFilter adds HTTP Strict Transport Security header to HTTPS responses This ensures browsers only access the website using HTTPS
func InitBalanceGate ¶
func InitBalanceGate()
InitBalanceGate reads Commerce connection parameters from app config and creates the balance gate. Must be called once during startup. If Commerce is not configured, the gate is not created and BalanceGateFilter is a no-op. IAM connection parameters are NOT read here: key resolution goes through the one resolver (controllers.GetUserByAccessKey), which owns that config.
func InitTierCache ¶
func InitTierCache()
InitTierCache reads Commerce connection parameters from app config and creates the tier cache. Must be called once during startup. If Commerce is not configured (no commerceEndpoint), the cache is not created and DefaultTierFunc falls back to env-var overrides or TierZenFree.
func InstallFilters ¶ added in v1.822.2
func InstallFilters()
InstallFilters inserts the request filter chain on App in order: twelve BeforeRouter filters (CORS, the traffic tap, security headers, rate limit, auto-signin, the balance gate, static, tenant, authz, prometheus and message recording) and two AfterExec filters (message recording and the secure-cookie writer). It is idempotent, so the runtime and the route tests share one wiring.
There are no path-rewriting filters here any more. Two used to lead the chain: /v1/cloud/* → /v1/* rewrote EVERY route into a second address, and /v1/iam/* did the same for the four account endpoints. Between them a single endpoint answered at three URLs, each one a place a policy could be applied inconsistently. Resources now live at exactly one address, generated from the table in resources.go — so there is nothing left to rewrite.
func OpenAPIPaths ¶ added in v1.831.12
OpenAPIPaths returns the OpenAPI 3.1 Path Item Objects for every route the resource table generates, keyed by path. The result is deterministic: maps are emitted in sorted order by the caller, and nothing here reads the clock, the environment, or a random source.
func OpenAPIPathsSorted ¶ added in v1.831.12
func OpenAPIPathsSorted() []string
OpenAPIPathsSorted returns the paths in a stable order, so a re-render produces byte-identical output and the drift test compares cleanly.
func PrometheusFilter ¶
func Prose ¶ added in v1.832.8
Prose is the sentence for every route App registers, keyed "METHOD /path" with the path in OpenAPI's `{name}` spelling.
The key carries the verb AS REGISTERED, "*" included: a route mapped "*" is one handler answering every method, so every method a projection chooses to publish there inherits that one handler's sentence. Expanding the star here would be this package deciding which verbs somebody else's document lists, which is not its question.
Both halves of the surface are here because both are described at their own source and neither is described twice: the resource half by routers/openapi.go, from the same table in resources.go that registers it, and the hand-written half by the doc comment on the handler.
func RateLimitFilter ¶
RateLimitFilter is a Beego BeforeRouter filter that enforces per-key rate limits on API endpoints. It extracts the API key from the Authorization header (Bearer token) or X-API-Key header.
Rate-limited paths: /v1/messages, /v1/messages, and other /v1/ endpoints that carry a bearer token. Excluded: health, metrics, models (read-only), static, UI routes.
func RecordMessage ¶
func SecureCookieFilter ¶
SecureCookieFilter ensures session cookies have the Secure flag set This is necessary when running behind a reverse proxy that handles HTTPS
func StaticFilter ¶
func TenantContextFilter ¶
TenantContextFilter captures IAM identity context for downstream scoping and observability. The org is taken from the VERIFIED principal (GetOrg), NOT the raw X-Org-Id header: on the direct ingress that header is client-controlled, so storing it verbatim would let any caller spoof a tenant. GetOrg honors the header only for the principal's own org (or a global admin), so the stored org is always the caller's real tenant.
func TrafficTapFilter ¶ added in v1.817.0
TrafficTapFilter is a BeforeRouter tap that folds each genuine inbound /v1 API request into the in-process traffic aggregate (object.GlobalTraffic), keyed by the EDGE-supplied geo (Cloudflare CF-IPCountry + optional CF-Region-Code) and a coarse service class derived from the path. It powers the public world.hanzo.ai live- traffic globe.
PRIVACY (load-bearing): it reads ONLY the country/region geo headers. It never reads CF-Connecting-IP or any client IP, never hashes anything, and hands the aggregate nothing but (country, region, service) — Record has no IP parameter to pass one to. It is a pure side effect: it never writes a response, never blocks, never errors, and returns immediately, so its position in the filter chain cannot affect any request's outcome.
Types ¶
type BalanceGate ¶
type BalanceGate struct {
// contains filtered or unexported fields
}
BalanceGate enforces a positive spendable balance before paid requests. The balance itself lives in the shared object.BalanceLedger — the ONE source of truth also used by the controller debit path to reserve (before a request) and settle (after). Reading the ledger here makes the gate reservation-aware and reflects local settles immediately, so the cache window can never serve a stale-positive balance after the funds are spent. The gate adds only its own freshness scheduling (async refresh from Commerce) and identity resolution.
type Doc ¶ added in v1.832.8
type Doc struct{ Summary, Description string }
Doc is one operation's prose: the opening sentence, and the whole comment.
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter tracks per-key rate limiters with automatic cleanup of stale entries.
func InitRateLimiter ¶
func InitRateLimiter(tierFunc func(string) Tier) *RateLimiter
InitRateLimiter creates the global rate limiter. Must be called once during startup (before beego.Run). Returns the instance so the caller can call Stop() on shutdown.
func NewRateLimiter ¶
func NewRateLimiter(tierFunc func(string) Tier, cleanupInterval time.Duration) *RateLimiter
NewRateLimiter creates a RateLimiter that starts a background goroutine to evict stale entries every cleanupInterval. The tierFunc callback resolves an API key to its Tier; pass nil to always use TierZenFree.
func (*RateLimiter) Allow ¶
func (rl *RateLimiter) Allow(apiKey string) bool
Allow checks whether a request from the given API key should be permitted. It returns true if the request is within the rate limit.
func (*RateLimiter) Metrics ¶
func (rl *RateLimiter) Metrics() (allowed, denied uint64)
Metrics returns the current rate limit hit/pass counters.
func (*RateLimiter) RetryAfter ¶
func (rl *RateLimiter) RetryAfter(apiKey string) int
RetryAfter returns the number of seconds until the next token is available for the given API key. Returns 0 if the key has no entry.
func (*RateLimiter) Stop ¶
func (rl *RateLimiter) Stop()
Stop terminates the background cleanup goroutine.
type Tier ¶
type Tier string
Tier represents an API usage tier with associated rate limits. All tiers follow the "zen-*" naming convention as the canonical identifier.
func DefaultTierFunc ¶
DefaultTierFunc resolves a rate-limit key to a Tier using a three-level lookup. The key is the IAM org slug (resolved by RateLimitFilter via resolveBillingKey) for authenticated traffic, or a raw API key for anonymous traffic — both flow through the same path:
- Static env-var overrides (RATE_LIMIT_TIERS) -- highest priority, for operator-managed mappings. Supports exact and prefix matching (works for both org slugs like "acme=zen-enterprise" and key prefixes like "sk-0d2eb").
- Commerce tier cache -- backed by async lookups to Commerce billing API (GET /v1/billing/tier?user=<org>). On cache hit, the cached tier is returned immediately. On cache miss, TierZenFree is returned and a background goroutine populates the cache so the next request uses the correct tier.
- TierZenFree -- default when no override or cache entry exists.
This function never blocks on network I/O. Commerce lookups happen asynchronously; the worst case is that a new org's first few requests are rate-limited at the free tier until the cache is populated.
Source Files
¶
- auth_available_filter.go
- authz_filter.go
- auto_signin_filter.go
- base.go
- cache_control_filter.go
- cors_filter.go
- filter_balance.go
- filters.go
- finetune_router.go
- hsts_filter.go
- openapi.go
- org_resolver.go
- prometheus_filter.go
- ratelimit.go
- record.go
- resources.go
- router.go
- secure_cookie_filter.go
- static_filter.go
- tenant_context_filter.go
- traffic_filter.go
- wired.go
- wired_gen.go