Documentation
¶
Overview ¶
Package edge is the runtime-mutable store for the cloud edge ("gateway role") policy: the CORS allowlist, the pre-auth per-client-IP flood cap, and the authenticated per-org rate ceiling. It is a LEAF package (stdlib + the Hanzo SQLite driver only, no import of the root cloud package) so BOTH consumers can use it without an import cycle:
- the edge middleware (package cloud, middleware_edge.go / middleware_ratelimit.go) reads the effective policy live, per request, so an operator's change takes effect without a redeploy;
- the /v1/gateway HTTP subsystem (clients/gateway) serves GET/PUT over the SAME store, IAM-scoped.
SCOPES. There are two, keyed by org in one encrypted per-tenant SQLite file:
- PLATFORM policy — the row stored under the admin org (cfg.AdminOrg). It holds the pre-auth edge knobs (CORS origins, per-IP cap + window) that have no tenant at evaluation time (CORS preflight + the anonymous-flood cap run BEFORE identity). Only a SuperAdmin may write it. It is layered over the static boot defaults (env/flags), so an un-provisioned deployment behaves exactly as the static config until an operator PUTs an override.
- PER-ORG policy — a tenant's own row, holding its self-service edge config: OrgRPM (authenticated rate ceiling), CacheTTLSec + CachePaths (edge-cache TTL, default and per-path), and Methods (accepted-method allowlist). An org admin writes its own; a SuperAdmin may write any. An unset field inherits the platform default, then the static default.
Fail-soft: every resolver (Platform/OrgRPM/CacheTTL/Methods) returns the static/platform default on any store error, so a policy-store outage never takes the edge down. Writes fail loud (an unavailable store returns an error to the PUT handler).
Index ¶
- Constants
- type Policy
- type Store
- func (s *Store) CacheTTL(org, path string) int
- func (s *Store) Close() error
- func (s *Store) Effective(org string) Policy
- func (s *Store) Get(ctx context.Context, org string) (Policy, bool, error)
- func (s *Store) Methods(org string) []string
- func (s *Store) OrgRPM(org string) int
- func (s *Store) Platform() Policy
- func (s *Store) Put(ctx context.Context, org string, p Policy) (Policy, error)
- func (s *Store) PutPlatform(ctx context.Context, p Policy) (Policy, error)
Constants ¶
const MaxCacheTTLSec = 7 * 24 * 60 * 60
MaxCacheTTLSec bounds a cache TTL (7 days) so a fat-fingered PUT can't pin a stale edge response indefinitely.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Policy ¶
type Policy struct {
// CORSOrigins is the PLATFORM-scope CORS allowlist EdgeCORS admits: an exact
// origin, a bare host, or a "*.host" wildcard. Writable only by a SuperAdmin —
// CORS is evaluated before identity, so it has no tenant to scope to.
CORSOrigins []string `json:"cors_origins,omitempty"`
// PerIPRPM is the PLATFORM-scope pre-auth flood cap: requests EdgeRateLimit
// admits per WindowSec from one client IP. SuperAdmin-only, same reason.
PerIPRPM int `json:"per_ip_rpm,omitempty"`
// WindowSec is the window PerIPRPM is counted over, in seconds. SuperAdmin-only.
WindowSec int `json:"window_sec,omitempty"`
// OrgRPM is the org's OWN authenticated rate ceiling, requests per minute, as
// ScopeRateLimit enforces it. Unset inherits the platform default, then the
// static boot default.
OrgRPM int `json:"org_rpm,omitempty"`
// CacheTTLSec is the org's default edge-cache TTL for its responses, in seconds;
// 0 means no caching. Unset inherits the platform default.
CacheTTLSec int `json:"cache_ttl_sec,omitempty"`
// CachePaths overrides CacheTTLSec per path PREFIX (key "/v1/models" → seconds).
// The longest matching prefix wins.
CachePaths map[string]int `json:"cache_paths,omitempty"`
// Methods is the allowlist of HTTP methods the edge accepts for this org. Empty
// means all are accepted.
Methods []string `json:"methods,omitempty"`
// UpdatedAt is the unix second this policy row was last written. Server-stamped;
// a client-supplied value is ignored.
UpdatedAt int64 `json:"updated_at,omitempty"`
// UpdatedBy is the validated user id that wrote this policy row. Server-stamped;
// a client-supplied value is ignored.
UpdatedBy string `json:"updated_by,omitempty"`
}
Policy is the edge policy for one scope. Zero-valued fields mean "inherit" (from the static default, then the platform policy) — so a PUT that sets only OrgRPM leaves the platform CORS/per-IP untouched. Every field is ENFORCED by a consumer; there is no stored-but-ignored knob. Every field carries its OWN doc comment rather than sharing a section header, because zipdoc lifts a field's comment into the published schema property and a header lifted onto three fields would document the GROUP where the FIELD goes.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store persists Policy per org to one encrypted SQLite file and resolves the effective platform / per-org policy for the edge middleware, cached with a short TTL. A nil db (SQLite unavailable at boot) degrades to STATIC-ONLY: reads return the static default, writes error — the edge never goes down.
func New ¶
New opens (or creates) {dataDir}/gateway.db and returns a Store layered over the static boot defaults. On any open/migrate error it logs nothing here (the caller owns logging) and returns a static-only Store plus the error, so the caller can wire the edge middleware with a working fallback regardless.
func (*Store) CacheTTL ¶
CacheTTL returns the edge-cache TTL (seconds) for org+path: the org's own longest-matching cache_paths prefix wins, else its default CacheTTLSec, else the platform default, else 0 (no caching). Cached with a short TTL, fail-open (0). The edge cache middleware reads this live, per request, so an operator's PUT takes effect without a redeploy (mirrors OrgRPM / Platform).
func (*Store) Effective ¶
Effective returns the read-back view for org: the platform edge policy (CORS + per-IP + window) with the org's OWN per-org config (rate ceiling, cache TTL / per-path overrides, method allowlist) overlaid. This is what GET /v1/gateway/config returns — a tenant sees the platform edge policy in force plus its own configuration.
func (*Store) Get ¶
Get returns the raw stored policy for org (found=false when none). A static-only store always reports not-found.
func (*Store) Methods ¶
Methods returns the allowlist of HTTP methods the edge accepts for org (nil = all allowed): the org's own list wins, else the platform default. Fail-open (nil). The edge method-guard reads this live.
func (*Store) OrgRPM ¶
OrgRPM returns the authenticated per-org rate ceiling (requests/min) for org: the org's own row wins, else the platform default's OrgRPM, else 0 (no policy limit). Cached with a short TTL, fail-open (0). Called per-request by ScopeRateLimit (post-identity).
func (*Store) Platform ¶
Platform returns the effective PLATFORM policy — the admin-org row merged over the static defaults — cached with a short TTL and fail-open to the static default. Called per-request by EdgeCORS/EdgeRateLimit (pre-identity).
func (*Store) Put ¶
Put upserts the policy for org (merged over any existing row so a partial write is additive) and invalidates the resolver cache. Errors on a static-only store — a write must never silently vanish.
func (*Store) PutPlatform ¶
PutPlatform upserts the PLATFORM policy — the row under the admin org — merged over any existing platform row. This is the ONLY write that may touch the pre-auth edge knobs (CORS, per-IP cap); the /v1/gateway subsystem gates it on SuperAdmin. Targeting the admin org explicitly (not the caller's possibly org-switched X-Org-Id) is what makes a SuperAdmin's platform PUT land on the platform row regardless of which tenant they are currently viewing.