From 72b321fc3bb3e6716af6227f9a48efd744fc17f1 Mon Sep 17 00:00:00 2001
From: dyzulk <66510723+dyzulk@users.noreply.github.com>
Date: Thu, 8 Jan 2026 18:39:38 +0700
Subject: [PATCH] feat(docs): add view details guide, fix dashboard workflows,
restore styling, and standardize icons
---
pages/_app.tsx | 2 +-
pages/guide/certificates/_meta.json | 1 +
pages/guide/certificates/download-install.mdx | 14 +++---
pages/guide/certificates/renewal.mdx | 17 +++++---
pages/guide/certificates/request-new.mdx | 15 ++++---
pages/guide/certificates/revocation.mdx | 19 ++++-----
pages/guide/certificates/view-details.mdx | 40 ++++++++++++++++++
.../getting-started/access-dashboard.mdx | 6 +--
.../guide/getting-started/install-root-ca.mdx | 6 +--
...tificate_management_view_1767869044987.png | Bin 0 -> 193276 bytes
.../certificates_list_view_1767869137654.png | Bin 0 -> 98460 bytes
11 files changed, 84 insertions(+), 36 deletions(-)
create mode 100644 pages/guide/certificates/view-details.mdx
create mode 100644 public/images/guide/certificate_management_view_1767869044987.png
create mode 100644 public/images/guide/certificates_list_view_1767869137654.png
diff --git a/pages/_app.tsx b/pages/_app.tsx
index acfd444..048541e 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -1,5 +1,5 @@
import '../styles/globals.css'
-
+
export default function App({ Component, pageProps }) {
return
}
diff --git a/pages/guide/certificates/_meta.json b/pages/guide/certificates/_meta.json
index 9f54b48..e8e7248 100644
--- a/pages/guide/certificates/_meta.json
+++ b/pages/guide/certificates/_meta.json
@@ -1,5 +1,6 @@
{
"request-new": "Requesting a Certificate",
+ "view-details": "View Details",
"download-install": "Download & Formats",
"renewal": "Renewal Process",
"revocation": "Revocation"
diff --git a/pages/guide/certificates/download-install.mdx b/pages/guide/certificates/download-install.mdx
index c9720de..5a00293 100644
--- a/pages/guide/certificates/download-install.mdx
+++ b/pages/guide/certificates/download-install.mdx
@@ -10,12 +10,16 @@ Once your certificate is issued, you can download it in various formats suitable
| **PFX / PKCS#12** | `.pfx`, `.p12` | IIS (Windows), Microsoft Exchange, Client Certificates (S/MIME). Contains both key and cert. |
| **JKS (Java)** | `.jks` | Java applications (Tomcat, Spring Boot). |
-## How to Download
+## How to Download (Copy & Save)
-1. Go to **"My Certificates"** in the dashboard.
-2. Click on the certificate ID or the **"View"** button.
-3. Scroll to the **"Downloads"** section.
-4. Select the format you need and click **Download**.
+The dashboard allows you to copy the raw certificate data directly.
+
+1. Navigate to **"My Certificates"** and click the **View (Eye Icon)** button on your certificate.
+2. **Certificate:** Scroll to the "Certificate (CRT)" section and click the **Copy Icon** in the top right. Paste this into a file named `domain.crt` or `domain.pem`.
+3. **Private Key:** Scroll to the "Private Key (KEY)" section, click **Show**, then click the **Copy Icon**. Paste this into a file named `domain.key`.
+
+> [!TIP]
+> Use a plain text editor (Notepad, VS Code, Nano) to save these files. Do not use Word or Rich Text editors.
> [!WARNING]
> The **Private Key** is generated securely. If you lose it, you cannot recover it. You must revoke and re-issue the certificate.
diff --git a/pages/guide/certificates/renewal.mdx b/pages/guide/certificates/renewal.mdx
index 15fc416..58d65a6 100644
--- a/pages/guide/certificates/renewal.mdx
+++ b/pages/guide/certificates/renewal.mdx
@@ -8,14 +8,17 @@ You will receive an email notification:
- **7 days** before expiration.
- **1 day** before expiration.
-## How to Renew
+## How to Renew (Manual Re-issue)
-1. Log in to TrustLab.
-2. Navigate to **"My Certificates"**.
-3. Identify certificates marked with the **"Expiring Soon"** badge.
-4. Click the **"Renew"** button next to the certificate.
-5. Review the details (CN, SANs). You can add or remove SANs at this stage.
-6. Click **Confirm Renewal**.
+To renew a certificate, you simply generate a fresh one with the same domain name.
+
+1. Go to **Certificates** and click **"Generate New"**.
+2. **Identity**: Enter the **same Common Name (CN)** as your expiring certificate.
+3. **Generate**: The system will issue a new certificate with a fresh validity period.
+4. **Replace**: Download the new `.crt` (and `.key` if you didn't reuse the CSI) and replace the files on your server.
+
+> [!NOTE]
+> The old certificate will remain valid until it expires naturally. You can safely delete it after verifying the new one works.
## What Happens Next?
- A **new certificate** is generated with a new validity period.
diff --git a/pages/guide/certificates/request-new.mdx b/pages/guide/certificates/request-new.mdx
index ab939ae..3879d9a 100644
--- a/pages/guide/certificates/request-new.mdx
+++ b/pages/guide/certificates/request-new.mdx
@@ -1,5 +1,5 @@
import { Steps, Callout, Cards, Card } from 'nextra/components'
-import { FileBadge, ShieldCheck, Globe, Code } from 'lucide-react'
+import { FileBadge, ShieldCheck, Globe, Code, Save, AlertTriangle } from 'lucide-react'
# Requesting a New Certificate
@@ -40,13 +40,14 @@ Toggle **"Manual Control"** if you need to override the default Identity fields
* **Country (C)**: ISO Code.
-### 4. Submit & Download
+### 4. Generate & Save
Click **Generate**.
-* **Private Key**: The system will prompt you to download the `.key` file. **This is the only time it is available.**
-* **Certificate**: The `.pem` / `.crt` file will be available for download immediately.
+* The **Certificate (.pem)** and **Private Key (.key)** will be generated.
+* You can copy them immediately or access them later from the **Certificate Details** page.
+
+}>
+ **Storage:** Your Private Key is securely stored. You can view it anytime by clicking **"View Details"** on the certificate list.
+
-
- **Security:** Your **Private Key** is shown/downloaded **ONLY ONCE**. Store it securely immediately. If lost, you must revoke and reissue the certificate.
-
diff --git a/pages/guide/certificates/revocation.mdx b/pages/guide/certificates/revocation.mdx
index e6d87a0..4439cee 100644
--- a/pages/guide/certificates/revocation.mdx
+++ b/pages/guide/certificates/revocation.mdx
@@ -7,17 +7,16 @@ Revocation invalidates a certificate before its expiration date. This is critica
- **Service Change**: The domain name effectively no longer belongs to the service.
- **Mistake**: The certificate was issued with incorrect details.
-## How to Revoke
+## How to Remove / Revoke
-1. Open the Certificate Detail page.
-2. Click the **"Revoke"** button (Danger Zone).
-3. Select a **Reason Code**:
- - `unspecified` (0)
- - `keyCompromise` (1)
- - `cACompromise` (2)
- - `superseded` (4)
- - `cessationOfOperation` (5)
-4. Confirm the action.
+If a certificate is compromised or no longer needed, you can remove it from the system.
+
+1. Go to the **Certificates** list.
+2. Identify the certificate to remove.
+3. Click the **Trash Icon** (Delete) on the right side of the row.
+4. **Confirm**: Type `DELETE` in the confirmation modal to permanently remove the certificate and its private key from TrustLab.
+
+
## CRL (Certificate Revocation List)
Once revoked, the certificate serial number is added to the TrustLab CRL. All clients checking the CRL will immediately reject the certificate.
diff --git a/pages/guide/certificates/view-details.mdx b/pages/guide/certificates/view-details.mdx
new file mode 100644
index 0000000..ad322f6
--- /dev/null
+++ b/pages/guide/certificates/view-details.mdx
@@ -0,0 +1,40 @@
+import { Callout } from 'nextra/components'
+import { ShieldAlert } from 'lucide-react'
+
+# Viewing Certificate Details
+
+After generating a certificate, you can view its full metadata, download the files, or retrieve the Private Key at any time.
+
+## Certificate List
+The main **Certificates** page lists all issuing certificates.
+* **Status Indicators**: Quickly see if a cert is `Valid`, `Expired`, or `Revoked`.
+* **Search**: Filter by Common Name or Serial Number.
+
+
+
+## Details View
+Clicking the **View Icon** (Eye) or the row opens the detailed management view.
+
+
+
+### 1. Metadata
+The top section displays critical information:
+* **Validity Period**: Start and End dates.
+* **Issuer**: The CA that signed this certificate.
+* **Subject Info**: Organization, Location, and Country.
+* **Key Strength**: 2048-bit or 4096-bit.
+
+### 2. Certificate (CRT)
+This text box contains the public certificate in **PEM format** (`-----BEGIN CERTIFICATE-----`).
+* **Copy**: Click the **Copy Icon** to copy the full block.
+* This is safe to share publicly.
+
+### 3. Private Key (KEY)
+This section contains your secret Private Key.
+* **Hidden by Default**: The specific key content is blurred/hidden for security.
+* **Show**: Click the **"Show"** button to reveal the key.
+* **Copy**: Click the **Copy Icon** to retrieve it.
+
+}>
+ **Security Warning:** Never share your Private Key. Anyone with this key can impersonate your server.
+
diff --git a/pages/guide/getting-started/access-dashboard.mdx b/pages/guide/getting-started/access-dashboard.mdx
index ea9f625..f65bd8c 100644
--- a/pages/guide/getting-started/access-dashboard.mdx
+++ b/pages/guide/getting-started/access-dashboard.mdx
@@ -1,5 +1,5 @@
import { Callout, Steps, Cards, Card } from 'nextra/components'
-import { Monitor, Smartphone, LayoutDashboard, Key, Shield } from 'lucide-react'
+import { Monitor, Smartphone, LayoutDashboard, Key, Shield, Info, Clock, AlertTriangle } from 'lucide-react'
# Accessing Dashboard
@@ -19,7 +19,7 @@ We prioritize security by offering modern, passwordless authentication options.
### 1. Single Sign-On (SSO)
The fastest way to log in. Click **Continue with Google** or **Continue with GitHub**.
-
+}>
**SSO Behavior:**
* **Existing Users:** You can only Log In via SSO if your social email address is already registered/linked to your account.
* **New Users:** You can **Register** a new account instantly by clicking the Social Login buttons on the *Sign In* or *Register* page.
@@ -39,7 +39,7 @@ You will receive an email with a unique, time-sensitive login link.
Click the **"Sign in to TrustLab"** button in the email. You will be instantly logged in to the dashboard.
-
+}>
**Expiration:** Magic links are valid for **15 minutes** only. If it expires, simply request a new one by entering your email again.
diff --git a/pages/guide/getting-started/install-root-ca.mdx b/pages/guide/getting-started/install-root-ca.mdx
index aca048a..5a420bc 100644
--- a/pages/guide/getting-started/install-root-ca.mdx
+++ b/pages/guide/getting-started/install-root-ca.mdx
@@ -1,5 +1,5 @@
import { Tabs, Steps, Cards, Card, Callout } from 'nextra/components'
-import { Monitor, Smartphone } from 'lucide-react'
+import { Monitor, Smartphone, AlertTriangle, Info } from 'lucide-react'
# Installing Root CA
@@ -43,11 +43,11 @@ Select your distribution to get the optimized installation command:
} title="macOS / iOS Profile (.mobileconfig)" href="https://cdn.trustlab.dyzulk.com/ca/bundles/trustlab-all.mobileconfig" arrow />
-
+}>
**Windows Users:** You **MUST** right-click the `.bat` file and select **"Run as Administrator"**. Double-clicking directly will likely fail due to permission restrictions.
-
+}>
**Apple Users:** After downloading the profile, go to **System Settings > Privacy & Security > Profiles** to install it. For iOS, see the *Individual Installation* section below for detailed trust steps.
diff --git a/public/images/guide/certificate_management_view_1767869044987.png b/public/images/guide/certificate_management_view_1767869044987.png
new file mode 100644
index 0000000000000000000000000000000000000000..69122f0aef50b7c4f803cf620424ea073408f2dc
GIT binary patch
literal 193276
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