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
|
* 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);
|
||||||
|
|
|
||||||
|
|
@ -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:", {
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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">
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue