Commit Graph
21 Commits
Author SHA1 Message Date
Evan JarrettandClaude Opus 5 416ba4a2eb serve HTTP/2, and reach it through the load balancer
The admin crew tab renders one row per crew member and gives each row its own
hx-get, so opening it on a hold with 551 crew issues 551 requests. Over
HTTP/1.1 a browser runs at most ~6 per origin, so they queue six at a time and
every other request to the same host queues behind them — which is why loading
the relay page stalls while the crew rows are still resolving, and why the rows
that lose the race come back as "Server error" toasts. The 504 behind that toast
is the load balancer's, not the hold's: the hold logs those requests as 200.

HTTP/2 multiplexes them over one connection and the queue disappears. It does
not make the slow rows fast — that is a separate fix to the per-row identity
lookup — but it stops one slow surface from blocking the rest of the panel.

Two halves, because neither works alone.

The load balancer terminates TLS and speaks cleartext to the origin, so ALPN
never runs on the backend leg and net/http can only answer HTTP/1.1 there. Both
servers now wrap their handler in h2c. The wrapper is opt-in per connection: it
upgrades only for a client sending the h2c preface or "Upgrade: h2c", and passes
everything else through untouched, so an HTTP/1.1 WebSocket upgrade is
unaffected. Verified both directions against this wiring — HTTP/1.1 for a plain
client, HTTP/2.0 with --http2-prior-knowledge.

The frontend's http2_enabled was never set, so it sat at the UpCloud default of
off. That is the half the browser actually sees. timeout_client is now stated
explicitly at its current 10s rather than left implicit: it is the boundary that
produces the 504s above, so it belongs somewhere visible. It is deliberately
unchanged — raising it without fixing the slow lookup would only make a stalled
row stall longer.

The hold's *backend* stays on HTTP/1.1. It serves subscribeRepos over WebSocket
to external relays and to the scanner, and WebSocket over HTTP/2 needs the RFC
8441 Extended CONNECT that Go's http2 server does not implement for Upgrade:.
Routing that backend over h2 would break the firehose. The appview accepts no
inbound WebSocket and has no such constraint. Both origins carry h2c regardless,
so enabling it for the hold later is a config change, not a code change.

createLoadBalancer only runs when there is no LB yet, so properties set there
would reach a new deployment and never an existing one. ensureLBHTTP2 reconciles
them onto an LB that already exists, following ensureLBForwardedHeaders: read
what is there, change only what differs, report what it did, and no-op on a
second run. Backend modifies carry the existing health check back, since
Properties replaces the object wholesale.

Also gofmt: provision.go was not gofmt-clean at HEAD, unrelated to this change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TA9D4DjaLZTvzQ7dJbu4eg
2026-09-08 22:35:35 -05:00
Evan Jarrett a0cc862798 lots of new work for authenticating between appview -> hold. fixed quota handling, improve integration tests for round-trip push/pull/auth/quota checking 2026-05-11 09:20:55 -05:00
Evan Jarrett 98a2cfea59 improve UI around credential helper authorization. have the hold requestCrawl on restart. Update comments that relay_endpoints must suport listreposbycollection 2026-05-08 20:44:04 -05:00
Evan Jarrett 4328eda814 holds now listen for deletes and labelers for takedowns. GC will defer takedowns for a grace period in case of reversal 2026-05-02 23:31:41 -05:00
Evan Jarrett ab66028151 more labeler improvements. standardize did work between labeler and hold. improve sql race conditions on local-only db 2026-05-02 22:13:53 -05:00
Evan Jarrett 136c0a0ecc billing refactor, move billing to appview, move webhooks to appview 2026-02-26 22:28:09 -06:00
Evan Jarrett dc31ca2f35 more work on webhook, implement getMetadata endpoint for appview and link holds to a preferred appview 2026-02-22 22:49:33 -06:00
Evan Jarrett f90a46e0a4 begin implement supporter badges, clean up lexicons, various other changes 2026-02-20 22:12:18 -06:00
Evan Jarrett 27cf78158b vuln scanner fixes, major refactor of the credential helper. 2026-02-17 22:38:25 -06:00
Evan Jarrett 6b87539ef8 update scanner, fix tests, fix dockerfile, move keys to db instead of flat files for appview 2026-02-16 21:04:40 -06:00
Evan Jarrett 2df5377541 more did:plc fixes, more vulnerability scanner fixes 2026-02-15 22:28:36 -06:00
Evan Jarrett 3085fc726b fix bluesky profile not emitting firehose event 2026-02-14 22:09:03 -06:00
Evan Jarrett f340158a79 tweaks related to did:plc, fix bluesky profile creation, update deploys to build locally then scp 2026-02-14 21:00:07 -06:00
Evan Jarrett e3843db9d8 Implement did:plc support for holds with the ability to import/export CARs.
did:plc Identity Support (pkg/hold/pds/did.go, pkg/hold/config.go, pkg/hold/server.go)

  The big feature — holds can now use did:plc identities instead of only did:web. This adds:
  - LoadOrCreateDID() — resolves hold DID by priority: config DID > did.txt on disk > create new
  - CreatePLCIdentity() — builds a genesis operation, signs with rotation key, submits to PLC directory
  - EnsurePLCCurrent() — on boot, compares local signing key + URL against PLC directory and auto-updates if they've drifted (requires rotation key)
  - New config fields: did_method (web/plc), did, plc_directory_url, rotation_key_path
  - GenerateDIDDocument() now uses the stored DID instead of always deriving did:web from URL
  - NewHoldServer wired up to call LoadOrCreateDID instead of GenerateDIDFromURL

  CAR Export/Import (pkg/hold/pds/export.go, pkg/hold/pds/import.go, cmd/hold/repo.go)

  New CLI subcommands for repo backup/restore:
  - atcr-hold repo export — streams the hold's repo as a CAR file to stdout
  - atcr-hold repo import <file>... — reads CAR files, upserts all records in a single atomic commit. Uses a bulkImportRecords method that opens a delta session, checks each record for
  create vs update, commits once, and fires repo events.
  - openHoldPDS() helper to spin up a HoldPDS from config for offline CLI operations

  Admin UI Fixes (pkg/hold/admin/)

  - Logout changed from GET to POST — nav template now uses a <form method=POST> instead of an <a> link (prevents CSRF on logout)
  - Removed return_to parameter from login flow — simplified redirect logic, auth middleware now redirects to /admin/auth/login without query params

  Config/Deploy

  - config-hold.example.yaml and deploy/upcloud/configs/hold.yaml.tmpl updated with the four new did:plc config fields
  - go.mod / go.sum — added github.com/did-method-plc/go-didplc dependency
2026-02-14 15:17:53 -06:00
Evan Jarrett de02e1f046 remove distribution from hold, add vulnerability scanning in appview.
1. Removing distribution/distribution from the Hold Service (biggest change)
  The hold service previously used distribution's StorageDriver interface for all blob operations. This replaces it with direct AWS SDK v2 calls through ATCR's own pkg/s3.S3Service:
  - New S3Service methods: Stat(), PutBytes(), Move(), Delete(), WalkBlobs(), ListPrefix() added to pkg/s3/types.go
  - Pull zone fix: Presigned URLs are now generated against the real S3 endpoint, then the host is swapped to the CDN URL post-signing (previously the CDN URL was set as the endpoint, which
  broke SigV4 signatures)
  - All hold subsystems migrated: GC, OCI uploads, XRPC handlers, profile uploads, scan broadcaster, manifest posts — all now use *s3.S3Service instead of storagedriver.StorageDriver
  - Config simplified: Removed configuration.Storage type and buildStorageConfigFromFields(); replaced with a simple S3Params() method
  - Mock expanded: MockS3Client gains an in-memory object store + 5 new methods, replacing duplicate mockStorageDriver implementations in tests (~160 lines deleted from each test file)
2. Vulnerability Scan UI in AppView (new feature)
  Displays scan results from the hold's PDS on the repository page:
  - New lexicon: io/atcr/hold/scan.json with vulnReportBlob field for storing full Grype reports
  - Two new HTMX endpoints: /api/scan-result (badge) and /api/vuln-details (modal with CVE table)
  - New templates: vuln-badge.html (severity count chips) and vuln-details.html (full CVE table with NVD/GHSA links)
  - Repository page: Lazy-loads scan badges per manifest via HTMX
  - Tests: ~590 lines of test coverage for both handlers
3. S3 Diagnostic Tool
  New cmd/s3-test/main.go (418 lines) — tests S3 connectivity with both SDK v1 and v2, including presigned URL generation, pull zone host swapping, and verbose signing debug output.
4. Deployment Tooling
  - New syncServiceUnit() for comparing/updating systemd units on servers
  - Update command now syncs config keys (adds missing keys from template) and service units with daemon-reload
5. DB Migration
  0011_fix_captain_successor_column.yaml — rebuilds hold_captain_records to add the successor column that was missed in a previous migration.
6. Documentation
  - APPVIEW-UI-FUTURE.md rewritten as a status-tracked feature inventory
  - DISTRIBUTION.md renamed to CREDENTIAL_HELPER.md
  - New REMOVING_DISTRIBUTION.md — 480-line analysis of fully removing distribution from the appview side
7. go.mod
  aws-sdk-go v1 moved from indirect to direct (needed by cmd/s3-test).
2026-02-13 15:26:24 -06:00
Evan Jarrett 92c31835e2 implement the ability to promote a hold as a successor as a way to migrate users to a new storage server 2026-02-12 20:14:19 -06:00
Evan Jarrett ac32a98104 clean up GC implementation 2026-02-11 20:44:07 -06:00
Evan Jarrett 7ba42080c5 more admin panel fixes, allow for fallback relays and jetstreams, improve star lexicon to allow for repo_page backlinks 2026-02-09 21:53:02 -06:00
Evan Jarrett d6114cf549 implementation of syft/grype scanner as a separate binary 2026-02-04 09:53:04 -06:00
Evan Jarrett 35f7a47af3 add simple stripe billing implementation for quotas 2026-02-03 21:52:31 -06:00
Evan Jarrett 34f342f637 lots of refactor and cleanup to allow for branding overrides 2026-02-02 22:42:15 -06:00