Prettier format pending files

This commit is contained in:
Builder.io 2025-11-17 08:47:57 +00:00
parent a4fe444b03
commit e2efadff2d
12 changed files with 159 additions and 67 deletions

View file

@ -185,9 +185,12 @@ export async function linkProviderToPassport(
* Generate a unique username from OAuth data * Generate a unique username from OAuth data
* Fallback: use provider_username + random suffix * Fallback: use provider_username + random suffix
*/ */
async function generateUniqueUsername(preferredUsername?: string): Promise<string> { async function generateUniqueUsername(
let username = preferredUsername?.toLowerCase().replace(/[^a-z0-9_-]/g, "") || "user"; preferredUsername?: string,
): Promise<string> {
let username =
preferredUsername?.toLowerCase().replace(/[^a-z0-9_-]/g, "") || "user";
// Ensure minimum length // Ensure minimum length
if (username.length < 3) { if (username.length < 3) {
username = "user" + Math.random().toString(36).substring(7); username = "user" + Math.random().toString(36).substring(7);

View file

@ -1,7 +1,10 @@
import { createClient } from "@supabase/supabase-js"; import { createClient } from "@supabase/supabase-js";
import { notifyAccountLinked } from "../../_notifications.js"; import { notifyAccountLinked } from "../../_notifications.js";
import { getAdminClient } from "../../_supabase.js"; import { getAdminClient } from "../../_supabase.js";
import { federateOAuthUser, linkProviderToPassport } from "../../_oauth-federation.js"; import {
federateOAuthUser,
linkProviderToPassport,
} from "../../_oauth-federation.js";
export const config = { export const config = {
runtime: "nodejs", runtime: "nodejs",
@ -185,7 +188,9 @@ export default async function handler(req: any, res: any) {
id: discordUser.id, id: discordUser.id,
email: discordUser.email, email: discordUser.email,
username: discordUser.username, username: discordUser.username,
avatar: discordUser.avatar ? `https://cdn.discordapp.com/avatars/${discordUser.id}/${discordUser.avatar}.webp` : undefined, avatar: discordUser.avatar
? `https://cdn.discordapp.com/avatars/${discordUser.id}/${discordUser.avatar}.webp`
: undefined,
}); });
console.log( console.log(
@ -212,7 +217,9 @@ export default async function handler(req: any, res: any) {
id: discordUser.id, id: discordUser.id,
email: discordUser.email, email: discordUser.email,
username: discordUser.username, username: discordUser.username,
avatar: discordUser.avatar ? `https://cdn.discordapp.com/avatars/${discordUser.id}/${discordUser.avatar}.webp` : undefined, avatar: discordUser.avatar
? `https://cdn.discordapp.com/avatars/${discordUser.id}/${discordUser.avatar}.webp`
: undefined,
}); });
console.log("[Discord OAuth] Federation result:", { console.log("[Discord OAuth] Federation result:", {

View file

@ -1,7 +1,10 @@
import { createClient } from "@supabase/supabase-js"; import { createClient } from "@supabase/supabase-js";
import { notifyAccountLinked } from "../../_notifications.js"; import { notifyAccountLinked } from "../../_notifications.js";
import { getAdminClient } from "../../_supabase.js"; import { getAdminClient } from "../../_supabase.js";
import { federateOAuthUser, linkProviderToPassport } from "../../_oauth-federation.js"; import {
federateOAuthUser,
linkProviderToPassport,
} from "../../_oauth-federation.js";
export const config = { export const config = {
runtime: "nodejs", runtime: "nodejs",

View file

@ -1,7 +1,10 @@
import { createClient } from "@supabase/supabase-js"; import { createClient } from "@supabase/supabase-js";
import { notifyAccountLinked } from "../../_notifications.js"; import { notifyAccountLinked } from "../../_notifications.js";
import { getAdminClient } from "../../_supabase.js"; import { getAdminClient } from "../../_supabase.js";
import { federateOAuthUser, linkProviderToPassport } from "../../_oauth-federation.js"; import {
federateOAuthUser,
linkProviderToPassport,
} from "../../_oauth-federation.js";
export const config = { export const config = {
runtime: "nodejs", runtime: "nodejs",

View file

@ -244,7 +244,6 @@ const App = () => (
element={<DiscordVerify />} element={<DiscordVerify />}
/> />
<Route <Route
path="/passport" path="/passport"
element={<Navigate to="/passport/me" replace />} element={<Navigate to="/passport/me" replace />}
@ -375,7 +374,6 @@ const App = () => (
element={<CorpContactUs />} element={<CorpContactUs />}
/> />
{/* Staff Arm Routes */} {/* Staff Arm Routes */}
<Route path="/staff" element={<Staff />} /> <Route path="/staff" element={<Staff />} />
<Route path="/staff/login" element={<StaffLogin />} /> <Route path="/staff/login" element={<StaffLogin />} />
@ -592,7 +590,6 @@ const App = () => (
<Route path="/blog" element={<Blog />} /> <Route path="/blog" element={<Blog />} />
<Route path="/blog/:slug" element={<BlogPost />} /> <Route path="/blog/:slug" element={<BlogPost />} />
{/* Ethos Guild Routes */} {/* Ethos Guild Routes */}
<Route <Route
path="/ethos/library" path="/ethos/library"

View file

@ -114,10 +114,11 @@ export default function Foundation() {
</h3> </h3>
<p className="text-gray-300 leading-relaxed"> <p className="text-gray-300 leading-relaxed">
GameForge is the Foundation's flagship "master-apprentice" GameForge is the Foundation's flagship "master-apprentice"
mentorship program. It's our "gym" where developers collaborate mentorship program. It's our "gym" where developers
on focused, high-impact game projects within 30-day sprints. collaborate on focused, high-impact game projects within
Teams of 5 (1 mentor + 4 mentees) tackle real game development 30-day sprints. Teams of 5 (1 mentor + 4 mentees) tackle real
challenges and ship playable games to our community arcade. game development challenges and ship playable games to our
community arcade.
</p> </p>
</div> </div>
@ -129,14 +130,19 @@ export default function Foundation() {
</h3> </h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-3"> <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
<div className="p-4 bg-black/40 rounded-lg border border-green-500/20 space-y-2"> <div className="p-4 bg-black/40 rounded-lg border border-green-500/20 space-y-2">
<p className="font-semibold text-green-300">Role 1: Community</p> <p className="font-semibold text-green-300">
Role 1: Community
</p>
<p className="text-sm text-gray-400"> <p className="text-sm text-gray-400">
Our "campfire" where developers meet, collaborate, and Our "campfire" where developers meet, collaborate, and
build their `aethex.me` passports through real project work. build their `aethex.me` passports through real project
work.
</p> </p>
</div> </div>
<div className="p-4 bg-black/40 rounded-lg border border-green-500/20 space-y-2"> <div className="p-4 bg-black/40 rounded-lg border border-green-500/20 space-y-2">
<p className="font-semibold text-green-300">Role 2: Education</p> <p className="font-semibold text-green-300">
Role 2: Education
</p>
<p className="text-sm text-gray-400"> <p className="text-sm text-gray-400">
Learn professional development practices: Code Review Learn professional development practices: Code Review
(SOP-102), Scope Management (KND-001), and shipping (SOP-102), Scope Management (KND-001), and shipping
@ -144,7 +150,9 @@ export default function Foundation() {
</p> </p>
</div> </div>
<div className="p-4 bg-black/40 rounded-lg border border-green-500/20 space-y-2"> <div className="p-4 bg-black/40 rounded-lg border border-green-500/20 space-y-2">
<p className="font-semibold text-green-300">Role 3: Pipeline</p> <p className="font-semibold text-green-300">
Role 3: Pipeline
</p>
<p className="text-sm text-gray-400"> <p className="text-sm text-gray-400">
Top performers become "Architects" ready to work on Top performers become "Architects" ready to work on
high-value projects. Your GameForge portfolio proves you high-value projects. Your GameForge portfolio proves you

View file

@ -419,7 +419,10 @@ export default function Login() {
window.location.search, window.location.search,
).get("next"); ).get("next");
if (next && next.startsWith("/")) if (next && next.startsWith("/"))
u.searchParams.set("state", JSON.stringify({ redirectTo: next })); u.searchParams.set(
"state",
JSON.stringify({ redirectTo: next }),
);
window.location.href = u.toString(); window.location.href = u.toString();
}} }}
> >

View file

@ -113,9 +113,7 @@ export default function LabsDashboard() {
if (affiliationRes.ok) { if (affiliationRes.ok) {
const data = await affiliationRes.json(); const data = await affiliationRes.json();
hasLabsAccess = hasLabsAccess =
data.arms?.includes("labs") || data.arms?.includes("labs") || data.role === "admin" || data.verified;
data.role === "admin" ||
data.verified;
} }
setIsAccessible(hasLabsAccess); setIsAccessible(hasLabsAccess);
@ -238,8 +236,8 @@ export default function LabsDashboard() {
What is LABS? What is LABS?
</h3> </h3>
<p className="text-sm text-gray-400"> <p className="text-sm text-gray-400">
LABS is our proprietary, for-profit R&D department that takes LABS is our proprietary, for-profit R&D department that
the open-source Axiom Protocol and builds competitive, takes the open-source Axiom Protocol and builds competitive,
closed-source "secret weapons" on top of it. closed-source "secret weapons" on top of it.
</p> </p>
<p className="text-sm text-gray-400"> <p className="text-sm text-gray-400">
@ -430,7 +428,9 @@ export default function LabsDashboard() {
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center justify-between text-xs"> <div className="flex items-center justify-between text-xs">
<span className="text-gray-400">Overall Progress</span> <span className="text-gray-400">
Overall Progress
</span>
<span className="font-mono text-amber-400"> <span className="font-mono text-amber-400">
{featured.progress}% {featured.progress}%
</span> </span>
@ -454,7 +454,8 @@ export default function LabsDashboard() {
)} )}
{/* Recent Publications */} {/* Recent Publications */}
{publications.filter((p) => p.status === "published").length > 0 && ( {publications.filter((p) => p.status === "published").length >
0 && (
<Card className="bg-gradient-to-br from-orange-950/40 to-orange-900/20 border-orange-500/20"> <Card className="bg-gradient-to-br from-orange-950/40 to-orange-900/20 border-orange-500/20">
<CardHeader> <CardHeader>
<CardTitle>Recent Publications</CardTitle> <CardTitle>Recent Publications</CardTitle>
@ -482,7 +483,9 @@ export default function LabsDashboard() {
</p> </p>
<p className="text-xs text-gray-400 mt-1"> <p className="text-xs text-gray-400 mt-1">
By {pub.author} {" "} By {pub.author} {" "}
{new Date(pub.published_date).toLocaleDateString()} {new Date(
pub.published_date,
).toLocaleDateString()}
</p> </p>
</div> </div>
<ExternalLink className="h-4 w-4 text-gray-500 flex-shrink-0 group-hover:text-orange-400 transition" /> <ExternalLink className="h-4 w-4 text-gray-500 flex-shrink-0 group-hover:text-orange-400 transition" />
@ -621,7 +624,10 @@ export default function LabsDashboard() {
</TabsContent> </TabsContent>
{/* Publications Tab */} {/* Publications Tab */}
<TabsContent value="publications" className="space-y-4 animate-fade-in"> <TabsContent
value="publications"
className="space-y-4 animate-fade-in"
>
{publications.length === 0 ? ( {publications.length === 0 ? (
<Card className="bg-gradient-to-br from-orange-950/40 to-orange-900/20 border-orange-500/20"> <Card className="bg-gradient-to-br from-orange-950/40 to-orange-900/20 border-orange-500/20">
<CardContent className="p-12 text-center space-y-4"> <CardContent className="p-12 text-center space-y-4">

View file

@ -160,12 +160,9 @@ export default function ClientDashboard() {
// Load team // Load team
try { try {
const teamRes = await fetch( const teamRes = await fetch(`${apiBase}/api/corp/team?limit=50`, {
`${apiBase}/api/corp/team?limit=50`, headers: { Authorization: `Bearer ${token}` },
{ });
headers: { Authorization: `Bearer ${token}` },
},
);
if (teamRes.ok) { if (teamRes.ok) {
const data = await teamRes.json(); const data = await teamRes.json();
setTeamMembers(Array.isArray(data) ? data : data.team || []); setTeamMembers(Array.isArray(data) ? data : data.team || []);
@ -195,7 +192,9 @@ export default function ClientDashboard() {
<h1 className="text-4xl font-bold bg-gradient-to-r from-blue-300 to-cyan-300 bg-clip-text text-transparent"> <h1 className="text-4xl font-bold bg-gradient-to-r from-blue-300 to-cyan-300 bg-clip-text text-transparent">
CORP Dashboard CORP Dashboard
</h1> </h1>
<p className="text-gray-400">Enterprise services & project management</p> <p className="text-gray-400">
Enterprise services & project management
</p>
<Button <Button
onClick={() => navigate("/login")} onClick={() => navigate("/login")}
className="w-full bg-gradient-to-r from-blue-600 to-cyan-600 hover:from-blue-700 hover:to-cyan-700 text-lg py-6" className="w-full bg-gradient-to-r from-blue-600 to-cyan-600 hover:from-blue-700 hover:to-cyan-700 text-lg py-6"
@ -210,8 +209,9 @@ export default function ClientDashboard() {
const totalProjectValue = projects.reduce((acc, p) => acc + p.budget, 0); const totalProjectValue = projects.reduce((acc, p) => acc + p.budget, 0);
const totalSpent = projects.reduce((acc, p) => acc + p.spent, 0); const totalSpent = projects.reduce((acc, p) => acc + p.spent, 0);
const activeProjects = projects.filter((p) => p.status === "in-progress") const activeProjects = projects.filter(
.length; (p) => p.status === "in-progress",
).length;
const overdueInvoices = invoices.filter((i) => i.status === "overdue").length; const overdueInvoices = invoices.filter((i) => i.status === "overdue").length;
const totalRevenue = invoices.reduce((acc, i) => acc + i.amount, 0); const totalRevenue = invoices.reduce((acc, i) => acc + i.amount, 0);
@ -261,7 +261,9 @@ export default function ClientDashboard() {
<p className="text-sm text-gray-400">Active Projects</p> <p className="text-sm text-gray-400">Active Projects</p>
<CheckCircle className="h-5 w-5 text-cyan-400" /> <CheckCircle className="h-5 w-5 text-cyan-400" />
</div> </div>
<p className="text-3xl font-bold text-white">{activeProjects}</p> <p className="text-3xl font-bold text-white">
{activeProjects}
</p>
</CardContent> </CardContent>
</Card> </Card>
@ -277,11 +279,13 @@ export default function ClientDashboard() {
</CardContent> </CardContent>
</Card> </Card>
<Card className={`bg-gradient-to-br ${ <Card
overdueInvoices > 0 className={`bg-gradient-to-br ${
? "from-red-950/40 to-red-900/20 border-red-500/20" overdueInvoices > 0
: "from-gray-950/40 to-gray-900/20 border-gray-500/20" ? "from-red-950/40 to-red-900/20 border-red-500/20"
}`}> : "from-gray-950/40 to-gray-900/20 border-gray-500/20"
}`}
>
<CardContent className="p-6 space-y-2"> <CardContent className="p-6 space-y-2">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<p className="text-sm text-gray-400">Overdue Invoices</p> <p className="text-sm text-gray-400">Overdue Invoices</p>
@ -299,7 +303,11 @@ export default function ClientDashboard() {
</div> </div>
{/* Tabs */} {/* Tabs */}
<Tabs value={activeTab} onValueChange={setActiveTab} className="w-full"> <Tabs
value={activeTab}
onValueChange={setActiveTab}
className="w-full"
>
<TabsList className="grid w-full grid-cols-4 bg-blue-950/30 border border-blue-500/20 p-1"> <TabsList className="grid w-full grid-cols-4 bg-blue-950/30 border border-blue-500/20 p-1">
<TabsTrigger value="overview">Overview</TabsTrigger> <TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="projects">Projects</TabsTrigger> <TabsTrigger value="projects">Projects</TabsTrigger>
@ -310,13 +318,12 @@ export default function ClientDashboard() {
{/* Overview Tab */} {/* Overview Tab */}
<TabsContent value="overview" className="space-y-6 animate-fade-in"> <TabsContent value="overview" className="space-y-6 animate-fade-in">
{/* Active Projects */} {/* Active Projects */}
{projects.filter((p) => p.status === "in-progress").length > 0 && ( {projects.filter((p) => p.status === "in-progress").length >
0 && (
<Card className="bg-gradient-to-br from-blue-950/40 to-blue-900/20 border-blue-500/20"> <Card className="bg-gradient-to-br from-blue-950/40 to-blue-900/20 border-blue-500/20">
<CardHeader> <CardHeader>
<CardTitle>Active Projects</CardTitle> <CardTitle>Active Projects</CardTitle>
<CardDescription> <CardDescription>Currently in development</CardDescription>
Currently in development
</CardDescription>
</CardHeader> </CardHeader>
<CardContent className="space-y-4"> <CardContent className="space-y-4">
{projects {projects
@ -373,9 +380,7 @@ export default function ClientDashboard() {
<Card className="bg-gradient-to-br from-green-950/40 to-green-900/20 border-green-500/20"> <Card className="bg-gradient-to-br from-green-950/40 to-green-900/20 border-green-500/20">
<CardHeader> <CardHeader>
<CardTitle>Recent Invoices</CardTitle> <CardTitle>Recent Invoices</CardTitle>
<CardDescription> <CardDescription>Latest billing activity</CardDescription>
Latest billing activity
</CardDescription>
</CardHeader> </CardHeader>
<CardContent className="space-y-3"> <CardContent className="space-y-3">
{invoices.slice(0, 5).map((invoice) => ( {invoices.slice(0, 5).map((invoice) => (
@ -520,7 +525,10 @@ export default function ClientDashboard() {
</div> </div>
</div> </div>
<Progress value={project.progress} className="h-2 mb-4" /> <Progress
value={project.progress}
className="h-2 mb-4"
/>
<Button <Button
size="sm" size="sm"
@ -537,7 +545,10 @@ export default function ClientDashboard() {
</TabsContent> </TabsContent>
{/* Contracts Tab */} {/* Contracts Tab */}
<TabsContent value="contracts" className="space-y-4 animate-fade-in"> <TabsContent
value="contracts"
className="space-y-4 animate-fade-in"
>
{contracts.length === 0 ? ( {contracts.length === 0 ? (
<Card className="bg-gradient-to-br from-blue-950/40 to-blue-900/20 border-blue-500/20"> <Card className="bg-gradient-to-br from-blue-950/40 to-blue-900/20 border-blue-500/20">
<CardContent className="p-12 text-center space-y-4"> <CardContent className="p-12 text-center space-y-4">
@ -584,7 +595,9 @@ export default function ClientDashboard() {
Start Start
</p> </p>
<p className="text-sm text-white"> <p className="text-sm text-white">
{new Date(contract.start_date).toLocaleDateString()} {new Date(
contract.start_date,
).toLocaleDateString()}
</p> </p>
</div> </div>
<div className="space-y-1"> <div className="space-y-1">

View file

@ -90,6 +90,7 @@ UNIQUE(user_id, provider) -- One user can only link one Discord accoun
#### Second Login with Different Provider Y (Same Person) #### Second Login with Different Provider Y (Same Person)
**Case A: Direct Provider Match** **Case A: Direct Provider Match**
``` ```
1. User clicks "Login with Discord" 1. User clicks "Login with Discord"
2. OAuth returns discord user data 2. OAuth returns discord user data
@ -101,6 +102,7 @@ UNIQUE(user_id, provider) -- One user can only link one Discord accoun
``` ```
**Case B: Email Match (Account Recovery)** **Case B: Email Match (Account Recovery)**
``` ```
1. User lost GitHub password, tries "Login with Discord" 1. User lost GitHub password, tries "Login with Discord"
2. Discord email matches existing Passport email 2. Discord email matches existing Passport email
@ -117,11 +119,12 @@ UNIQUE(user_id, provider) -- One user can only link one Discord accoun
```typescript ```typescript
async function federateOAuthUser( async function federateOAuthUser(
provider: string, provider: string,
oauthUser: OAuthUser oauthUser: OAuthUser,
): Promise<FederationResult> ): Promise<FederationResult>;
``` ```
**Logic:** **Logic:**
1. Look up `provider_identities` table 1. Look up `provider_identities` table
- If found → return linked Passport user_id - If found → return linked Passport user_id
- If not found → create new Passport + provider link - If not found → create new Passport + provider link
@ -159,6 +162,7 @@ redirect("/dashboard");
## Login Flow (Updated) ## Login Flow (Updated)
### Before (No Federation) ### Before (No Federation)
``` ```
GitHub → GitHub auth session GitHub → GitHub auth session
Discord → Discord auth session (different user) Discord → Discord auth session (different user)
@ -166,6 +170,7 @@ Google → Google auth session (different user)
``` ```
### After (Federation) ### After (Federation)
``` ```
GitHub → Federate to Foundation → Passport A session GitHub → Federate to Foundation → Passport A session
Discord → Federate to Foundation → Passport A session (same) Discord → Federate to Foundation → Passport A session (same)
@ -181,7 +186,7 @@ Google → Federate to Foundation → Passport A session (same)
``` ```
1. User signs up with GitHub 1. User signs up with GitHub
→ Creates Passport, logs in → Creates Passport, logs in
2. User logs out, wants to use Discord 2. User logs out, wants to use Discord
→ Logs in with Discord → Logs in with Discord
→ System recognizes Discord is new → System recognizes Discord is new
@ -208,19 +213,24 @@ Google → Federate to Foundation → Passport A session (same)
## Security Considerations ## Security Considerations
### Provider ID Collision (Prevented) ### Provider ID Collision (Prevented)
```sql ```sql
UNIQUE(provider, provider_user_id) UNIQUE(provider, provider_user_id)
``` ```
→ Prevents provider ID from linking to multiple Passports → Prevents provider ID from linking to multiple Passports
### Account Takeover (Prevented) ### Account Takeover (Prevented)
```sql ```sql
UNIQUE(user_id, provider) UNIQUE(user_id, provider)
``` ```
→ User can't link same provider twice → User can't link same provider twice
→ User can't have duplicate providers → User can't have duplicate providers
### Email Verification (Recommended) ### Email Verification (Recommended)
→ For auto-linking on email match, require email verification → For auto-linking on email match, require email verification
→ Prevent account takeover via unverified email addresses → Prevent account takeover via unverified email addresses
@ -262,7 +272,7 @@ If you had existing users with separate GitHub/Discord/Google accounts:
**Data Consistency** - No duplicate user records **Data Consistency** - No duplicate user records
**Security** - Prevents account fragmentation **Security** - Prevents account fragmentation
**Future Growth** - Easy to add new OAuth providers **Future Growth** - Easy to add new OAuth providers
**Account Recovery** - Email-based recovery across providers **Account Recovery** - Email-based recovery across providers
--- ---

View file

@ -13,15 +13,18 @@
## Role 1: The "Product" (The User's Workspace) ## Role 1: The "Product" (The User's Workspace)
### What It Is ### What It Is
The tangible dashboard where GameForge participants manage their team, tasks, and sprint progress. The tangible dashboard where GameForge participants manage their team, tasks, and sprint progress.
### Details ### Details
- **URL:** `/dashboard/gameforge` - **URL:** `/dashboard/gameforge`
- **Theme:** "Modern Retro" (Green accents, Pixel fonts, Hex grid wallpaper) - **Theme:** "Modern Retro" (Green accents, Pixel fonts, Hex grid wallpaper)
- **Access:** Soft-gated - Any logged-in user with an AeThex Passport can view. Non-team members see "Join the Next Game Jam!" CTA linking to Foundation - **Access:** Soft-gated - Any logged-in user with an AeThex Passport can view. Non-team members see "Join the Next Game Jam!" CTA linking to Foundation
- **JTBD:** "As a GameForge mentee, I need to see my team, my tasks, and my deadline for this month's game." - **JTBD:** "As a GameForge mentee, I need to see my team, my tasks, and my deadline for this month's game."
### Bespoke Features (Planned for Phase 3) ### Bespoke Features (Planned for Phase 3)
- **"Active Sprint" Header** - Prominent "Mission Control" header with live countdown to 4-week deadline - **"Active Sprint" Header** - Prominent "Mission Control" header with live countdown to 4-week deadline
- **"The Scope Anchor"** - Read-only widget displaying the 1-Paragraph GDD (KND-001) as the "North Star" - **"The Scope Anchor"** - Read-only widget displaying the 1-Paragraph GDD (KND-001) as the "North Star"
- **"My Sprint Team"** - 5-person master-apprentice widget showing Forge Master and 4 Mentees (Scripter, Builder, Sound, Narrative), each linking to their aethex.me Passport - **"My Sprint Team"** - 5-person master-apprentice widget showing Forge Master and 4 Mentees (Scripter, Builder, Sound, Narrative), each linking to their aethex.me Passport
@ -29,6 +32,7 @@ The tangible dashboard where GameForge participants manage their team, tasks, an
- **"Submit Final Build" CTA** - Pushes final game to aethex.fun Arcade - **"Submit Final Build" CTA** - Pushes final game to aethex.fun Arcade
### Current Status (Phase 1) ### Current Status (Phase 1)
**V0 (MVP):** Simple placeholder page with CTA links to Foundation and Discord channels. **V0 (MVP):** Simple placeholder page with CTA links to Foundation and Discord channels.
**Timeline:** Full dashboard deferred to Phase 3 (Post-Monetization) per strategic roadmap. **Timeline:** Full dashboard deferred to Phase 3 (Post-Monetization) per strategic roadmap.
@ -37,21 +41,25 @@ The tangible dashboard where GameForge participants manage their team, tasks, an
## Role 2: The "Program" (The Non-Profit's Mission) ## Role 2: The "Program" (The Non-Profit's Mission)
### What It Is ### What It Is
The **legal and cultural** "why" behind GameForge. This is the educational program run by **The AeThex Foundation** (Non-Profit) that lives inside the aethex.dev app. The **legal and cultural** "why" behind GameForge. This is the educational program run by **The AeThex Foundation** (Non-Profit) that lives inside the aethex.dev app.
### The Foundation's Role ### The Foundation's Role
#### 1. The "University" (Mentorship Program - Part VIII) #### 1. The "University" (Mentorship Program - Part VIII)
- **Purpose:** GameForge is the flagship "master-apprentice" program of the Foundation's Mentorship Program - **Purpose:** GameForge is the flagship "master-apprentice" program of the Foundation's Mentorship Program
- **Function:** The "lab" for our educational "university" - **Function:** The "lab" for our educational "university"
- **Model:** NOT a commercial venture; an **educational program** - **Model:** NOT a commercial venture; an **educational program**
#### 2. The "Community Builder" (Community is Our Core - Part I) #### 2. The "Community Builder" (Community is Our Core - Part I)
- **Purpose:** The "campfire" where developers meet, collaborate, and build community - **Purpose:** The "campfire" where developers meet, collaborate, and build community
- **Function:** A non-profit "gym" where developers can meet, collaborate, build their aethex.me Passports, and **ship a real product in 30 days** - **Function:** A non-profit "gym" where developers can meet, collaborate, build their aethex.me Passports, and **ship a real product in 30 days**
- **Value:** Proves our community is talented and serves as a marketing funnel - **Value:** Proves our community is talented and serves as a marketing funnel
#### 3. The "Showcase" (Portfolio Platform - aethex.fun) #### 3. The "Showcase" (Portfolio Platform - aethex.fun)
- **Purpose:** Host non-commercial games as "social proof" - **Purpose:** Host non-commercial games as "social proof"
- **Function:** Games ship to aethex.fun Arcade after completion - **Function:** Games ship to aethex.fun Arcade after completion
- **Impact:** Attracts new developers to the Foundation and demonstrates capability - **Impact:** Attracts new developers to the Foundation and demonstrates capability
@ -59,6 +67,7 @@ The **legal and cultural** "why" behind GameForge. This is the educational progr
### How It Works ### How It Works
**Team Structure (SOP-008 / Master-Apprentice Model)** **Team Structure (SOP-008 / Master-Apprentice Model)**
- **Forge Master (1)** - Experienced mentor who guides the team - **Forge Master (1)** - Experienced mentor who guides the team
- **Apprentices (4)** - Specialized roles: - **Apprentices (4)** - Specialized roles:
- **Scripter** - Gameplay programming - **Scripter** - Gameplay programming
@ -67,6 +76,7 @@ The **legal and cultural** "why" behind GameForge. This is the educational progr
- **Narrative** - Story, dialogue, characters - **Narrative** - Story, dialogue, characters
**Sprint Structure (30-Day Cycle)** **Sprint Structure (30-Day Cycle)**
1. **Team Formation** - Developers are matched with mentors 1. **Team Formation** - Developers are matched with mentors
2. **Scope Setting (KND-001)** - Create 1-paragraph GDD to prevent feature creep 2. **Scope Setting (KND-001)** - Create 1-paragraph GDD to prevent feature creep
3. **Sprint Work** - 4 weeks of focused development 3. **Sprint Work** - 4 weeks of focused development
@ -74,6 +84,7 @@ The **legal and cultural** "why" behind GameForge. This is the educational progr
5. **Evaluation** - Mentor feedback and performance assessment 5. **Evaluation** - Mentor feedback and performance assessment
**Program Goals** **Program Goals**
- Developers learn professional practices (Code Review, Scope Management, Shipping Excellence) - Developers learn professional practices (Code Review, Scope Management, Shipping Excellence)
- Top performers (3+ shipped games) earn **"Architect" 🛡️** status - Top performers (3+ shipped games) earn **"Architect" 🛡️** status
- Build aethex.me Passport portfolio with shipping experience - Build aethex.me Passport portfolio with shipping experience
@ -84,18 +95,22 @@ The **legal and cultural** "why" behind GameForge. This is the educational progr
## Role 3: The "Strategic Asset" (The For-Profit's Advantage) ## Role 3: The "Strategic Asset" (The For-Profit's Advantage)
### What It Is ### What It Is
How the **Non-Profit "Guardian"** provides massive, tangible value to the **For-Profit "Engine."** How the **Non-Profit "Guardian"** provides massive, tangible value to the **For-Profit "Engine."**
GameForge is a **"dual-purpose" asset** that serves both: GameForge is a **"dual-purpose" asset** that serves both:
- The Foundation's mission (education, community, non-profit) - The Foundation's mission (education, community, non-profit)
- AeThex.dev's commercial goals (revenue, talent, R&D) - AeThex.dev's commercial goals (revenue, talent, R&D)
### Asset 1: The "Talent Flywheel" (Funnel 3) ### Asset 1: The "Talent Flywheel" (Funnel 3)
#### The Problem #### The Problem
A random developer applies to NEXUS marketplace. How do we know if they can truly "Execute with Excellence"? We don't. A random developer applies to NEXUS marketplace. How do we know if they can truly "Execute with Excellence"? We don't.
#### The Solution: GameForge as Internal Vetting #### The Solution: GameForge as Internal Vetting
1. **Entry:** New dev joins the Foundation and enters GameForge 1. **Entry:** New dev joins the Foundation and enters GameForge
2. **Battleground:** They ship **3 games in 3 months**, learning: 2. **Battleground:** They ship **3 games in 3 months**, learning:
- **SOP-102** (Code Review standards) - **SOP-102** (Code Review standards)
@ -105,6 +120,7 @@ A random developer applies to NEXUS marketplace. How do we know if they can trul
4. **Promotion:** Developer is now **battle-tested** and promoted to **"Architect" 🛡️** status 4. **Promotion:** Developer is now **battle-tested** and promoted to **"Architect" 🛡️** status
#### The Payoff #### The Payoff
- **Scenario:** CORP signs a **$250,000** enterprise client project - **Scenario:** CORP signs a **$250,000** enterprise client project
- **Question:** Who does CORP hire from NEXUS? - **Question:** Who does CORP hire from NEXUS?
- NOT the random dev with 0 shipping experience - NOT the random dev with 0 shipping experience
@ -116,9 +132,11 @@ A random developer applies to NEXUS marketplace. How do we know if they can trul
### Asset 2: The "R&D Testbed" (LABS Integration) ### Asset 2: The "R&D Testbed" (LABS Integration)
#### The Problem #### The Problem
LABS invents a new, proprietary **"AI-Powered Procedural Content Generation (PCG) Engine."** It's a buggy, experimental "beta." We *cannot* sell this to a $250k client—it's too risky.
LABS invents a new, proprietary **"AI-Powered Procedural Content Generation (PCG) Engine."** It's a buggy, experimental "beta." We _cannot_ sell this to a $250k client—it's too risky.
#### The Solution: GameForge as Free QA Army #### The Solution: GameForge as Free QA Army
1. **The Bridge:** LABS licenses the "beta" engine to GameForge (Non-Profit) as a "new tool" for the next month's game jam 1. **The Bridge:** LABS licenses the "beta" engine to GameForge (Non-Profit) as a "new tool" for the next month's game jam
2. **The Pressure Test:** **100 GameForge teams (500 developers)** compete to use this new AI engine 2. **The Pressure Test:** **100 GameForge teams (500 developers)** compete to use this new AI engine
- They find hundreds of bugs - They find hundreds of bugs
@ -126,12 +144,14 @@ LABS invents a new, proprietary **"AI-Powered Procedural Content Generation (PCG
3. **The Feedback:** LABS gets **thousands of hours of free, real-world QA and user feedback** 3. **The Feedback:** LABS gets **thousands of hours of free, real-world QA and user feedback**
#### The Payoff #### The Payoff
- **V0 → V1 Development:** LABS patches bugs, integrates new ideas - **V0 → V1 Development:** LABS patches bugs, integrates new ideas
- **Result:** Rock-solid, battle-tested V2.0 of the "secret weapon" - **Result:** Rock-solid, battle-tested V2.0 of the "secret weapon"
- **Deployment:** Now LABS can confidently sell this to high-paying enterprise clients - **Deployment:** Now LABS can confidently sell this to high-paying enterprise clients
- **Revenue Impact:** De-risked IP → Higher client confidence → Premium pricing - **Revenue Impact:** De-risked IP → Higher client confidence → Premium pricing
**Example Timeline:** **Example Timeline:**
- **Month 1:** LABS releases "beta AI-PCG" to GameForge - **Month 1:** LABS releases "beta AI-PCG" to GameForge
- **Month 1-4:** 500 GameForge devs use it, report bugs, discover uses - **Month 1-4:** 500 GameForge devs use it, report bugs, discover uses
- **Month 5:** LABS releases V2.0 (polished, battle-tested) - **Month 5:** LABS releases V2.0 (polished, battle-tested)
@ -159,6 +179,7 @@ AETHEX.DEV (For-Profit)
``` ```
### The Complete Loop ### The Complete Loop
1. **Foundation runs GameForge** (non-profit, educational) 1. **Foundation runs GameForge** (non-profit, educational)
2. **Developers ship games, build portfolios, learn from mentors** 2. **Developers ship games, build portfolios, learn from mentors**
3. **Top performers become "Architects"** (verified by 3 shipped games) 3. **Top performers become "Architects"** (verified by 3 shipped games)
@ -173,16 +194,19 @@ AETHEX.DEV (For-Profit)
## Implementation Roadmap ## Implementation Roadmap
### Phase 1 (Current): MVP ### Phase 1 (Current): MVP
- ✅ Foundation landing page featuring GameForge - ✅ Foundation landing page featuring GameForge
- ✅ Simple `/dashboard/gameforge` placeholder with Discord/Foundation CTAs - ✅ Simple `/dashboard/gameforge` placeholder with Discord/Foundation CTAs
- 🔄 Manual operations via Discord and Trello - 🔄 Manual operations via Discord and Trello
### Phase 2 (Post-Monetization) ### Phase 2 (Post-Monetization)
- Implement basic GameForge dashboard - Implement basic GameForge dashboard
- Integrate with team management - Integrate with team management
- Link to aethex.fun (basic MVP) - Link to aethex.fun (basic MVP)
### Phase 3 (Ecosystem Scale) ### Phase 3 (Ecosystem Scale)
- Full bespoke dashboard with all 4 widgets - Full bespoke dashboard with all 4 widgets
- aethex.fun Arcade with full game hosting - aethex.fun Arcade with full game hosting
- LABS → GameForge beta tech distribution system - LABS → GameForge beta tech distribution system
@ -193,6 +217,7 @@ AETHEX.DEV (For-Profit)
## Success Metrics ## Success Metrics
### Foundation Side (Non-Profit) ### Foundation Side (Non-Profit)
- Number of GameForge cohorts per month - Number of GameForge cohorts per month
- Developer retention and progression - Developer retention and progression
- Mentorship satisfaction scores - Mentorship satisfaction scores
@ -200,6 +225,7 @@ AETHEX.DEV (For-Profit)
- Community engagement metrics - Community engagement metrics
### For-Profit Side (aethex.dev) ### For-Profit Side (aethex.dev)
- % of NEXUS contractors who are "Architects" - % of NEXUS contractors who are "Architects"
- Average project value for "Architect" projects - Average project value for "Architect" projects
- Time-to-hire reduction through verified talent - Time-to-hire reduction through verified talent

View file

@ -7,6 +7,7 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
### The Complete Ecosystem Picture ### The Complete Ecosystem Picture
#### `aethex.foundation` (The "Guardian") #### `aethex.foundation` (The "Guardian")
- **Type:** Non-Profit - **Type:** Non-Profit
- **Primary Role:** Identity issuance and open-source research - **Primary Role:** Identity issuance and open-source research
- **Key Function:** Guardian of the open-source **Axiom Protocol** - **Key Function:** Guardian of the open-source **Axiom Protocol**
@ -14,6 +15,7 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
- **Focus:** Community education, mentorship, and open-source development - **Focus:** Community education, mentorship, and open-source development
#### `aethex.dev` (The "Engine") #### `aethex.dev` (The "Engine")
- **Type:** For-Profit - **Type:** For-Profit
- **Primary Role:** Commercial application platform - **Primary Role:** Commercial application platform
- **Research & Development:** The **LABS** (Yellow) Arm - **Research & Development:** The **LABS** (Yellow) Arm
@ -22,13 +24,13 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
### Research vs. Development ### Research vs. Development
| Aspect | Foundation | LABS | | Aspect | Foundation | LABS |
|--------|-----------|------| | --------------- | -------------------------- | --------------------------------- |
| **Entity Type** | Non-Profit | For-Profit | | **Entity Type** | Non-Profit | For-Profit |
| **Focus** | Open-Source Research | Proprietary Development | | **Focus** | Open-Source Research | Proprietary Development |
| **Role** | Guardian of Axiom Protocol | Internal R&D Department | | **Role** | Guardian of Axiom Protocol | Internal R&D Department |
| **Output** | Community Knowledge | Competitive Advantage | | **Output** | Community Knowledge | Competitive Advantage |
| **Access** | Public | A-Corp Employees / Verified Users | | **Access** | Public | A-Corp Employees / Verified Users |
## LABS Dashboard Architecture ## LABS Dashboard Architecture
@ -45,11 +47,13 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
**Purpose:** High-level Kanban or list of all internal, proprietary R&D projects. **Purpose:** High-level Kanban or list of all internal, proprietary R&D projects.
**Sample Data:** **Sample Data:**
- **"Axiom PCG Engine (for dev-link.me)"** [Status: In Development] - **"Axiom PCG Engine (for dev-link.me)"** [Status: In Development]
- **".aethex TLD Smart Contracts"** [Status: In Research] - **".aethex TLD Smart Contracts"** [Status: In Research]
- **"QuantumLeap Predictive Model v2"** [Status: Scoping] - **"QuantumLeap Predictive Model v2"** [Status: Scoping]
**Functionality:** **Functionality:**
- Display project status (Scoping → Research → In Development → Testing → Released) - Display project status (Scoping → Research → In Development → Testing → Released)
- Show progress indicators - Show progress indicators
- Link to project details and whitepapers - Link to project details and whitepapers
@ -66,6 +70,7 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
| aethex.me IP | [Secured] | The AeThex Corp | | aethex.me IP | [Secured] | The AeThex Corp |
**Functionality:** **Functionality:**
- Track all proprietary IP (Patents, Trademarks, Trade Secrets) - Track all proprietary IP (Patents, Trademarks, Trade Secrets)
- Show filing status and dates - Show filing status and dates
- Indicate which subsidiaries/entities are licensed - Indicate which subsidiaries/entities are licensed
@ -76,10 +81,12 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
**Purpose:** Dashboard for the Marketing Team (SOP-402) to track R&D content and thought leadership. **Purpose:** Dashboard for the Marketing Team (SOP-402) to track R&D content and thought leadership.
**Sample Data:** **Sample Data:**
- "The Tech Behind PCG" [Status: Drafting] - "The Tech Behind PCG" [Status: Drafting]
- "Why We Chose a .aethex TLD" [Status: Published on aethex.blog] - "Why We Chose a .aethex TLD" [Status: Published on aethex.blog]
**Functionality:** **Functionality:**
- List upcoming technical whitepapers and blog posts - List upcoming technical whitepapers and blog posts
- Show publication status (Drafting → Review → Published) - Show publication status (Drafting → Review → Published)
- Link to published content on aethex.blog - Link to published content on aethex.blog
@ -91,6 +98,7 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
**Purpose:** A filtered view of the NEXUS bounty board showing only high-difficulty, high-reward "Research Bounties" that LABS has posted for elite "Architect" community members to help with. **Purpose:** A filtered view of the NEXUS bounty board showing only high-difficulty, high-reward "Research Bounties" that LABS has posted for elite "Architect" community members to help with.
**Functionality:** **Functionality:**
- Filter NEXUS bounties by "research" category - Filter NEXUS bounties by "research" category
- Show only high-reward opportunities - Show only high-reward opportunities
- Display difficulty level and required expertise - Display difficulty level and required expertise
@ -105,6 +113,7 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
## Access Control & Soft-Gating ## Access Control & Soft-Gating
### Public Users (Not A-Corp Employees) ### Public Users (Not A-Corp Employees)
- See header: "Research LABS" - See header: "Research LABS"
- See "Join Labs?" CTA - See "Join Labs?" CTA
- Can view published whitepapers (Publication Pipeline - published only) - Can view published whitepapers (Publication Pipeline - published only)
@ -112,6 +121,7 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
- Navigation: CTA button links to `/labs/join-request` or similar - Navigation: CTA button links to `/labs/join-request` or similar
### A-Corp Employees / Verified Users ### A-Corp Employees / Verified Users
- Full access to all widgets - Full access to all widgets
- Can see all research tracks and progress - Can see all research tracks and progress
- Can view IP dashboard (with appropriate role restrictions) - Can view IP dashboard (with appropriate role restrictions)
@ -122,12 +132,14 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
## Technical Implementation Notes ## Technical Implementation Notes
1. **Database Tables Needed:** 1. **Database Tables Needed:**
- `labs_research_tracks` (projects, status, progress, lead_id) - `labs_research_tracks` (projects, status, progress, lead_id)
- `labs_ip_portfolio` (ip_name, type, status, filing_date, licensed_to) - `labs_ip_portfolio` (ip_name, type, status, filing_date, licensed_to)
- `labs_publications` (title, description, status, published_date, content_url) - `labs_publications` (title, description, status, published_date, content_url)
- `labs_bounties` (links to nexus opportunities, filtered by category) - `labs_bounties` (links to nexus opportunities, filtered by category)
2. **API Endpoints:** 2. **API Endpoints:**
- `GET /api/labs/research-tracks` - Fetch all research tracks - `GET /api/labs/research-tracks` - Fetch all research tracks
- `GET /api/labs/ip-portfolio` - Fetch IP portfolio (admin + A-Corp) - `GET /api/labs/ip-portfolio` - Fetch IP portfolio (admin + A-Corp)
- `GET /api/labs/publications` - Fetch publications (public + A-Corp) - `GET /api/labs/publications` - Fetch publications (public + A-Corp)
@ -136,6 +148,7 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
- `POST /api/labs/join-request` - Request to join LABS (soft-gating) - `POST /api/labs/join-request` - Request to join LABS (soft-gating)
3. **Soft-Gating Logic:** 3. **Soft-Gating Logic:**
- Check user's `arm_affiliations` table for "labs" affiliation - Check user's `arm_affiliations` table for "labs" affiliation
- Check if user has A-Corp role or is verified member - Check if user has A-Corp role or is verified member
- Return different UI based on access level - Return different UI based on access level