Skip to content

feat: add public spaces with unauthenticated read endpoints#23

Merged
skgbafa merged 3 commits intomainfrom
feature/public-spaces
Feb 24, 2026
Merged

feat: add public spaces with unauthenticated read endpoints#23
skgbafa merged 3 commits intomainfrom
feature/public-spaces

Conversation

@skgbafa
Copy link
Contributor

@skgbafa skgbafa commented Feb 24, 2026

Summary

  • Add unauthenticated public REST endpoints (GET/HEAD /public/{spaceId}/kv/{key}, GET /public/{spaceId}/kv?prefix=) for spaces named public
  • Public space detection via name-based policy (space_id.name() == "public")
  • Response headers: ETag (blake3), Cache-Control: public, max-age=60, full CORS (Access-Control-Allow-Origin: *)
  • Conditional request support (If-None-Match → 304 Not Modified)
  • Per-IP token bucket rate limiting (default 60 req/min, burst 10)
  • Separate storage quota for public spaces (default 10MB)
  • New [public_spaces] config section

Files changed

  • src/routes/public.rs — new public endpoint handlers
  • src/routes/mod.rs — module declaration
  • src/lib.rs — route mounting and rate limiter state
  • src/config.rs — PublicSpacesConfig struct
  • tinycloud-core/src/db.rs — public KV read methods on SpaceDatabase

Test plan

  • cargo build succeeds
  • cargo clippy -- -D warnings passes
  • Test GET /public/{publicSpaceId}/kv/{key} returns data without auth
  • Test non-public space returns 403
  • Test If-None-Match with matching ETag returns 304
  • Test rate limiting triggers after burst
  • Test CORS headers present on response

…rage quota

Implement the public spaces feature for TinyCloud. Spaces with name "public"
are recognized as public and served via unauthenticated REST endpoints.

- New GET/HEAD/OPTIONS endpoints at /public/<space_id>/kv/<key> and
  /public/<space_id>/kv?prefix=<p> for unauthenticated KV reads
- is_public_space() detection based on space name == "public"
- Per-IP token bucket rate limiter (default 60 req/min, burst 10)
- If-None-Match / ETag conditional request support (304 Not Modified)
- CORS headers (Access-Control-Allow-Origin: *) on all public responses
- Cache-Control: public, max-age=60 on all public responses
- Separate storage quota for public spaces (default 10MB vs regular limit)
- Configurable via [public_spaces] config section
Rocket's PathBuf rejects path segments starting with dots (e.g.
.well-known/profile). Replace PathBuf with a KVKey FromRequest
guard that extracts the key from the raw request URI, and a
RawKeyPath FromSegments type for route matching.
Rocket's PathBuf rejects dot-prefixed path segments like .well-known/
as a security measure. Replace with RawKeyPath (custom FromSegments)
that joins segments without filtering. Also merge duplicate OPTIONS
handlers into a single route to avoid collision.
@skgbafa skgbafa merged commit ce21e65 into main Feb 24, 2026
13 checks passed
@skgbafa skgbafa deleted the feature/public-spaces branch February 24, 2026 20:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant