chore: remove completed feature specs and apply dx fmt
All checks were successful
CI / Format (pull_request) Successful in 6m55s
CI / Clippy (pull_request) Successful in 2m28s
CI / Security Audit (pull_request) Successful in 1m46s
CI / Tests (pull_request) Successful in 2m56s
CI / Deploy (pull_request) Has been skipped
CI / Format (push) Successful in 6m15s
CI / Clippy (push) Successful in 2m16s
CI / Security Audit (push) Successful in 1m38s
CI / Tests (push) Successful in 2m45s
CI / Deploy (push) Has been skipped

Remove CAI-1 and CAI-2 feature files that have been implemented.
Apply dx fmt formatting to landing and privacy pages.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-02-19 10:35:26 +01:00
parent 58420b4547
commit 8b16eba1ad
5 changed files with 145 additions and 76 deletions

View File

@@ -237,10 +237,6 @@ The SaaS application dashboard is the landing page for the company admin to view
This project is written in dioxus with fullstack and router features. MongoDB is used as a database for maintaining user state. Keycloak is used as identity provider for user management.
## Features management
All features are detailed and described under the features folder in clear markdown instructions which are valid for both human and AI code developers.
## Code structure
The following folder structure is maintained for separation of concerns:
- src/components/*.rs : All components that are required to be rendered are placed here. These are frontend only, reusable components that are specific for the application.

View File

@@ -1,9 +0,0 @@
# CAI-1
This feature creates a new login/registration page for the GenAI admin dashboard. The user management is provided by Keycloak, which also serves the login/registration flow. The dioxus app should detect if a user is already logged-in or not, and if not, redirect the user to the keycloak landing page and after successful login, capture the user's access token in a state and save a session state.
Steps to follow:
- Create a docker-compose file for hosting a local keycloak and create a realm for testing and a client for Oauth.
- Setup the environment variables using .env. Fill the environment with keycloak URL, realm, client ID and secret.
- Create a user state in Dioxus which manages the session and the access token. Add other user identifying information like email address to the state.
- Modify dioxus to check the state and load the correct URL based on the state.

View File

@@ -1,3 +0,0 @@
# CERTifAI 2
This feature defines the types for database as well as the API between the dashboard backend and frontend.

View File

@@ -46,12 +46,16 @@ fn LandingNav() -> Element {
}
div { class: "landing-nav-actions",
Link {
to: Route::Login { redirect_url: "/dashboard".into() },
to: Route::Login {
redirect_url: "/dashboard".into(),
},
class: "btn btn-ghost btn-sm",
"Log In"
}
Link {
to: Route::Login { redirect_url: "/dashboard".into() },
to: Route::Login {
redirect_url: "/dashboard".into(),
},
class: "btn btn-primary btn-sm",
"Get Started"
}
@@ -67,9 +71,7 @@ fn HeroSection() -> Element {
rsx! {
section { class: "hero-section",
div { class: "hero-content",
div { class: "hero-badge badge badge-outline",
"Privacy-First GenAI Infrastructure"
}
div { class: "hero-badge badge badge-outline", "Privacy-First GenAI Infrastructure" }
h1 { class: "hero-title",
"Your AI. Your Data."
br {}
@@ -82,16 +84,14 @@ fn HeroSection() -> Element {
}
div { class: "hero-actions",
Link {
to: Route::Login { redirect_url: "/dashboard".into() },
to: Route::Login {
redirect_url: "/dashboard".into(),
},
class: "btn btn-primary btn-lg",
"Get Started"
Icon { icon: BsArrowRight, width: 18, height: 18 }
}
a {
href: "#features",
class: "btn btn-outline btn-lg",
"Learn More"
}
a { href: "#features", class: "btn btn-outline btn-lg", "Learn More" }
}
}
div { class: "hero-graphic",
@@ -105,27 +105,44 @@ fn HeroSection() -> Element {
defs {
linearGradient {
id: "grad1",
x1: "0%", y1: "0%",
x2: "100%", y2: "100%",
x1: "0%",
y1: "0%",
x2: "100%",
y2: "100%",
stop { offset: "0%", stop_color: "#91a4d2" }
stop { offset: "100%", stop_color: "#6d85c6" }
}
linearGradient {
id: "grad2",
x1: "0%", y1: "100%",
x2: "100%", y2: "0%",
x1: "0%",
y1: "100%",
x2: "100%",
y2: "0%",
stop { offset: "0%", stop_color: "#f97066" }
stop { offset: "100%", stop_color: "#f9a066" }
}
radialGradient {
id: "glow",
cx: "50%", cy: "50%", r: "50%",
stop { offset: "0%", stop_color: "rgba(145,164,210,0.3)" }
stop { offset: "100%", stop_color: "rgba(145,164,210,0)" }
cx: "50%",
cy: "50%",
r: "50%",
stop {
offset: "0%",
stop_color: "rgba(145,164,210,0.3)",
}
stop {
offset: "100%",
stop_color: "rgba(145,164,210,0)",
}
}
}
// Background glow
circle { cx: "200", cy: "200", r: "180", fill: "url(#glow)" }
circle {
cx: "200",
cy: "200",
r: "180",
fill: "url(#glow)",
}
// Shield outline
path {
d: "M200 40 L340 110 L340 230 C340 300 270 360 200 380 \
@@ -145,36 +162,98 @@ fn HeroSection() -> Element {
opacity: "0.8",
}
// Network nodes
circle { cx: "200", cy: "180", r: "8", fill: "url(#grad1)" }
circle { cx: "150", cy: "230", r: "6", fill: "url(#grad2)" }
circle { cx: "250", cy: "230", r: "6", fill: "url(#grad2)" }
circle { cx: "200", cy: "280", r: "6", fill: "url(#grad1)" }
circle { cx: "130", cy: "170", r: "4", fill: "#91a4d2", opacity: "0.6" }
circle { cx: "270", cy: "170", r: "4", fill: "#91a4d2", opacity: "0.6" }
circle {
cx: "200",
cy: "180",
r: "8",
fill: "url(#grad1)",
}
circle {
cx: "150",
cy: "230",
r: "6",
fill: "url(#grad2)",
}
circle {
cx: "250",
cy: "230",
r: "6",
fill: "url(#grad2)",
}
circle {
cx: "200",
cy: "280",
r: "6",
fill: "url(#grad1)",
}
circle {
cx: "130",
cy: "170",
r: "4",
fill: "#91a4d2",
opacity: "0.6",
}
circle {
cx: "270",
cy: "170",
r: "4",
fill: "#91a4d2",
opacity: "0.6",
}
// Network connections
line {
x1: "200", y1: "180", x2: "150", y2: "230",
stroke: "#91a4d2", stroke_width: "1", opacity: "0.4",
x1: "200",
y1: "180",
x2: "150",
y2: "230",
stroke: "#91a4d2",
stroke_width: "1",
opacity: "0.4",
}
line {
x1: "200", y1: "180", x2: "250", y2: "230",
stroke: "#91a4d2", stroke_width: "1", opacity: "0.4",
x1: "200",
y1: "180",
x2: "250",
y2: "230",
stroke: "#91a4d2",
stroke_width: "1",
opacity: "0.4",
}
line {
x1: "150", y1: "230", x2: "200", y2: "280",
stroke: "#91a4d2", stroke_width: "1", opacity: "0.4",
x1: "150",
y1: "230",
x2: "200",
y2: "280",
stroke: "#91a4d2",
stroke_width: "1",
opacity: "0.4",
}
line {
x1: "250", y1: "230", x2: "200", y2: "280",
stroke: "#91a4d2", stroke_width: "1", opacity: "0.4",
x1: "250",
y1: "230",
x2: "200",
y2: "280",
stroke: "#91a4d2",
stroke_width: "1",
opacity: "0.4",
}
line {
x1: "200", y1: "180", x2: "130", y2: "170",
stroke: "#91a4d2", stroke_width: "1", opacity: "0.3",
x1: "200",
y1: "180",
x2: "130",
y2: "170",
stroke: "#91a4d2",
stroke_width: "1",
opacity: "0.3",
}
line {
x1: "200", y1: "180", x2: "270", y2: "170",
stroke: "#91a4d2", stroke_width: "1", opacity: "0.3",
x1: "200",
y1: "180",
x2: "270",
y2: "170",
stroke: "#91a4d2",
stroke_width: "1",
opacity: "0.3",
}
// Checkmark inside shield center
path {
@@ -236,37 +315,49 @@ fn FeaturesGrid() -> Element {
}
div { class: "features-grid",
FeatureCard {
icon: rsx! { Icon { icon: BsServer, width: 28, height: 28 } },
icon: rsx! {
Icon { icon: BsServer, width: 28, height: 28 }
},
title: "Self-Hosted Infrastructure",
description: "Deploy on your own hardware or private cloud. \
Full control over your AI stack with no external dependencies.",
}
FeatureCard {
icon: rsx! { Icon { icon: BsShieldCheck, width: 28, height: 28 } },
icon: rsx! {
Icon { icon: BsShieldCheck, width: 28, height: 28 }
},
title: "GDPR Compliant",
description: "EU data residency guaranteed. Your data never \
leaves your infrastructure or gets shared with third parties.",
}
FeatureCard {
icon: rsx! { Icon { icon: FaCubes, width: 28, height: 28 } },
icon: rsx! {
Icon { icon: FaCubes, width: 28, height: 28 }
},
title: "LLM Management",
description: "Deploy, monitor, and manage multiple language \
models. Switch between models with zero downtime.",
}
FeatureCard {
icon: rsx! { Icon { icon: BsRobot, width: 28, height: 28 } },
icon: rsx! {
Icon { icon: BsRobot, width: 28, height: 28 }
},
title: "Agent Builder",
description: "Create custom AI agents with integrated Langchain \
and Langfuse for full observability and control.",
}
FeatureCard {
icon: rsx! { Icon { icon: BsGlobe2, width: 28, height: 28 } },
icon: rsx! {
Icon { icon: BsGlobe2, width: 28, height: 28 }
},
title: "MCP Server Management",
description: "Manage Model Context Protocol servers to extend \
your AI capabilities with external tool integrations.",
}
FeatureCard {
icon: rsx! { Icon { icon: BsKey, width: 28, height: 28 } },
icon: rsx! {
Icon { icon: BsKey, width: 28, height: 28 }
},
title: "API Key Management",
description: "Generate API keys, track usage per seat, and \
set fine-grained permissions for every integration.",
@@ -300,9 +391,7 @@ fn HowItWorks() -> Element {
rsx! {
section { id: "how-it-works", class: "how-it-works-section",
h2 { class: "section-title", "Up and Running in Minutes" }
p { class: "section-subtitle",
"Three steps to sovereign AI infrastructure."
}
p { class: "section-subtitle", "Three steps to sovereign AI infrastructure." }
div { class: "steps-grid",
StepCard {
number: "01",
@@ -353,21 +442,23 @@ fn StepCard(number: &'static str, title: &'static str, description: &'static str
fn CtaBanner() -> Element {
rsx! {
section { class: "cta-banner",
h2 { class: "cta-title",
"Ready to take control of your AI infrastructure?"
}
h2 { class: "cta-title", "Ready to take control of your AI infrastructure?" }
p { class: "cta-subtitle",
"Start deploying sovereign GenAI today. No credit card required."
}
div { class: "cta-actions",
Link {
to: Route::Login { redirect_url: "/dashboard".into() },
to: Route::Login {
redirect_url: "/dashboard".into(),
},
class: "btn btn-primary btn-lg",
"Get Started Free"
Icon { icon: BsArrowRight, width: 18, height: 18 }
}
Link {
to: Route::Login { redirect_url: "/dashboard".into() },
to: Route::Login {
redirect_url: "/dashboard".into(),
},
class: "btn btn-outline btn-lg",
"Log In"
}
@@ -389,9 +480,7 @@ fn LandingFooter() -> Element {
}
span { "CERTifAI" }
}
p { class: "footer-tagline",
"Sovereign GenAI infrastructure for enterprises."
}
p { class: "footer-tagline", "Sovereign GenAI infrastructure for enterprises." }
}
div { class: "footer-links-group",
h4 { class: "footer-links-heading", "Product" }

View File

@@ -22,9 +22,7 @@ pub fn PrivacyPage() -> Element {
}
main { class: "legal-content",
h1 { "Privacy Policy" }
p { class: "legal-updated",
"Last updated: February 2026"
}
p { class: "legal-updated", "Last updated: February 2026" }
h2 { "1. Introduction" }
p {
@@ -90,9 +88,7 @@ pub fn PrivacyPage() -> Element {
li { "Request erasure of your data" }
li { "Restrict or object to processing" }
li { "Data portability" }
li {
"Lodge a complaint with a supervisory authority"
}
li { "Lodge a complaint with a supervisory authority" }
}
h2 { "7. Contact" }