diff --git a/README.md b/README.md
index 04106b3..c08494a 100644
--- a/README.md
+++ b/README.md
@@ -84,6 +84,29 @@ trunk serve --open
* Copy the URL (e.g., `http://localhost:8080/project/my-cool-tool`).
* Send it to users. They will get a fresh clone of the environment you set up!
+## Security Architecture
+
+### Embed Authorization
+
+TryCli Studio implements a dual-layer security model for embedded projects:
+
+1. **VIP Pass (embed_key):** A private key that grants unrestricted access to embedded projects. Only project owners have access to this key.
+2. **Guest List (whitelist):** A list of authorized URLs that can embed the project publicly.
+
+#### Embed Key Protection
+
+To prevent accidental exposure of the `embed_key` through browser dev tools or network inspection:
+
+* The `embed_key` is **not** included in the main project response (`/api/project/:username/:slug`)
+* Instead, a dedicated authenticated endpoint (`/api/project/:slug/embed-key`) is used to retrieve the key
+* This endpoint requires authentication and verifies project ownership
+* The key is only fetched when the user explicitly clicks the "Share / Embed" button
+
+This separation ensures that:
+* Screen sharing during project viewing won't expose the key
+* Browser extensions or network logs won't capture the key during normal browsing
+* The key is only retrieved when intentionally needed for sharing purposes
+
## Troubleshooting
* **"Container ID not found":** Ensure you wait for the terminal to initialize before clicking Publish.
diff --git a/client/src/api.rs b/client/src/api.rs
index 4ca6589..5c23c84 100644
--- a/client/src/api.rs
+++ b/client/src/api.rs
@@ -1,4 +1,4 @@
-// CONFIGURATION HELPERS
+// CONFIGURATION HELPERS
pub fn api_base() -> &'static str {
option_env!("API_URL").unwrap_or("http://localhost:3000")
}
diff --git a/client/src/app.rs b/client/src/app.rs
index 776be65..b0cf2d2 100644
--- a/client/src/app.rs
+++ b/client/src/app.rs
@@ -1,7 +1,11 @@
+use crate::components::protected::ProtectedRoute;
+use crate::pages::{
+ admin::AdminPage, analytics::AnalyticsPage, blogs::BlogsPage, create::CreatePage,
+ dashboard::DashboardPage, docs::DocsPage, embed::EmbedPage, home::LandingPage,
+ policy::PolicyPage, view::ViewPage,
+};
use leptos::*;
use leptos_router::*;
-use crate::components::protected::ProtectedRoute;
-use crate::pages::{home::LandingPage, dashboard::DashboardPage, create::CreatePage, view::ViewPage, embed::EmbedPage, docs::DocsPage, blogs::BlogsPage, analytics::AnalyticsPage, admin::AdminPage, policy::PolicyPage};
#[component]
pub fn App() -> impl IntoView {
@@ -23,8 +27,8 @@ pub fn App() -> impl IntoView {
"Please try again later or contact the owner."
"Are you the owner?"
- "Request More Compute" - @@ -34,4 +34,4 @@ pub fn LimitReached() -> impl IntoView {+ "VIP link is being generated..." +
++ "This may take a moment. The link will appear here once ready." +
++ "Security warning:" + " This VIP link bypasses the Guest List and must only be shared privately. Do NOT embed it on public websites, iframes, or forums; anyone with this link can access your terminal." +
+ > + }.into_view() + } + }} +