Prettier format pending files
This commit is contained in:
parent
a4fe444b03
commit
e2efadff2d
12 changed files with 159 additions and 67 deletions
|
|
@ -185,9 +185,12 @@ export async function linkProviderToPassport(
|
|||
* Generate a unique username from OAuth data
|
||||
* Fallback: use provider_username + random suffix
|
||||
*/
|
||||
async function generateUniqueUsername(preferredUsername?: string): Promise<string> {
|
||||
let username = preferredUsername?.toLowerCase().replace(/[^a-z0-9_-]/g, "") || "user";
|
||||
|
||||
async function generateUniqueUsername(
|
||||
preferredUsername?: string,
|
||||
): Promise<string> {
|
||||
let username =
|
||||
preferredUsername?.toLowerCase().replace(/[^a-z0-9_-]/g, "") || "user";
|
||||
|
||||
// Ensure minimum length
|
||||
if (username.length < 3) {
|
||||
username = "user" + Math.random().toString(36).substring(7);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { createClient } from "@supabase/supabase-js";
|
||||
import { notifyAccountLinked } from "../../_notifications.js";
|
||||
import { getAdminClient } from "../../_supabase.js";
|
||||
import { federateOAuthUser, linkProviderToPassport } from "../../_oauth-federation.js";
|
||||
import {
|
||||
federateOAuthUser,
|
||||
linkProviderToPassport,
|
||||
} from "../../_oauth-federation.js";
|
||||
|
||||
export const config = {
|
||||
runtime: "nodejs",
|
||||
|
|
@ -185,7 +188,9 @@ export default async function handler(req: any, res: any) {
|
|||
id: discordUser.id,
|
||||
email: discordUser.email,
|
||||
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(
|
||||
|
|
@ -212,7 +217,9 @@ export default async function handler(req: any, res: any) {
|
|||
id: discordUser.id,
|
||||
email: discordUser.email,
|
||||
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:", {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { createClient } from "@supabase/supabase-js";
|
||||
import { notifyAccountLinked } from "../../_notifications.js";
|
||||
import { getAdminClient } from "../../_supabase.js";
|
||||
import { federateOAuthUser, linkProviderToPassport } from "../../_oauth-federation.js";
|
||||
import {
|
||||
federateOAuthUser,
|
||||
linkProviderToPassport,
|
||||
} from "../../_oauth-federation.js";
|
||||
|
||||
export const config = {
|
||||
runtime: "nodejs",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { createClient } from "@supabase/supabase-js";
|
||||
import { notifyAccountLinked } from "../../_notifications.js";
|
||||
import { getAdminClient } from "../../_supabase.js";
|
||||
import { federateOAuthUser, linkProviderToPassport } from "../../_oauth-federation.js";
|
||||
import {
|
||||
federateOAuthUser,
|
||||
linkProviderToPassport,
|
||||
} from "../../_oauth-federation.js";
|
||||
|
||||
export const config = {
|
||||
runtime: "nodejs",
|
||||
|
|
|
|||
|
|
@ -244,7 +244,6 @@ const App = () => (
|
|||
element={<DiscordVerify />}
|
||||
/>
|
||||
|
||||
|
||||
<Route
|
||||
path="/passport"
|
||||
element={<Navigate to="/passport/me" replace />}
|
||||
|
|
@ -375,7 +374,6 @@ const App = () => (
|
|||
element={<CorpContactUs />}
|
||||
/>
|
||||
|
||||
|
||||
{/* Staff Arm Routes */}
|
||||
<Route path="/staff" element={<Staff />} />
|
||||
<Route path="/staff/login" element={<StaffLogin />} />
|
||||
|
|
@ -592,7 +590,6 @@ const App = () => (
|
|||
<Route path="/blog" element={<Blog />} />
|
||||
<Route path="/blog/:slug" element={<BlogPost />} />
|
||||
|
||||
|
||||
{/* Ethos Guild Routes */}
|
||||
<Route
|
||||
path="/ethos/library"
|
||||
|
|
|
|||
|
|
@ -114,10 +114,11 @@ export default function Foundation() {
|
|||
</h3>
|
||||
<p className="text-gray-300 leading-relaxed">
|
||||
GameForge is the Foundation's flagship "master-apprentice"
|
||||
mentorship program. It's our "gym" where developers collaborate
|
||||
on focused, high-impact game projects within 30-day sprints.
|
||||
Teams of 5 (1 mentor + 4 mentees) tackle real game development
|
||||
challenges and ship playable games to our community arcade.
|
||||
mentorship program. It's our "gym" where developers
|
||||
collaborate on focused, high-impact game projects within
|
||||
30-day sprints. Teams of 5 (1 mentor + 4 mentees) tackle real
|
||||
game development challenges and ship playable games to our
|
||||
community arcade.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
@ -129,14 +130,19 @@ export default function Foundation() {
|
|||
</h3>
|
||||
<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">
|
||||
<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">
|
||||
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>
|
||||
</div>
|
||||
<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">
|
||||
Learn professional development practices: Code Review
|
||||
(SOP-102), Scope Management (KND-001), and shipping
|
||||
|
|
@ -144,7 +150,9 @@ export default function Foundation() {
|
|||
</p>
|
||||
</div>
|
||||
<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">
|
||||
Top performers become "Architects" ready to work on
|
||||
high-value projects. Your GameForge portfolio proves you
|
||||
|
|
|
|||
|
|
@ -419,7 +419,10 @@ export default function Login() {
|
|||
window.location.search,
|
||||
).get("next");
|
||||
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();
|
||||
}}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -113,9 +113,7 @@ export default function LabsDashboard() {
|
|||
if (affiliationRes.ok) {
|
||||
const data = await affiliationRes.json();
|
||||
hasLabsAccess =
|
||||
data.arms?.includes("labs") ||
|
||||
data.role === "admin" ||
|
||||
data.verified;
|
||||
data.arms?.includes("labs") || data.role === "admin" || data.verified;
|
||||
}
|
||||
|
||||
setIsAccessible(hasLabsAccess);
|
||||
|
|
@ -238,8 +236,8 @@ export default function LabsDashboard() {
|
|||
What is LABS?
|
||||
</h3>
|
||||
<p className="text-sm text-gray-400">
|
||||
LABS is our proprietary, for-profit R&D department that takes
|
||||
the open-source Axiom Protocol and builds competitive,
|
||||
LABS is our proprietary, for-profit R&D department that
|
||||
takes the open-source Axiom Protocol and builds competitive,
|
||||
closed-source "secret weapons" on top of it.
|
||||
</p>
|
||||
<p className="text-sm text-gray-400">
|
||||
|
|
@ -430,7 +428,9 @@ export default function LabsDashboard() {
|
|||
|
||||
<div className="space-y-2">
|
||||
<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">
|
||||
{featured.progress}%
|
||||
</span>
|
||||
|
|
@ -454,7 +454,8 @@ export default function LabsDashboard() {
|
|||
)}
|
||||
|
||||
{/* 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">
|
||||
<CardHeader>
|
||||
<CardTitle>Recent Publications</CardTitle>
|
||||
|
|
@ -482,7 +483,9 @@ export default function LabsDashboard() {
|
|||
</p>
|
||||
<p className="text-xs text-gray-400 mt-1">
|
||||
By {pub.author} •{" "}
|
||||
{new Date(pub.published_date).toLocaleDateString()}
|
||||
{new Date(
|
||||
pub.published_date,
|
||||
).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
{/* 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 ? (
|
||||
<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">
|
||||
|
|
|
|||
|
|
@ -160,12 +160,9 @@ export default function ClientDashboard() {
|
|||
|
||||
// Load team
|
||||
try {
|
||||
const teamRes = await fetch(
|
||||
`${apiBase}/api/corp/team?limit=50`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
const teamRes = await fetch(`${apiBase}/api/corp/team?limit=50`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
if (teamRes.ok) {
|
||||
const data = await teamRes.json();
|
||||
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">
|
||||
CORP Dashboard
|
||||
</h1>
|
||||
<p className="text-gray-400">Enterprise services & project management</p>
|
||||
<p className="text-gray-400">
|
||||
Enterprise services & project management
|
||||
</p>
|
||||
<Button
|
||||
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"
|
||||
|
|
@ -210,8 +209,9 @@ export default function ClientDashboard() {
|
|||
|
||||
const totalProjectValue = projects.reduce((acc, p) => acc + p.budget, 0);
|
||||
const totalSpent = projects.reduce((acc, p) => acc + p.spent, 0);
|
||||
const activeProjects = projects.filter((p) => p.status === "in-progress")
|
||||
.length;
|
||||
const activeProjects = projects.filter(
|
||||
(p) => p.status === "in-progress",
|
||||
).length;
|
||||
const overdueInvoices = invoices.filter((i) => i.status === "overdue").length;
|
||||
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>
|
||||
<CheckCircle className="h-5 w-5 text-cyan-400" />
|
||||
</div>
|
||||
<p className="text-3xl font-bold text-white">{activeProjects}</p>
|
||||
<p className="text-3xl font-bold text-white">
|
||||
{activeProjects}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
|
|
@ -277,11 +279,13 @@ export default function ClientDashboard() {
|
|||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className={`bg-gradient-to-br ${
|
||||
overdueInvoices > 0
|
||||
? "from-red-950/40 to-red-900/20 border-red-500/20"
|
||||
: "from-gray-950/40 to-gray-900/20 border-gray-500/20"
|
||||
}`}>
|
||||
<Card
|
||||
className={`bg-gradient-to-br ${
|
||||
overdueInvoices > 0
|
||||
? "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">
|
||||
<div className="flex items-center justify-between">
|
||||
<p className="text-sm text-gray-400">Overdue Invoices</p>
|
||||
|
|
@ -299,7 +303,11 @@ export default function ClientDashboard() {
|
|||
</div>
|
||||
|
||||
{/* 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">
|
||||
<TabsTrigger value="overview">Overview</TabsTrigger>
|
||||
<TabsTrigger value="projects">Projects</TabsTrigger>
|
||||
|
|
@ -310,13 +318,12 @@ export default function ClientDashboard() {
|
|||
{/* Overview Tab */}
|
||||
<TabsContent value="overview" className="space-y-6 animate-fade-in">
|
||||
{/* 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">
|
||||
<CardHeader>
|
||||
<CardTitle>Active Projects</CardTitle>
|
||||
<CardDescription>
|
||||
Currently in development
|
||||
</CardDescription>
|
||||
<CardDescription>Currently in development</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{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">
|
||||
<CardHeader>
|
||||
<CardTitle>Recent Invoices</CardTitle>
|
||||
<CardDescription>
|
||||
Latest billing activity
|
||||
</CardDescription>
|
||||
<CardDescription>Latest billing activity</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
{invoices.slice(0, 5).map((invoice) => (
|
||||
|
|
@ -520,7 +525,10 @@ export default function ClientDashboard() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<Progress value={project.progress} className="h-2 mb-4" />
|
||||
<Progress
|
||||
value={project.progress}
|
||||
className="h-2 mb-4"
|
||||
/>
|
||||
|
||||
<Button
|
||||
size="sm"
|
||||
|
|
@ -537,7 +545,10 @@ export default function ClientDashboard() {
|
|||
</TabsContent>
|
||||
|
||||
{/* 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 ? (
|
||||
<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">
|
||||
|
|
@ -584,7 +595,9 @@ export default function ClientDashboard() {
|
|||
Start
|
||||
</p>
|
||||
<p className="text-sm text-white">
|
||||
{new Date(contract.start_date).toLocaleDateString()}
|
||||
{new Date(
|
||||
contract.start_date,
|
||||
).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ UNIQUE(user_id, provider) -- One user can only link one Discord accoun
|
|||
#### Second Login with Different Provider Y (Same Person)
|
||||
|
||||
**Case A: Direct Provider Match**
|
||||
|
||||
```
|
||||
1. User clicks "Login with Discord"
|
||||
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)**
|
||||
|
||||
```
|
||||
1. User lost GitHub password, tries "Login with Discord"
|
||||
2. Discord email matches existing Passport email
|
||||
|
|
@ -117,11 +119,12 @@ UNIQUE(user_id, provider) -- One user can only link one Discord accoun
|
|||
```typescript
|
||||
async function federateOAuthUser(
|
||||
provider: string,
|
||||
oauthUser: OAuthUser
|
||||
): Promise<FederationResult>
|
||||
oauthUser: OAuthUser,
|
||||
): Promise<FederationResult>;
|
||||
```
|
||||
|
||||
**Logic:**
|
||||
|
||||
1. Look up `provider_identities` table
|
||||
- If found → return linked Passport user_id
|
||||
- If not found → create new Passport + provider link
|
||||
|
|
@ -159,6 +162,7 @@ redirect("/dashboard");
|
|||
## Login Flow (Updated)
|
||||
|
||||
### Before (No Federation)
|
||||
|
||||
```
|
||||
GitHub → GitHub auth session
|
||||
Discord → Discord auth session (different user)
|
||||
|
|
@ -166,6 +170,7 @@ Google → Google auth session (different user)
|
|||
```
|
||||
|
||||
### After (Federation)
|
||||
|
||||
```
|
||||
GitHub → Federate to Foundation → Passport A session
|
||||
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
|
||||
→ Creates Passport, logs in
|
||||
|
||||
|
||||
2. User logs out, wants to use Discord
|
||||
→ Logs in with Discord
|
||||
→ System recognizes Discord is new
|
||||
|
|
@ -208,19 +213,24 @@ Google → Federate to Foundation → Passport A session (same)
|
|||
## Security Considerations
|
||||
|
||||
### Provider ID Collision (Prevented)
|
||||
|
||||
```sql
|
||||
UNIQUE(provider, provider_user_id)
|
||||
```
|
||||
|
||||
→ Prevents provider ID from linking to multiple Passports
|
||||
|
||||
### Account Takeover (Prevented)
|
||||
|
||||
```sql
|
||||
UNIQUE(user_id, provider)
|
||||
```
|
||||
|
||||
→ User can't link same provider twice
|
||||
→ User can't have duplicate providers
|
||||
|
||||
### Email Verification (Recommended)
|
||||
|
||||
→ For auto-linking on email match, require email verification
|
||||
→ 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
|
||||
✅ **Security** - Prevents account fragmentation
|
||||
✅ **Future Growth** - Easy to add new OAuth providers
|
||||
✅ **Account Recovery** - Email-based recovery across providers
|
||||
✅ **Account Recovery** - Email-based recovery across providers
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -13,15 +13,18 @@
|
|||
## Role 1: The "Product" (The User's Workspace)
|
||||
|
||||
### What It Is
|
||||
|
||||
The tangible dashboard where GameForge participants manage their team, tasks, and sprint progress.
|
||||
|
||||
### Details
|
||||
|
||||
- **URL:** `/dashboard/gameforge`
|
||||
- **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
|
||||
- **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)
|
||||
|
||||
- **"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"
|
||||
- **"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
|
||||
|
||||
### Current Status (Phase 1)
|
||||
|
||||
**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.
|
||||
|
||||
|
|
@ -37,21 +41,25 @@ The tangible dashboard where GameForge participants manage their team, tasks, an
|
|||
## Role 2: The "Program" (The Non-Profit's Mission)
|
||||
|
||||
### 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 Foundation's Role
|
||||
|
||||
#### 1. The "University" (Mentorship Program - Part VIII)
|
||||
|
||||
- **Purpose:** GameForge is the flagship "master-apprentice" program of the Foundation's Mentorship Program
|
||||
- **Function:** The "lab" for our educational "university"
|
||||
- **Model:** NOT a commercial venture; an **educational program**
|
||||
|
||||
#### 2. The "Community Builder" (Community is Our Core - Part I)
|
||||
|
||||
- **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**
|
||||
- **Value:** Proves our community is talented and serves as a marketing funnel
|
||||
|
||||
#### 3. The "Showcase" (Portfolio Platform - aethex.fun)
|
||||
|
||||
- **Purpose:** Host non-commercial games as "social proof"
|
||||
- **Function:** Games ship to aethex.fun Arcade after completion
|
||||
- **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
|
||||
|
||||
**Team Structure (SOP-008 / Master-Apprentice Model)**
|
||||
|
||||
- **Forge Master (1)** - Experienced mentor who guides the team
|
||||
- **Apprentices (4)** - Specialized roles:
|
||||
- **Scripter** - Gameplay programming
|
||||
|
|
@ -67,6 +76,7 @@ The **legal and cultural** "why" behind GameForge. This is the educational progr
|
|||
- **Narrative** - Story, dialogue, characters
|
||||
|
||||
**Sprint Structure (30-Day Cycle)**
|
||||
|
||||
1. **Team Formation** - Developers are matched with mentors
|
||||
2. **Scope Setting (KND-001)** - Create 1-paragraph GDD to prevent feature creep
|
||||
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
|
||||
|
||||
**Program Goals**
|
||||
|
||||
- Developers learn professional practices (Code Review, Scope Management, Shipping Excellence)
|
||||
- Top performers (3+ shipped games) earn **"Architect" 🛡️** status
|
||||
- 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)
|
||||
|
||||
### What It Is
|
||||
|
||||
How the **Non-Profit "Guardian"** provides massive, tangible value to the **For-Profit "Engine."**
|
||||
|
||||
GameForge is a **"dual-purpose" asset** that serves both:
|
||||
|
||||
- The Foundation's mission (education, community, non-profit)
|
||||
- AeThex.dev's commercial goals (revenue, talent, R&D)
|
||||
|
||||
### Asset 1: The "Talent Flywheel" (Funnel 3)
|
||||
|
||||
#### The Problem
|
||||
|
||||
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
|
||||
|
||||
1. **Entry:** New dev joins the Foundation and enters GameForge
|
||||
2. **Battleground:** They ship **3 games in 3 months**, learning:
|
||||
- **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
|
||||
|
||||
#### The Payoff
|
||||
|
||||
- **Scenario:** CORP signs a **$250,000** enterprise client project
|
||||
- **Question:** Who does CORP hire from NEXUS?
|
||||
- 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)
|
||||
|
||||
#### 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
|
||||
|
||||
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
|
||||
- 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**
|
||||
|
||||
#### The Payoff
|
||||
|
||||
- **V0 → V1 Development:** LABS patches bugs, integrates new ideas
|
||||
- **Result:** Rock-solid, battle-tested V2.0 of the "secret weapon"
|
||||
- **Deployment:** Now LABS can confidently sell this to high-paying enterprise clients
|
||||
- **Revenue Impact:** De-risked IP → Higher client confidence → Premium pricing
|
||||
|
||||
**Example Timeline:**
|
||||
|
||||
- **Month 1:** LABS releases "beta AI-PCG" to GameForge
|
||||
- **Month 1-4:** 500 GameForge devs use it, report bugs, discover uses
|
||||
- **Month 5:** LABS releases V2.0 (polished, battle-tested)
|
||||
|
|
@ -159,6 +179,7 @@ AETHEX.DEV (For-Profit)
|
|||
```
|
||||
|
||||
### The Complete Loop
|
||||
|
||||
1. **Foundation runs GameForge** (non-profit, educational)
|
||||
2. **Developers ship games, build portfolios, learn from mentors**
|
||||
3. **Top performers become "Architects"** (verified by 3 shipped games)
|
||||
|
|
@ -173,16 +194,19 @@ AETHEX.DEV (For-Profit)
|
|||
## Implementation Roadmap
|
||||
|
||||
### Phase 1 (Current): MVP
|
||||
|
||||
- ✅ Foundation landing page featuring GameForge
|
||||
- ✅ Simple `/dashboard/gameforge` placeholder with Discord/Foundation CTAs
|
||||
- 🔄 Manual operations via Discord and Trello
|
||||
|
||||
### Phase 2 (Post-Monetization)
|
||||
|
||||
- Implement basic GameForge dashboard
|
||||
- Integrate with team management
|
||||
- Link to aethex.fun (basic MVP)
|
||||
|
||||
### Phase 3 (Ecosystem Scale)
|
||||
|
||||
- Full bespoke dashboard with all 4 widgets
|
||||
- aethex.fun Arcade with full game hosting
|
||||
- LABS → GameForge beta tech distribution system
|
||||
|
|
@ -193,6 +217,7 @@ AETHEX.DEV (For-Profit)
|
|||
## Success Metrics
|
||||
|
||||
### Foundation Side (Non-Profit)
|
||||
|
||||
- Number of GameForge cohorts per month
|
||||
- Developer retention and progression
|
||||
- Mentorship satisfaction scores
|
||||
|
|
@ -200,6 +225,7 @@ AETHEX.DEV (For-Profit)
|
|||
- Community engagement metrics
|
||||
|
||||
### For-Profit Side (aethex.dev)
|
||||
|
||||
- % of NEXUS contractors who are "Architects"
|
||||
- Average project value for "Architect" projects
|
||||
- Time-to-hire reduction through verified talent
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ The `LABS` (Yellow) Arm is **100% For-Profit** and remains part of `aethex.dev`.
|
|||
### The Complete Ecosystem Picture
|
||||
|
||||
#### `aethex.foundation` (The "Guardian")
|
||||
|
||||
- **Type:** Non-Profit
|
||||
- **Primary Role:** Identity issuance and open-source research
|
||||
- **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
|
||||
|
||||
#### `aethex.dev` (The "Engine")
|
||||
|
||||
- **Type:** For-Profit
|
||||
- **Primary Role:** Commercial application platform
|
||||
- **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
|
||||
|
||||
| Aspect | Foundation | LABS |
|
||||
|--------|-----------|------|
|
||||
| **Entity Type** | Non-Profit | For-Profit |
|
||||
| **Focus** | Open-Source Research | Proprietary Development |
|
||||
| **Role** | Guardian of Axiom Protocol | Internal R&D Department |
|
||||
| **Output** | Community Knowledge | Competitive Advantage |
|
||||
| **Access** | Public | A-Corp Employees / Verified Users |
|
||||
| Aspect | Foundation | LABS |
|
||||
| --------------- | -------------------------- | --------------------------------- |
|
||||
| **Entity Type** | Non-Profit | For-Profit |
|
||||
| **Focus** | Open-Source Research | Proprietary Development |
|
||||
| **Role** | Guardian of Axiom Protocol | Internal R&D Department |
|
||||
| **Output** | Community Knowledge | Competitive Advantage |
|
||||
| **Access** | Public | A-Corp Employees / Verified Users |
|
||||
|
||||
## 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.
|
||||
|
||||
**Sample Data:**
|
||||
|
||||
- **"Axiom PCG Engine (for dev-link.me)"** [Status: In Development]
|
||||
- **".aethex TLD Smart Contracts"** [Status: In Research]
|
||||
- **"QuantumLeap Predictive Model v2"** [Status: Scoping]
|
||||
|
||||
**Functionality:**
|
||||
|
||||
- Display project status (Scoping → Research → In Development → Testing → Released)
|
||||
- Show progress indicators
|
||||
- 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 |
|
||||
|
||||
**Functionality:**
|
||||
|
||||
- Track all proprietary IP (Patents, Trademarks, Trade Secrets)
|
||||
- Show filing status and dates
|
||||
- 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.
|
||||
|
||||
**Sample Data:**
|
||||
|
||||
- "The Tech Behind PCG" [Status: Drafting]
|
||||
- "Why We Chose a .aethex TLD" [Status: Published on aethex.blog]
|
||||
|
||||
**Functionality:**
|
||||
|
||||
- List upcoming technical whitepapers and blog posts
|
||||
- Show publication status (Drafting → Review → Published)
|
||||
- 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.
|
||||
|
||||
**Functionality:**
|
||||
|
||||
- Filter NEXUS bounties by "research" category
|
||||
- Show only high-reward opportunities
|
||||
- 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
|
||||
|
||||
### Public Users (Not A-Corp Employees)
|
||||
|
||||
- See header: "Research LABS"
|
||||
- See "Join Labs?" CTA
|
||||
- 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
|
||||
|
||||
### A-Corp Employees / Verified Users
|
||||
|
||||
- Full access to all widgets
|
||||
- Can see all research tracks and progress
|
||||
- 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
|
||||
|
||||
1. **Database Tables Needed:**
|
||||
|
||||
- `labs_research_tracks` (projects, status, progress, lead_id)
|
||||
- `labs_ip_portfolio` (ip_name, type, status, filing_date, licensed_to)
|
||||
- `labs_publications` (title, description, status, published_date, content_url)
|
||||
- `labs_bounties` (links to nexus opportunities, filtered by category)
|
||||
|
||||
2. **API Endpoints:**
|
||||
|
||||
- `GET /api/labs/research-tracks` - Fetch all research tracks
|
||||
- `GET /api/labs/ip-portfolio` - Fetch IP portfolio (admin + 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)
|
||||
|
||||
3. **Soft-Gating Logic:**
|
||||
|
||||
- Check user's `arm_affiliations` table for "labs" affiliation
|
||||
- Check if user has A-Corp role or is verified member
|
||||
- Return different UI based on access level
|
||||
|
|
|
|||
Loading…
Reference in a new issue