A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go
80
fork

Configure Feed

Select the types of activity you want to include in your feed.

update configs, fix foreign key issues

+63 -3
+9 -1
config-appview.example.yaml
··· 39 39 registry_domains: [] 40 40 # Web UI settings. 41 41 ui: 42 - # SQLite database for OAuth sessions, stars, pull counts, and device approvals. 42 + # SQLite/libSQL database for OAuth sessions, stars, pull counts, and device approvals. 43 43 database_path: /var/lib/atcr/ui.db 44 + # Visual theme name (e.g. "seamark"). Empty uses default atcr.io branding. 45 + theme: "" 46 + # libSQL sync URL (libsql://...). Works with Turso cloud or self-hosted libsql-server. Leave empty for local-only SQLite. 47 + libsql_sync_url: "" 48 + # Auth token for libSQL sync. Required if libsql_sync_url is set. 49 + libsql_auth_token: "" 50 + # How often to sync with remote libSQL server. Default: 60s. 51 + libsql_sync_interval: 1m0s 44 52 # Health check and cache settings. 45 53 health: 46 54 # How long to cache hold health check results.
+4
config-hold.example.yaml
··· 86 86 defaults: 87 87 # Tier assigned to new crew members who don't have an explicit tier. 88 88 new_crew_tier: deckhand 89 + # Vulnerability scanner settings. Empty disables scanning. 90 + scanner: 91 + # Shared secret for scanner WebSocket auth. Empty disables scanning. 92 + secret: ""
+15
deploy/upcloud/configs/appview.yaml.tmpl
··· 1 1 version: "0.1" 2 2 log_level: info 3 + log_shipper: 4 + backend: "" 5 + url: "" 6 + batch_size: 100 7 + flush_interval: 5s 8 + username: "" 9 + password: "" 3 10 server: 4 11 addr: :5000 5 12 base_url: "https://seamark.dev" ··· 13 20 ui: 14 21 database_path: "{{.BasePath}}/ui.db" 15 22 theme: seamark 23 + libsql_sync_url: "" 24 + libsql_auth_token: "" 25 + libsql_sync_interval: 1m0s 26 + health: 27 + cache_ttl: 15m0s 28 + check_interval: 15m0s 16 29 jetstream: 17 30 url: wss://jetstream2.us-west.bsky.network/subscribe 18 31 backfill_enabled: true ··· 20 33 auth: 21 34 key_path: "{{.BasePath}}/auth/private-key.pem" 22 35 cert_path: "{{.BasePath}}/auth/private-key.crt" 36 + credential_helper: 37 + tangled_repo: "" 23 38 legal: 24 39 company_name: Seamark 25 40 jurisdiction: State of Texas, United States
+2 -2
deploy/upcloud/configs/cloudinit.sh.tmpl
··· 43 43 npm ci 44 44 go generate ./... 45 45 CGO_ENABLED=1 go build \ 46 - -ldflags="-s -w -linkmode external -extldflags '-static'" \ 47 - -tags sqlite_omit_load_extension -trimpath \ 46 + -ldflags="-s -w" \ 47 + -trimpath \ 48 48 -o bin/{{.BinaryName}} ./cmd/{{.BuildCmd}} 49 49 50 50 # Service user & data dirs
+15
deploy/upcloud/configs/hold.yaml.tmpl
··· 1 1 version: "0.1" 2 2 log_level: info 3 + log_shipper: 4 + backend: "" 5 + url: "" 6 + batch_size: 100 7 + flush_interval: 5s 8 + username: "" 9 + password: "" 3 10 storage: 4 11 access_key: "{{.S3AccessKey}}" 5 12 secret_key: "{{.S3SecretKey}}" ··· 10 17 addr: :8080 11 18 public_url: "https://{{.HoldDomain}}" 12 19 public: false 20 + relay_endpoint: "" 21 + read_timeout: 5m0s 22 + write_timeout: 5m0s 13 23 registration: 14 24 owner_did: "did:plc:pddp4xt5lgnv2qsegbzzs4xg" 15 25 allow_all_crew: true 26 + profile_avatar_url: https://imgs.blue/evan.jarrett.net/1TpTOdtS60GdJWBYEqtK22y688jajbQ9a5kbYRFtwuqrkBAE 16 27 enable_bluesky_posts: false 28 + region: "" 17 29 database: 18 30 path: "{{.BasePath}}" 31 + key_path: "" 19 32 admin: 20 33 enabled: true 21 34 quota: ··· 28 41 quota: 100GB 29 42 defaults: 30 43 new_crew_tier: deckhand 44 + scanner: 45 + secret: ""
+8
pkg/appview/jetstream/processor.go
··· 410 410 if err := json.Unmarshal(recordData, &starRecord); err != nil { 411 411 return fmt.Errorf("failed to unmarshal star: %w", err) 412 412 } 413 + 414 + // Ensure the starred repository's owner exists in the users table 415 + // (the starrer is already ensured by ProcessRecord, but the owner 416 + // may not have been processed yet during backfill or live events) 417 + if err := p.EnsureUser(ctx, starRecord.Subject.DID); err != nil { 418 + return fmt.Errorf("failed to ensure star subject user: %w", err) 419 + } 420 + 413 421 // Upsert the star record (idempotent - won't duplicate) 414 422 // The DID here is the starrer (user who starred) 415 423 // The subject contains the owner DID and repository
+10
pkg/appview/jetstream/processor_test.go
··· 425 425 database := setupTestDB(t) 426 426 defer database.Close() 427 427 428 + // Insert test users (starrer + owner) so EnsureUser finds them without network calls 429 + for _, did := range []string{"did:plc:starrer123", "did:plc:owner123"} { 430 + _, err := database.Exec( 431 + `INSERT INTO users (did, handle, pds_endpoint, last_seen) VALUES (?, ?, ?, ?)`, 432 + did, did+".test", "https://pds.example.com", time.Now()) 433 + if err != nil { 434 + t.Fatalf("Failed to insert test user %s: %v", did, err) 435 + } 436 + } 437 + 428 438 p := NewProcessor(database, false, nil) 429 439 ctx := context.Background() 430 440