Skip to content

Faucet Service

The faucet is the platform's sign-up desk. A prospective user hands it an email; it checks the email, creates their account (via the platform service), and — for the free tier — seeds them at the fair-share cap so continuous accrual takes over from there. It emails the user their access token. Small FastAPI app on port 8500, backed by Postgres (creates its own database on first start).

The name is historical — it began as a credit "faucet" that dripped periodic top-ups. Today it's really the signup service; the ongoing top-ups now come from the credit service's fair-share accrual.

It's standalone — it owns its own tables and talks to just one service over HTTP: the platform service (/v1/auth/onboard), which does the actual granting. There's no weekly refill and the faucet no longer talks to the credit service directly — the credit service's fair-share accrual owns ongoing free credits.

Who gets what: free vs paid

Free tier Paid tier
Who University / allowed-domain email (.edu, …) Anyone else
Allowed to sign up? Always Only when open_registration is on
Starting credits Seeded at the fair-share cap + marked accrual_eligible None (buy paid credits via Stripe)
Ongoing credits Continuous fair-share accrual (credit service) —

The faucet's real job is the free tier: verify the student, seed them, and hand accrual the keys. Paid users just get an account.

Signing up

Signup is owned by the platform (POST /v1/auth/signup, verified email). The platform then calls the admin-auth POST /v1/faucet/register to record the user and enforce the registration policy. The faucet issues no tokens; the anonymous /v1/faucet/claim route was removed (#251) because it returned a platform JWT without proof of mailbox ownership.

Ongoing credits come from the credit service's fair-share accrual (documented there), not the faucet.

Admin

All admin endpoints require Authorization: Bearer <ADMIN_TOKEN> and fail closed if the token is unset.

  • Registration toggle (/v1/faucet/pool) — open_registration gates whether non-university emails can sign up.
  • User management (/v1/faucet/users/…) — list users, read one user's status, change their tier, and revoke / restore them. Platform auth reads …/users/{email}/status on every request, so revoking a user here blocks their access everywhere.

Tables

Table Purpose
claims One row per email — last_claim timestamp for the cooldown / claim lock
users Registered users — user_type (free/paid), status (active/revoked)
pool_config Singleton — just open_registration

Endpoints

Method Path Auth What it does
GET /healthz — Health check
POST /v1/faucet/register admin Record a user in the registry (policy-checked); issues no token
GET·PUT /v1/faucet/pool admin Read / toggle open_registration
GET /v1/faucet/users admin List registered users
GET /v1/faucet/users/{email}/status admin One user's status/tier (platform reads this for revocation)
PUT /v1/faucet/users/{email} admin Change a user's tier
POST /v1/faucet/users/{email}/revoke · /restore admin Disable / re-enable an account

Configuration

Variable Default Description
FAUCET_DATABASE_URL — (required) Postgres connection string (DB auto-created if missing)
FAUCET_PORT 8500 Service port
ADMIN_TOKEN — Shared secret for admin + the onboard call
PLATFORM_URL http://platform:8100 Where accounts are created + seeded
ALLOWED_EMAIL_DOMAINS .edu,gmail.com,atomicmail.io Free-tier domains (comma-separated)
CLAIM_COOLDOWN_HOURS ~0.017 (≈1 min) Minimum gap between claims per email
SMTP_HOST/SMTP_PORT/SMTP_USER/SMTP_PASS/SMTP_FROM Brevo defaults Email delivery
CORS_ORIGINS * Allowed origins
RATE_LIMIT_PER_MINUTE 120 Per-IP rate limit

Running & testing

# Unit tests need a Postgres (test compose exposes one on host port 5433):
docker compose -f docker-compose.test.yml --profile faucet up postgres -d
pytest tests/faucet_service/ -v --ignore=tests/faucet_service/test_docker.py

# Full stack for the Docker integration test:
docker compose -f docker-compose.test.yml --profile faucet up --build -d
pytest tests/faucet_service/test_docker.py -v

Coverage: test_claim / test_claim_flows (domain rules, cooldown, tiers), test_claim_concurrency (no double-signup under a race), test_pool (open_registration), test_admin_users (user management), test_endpoints (claim + seed wiring), test_email_verify (SMTP), test_docker (deployed).