Documentation
¶
Overview ¶
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 ¶
- func AfterRecordMessage(ctx *context.Context)
- func AuthzFilter(ctx *context.Context)
- func AutoSigninFilter(ctx *context.Context)
- func BalanceGateFilter(ctx *context.Context)
- func CacheControlFilter(ctx *context.Context)
- func CorsFilter(ctx *context.Context)
- func GetEffectiveOrg(ctx *context.Context) string
- func GetSessionUser(ctx *context.Context) *iam.User
- func GetTenantOrgID(ctx *context.Context) string
- func GetTenantProjectID(ctx *context.Context) string
- func GetTenantUserID(ctx *context.Context) string
- func HstsFilter(ctx *context.Context)
- func InitBalanceGate()
- func InitTierCache()
- func PrometheusFilter(ctx *context.Context)
- func RateLimitFilter(ctx *context.Context)
- func RecordMessage(ctx *context.Context)
- func SecureCookieFilter(ctx *context.Context)
- func StaticFilter(ctx *context.Context)
- func TenantContextFilter(ctx *context.Context)
- func V1CloudRewriteFilter(ctx *context.Context)
- func V1IamRewriteFilter(ctx *context.Context)
- type BalanceGate
- type RateLimiter
- type Response
- type Tier
- type TierCache
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AfterRecordMessage ¶
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.
Design: fail-open. If Commerce is unreachable or the user cannot be identified, the request is allowed through. The controller-level balance check in resolveProviderForUser remains as a defense-in-depth backstop.
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 GetEffectiveOrg ¶
GetEffectiveOrg 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 context.
func GetTenantProjectID ¶
GetTenantProjectID returns the project ID from IAM context.
func GetTenantUserID ¶
GetTenantUserID returns the user ID from IAM context.
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 and IAM 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.
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 PrometheusFilter ¶
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 (GetEffectiveOrg), 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. GetEffectiveOrg 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 V1CloudRewriteFilter ¶
V1CloudRewriteFilter rewrites /v1/cloud/* requests to /api/* so the canonical /<version>/<service>/<path> pattern works without duplicating every route in router.go.
Example: /v1/cloud/get-stores → /api/get-stores
func V1IamRewriteFilter ¶ added in v1.789.0
V1IamRewriteFilter canonicalizes the organized auth namespace /v1/iam/<account> → /v1/<account> for the account surface, so /v1/iam/ is the ONE way the consoles reach auth while the proven authz/balance gates keep operating unchanged on the canonical path (one policy, zero duplication).
Mirrors V1CloudRewriteFilter; registered FIRST in the BeforeRouter chain so AutoSigninFilter, BalanceGateFilter and AuthzFilter all see the canonical path.
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 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 "hk-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.