CulverLab / CulverLab/sparcd-exploration

The legacy Java desktop app can still log in through the shard proxy

Open
#258 1 comment 0 reactions 2 assignees Claimed by @Chris-Schnaufer View on GitHub
Dominant language
TypeScript
Stars
6
Forks
3
Avg merge
2d 13h
Merged PRs (30d)
106

Description

The legacy Java desktop app (CulverLab/sparcd, AWS SDK v1) can log in through the shard proxy with the same credentials the web apps use, and then write into the store with its own layout. Since 2026-09-09 the exploration apps are the only reader we support, so the proxy should turn the Java app away with a message that tells the person where to go instead.

## What we know

The Java app never sets a user agent or any custom header. It builds a plain `AmazonS3ClientBuilder` in `Sanimal FX/src/main/java/model/s3/S3ConnectionManager.java` (path style, SigV4 forced), so every request carries the stock SDK string `User-Agent: aws-sdk-java/1.11.642 `. The first call after login is `listBuckets()`, and a failure there lands in `S3ConnectionManager.login()`, which shows an "Authentication failed" JavaFX alert with the full exception text. The SDK parses the S3 XML error body, so whatever we put in `` shows up in that alert as selectable text. The app can open a browser (`Desktop.browse` in `SanimalHomeController`), but nothing in the error path uses it, so a link in the message is copy-and-paste only.

The browser clients go through `SafeS3Client` in `packages/s3-safe/src/index.ts`, which already has a build-step middleware (`stripXIdQueryParam`). A header added there gets signed, so the upstream keeps validating it. The explorer notebook uses the Python `minio` client directly and would need its own change.

The proxy answers CORS preflight itself. The allowed-headers list lives in three places that must stay in sync: `apps/sparcd-shard-proxy/Caddyfile`, the verbatim copy in `deploy/jetstream2/cloud-init.yaml`, and `ALLOW_HEADERS` plus `FORWARD_HEADERS` in `deploy/cloudflare-worker/worker.js`.

## Plan

1. Confirm the headers live. Point the Java app at the JS2 proxy (proxy-03), log in, and read the request in the proxy access log. Expect `User-Agent: aws-sdk-java/...` and no `x-amz-user-agent`.
2. Gate on the User-Agent first. One Caddy matcher on `aws-sdk-java/` inside the `(s3shard)` snippet, before `reverse_proxy`, answering 403 with an S3-style XML body. Zero client changes, and it catches every copy of the Java app in the field.
3. Add a positive header from the web apps. `x-sparcd-client: /` set in the `SafeS3Client` build step, allowed in all three allow-header lists, forwarded by the Worker, and set by the explorer's minio client. Then flip the proxy to reject any non-OPTIONS request without it. This is the durable version, since anything that isn't one of our apps gets the same answer.
4. Custom error body. Something like:

```xml

ClientNotSupported
The SPARC'd desktop app is no longer supported at this endpoint. Use the web app: https://culverlab.github.io/sparcd-exploration/

```

Check in the running Java app that the alert shows the message and the URL intact, and note in the README that the link is plain text there. Decide whether the message should name a shorter, memorable URL.
5. Tests and docs. A `smoke.mjs` check that a request with the Java user agent, and later one without the header, gets the 403 and the `ClientNotSupported` code, while a request with the header succeeds. Add the header as the third client requirement in the shard proxy README "Client side" section.

Open question for the team: the same gate would block `mc`, `rclone` and the AWS CLI for admin work through the proxy. Direct access to the store stays open, so this may be fine, but it should be a deliberate call.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.