Documentation
¶
Overview ¶
Package hold implements the ATCR hold service, which provides BYOS (Bring Your Own Storage) functionality. It includes an embedded PDS for storing captain and crew records, generates presigned URLs for blob storage, and handles authorization based on crew membership. Configuration is loaded via Viper with YAML file support and environment variable overrides.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExampleYAML ¶
ExampleYAML returns a fully-commented YAML configuration with default values. Includes example quota tiers for documentation (defaults have quotas disabled).
func URLFromDIDWeb ¶
URLFromDIDWeb converts a did:web identifier to an HTTPS URL. This is the inverse of the did:web spec encoding:
"did:web:atcr.io" → "https://atcr.io" "did:web:localhost%3A8080" → "https://localhost:8080"
Returns empty string for non-did:web identifiers.
Types ¶
type AdminConfig ¶
type AdminConfig struct {
// Enable the web-based admin panel.
Enabled bool `yaml:"enabled" comment:"Enable the web-based admin panel for crew and storage management."`
}
AdminConfig defines admin panel settings
type CloudMetadata ¶
type CloudMetadata struct {
Region string
}
CloudMetadata contains region info from cloud metadata service
func DetectCloudMetadata ¶
func DetectCloudMetadata(ctx context.Context) (*CloudMetadata, error)
DetectCloudMetadata queries the instance metadata service (169.254.169.254) Currently supports UpCloud. Others can be added via PR.
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."`
Storage StorageConfig `yaml:"storage" comment:"S3-compatible blob storage settings."`
Server ServerConfig `yaml:"server" comment:"HTTP server and identity settings."`
Registration RegistrationConfig `yaml:"registration" comment:"Auto-registration and bootstrap settings."`
Database DatabaseConfig `yaml:"database" comment:"Embedded PDS database settings."`
Admin AdminConfig `yaml:"admin" comment:"Admin panel settings."`
GC gc.Config `yaml:"gc" comment:"Garbage collection settings."`
Quota quota.Config `yaml:"quota" comment:"Storage quota tiers. Empty disables quota enforcement."`
Scanner ScannerConfig `yaml:"scanner" comment:"Vulnerability scanner settings. Empty disables scanning."`
Labeler LabelerConfig `` /* 243-byte string literal not displayed */
// contains filtered or unexported fields
}
Config represents the hold 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).
func (*Config) ConfigPath ¶
ConfigPath returns the path to the YAML configuration file used to load this config. Subsystems (e.g. billing) use this to re-read the same file for extended fields.
type DatabaseConfig ¶
type DatabaseConfig struct {
// Directory for the embedded PDS database.
Path string `yaml:"path" comment:"Directory for the embedded PDS database (carstore + SQLite)."`
// PDS signing key path.
KeyPath string `yaml:"key_path" comment:"PDS signing key path. Defaults to {database.path}/signing.key."`
// DID method for hold identity: "web" (default) or "plc".
DIDMethod string `yaml:"did_method" comment:"DID method: 'web' (default, derived from public_url) or 'plc' (registered with PLC directory)."`
// Explicit DID for this hold. Used for recovery/migration with did:plc.
DID string `` /* 152-byte string literal not displayed */
// PLC directory URL. Only used when did_method is "plc".
PLCDirectoryURL string `yaml:"plc_directory_url" comment:"PLC directory URL. Only used when did_method is 'plc'. Default: https://plc.directory"`
// Rotation key for did:plc (multibase-encoded private key, K-256 or P-256).
RotationKey string `` /* 213-byte string literal not displayed */
// libSQL sync URL for embedded replica mode.
LibsqlSyncURL string `` /* 163-byte string literal not displayed */
// Auth token for libSQL sync.
LibsqlAuthToken string `yaml:"libsql_auth_token" comment:"Auth token for libSQL sync. Required if libsql_sync_url is set."`
// How often to sync with remote libSQL server.
LibsqlSyncInterval time.Duration `yaml:"libsql_sync_interval" comment:"How often to sync with remote libSQL server. Default: 60s."`
}
DatabaseConfig defines embedded PDS database settings
type HoldServer ¶
type HoldServer struct {
// Router is the chi router. Add routes before calling Serve().
Router chi.Router
// PDS is the embedded ATProto PDS. Nil if database path is not configured.
PDS *pds.HoldPDS
// QuotaManager manages storage quotas per tier.
QuotaManager *quota.Manager
// Config is the hold service configuration.
Config *Config
// contains filtered or unexported fields
}
HoldServer is the hold service with an exposed router for extensibility. Consumers can add routes to Router before calling Serve().
func NewHoldServer ¶
func NewHoldServer(cfg *Config) (*HoldServer, error)
NewHoldServer initializes PDS, storage, quota, XRPC handlers, and returns before starting. Consumer can add routes to Router before calling Serve().
func (*HoldServer) Serve ¶
func (s *HoldServer) Serve() error
Serve starts the HTTP server and blocks until shutdown signal.
type LabelerConfig ¶ added in v0.1.3
type LabelerConfig struct {
// DID or URL of the labeler service. Accepts did:web:... (resolved to
// the corresponding HTTPS host) or a raw http/https URL. Empty disables
// labeler integration.
DID string `yaml:"did" comment:"DID or URL of the ATProto labeler (e.g., did:web:labeler.atcr.io). Empty disables labeler integration."`
// Grace window for reversibility. Until a takedown is older than this,
// the GC keeps blobs referenced even though their layer records were
// purged. After this window blobs become eligible for collection.
GraceWindow time.Duration `` /* 202-byte string literal not displayed */
}
LabelerConfig defines labeler subscription settings.
When DID is set, the hold opens a websocket to the labeler's com.atproto.label.subscribeLabels endpoint and only honors labels whose Src matches the same DID. Active takedowns are cached locally with their Cts timestamp; on receipt of a !takedown label the hold immediately purges layer/scan/image-config records for the labeled manifest (or all manifests by the labeled DID for user-level takedowns). Negations drop the cache entry. The GC consults the cache when computing referenced sets so blobs survive a configurable grace window before being collected, preserving reversibility.
type RegistrationConfig ¶
type RegistrationConfig struct {
// DID of the hold captain.
OwnerDID string `yaml:"owner_did" comment:"DID of the hold captain. If set, auto-creates captain and profile records on startup."`
// Allow any authenticated user to join as crew.
AllowAllCrew bool `yaml:"allow_all_crew" comment:"Create a wildcard crew record allowing any authenticated user to join."`
// URL to fetch avatar image from during bootstrap.
ProfileAvatarURL string `yaml:"profile_avatar_url" comment:"URL to fetch avatar image from during bootstrap."`
// Bluesky profile display name. Synced on every startup.
ProfileDisplayName string `yaml:"profile_display_name" comment:"Bluesky profile display name. Synced on every startup."`
// Bluesky profile description. Synced on every startup.
ProfileDescription string `yaml:"profile_description" comment:"Bluesky profile description. Synced on every startup."`
// Post to Bluesky when users push images.
EnableBlueskyPosts bool `yaml:"enable_bluesky_posts" comment:"Post to Bluesky when users push images. Synced to captain record on startup."`
// Deployment region, auto-detected from cloud metadata or S3 config.
Region string `yaml:"region" comment:"Deployment region, auto-detected from cloud metadata or S3 config."`
}
RegistrationConfig defines auto-registration settings
type ScannerConfig ¶
type ScannerConfig struct {
// Shared secret for scanner WebSocket authentication. Empty disables scanning.
Secret string `yaml:"secret" comment:"Shared secret for scanner WebSocket auth. Empty disables scanning."`
// Minimum interval between re-scans of the same manifest. 0 disables proactive scanning.
RescanInterval time.Duration `` /* 206-byte string literal not displayed */
}
ScannerConfig defines vulnerability scanner settings
type ServerConfig ¶
type ServerConfig struct {
// Listen address for the HTTP server.
Addr string `yaml:"addr" comment:"Listen address, e.g. \":8080\" or \"0.0.0.0:8080\"."`
// Externally reachable URL used for did:web identity.
PublicURL string `yaml:"public_url" comment:"Externally reachable URL used for did:web identity (REQUIRED), e.g. \"https://hold.example.com\"."`
// Allow unauthenticated blob reads.
Public bool `yaml:"public" comment:"Allow unauthenticated blob reads. If false, readers need crew membership."`
// DID of successor hold for migration.
Successor string `yaml:"successor" comment:"DID of successor hold for migration. Appview redirects all requests to the successor."`
// Use localhost for OAuth redirects during development.
TestMode bool `yaml:"test_mode" comment:"Use localhost for OAuth redirects during development."`
// Relay endpoints used primarily for proactive scan discovery via
// com.atproto.sync.listReposByCollection. Endpoints listed here MUST
// support listReposByCollection. They are also sent requestCrawl on
// startup (in addition to the built-in known-relay list); endpoints that
// don't implement requestCrawl just 404 silently.
RelayEndpoints []string `` /* 217-byte string literal not displayed */
// DID of the appview this hold is managed by. Resolved via did:web for URL and public key discovery.
AppviewDID string `` /* 140-byte string literal not displayed */
// ReadTimeout for HTTP requests.
ReadTimeout time.Duration `yaml:"read_timeout" comment:"Read timeout for HTTP requests."`
// WriteTimeout for HTTP requests.
WriteTimeout time.Duration `yaml:"write_timeout" comment:"Write timeout for HTTP requests."`
}
ServerConfig defines server settings
func (ServerConfig) AppviewURL ¶
func (s ServerConfig) AppviewURL() string
AppviewURL derives the appview base URL from AppviewDID.
type StorageConfig ¶
type StorageConfig struct {
// S3-compatible access key.
AccessKey string `yaml:"access_key" comment:"S3-compatible access key (AWS, Storj, Minio, UpCloud)."`
// S3-compatible secret key.
SecretKey string `yaml:"secret_key" comment:"S3-compatible secret key."`
// S3 region.
Region string `yaml:"region" comment:"S3 region, e.g. \"us-east-1\". Used for request signing."`
// S3 bucket name.
Bucket string `yaml:"bucket" comment:"S3 bucket for blob storage (REQUIRED). Must already exist."`
// Custom S3 endpoint for non-AWS providers.
Endpoint string `yaml:"endpoint" comment:"Custom S3 endpoint for non-AWS providers (e.g. \"https://gateway.storjshare.io\")."`
// CDN pull zone URL for presigned download URLs.
PullZone string `` /* 184-byte string literal not displayed */
}
StorageConfig holds S3 storage credentials.
func (StorageConfig) S3Params ¶
func (s StorageConfig) S3Params() map[string]any
S3Params returns a params map suitable for s3.NewS3Service.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package admin provides an owner-only web UI for managing the hold service.
|
Package admin provides an owner-only web UI for managing the hold service. |
|
Package db contains a vendored from github.com/bluesky-social/indigo/carstore/sqlite_store.go Source: github.com/bluesky-social/indigo@v0.0.0-20260203235305-a86f3ae1f8ec/carstore/ Reason: indigo's carstore hardcodes mattn/go-sqlite3, which conflicts with go-libsql (both bundle SQLite C libraries and cannot coexist in the same binary).
|
Package db contains a vendored from github.com/bluesky-social/indigo/carstore/sqlite_store.go Source: github.com/bluesky-social/indigo@v0.0.0-20260203235305-a86f3ae1f8ec/carstore/ Reason: indigo's carstore hardcodes mattn/go-sqlite3, which conflicts with go-libsql (both bundle SQLite C libraries and cannot coexist in the same binary). |
|
Package gc implements garbage collection for the hold service.
|
Package gc implements garbage collection for the hold service. |
|
Package labeler provides a labeler subscription client for the hold service.
|
Package labeler provides a labeler subscription client for the hold service. |
|
Package oci provides OCI registry endpoints for the hold service.
|
Package oci provides OCI registry endpoints for the hold service. |
|
Package pds implements a minimal ATProto PDS for the hold service.
|
Package pds implements a minimal ATProto PDS for the hold service. |
|
Package quota provides storage quota management for hold services.
|
Package quota provides storage quota management for hold services. |