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

View File

@@ -1,4 +1,9 @@
import { schema, table, t } from "spacetimedb/server";
import { schema, table, t, SenderError } from "spacetimedb/server";
// Better Auth OIDC configuration — must match the BETTER_AUTH_URL env var of the auth server.
// SpacetimeDB modules don't have access to process.env, so this is hardcoded.
const BETTER_AUTH_ISSUER = "http://localhost:4000";
const OIDC_AUDIENCE = BETTER_AUTH_ISSUER;
const STARTER_SYSTEM_ID = "solace";
const STARTER_STATION_ID = "solace-prime";
@@ -135,6 +140,29 @@ const spacetimedb = schema({
});
export default spacetimedb;
// ── OIDC Authentication ────────────────────────────────────────────────────────
// Validate incoming JWTs from Better Auth when clients connect.
// SpacetimeDB decodes the JWT automatically; we verify issuer & audience.
export const onConnect = spacetimedb.clientConnected((ctx) => {
const jwt = ctx.senderAuth.jwt;
if (jwt == null) {
throw new SenderError("Unauthorized: JWT is required to connect.");
}
// Restrict to tokens issued by our Better Auth server
if (jwt.issuer !== BETTER_AUTH_ISSUER) {
throw new SenderError(`Unauthorized: Invalid issuer '${jwt.issuer}'.`);
}
// Verify the audience matches our application
if (!jwt.audience.some((aud) => aud === OIDC_AUDIENCE)) {
throw new SenderError(`Unauthorized: Invalid audience '${jwt.audience}'.`);
}
// Client authenticated successfully — sub: jwt.subject, iss: jwt.issuer
});
export const seedWorld = spacetimedb.reducer({}, (ctx) => {
seedStarterWorld(ctx);
writeEvent(ctx, "world_seeded", "Starter system and station are available.");