catalog

package
v1.801.469 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: Apache-2.0 Imports: 24 Imported by: 0

Documentation

Overview

Package catalog is one place to browse every project, app and site built here.

It is the CROSS-ORG discovery lens: the corpus spans orgs, so a project is findable whichever org built it.

It owns no store. The corpus lives in the lexical index (apps/index) — the same store the Meilisearch dialect serves — so relevance, paging, persistence and encryption at rest are the ones the platform already runs. What this package adds is the ONE thing the index cannot express on its own: a corpus that spans orgs.

How that stays safe

The index pins every row to an org and every query to one org. Cross-org discovery is therefore not a weaker filter — it is a SECOND corpus:

PublicOrg ("~catalog")   the published, world-readable catalog. Every caller
                         reads it. Nobody can write it: an org id is minted
                         from a validated IAM owner claim and IAM org slugs
                         begin with an alphanumeric, so no principal can ever
                         BE "~catalog".
the caller's own org     their private projects, read with principal.Org and
                         nothing else — never a request field (HIP-0026).

A customer's private project is a row in their own org's `catalog` index. It cannot appear in another tenant's results because the query that would return it is never run for them. Nothing PUBLISHES over HTTP either: the published corpus is reconciled from sources that are public by construction (sync.go), so no credential exists that could promote a tenant row into it. The swap itself is a call on the internal plane — a socket the edge router does not carry, reachable only from inside this deployment — so "no write route" stays literally true of every surface a caller can reach.

Surface:

GET /v1/catalog   search + browse: ?q= &org= &kind= &archetype= &language=
                  &origin=template|community|third-party|product
                  &template=<parent id>   (lineage: what was forked from it)
                  &forkable=true|false &official=true|false
                  (absent = both; see filter)

origin is the axis the two hanzo.app lanes are cut on — /templates browses origin=template, /community browses origin=community — so they are TWO VIEWS of this one corpus and not two catalogs that can disagree.

There is no write route. The corpus reconciles itself (sync.go), which is why there is no credential that could publish into the published catalog at all.

Index

Constants

View Source
const (
	// OriginTemplate is one of OUR curated starters — the thing you fork FROM.
	OriginTemplate = "template"
	// OriginCommunity is something somebody BUILT — whose, is its Org.
	OriginCommunity = "community"
	// OriginThirdParty is somebody ELSE's work, shown only with its credit.
	OriginThirdParty = "third-party"
	// OriginProduct is our own software: the fleet's repos.
	OriginProduct = "product"
)

The four origins. A row always has exactly one: "nobody said" is the state this file exists to abolish, so Entry.Origin is not omitempty either.

View Source
const (
	// PublicOrg owns the published cross-org corpus. The leading "~" is what
	// makes it unforgeable: IAM org slugs start with an alphanumeric, so this is
	// a name SanitizeIdentity can never mint from a bearer token.
	PublicOrg = "~catalog"
)

Variables

This section is empty.

Functions

func Mount

func Mount(app cloud.Router, deps cloud.Deps) error

Mount wires the lens and starts the corpus reconcile. No store, no DataDir: the corpus is the index's, and the sync is a goroutine, not an endpoint.

Types

type Entry

type Entry struct {
	ID    string `json:"id"`
	Org   string `json:"org"` // hanzo | lux | zoo
	Name  string `json:"name"`
	Title string `json:"title,omitempty"`
	Kind  string `json:"kind"` // repo | site
	// Origin is WHAT THIS IS TO YOU: template | community | third-party | product
	// (origin.go owns the four nouns and derives them). Not omitempty, for the
	// same reason Forkable is not: every row has an answer, and a missing one is
	// exactly the flattening this field exists to end.
	Origin      string `json:"origin"`
	Archetype   string `json:"archetype,omitempty"`
	Language    string `json:"language,omitempty"`
	Description string `json:"description,omitempty"`
	URL         string `json:"url,omitempty"`      // live, if it is deployed
	Repo        string `json:"repo,omitempty"`     // source
	Template    string `json:"template,omitempty"` // lineage, if forked from one
	// Forkable is NOT omitempty: false is an answer here, not a missing field.
	// Omitted, a client could not tell "you cannot fork this" from "nobody said".
	Forkable bool   `json:"forkable"`
	Stars    int    `json:"stars,omitempty"`
	Updated  string `json:"updated,omitempty"`
	// Upstream/License credit the third-party work an entry was published from:
	// the difference between "this org built it" and "somebody else built it and
	// we are showing it to you".
	//
	// WHO built it is Org, above — the account that paid for the project. There
	// was once a separate admin-gated `official` boolean here claiming the same
	// thing, and because it was gated it disagreed: apps Hanzo wrote and hosts
	// were published by a script holding an ordinary org token, so it stayed
	// false on all of them and this directory filed our own work as somebody
	// else's. A field that restates an unforgeable fact can only ever be the
	// wrong copy of it.
	Upstream string `json:"upstream,omitempty"`
	License  string `json:"license,omitempty"`
	// Scope is provenance, not storage: "public" for a row from the published
	// corpus, "org" for one only this caller can see. A UI that cannot tell them
	// apart cannot warn before sharing a link.
	Scope string `json:"scope"`
	// Note is why a row is NOT in the published catalog, set by the admission gate
	// (gate.go) on the sites it holds back. It is the difference between a demo
	// that silently vanished from the public lens and one whose owner can read the
	// reason and fix it. A published row never carries one.
	Note string `json:"note,omitempty"`
}

Entry is one thing the fleet built. The fields are deliberately the four axes discovery is done along (org, archetype, language, forkable) plus the two links that make a hit actionable (URL to see it, Repo to read it).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL