Replace TS game shell with Bevy/Rust client, add auth service, purge legacy archive

- Replace apps/game (TypeScript/Vite/R3F) with a Bevy 0.16 Rust client
  featuring main menu, star map, and flight states
- Add services/auth: Express + better-auth server with SpacetimeDB
  token exchange endpoint
- Delete archive/legacy-static/ (old JS demos, CSS, assets)
- Update docs pages (architecture, gameplay, roadmap, social, overview)
  to reflect Bevy pivot
- Clean up workspace config: remove apps/game from pnpm workspace,
  update dev scripts, tsconfig, and AGENTS.md files
- Add .vscode/settings.json for Rust tooling
This commit is contained in:
2026-06-04 01:10:02 -04:00
parent 7c93b8a1ae
commit a1717e12db
138 changed files with 7352 additions and 24075 deletions

38
services/auth/src/auth.ts Normal file
View File

@@ -0,0 +1,38 @@
import { betterAuth } from "better-auth";
import Database from "better-sqlite3";
import { jwt } from "better-auth/plugins";
import { oidcProvider } from "better-auth/plugins";
export const auth = betterAuth({
database: new Database("./auth.db"),
baseURL: process.env.BETTER_AUTH_URL ?? "http://localhost:4000",
emailAndPassword: {
enabled: true,
},
session: {
cookieCache: {
enabled: true,
maxAge: 60 * 5, // 5 minutes
},
},
plugins: [
jwt({
// SpacetimeDB will verify JWTs via JWKS
jwks: true,
// Include standard OIDC claims that SpacetimeDB expects
definePayload: async ({ session, user }) => ({
sub: user.id,
email: user.email,
name: user.name,
}),
}),
oidcProvider({
loginPage: "/sign-in",
metadata: {
issuer: process.env.BETTER_AUTH_URL ?? "http://localhost:4000",
},
}),
],
});
export type Auth = typeof auth;

View File

@@ -0,0 +1,53 @@
import express from "express";
import cors from "cors";
import { toNodeHandler, fromNodeHeaders } from "better-auth/node";
import { auth } from "./auth.js";
const app = express();
const PORT = Number(process.env.AUTH_PORT ?? 4000);
app.use(
cors({
origin: [
"http://localhost:5173",
"http://localhost:5174",
"http://localhost:5175",
],
credentials: true,
}),
);
// Mount better-auth handler FIRST — it handles /api/auth/*splat
// Note: do NOT use express.json() before this handler
app.all("/api/auth/*splat", toNodeHandler(auth));
// Mount json middleware only for routes below
app.use(express.json());
// Token exchange endpoint: game client calls this with its session cookie
// and receives a JWT suitable for SpacetimeDB
app.get("/api/auth/spacetimedb-token", async (req, res) => {
const session = await auth.api.getSession({
headers: fromNodeHeaders(req.headers),
});
if (!session) {
return res.status(401).json({ error: "Not authenticated" });
}
// Get a JWT for this session
const jwtResult = await auth.api.getToken({
headers: fromNodeHeaders(req.headers),
});
if (!jwtResult?.token) {
return res.status(500).json({ error: "Failed to generate token" });
}
return res.json({ token: jwtResult.token });
});
app.listen(PORT, () => {
console.log(`[auth] Auth server running on http://localhost:${PORT}`);
console.log(`[auth] OIDC issuer: ${process.env.BETTER_AUTH_URL ?? `http://localhost:${PORT}`}`);
});