Documentation
¶
Overview ¶
Package world mounts the Hanzo Cloud "World" news data plane: a per-org, per-project intelligence feed that normalizes GDELT + host-allowlisted RSS/Atom into one NewsItem stream, applies the project's keyword/region/source filter, and serves it over REST + SSE. It is the Go backend for the World monitor frontend (hanzoai/world), replacing that app's Vercel edge functions (api/gdelt-doc.js, api/rss-proxy.js) with an org-scoped, in-binary subsystem.
Surface (all org/project-scoped; /v1 only):
GET /v1/world/news merged, filtered, freshest-first feed -> {items:[…]}
GET /v1/world/pipeline per-project pipeline config (read) -> {…}
PUT /v1/world/pipeline per-project pipeline config (write) -> {…}
GET /v1/world/stream SSE live refresh (ZAP-native) -> event: news
TENANT ISOLATION is enforced SERVER-SIDE on every request. The (org, project) tuple is principal.Tenant + principal.Project (the values SanitizeIdentity minted from the VALIDATED bearer, HIP-0026) — never a query param, body, or client header. Every store statement carries `WHERE org=? AND project=?`; the SSE bus filters on org and the stream loop drops other projects. A request with no validated principal is a 403.
SECURITY. The RSS fetcher is an SSRF boundary: a feed URL's host must be in the ported rss-proxy.js allowlist (allowlist.go), enforced at BOTH the PUT write boundary and at fetch time, including on redirect targets (client CheckRedirect).
Order 142 binds /v1/world/* ahead of the AI /v1/* catch-all (150).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Filters ¶
type Filters struct {
Regions []string `json:"regions"`
Keywords []string `json:"keywords"`
Sources []string `json:"sources"`
}
Filters narrows the merged news stream. Each axis is an OR-set of terms; a non-empty axis is an AND predicate against the item (empty axis = pass-through). Keywords ALSO seed the GDELT queries, so it is both a fetch input (fresh keyword-matched articles) and a post-merge filter.
type NewsItem ¶
type NewsItem struct {
Source string `json:"source"`
Title string `json:"title"`
Link string `json:"link"`
PubDate string `json:"pubDate"` // RFC3339 UTC, or "" when the upstream gave no parseable date
Lang string `json:"lang,omitempty"`
Image string `json:"image,omitempty"`
Tone string `json:"tone,omitempty"`
}
NewsItem is the normalized, source-agnostic shape every upstream (GDELT, RSS, Atom) is projected into and the wire contract for GET /v1/world/news.
type Pipeline ¶
type Pipeline struct {
Org string
Project string
Feeds []string
Filters Filters
CreatedAt int64
UpdatedAt int64
}
Pipeline is the persisted per-(org,project) news pipeline config. Feeds are host-allowlisted RSS/Atom URLs; Filters narrows the merged result.
type PipelineStore ¶
type PipelineStore struct {
// contains filtered or unexported fields
}
PipelineStore is the world pipeline metastore over one SQLite file ({DataDir}/world.db). Tenancy is the (org, project) key.
func (*PipelineStore) Close ¶
func (s *PipelineStore) Close() error
Close closes the underlying database.