Documentation
¶
Overview ¶
Package appview implements the ATCR AppView component, which serves as the main OCI Distribution API server. It resolves identities (handle/DID to PDS endpoint), routes manifests to user's PDS, routes blobs to hold services, validates OAuth tokens, and issues registry JWTs. This package provides Viper-based configuration with YAML file support, environment variable overrides, and HTTP server setup for the AppView service.
Index ¶
- func AssetHash(path string) string
- func CacheMiddleware(h http.Handler, maxAge int) http.Handler
- func ComputeAssetHashes(overrides *BrandingOverrides)
- func DIDFromBaseURL(baseURL string) string
- func DomainRoutingMiddleware(registryDomains []string, uiBaseURL string) func(http.Handler) http.Handler
- func ExampleYAML() ([]byte, error)
- func PublicHandler(overrides *BrandingOverrides) http.Handler
- func PublicRootFiles(overrides *BrandingOverrides) ([]string, error)
- func PublicSubdir(name string, overrides *BrandingOverrides) http.Handler
- func RegisterTheme(name string, fn func() *BrandingOverrides)
- func Templates(overrides *BrandingOverrides) (*template.Template, error)
- type AIConfig
- type AppViewServer
- type AuthConfig
- type BrandingOverrides
- type Config
- type CredentialHelperConfig
- type HealthConfig
- type JetstreamConfig
- type LabelerRefConfig
- type LegalConfig
- type OAuthPostAuthHook
- type ServerConfig
- type TokenPostAuthHook
- type UIConfig
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CacheMiddleware ¶
CacheMiddleware adds Cache-Control headers to static file responses
func ComputeAssetHashes ¶
func ComputeAssetHashes(overrides *BrandingOverrides)
ComputeAssetHashes recomputes cache-busting hashes using the overlay FS. Call this before serving requests if using BrandingOverrides.
func DIDFromBaseURL ¶
DIDFromBaseURL derives a did:web identifier from a base URL. Per the did:web spec, non-standard ports are percent-encoded. Examples:
"https://atcr.io" → "did:web:atcr.io" "http://localhost:5000" → "did:web:localhost%3A5000"
func DomainRoutingMiddleware ¶
func DomainRoutingMiddleware(registryDomains []string, uiBaseURL string) func(http.Handler) http.Handler
DomainRoutingMiddleware enforces three-tier domain routing:
- UI domain (BaseURL hostname): serves web UI, auth, and static assets. Blocks /v2/* with an OCI UNSUPPORTED error — registry API lives on the dedicated registry domain(s).
- Registry domains: allows /v2/* for Docker clients. Redirects everything else to the UI domain with 307 Temporary Redirect.
- Unknown domains (CDN origins, IPs, etc.): redirects all requests to the UI domain with 307, except /health for load balancer probes.
func ExampleYAML ¶
ExampleYAML returns a fully-commented YAML configuration with default values.
func PublicHandler ¶
func PublicHandler(overrides *BrandingOverrides) http.Handler
PublicHandler returns HTTP handler for static files. Pass nil for default atcr.io behavior.
func PublicRootFiles ¶
func PublicRootFiles(overrides *BrandingOverrides) ([]string, error)
PublicRootFiles returns list of root-level files in static directory (not subdirectories). Pass nil for default atcr.io behavior.
func PublicSubdir ¶
func PublicSubdir(name string, overrides *BrandingOverrides) http.Handler
PublicSubdir returns an http.Handler for a subdirectory within public/. Pass nil for default atcr.io behavior.
func RegisterTheme ¶
func RegisterTheme(name string, fn func() *BrandingOverrides)
RegisterTheme registers a named theme. Call from init() in theme packages.
Types ¶
type AIConfig ¶
type AIConfig struct {
// Anthropic API key for the AI Image Advisor feature.
APIKey string `yaml:"api_key" comment:"Anthropic API key for AI Image Advisor. Also reads CLAUDE_API_KEY env var as fallback."`
}
AIConfig defines AI-powered image advisor settings
type AppViewServer ¶
type AppViewServer struct {
// Router is the chi router. Add routes before calling Serve().
Router chi.Router
// Config is the AppView configuration.
Config *Config
// Database is the read-write SQLite database.
Database *sql.DB
// ReadOnlyDB is the read-only SQLite database connection.
ReadOnlyDB *sql.DB
// SessionStore manages web UI sessions.
SessionStore *db.SessionStore
// DeviceStore manages device authorization flows.
DeviceStore *db.DeviceStore
// OAuthStore manages OAuth session persistence.
OAuthStore *db.OAuthStore
// OAuthServer handles OAuth authorization and callback endpoints.
OAuthServer *oauth.Server
// OAuthClientApp is the indigo OAuth client application.
OAuthClientApp *indigooauth.ClientApp
// Refresher manages OAuth session refresh and caching.
Refresher *oauth.Refresher
// Templates are the parsed HTML templates.
Templates *template.Template
// HealthChecker checks hold service health.
HealthChecker *holdhealth.Checker
// ReadmeFetcher fetches README content for repository pages.
ReadmeFetcher *readme.Fetcher
// TokenIssuer issues registry JWTs (nil if auth is not configured).
TokenIssuer *token.Issuer
// HoldAuthorizer checks hold access permissions.
HoldAuthorizer auth.HoldAuthorizer
// OAuthKey is the P-256 private key used for OAuth client auth and appview service identity.
OAuthKey *atcrypto.PrivateKeyP256
// BillingManager handles Stripe billing and tier updates (nil if billing disabled).
BillingManager *billing.Manager
// WebhookDispatcher dispatches scan webhooks (stored in appview DB).
WebhookDispatcher *webhooks.Dispatcher
// contains filtered or unexported fields
}
AppViewServer is the AppView service with an exposed router for extensibility. Consumers can add routes to Router and hooks before calling Serve().
func NewAppViewServer ¶
func NewAppViewServer(cfg *Config, branding *BrandingOverrides) (*AppViewServer, error)
NewAppViewServer creates a fully-initialized AppView server ready for the consumer to add routes and hooks before calling Serve(). Pass nil for branding to use default atcr.io assets and templates.
func (*AppViewServer) AddOAuthPostAuthHook ¶
func (s *AppViewServer) AddOAuthPostAuthHook(hook OAuthPostAuthHook)
AddOAuthPostAuthHook registers a hook that runs after the default OAuth post-auth logic. Multiple hooks run in registration order.
func (*AppViewServer) AddTokenPostAuthHook ¶
func (s *AppViewServer) AddTokenPostAuthHook(hook TokenPostAuthHook)
AddTokenPostAuthHook registers a hook that runs after the default token post-auth logic. Multiple hooks run in registration order.
func (*AppViewServer) DID ¶
func (s *AppViewServer) DID() string
DID returns the appview's did:web identity derived from its BaseURL.
func (*AppViewServer) Serve ¶
func (s *AppViewServer) Serve() error
Serve starts the HTTP server and blocks until shutdown signal.
type AuthConfig ¶
type AuthConfig struct {
// X.509 certificate matching the JWT signing key.
CertPath string `` /* 137-byte string literal not displayed */
// TokenExpiration is the JWT expiration duration (5 minutes, not configurable)
TokenExpiration time.Duration `yaml:"-"`
// ServiceName is the service name used for JWT issuer and service fields.
// Derived from base URL hostname (e.g., "atcr.io")
ServiceName string `yaml:"-"`
}
AuthConfig defines authentication settings
type BrandingOverrides ¶
type BrandingOverrides struct {
// PublicFS overlays public/ assets (favicons, CSS, images, etc.).
// Files in this FS take priority over the embedded defaults.
PublicFS fs.FS
// TemplatesFS overlays templates/ (nav-brand.html, hero.html, etc.).
// Go's template.ParseFS replaces {{ define "name" }} blocks when
// called twice with the same name, so consumer templates naturally
// override defaults.
TemplatesFS fs.FS
// ExtraCSS is injected as a <style> block after the main stylesheet.
// Useful for DaisyUI color variable overrides without build tooling.
ExtraCSS string
// ExtraFuncMap is merged into the template FuncMap.
ExtraFuncMap template.FuncMap
}
BrandingOverrides allows consumers to customize the AppView's public assets, templates, CSS, and template functions. Pass nil for default atcr.io behavior.
func LookupTheme ¶
func LookupTheme(name string) (*BrandingOverrides, error)
LookupTheme returns BrandingOverrides for a registered theme name. Returns nil for empty name (default branding). Returns an error for unknown theme names.
type Config ¶
type Config struct {
Version string `yaml:"version" comment:"Configuration format version."`
LogLevel string `yaml:"log_level" comment:"Log level: debug, info, warn, error."`
LogShipper config.LogShipperConfig `yaml:"log_shipper" comment:"Remote log shipping settings."`
Server ServerConfig `yaml:"server" comment:"HTTP server and identity settings."`
UI UIConfig `yaml:"ui" comment:"Web UI settings."`
Health HealthConfig `yaml:"health" comment:"Health check and cache settings."`
Jetstream JetstreamConfig `yaml:"jetstream" comment:"ATProto Jetstream event stream settings."`
Auth AuthConfig `yaml:"auth" comment:"JWT authentication settings."`
CredentialHelper CredentialHelperConfig `yaml:"credential_helper" comment:"Credential helper download settings."`
Legal LegalConfig `yaml:"legal" comment:"Legal page customization for self-hosted instances."`
AI AIConfig `yaml:"ai" comment:"AI-powered image advisor settings."`
Labeler LabelerRefConfig `yaml:"labeler" comment:"ATProto labeler for content moderation (DMCA takedowns)."`
Billing billing.Config `yaml:"billing" comment:"Stripe billing integration (requires -tags billing build)."`
Distribution *configuration.Configuration `yaml:"-"` // Wrapped distribution config for compatibility
}
Config represents the AppView service configuration
func DefaultConfig ¶
func DefaultConfig() *Config
DefaultConfig returns a Config populated with all default values (no validation).
func LoadConfig ¶
LoadConfig builds a complete configuration using Viper layered loading: defaults -> YAML file -> environment variables. yamlPath is optional; empty string means env-only (backward compatible).
type CredentialHelperConfig ¶
type CredentialHelperConfig struct {
// TangledRepo is the Tangled repository URL for downloads
TangledRepo string `yaml:"tangled_repo" comment:"Tangled repository URL for credential helper downloads."`
}
CredentialHelperConfig defines credential helper download settings
type HealthConfig ¶
type HealthConfig struct {
// How long to cache hold health check results.
CacheTTL time.Duration `yaml:"cache_ttl" comment:"How long to cache hold health check results."`
// How often to refresh hold health checks.
CheckInterval time.Duration `yaml:"check_interval" comment:"How often to refresh hold health checks."`
}
HealthConfig defines health check and cache settings
type JetstreamConfig ¶
type JetstreamConfig struct {
// Jetstream WebSocket endpoints, tried in order on failure.
URLs []string `yaml:"urls" comment:"Jetstream WebSocket endpoints, tried in order on failure."`
// Sync existing records from PDS on startup.
BackfillEnabled bool `yaml:"backfill_enabled" comment:"Sync existing records from PDS on startup."`
// How often to re-run backfill to catch missed events. Set to 0 to only backfill on startup.
BackfillInterval time.Duration `yaml:"backfill_interval" comment:"How often to re-run backfill to catch missed events. Set to 0 to only backfill on startup."`
// Relay endpoints for backfill — MUST support com.atproto.sync.listReposByCollection. Tried in order on failure.
RelayEndpoints []string `` /* 141-byte string literal not displayed */
}
JetstreamConfig defines ATProto Jetstream settings
type LabelerRefConfig ¶ added in v0.1.3
type LabelerRefConfig struct {
// DID or URL of the labeler service for content moderation.
DID string `yaml:"did" comment:"DID or URL of the ATProto labeler (e.g., did:web:labeler.atcr.io). Empty disables label filtering."`
}
LabelerRefConfig defines the connection to an ATProto labeler service.
type LegalConfig ¶
type LegalConfig struct {
// Organization name for legal pages. Defaults to ClientName.
CompanyName string `yaml:"company_name" comment:"Organization name for Terms of Service and Privacy Policy. Defaults to server.client_name."`
// Governing law jurisdiction for legal terms.
Jurisdiction string `yaml:"jurisdiction" comment:"Governing law jurisdiction for legal terms."`
}
LegalConfig defines legal page customization for self-hosted instances
type OAuthPostAuthHook ¶
OAuthPostAuthHook is called after the default OAuth post-auth logic (profile creation, avatar fetch, crew registration). Hooks added after NewAppViewServer but before the first request work correctly.
type ServerConfig ¶
type ServerConfig struct {
// Listen address for the HTTP server.
Addr string `yaml:"addr" comment:"Listen address, e.g. \":5000\" or \"127.0.0.1:5000\"."`
// Public-facing URL for OAuth callbacks and JWT realm.
BaseURL string `yaml:"base_url" comment:"Public-facing URL for OAuth callbacks and JWT realm. Auto-detected if empty."`
// DID of the default hold service for blob storage.
DefaultHoldDID string `yaml:"default_hold_did" comment:"DID of the hold service for blob storage, e.g. \"did:web:hold01.atcr.io\" (REQUIRED)."`
// Allows HTTP (not HTTPS) for DID resolution.
TestMode bool `yaml:"test_mode" comment:"Allows HTTP (not HTTPS) for DID resolution and uses transition:generic OAuth scope."`
// Display name shown on OAuth authorization screens.
ClientName string `yaml:"client_name" comment:"Display name shown on OAuth authorization screens."`
// Short name used in page titles and browser tabs.
ClientShortName string `yaml:"client_short_name" comment:"Short name used in page titles and browser tabs."`
// Separate domains for OCI registry API. First entry is the primary (used for JWT service name and UI display).
RegistryDomains []string `` /* 147-byte string literal not displayed */
// DIDs of holds this appview manages billing for.
ManagedHolds []string `yaml:"managed_holds" comment:"DIDs of holds this appview manages billing for. Tier updates are pushed to these holds."`
}
ServerConfig defines server settings
type TokenPostAuthHook ¶
type TokenPostAuthHook func(ctx context.Context, did, handle, pdsEndpoint, accessToken string) error
TokenPostAuthHook is called after the default token post-auth logic (profile creation). Hooks added after NewAppViewServer but before the first request work correctly.
type UIConfig ¶
type UIConfig struct {
// SQLite database path.
DatabasePath string `yaml:"database_path" comment:"SQLite/libSQL database for OAuth sessions, stars, pull counts, and device approvals."`
// Visual theme name (e.g. "seamark"). Empty string uses default atcr.io branding.
Theme string `yaml:"theme" comment:"Visual theme name (e.g. \"seamark\"). Empty uses default atcr.io branding."`
// libSQL sync URL for embedded replicas. Works with Turso cloud or self-hosted libsql-server.
// Leave empty for local-only SQLite mode (selfhost/dev).
LibsqlSyncURL string `` /* 152-byte string literal not displayed */
// Auth token for libSQL sync. Required if LibsqlSyncURL is set.
LibsqlAuthToken string `yaml:"libsql_auth_token" comment:"Auth token for libSQL sync. Required if libsql_sync_url is set."`
// How often to sync with the remote libSQL server.
LibsqlSyncInterval time.Duration `yaml:"libsql_sync_interval" comment:"How often to sync with remote libSQL server. Default: 60s."`
// Source code URL displayed in the footer "Source" link.
SourceURL string `yaml:"source_url" comment:"Source code URL displayed in the footer \"Source\" link. Defaults to the upstream ATCR project."`
}
UIConfig defines web UI settings
Directories
¶
| Path | Synopsis |
|---|---|
|
Package db provides the database layer for the AppView web UI, including SQLite schema initialization, migrations, and query functions for OAuth sessions, device flows, repository metadata, stars, pull counts, and user profiles.
|
Package db provides the database layer for the AppView web UI, including SQLite schema initialization, migrations, and query functions for OAuth sessions, device flows, repository metadata, stars, pull counts, and user profiles. |
|
Package handlers provides HTTP handlers for the AppView web UI, including home page, repository browsing, search, user authentication, settings, device management, and API endpoints for the web interface.
|
Package handlers provides HTTP handlers for the AppView web UI, including home page, repository browsing, search, user authentication, settings, device management, and API endpoints for the web interface. |
|
Package holdclient provides client functions for the appview to call hold XRPC endpoints.
|
Package holdclient provides client functions for the appview to call hold XRPC endpoints. |
|
Package holdhealth provides health checking for hold service endpoints.
|
Package holdhealth provides health checking for hold service endpoints. |
|
Package jetstream provides an ATProto Jetstream consumer for real-time updates.
|
Package jetstream provides an ATProto Jetstream consumer for real-time updates. |
|
Package labeler provides a subscription client for consuming labels from an ATProto labeler service.
|
Package labeler provides a subscription client for consuming labels from an ATProto labeler service. |
|
Package licenses provides SPDX license validation and parsing for container image annotations.
|
Package licenses provides SPDX license validation and parsing for container image annotations. |
|
Package middleware provides HTTP middleware for AppView, including authentication (session-based for web UI, token-based for registry), identity resolution (handle/DID to PDS endpoint), and hold discovery for routing blobs to storage endpoints.
|
Package middleware provides HTTP middleware for AppView, including authentication (session-based for web UI, token-based for registry), identity resolution (handle/DID to PDS endpoint), and hold discovery for routing blobs to storage endpoints. |
|
Package ogcard provides OpenGraph card image generation for ATCR.
|
Package ogcard provides OpenGraph card image generation for ATCR. |
|
Package readme provides fetching and rendering of README files from Git hosting platforms.
|
Package readme provides fetching and rendering of README files from Git hosting platforms. |
|
Package routes provides route registration for the AppView web UI and API endpoints.
|
Package routes provides route registration for the AppView web UI and API endpoints. |
|
Package storage implements the storage routing layer for AppView.
|
Package storage implements the storage routing layer for AppView. |
|
Package webhooks provides webhook dispatch and formatting for push and scan notifications.
|
Package webhooks provides webhook dispatch and formatting for push and scan notifications. |