Files
at-container-registry/config-hold.example.yaml
T
Evan JarrettandClaude Fable 5.1 0080957a21 remove the runtime test_mode switch; the testmode build tag is the only one
server.test_mode survived the build-tag refactor only to feed five
behavioral branches: the registry's fall-back to the default hold when
the user's hold is unreachable, backfill warning suppression for
external holds, the appview listener close on shutdown, the hold's
relay-crawl skip, and the hold's appview-issuer tolerance. Every one of
them is a "this is a local development build" decision, which is what
the tag already says, and local development has to build with the tag
or nothing resolves. So they read atproto.TestModeBuild now, and the
flag, SetTestMode, IsTestMode, the middleware option, the backfill
constructor parameter, the never-read field on RemoteHoldAuthorizer,
the example and template YAML lines, and the docker-compose env vars
are gone. The registry keeps the fallback as a field seeded from the
constant so the production-path tests can pin it off under the tag.

The 24 SetTestMode calls in tests were dead already: stripping them and
running the affected packages tagged changed nothing.

Tests that resolve a loopback did:web used to t.Fatal naming the tag,
which left a bare `go test ./...` permanently red in five packages.
They now live under `//go:build testmode`: whole-file constraints where
every test needs it, and sibling *_testmode_test.go files holding the
moved tests plus their fixtures where a file mixed. The harness carries
the constraint too, with its package doc in an untagged doc.go so the
package still exists without it. An untagged run compiles those tests
out and passes; make test keeps the tag and runs everything.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UwYzaG3Yy7uA8FbZ5qk3tQ
2026-09-11 11:09:44 -05:00

144 lines
7.0 KiB
YAML

# ATCR Hold Service Configuration
# Generated with defaults — edit as needed.
# Configuration format version.
version: "0.1"
# Log level: debug, info, warn, error.
log_level: info
# Remote log shipping settings.
log_shipper:
# Log shipping backend: "victoria", "opensearch", or "loki". Empty disables shipping.
backend: ""
# Remote log service endpoint, e.g. "http://victorialogs:9428".
url: ""
# Number of log entries to buffer before flushing to the remote service.
batch_size: 100
# Maximum time between flushes, even if batch is not full.
flush_interval: 5s
# Basic auth username for the log service (optional).
username: ""
# Basic auth password for the log service (optional).
password: ""
# S3-compatible blob storage settings.
storage:
# S3-compatible access key (AWS, Storj, Minio, UpCloud).
access_key: ""
# S3-compatible secret key.
secret_key: ""
# S3 region, e.g. "us-east-1". Used for request signing.
region: us-east-1
# S3 bucket for blob storage (REQUIRED). Must already exist.
bucket: ""
# Custom S3 endpoint for non-AWS providers (e.g. "https://gateway.storjshare.io").
endpoint: ""
# CDN pull zone URL for downloads. When set, presigned GET/HEAD URLs use this host instead of the S3 endpoint. Uploads and API calls still use the S3 endpoint.
pull_zone: ""
# HTTP server and identity settings.
server:
# Listen address, e.g. ":8080" or "0.0.0.0:8080".
addr: :8080
# Externally reachable URL used for did:web identity (REQUIRED), e.g. "https://hold.example.com".
public_url: ""
# Allow unauthenticated blob reads. If false, readers need crew membership.
public: false
# DID of successor hold for migration. Appview redirects all requests to the successor.
successor: ""
# Endpoints used for proactive scan discovery. MUST support com.atproto.sync.listReposByCollection. Also sent requestCrawl on startup (best-effort, in addition to built-in known relays).
relay_endpoints:
- https://relay1.us-east.bsky.network
- https://relay1.us-west.bsky.network
# DID of the appview this hold is managed by (e.g. did:web:atcr.io). Resolved via did:web for URL and public key.
appview_did: did:web:172.28.0.2%3A5000
# Read timeout for HTTP requests.
read_timeout: 5m0s
# Write timeout for HTTP requests.
write_timeout: 5m0s
# Auto-registration and bootstrap settings.
registration:
# DID of the hold captain. If set, auto-creates captain and profile records on startup.
owner_did: ""
# Create a wildcard crew record allowing any authenticated user to join.
allow_all_crew: false
# URL to fetch avatar image from during bootstrap.
profile_avatar_url: https://atcr.io/web-app-manifest-192x192.png
# Bluesky profile display name. Synced on every startup.
profile_display_name: Cargo Hold
# Bluesky profile description. Synced on every startup.
profile_description: ahoy from the cargo hold
# Post to Bluesky when users push images. Synced to captain record on startup.
enable_bluesky_posts: false
# Deployment region, auto-detected from cloud metadata or S3 config.
region: ""
# Embedded PDS database settings.
database:
# Directory for the embedded PDS database (carstore + SQLite).
path: /var/lib/atcr-hold
# PDS signing key path. Defaults to {database.path}/signing.key.
key_path: ""
# DID method: 'web' (default, derived from public_url) or 'plc' (registered with PLC directory).
did_method: web
# Explicit DID for this hold. If set with did_method 'plc', adopts this identity instead of creating new. Use for recovery/migration.
did: ""
# PLC directory URL. Only used when did_method is 'plc'. Default: https://plc.directory
plc_directory_url: https://plc.directory
# Rotation key for did:plc in multibase format (starting with 'z'). Generate with: goat key generate. Supports K-256 and P-256 curves. Controls DID identity (separate from signing key).
rotation_key: ""
# libSQL sync URL (libsql://...). Works with Turso cloud, Bunny DB, or self-hosted libsql-server. Leave empty for local-only SQLite.
libsql_sync_url: ""
# Auth token for libSQL sync. Required if libsql_sync_url is set.
libsql_auth_token: ""
# How often to sync with remote libSQL server. Default: 60s.
libsql_sync_interval: 1m0s
# Admin panel settings.
admin:
# Enable the web-based admin panel for crew and storage management.
enabled: true
# Garbage collection settings.
gc:
# Enable nightly garbage collection of orphaned blobs and records.
enabled: false
# Storage quota tiers. Empty disables quota enforcement.
quota:
# Quota tiers ordered by rank (lowest to highest). Position determines rank.
tiers:
- # Tier name used as the key for crew assignments.
name: free
# Storage quota limit (e.g. "5GB", "50GB", "1TB").
quota: 5GB
# Trigger vulnerability scan immediately on push. When false, images are still scanned by background scheduling.
scan_on_push: false
- # Tier name used as the key for crew assignments.
name: deckhand
# Storage quota limit (e.g. "5GB", "50GB", "1TB").
quota: 5GB
# Trigger vulnerability scan immediately on push. When false, images are still scanned by background scheduling.
scan_on_push: false
- # Tier name used as the key for crew assignments.
name: bosun
# Storage quota limit (e.g. "5GB", "50GB", "1TB").
quota: 50GB
# Trigger vulnerability scan immediately on push. When false, images are still scanned by background scheduling.
scan_on_push: true
- # Tier name used as the key for crew assignments.
name: quartermaster
# Storage quota limit (e.g. "5GB", "50GB", "1TB").
quota: 100GB
# Trigger vulnerability scan immediately on push. When false, images are still scanned by background scheduling.
scan_on_push: true
# Default tier assignment for new crew members.
defaults:
# Tier assigned to new crew members who don't have an explicit tier.
new_crew_tier: deckhand
# Vulnerability scanner settings. Empty disables scanning.
scanner:
# Shared secret for scanner WebSocket auth. Empty disables scanning.
secret: ""
# Minimum interval between re-scans of the same manifest. When set, the hold proactively scans manifests when the scanner is idle. Default: 168h (7 days). Set to 0 to disable.
rescan_interval: 168h0m0s
# Labeler subscription settings. When configured, the hold consumes takedown labels from the named labeler and purges affected records on receipt; GC consults the cache to gate blob cleanup. Empty subscribe_url disables.
labeler:
# DID of the ATProto labeler (did:plc:... or did:web:...). Empty disables labeler integration.
did: ""
# Reversibility window for takedowns. Blobs survive this long after a takedown so the action can be reversed. After this window the GC reclaims them. Default: 720h (30 days).
grace_window: 720h0m0s