# AGS Account — single sign-on for All Gifted

Central identity + SSO orchestrator for the All Gifted family of apps
(AGS Vocab, AGS Math, the high-school Forma LMS, and future products).

## What this is

- Small Laravel 11 app that owns the canonical user identity (email,
  phone, kudos total, premium status).
- OTP login (email + SMS); no passwords for normal learners.
- Issues short-lived HS256 JWTs to client apps via a dashboard "launch"
  flow. Each app validates the JWT with its own per-app shared secret
  and mints a local session for the user.
- A user signs in once at https://account.allgifted.com and lands
  signed-in inside any registered app with one click.

## What it is not

- Not an OIDC provider. We picked per-app HS256 over RS256 because we
  operate all the client apps ourselves; a leaked secret in one app
  can't forge tokens for another, and there's no third-party client
  flow to worry about. If we ever onboard external apps, RS256 +
  discovery doc is the natural upgrade path.
- Not a user-facing application. The dashboard is the only UI;
  everything else happens inside the client apps.

## Architecture

```
                  ┌─────────────────────────────────┐
                  │   account.allgifted.com         │
                  │   (Laravel + JWT)               │
                  │                                 │
                  │   users  ──┬──→  client_apps    │
                  │            │     jwt_secret     │
                  │   otp_codes│     launch_url     │
                  └────────────┼────────────────────┘
                               │ HS256 JWT, aud=<slug>
                ┌──────────────┼──────────────┐
                ▼              ▼              ▼
        vocab.allgifted   quiz.allgifted   highschool.allgifted
        /api/sso/exchange /api/sso/exchange (Forma — magic-link
        → Sanctum token   → Sanctum token    orchestrator, not JWT)
```

## Tables

| Table | Purpose |
|---|---|
| `users` | Canonical AGS identity. One row per human. |
| `otp_codes` | Pending + consumed OTP attempts (hashed). |
| `client_apps` | Registered client apps + per-app HS256 `jwt_secret`. |
| `personal_access_tokens` | Sanctum tokens (API access for trusted services). |
| `sessions` | Web sessions for the dashboard. |

## Endpoints

| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET    | `/login`               | guest | OTP request form |
| POST   | `/login`               | guest | Send OTP |
| GET    | `/verify`              | guest | Enter code form |
| POST   | `/verify`              | guest | Verify code → sign in |
| POST   | `/logout`              | auth  | Sign out |
| GET    | `/`                    | auth  | Dashboard (app cards) |
| GET    | `/apps/{slug}/launch`  | auth  | Issue JWT + redirect to client's `launch_url` |

Future (slice 2):
- POST `/api/auth/request-otp`, `/api/auth/verify-otp`, `/api/me`
- POST `/api/kudos/ingest` (receives `OutboundKudosSync` payloads)

## Per-app JWT secret rotation

```bash
# On the server, in this app:
mysql -uroot -p"$DBPASS" account \
  -e "UPDATE client_apps SET jwt_secret='<new 96-char hex>' WHERE slug='vocab';"

# In the consumer app:
sed -i "s|^SSO_JWT_SECRET=.*|SSO_JWT_SECRET=<new>|" /var/www/html/vocabapi/.env
cd /var/www/html/vocabapi && php artisan config:cache && systemctl reload apache2
```

## Local development

```bash
composer install
cp .env.example .env
php artisan key:generate
# Edit .env to point DB_DATABASE=account, set MAIL_* if you want real OTPs
php artisan migrate
php artisan db:seed
php artisan serve --host=127.0.0.1 --port=8004
```

The seeder creates Pamela as an admin user and registers vocab / math /
forma with random per-app `jwt_secret`s. Copy each one into the matching
consumer app's `.env` for SSO to round-trip.

## Production

Deployed at `/var/www/html/account` on the same droplet as math + vocab.
Apache vhost + Let's Encrypt. Bootstrap + redeploy scripts in `deploy/`.
Full session log in `2ppaamm/vocab` repo under `docs/SESSION-LOG.md` —
the AGS Account work is journalled there with the rest of the deploy.

## Documentation

- **[docs/SSO.md](docs/SSO.md)** — the complete SSO contract: runtime
  flow with sequence diagram, JWT shape, table schemas on both sides,
  step-by-step checklist for adding a new consumer app, JWT secret
  rotation procedure, privacy & threat model, and design rationale.
