From e7fe4e5526731605bc677c1b5c322b20c7ce13c8 Mon Sep 17 00:00:00 2001 From: "Rodrigo Rodriguez (Pragmatismo)" Date: Mon, 1 Dec 2025 16:15:52 -0300 Subject: [PATCH] Add documentation infrastructure and certificate pinning - Add mdBook configuration (book.toml) for documentation - Create new docs style guide appendix for conversation examples - Add WhatsApp-style chat CSS for consistent doc formatting - Replace flow diagram references with screen mockup SVGs - Create comprehensive SVG interface mockups for all Suite apps: - Main suite layout and individual app screens - Analytics, Calendar, Chat, Compliance, Designer - Drive, Mail, Meet, Paper, Player, Research - Sources, Tasks interfaces - Implement certificate pinning module (cert_pinning.rs) with: - SPKI fingerprint validation using SHA-256 - Support for primary and backup pins - Pin rotation with expiration tracking - Report-only mode for testing - Validation caching for performance - Add ring crate dependency for cryptographic operations --- Cargo.lock | 1 + Cargo.toml | 1 + docs/book.toml | 19 + docs/src/SUMMARY.md | 2 + .../conversation-examples.md | 235 +++++ .../assets/chapter-04/analytics-interface.svg | 195 ++++ .../assets/chapter-04/calendar-interface.svg | 211 +++++ .../chapter-04/compliance-interface.svg | 200 ++++ .../assets/chapter-04/designer-interface.svg | 258 ++++++ .../src/assets/chapter-04/drive-interface.svg | 155 ++++ docs/src/assets/chapter-04/mail-interface.svg | 147 +++ docs/src/assets/chapter-04/meet-interface.svg | 139 +++ .../src/assets/chapter-04/paper-interface.svg | 179 ++++ .../assets/chapter-04/research-interface.svg | 168 ++++ .../assets/chapter-04/sources-interface.svg | 206 +++++ .../assets/chapter-04/suite-main-layout.svg | 82 ++ .../src/assets/chapter-04/tasks-interface.svg | 151 ++++ docs/src/assets/suite/analytics-screen.svg | 228 +++++ docs/src/assets/suite/calendar-screen.svg | 265 ++++++ docs/src/assets/suite/chat-screen.svg | 182 ++++ docs/src/assets/suite/compliance-screen.svg | 279 ++++++ docs/src/assets/suite/designer-screen.svg | 279 ++++++ docs/src/assets/suite/drive-screen.svg | 187 ++++ docs/src/assets/suite/mail-screen.svg | 192 ++++ docs/src/assets/suite/meet-screen.svg | 185 ++++ docs/src/assets/suite/paper-screen.svg | 209 +++++ docs/src/assets/suite/player-screen.svg | 203 +++++ docs/src/assets/suite/research-screen.svg | 160 ++++ docs/src/assets/suite/sources-screen.svg | 248 +++++ docs/src/assets/suite/suite-screen.svg | 220 +++++ docs/src/assets/suite/tasks-screen.svg | 211 +++++ docs/src/assets/wa-chat.css | 209 +++++ docs/src/chapter-04-gbui/apps/analytics.md | 2 +- docs/src/chapter-04-gbui/apps/calendar.md | 2 +- docs/src/chapter-04-gbui/apps/chat.md | 2 +- docs/src/chapter-04-gbui/apps/compliance.md | 2 +- docs/src/chapter-04-gbui/apps/designer.md | 2 +- docs/src/chapter-04-gbui/apps/drive.md | 2 +- docs/src/chapter-04-gbui/apps/mail.md | 2 +- docs/src/chapter-04-gbui/apps/meet.md | 2 +- docs/src/chapter-04-gbui/apps/paper.md | 2 +- docs/src/chapter-04-gbui/apps/player.md | 2 +- docs/src/chapter-04-gbui/apps/research.md | 2 +- docs/src/chapter-04-gbui/apps/sources.md | 2 +- docs/src/chapter-04-gbui/apps/suite.md | 2 +- docs/src/chapter-04-gbui/apps/tasks.md | 2 +- docs/src/chapter-04-gbui/suite-manual.md | 254 +----- docs/src/favicon.png | Bin 0 -> 25670 bytes src/security/cert_pinning.rs | 852 ++++++++++++++++++ src/security/mod.rs | 5 + 50 files changed, 6490 insertions(+), 255 deletions(-) create mode 100644 docs/book.toml create mode 100644 docs/src/appendix-docs-style/conversation-examples.md create mode 100644 docs/src/assets/chapter-04/analytics-interface.svg create mode 100644 docs/src/assets/chapter-04/calendar-interface.svg create mode 100644 docs/src/assets/chapter-04/compliance-interface.svg create mode 100644 docs/src/assets/chapter-04/designer-interface.svg create mode 100644 docs/src/assets/chapter-04/drive-interface.svg create mode 100644 docs/src/assets/chapter-04/mail-interface.svg create mode 100644 docs/src/assets/chapter-04/meet-interface.svg create mode 100644 docs/src/assets/chapter-04/paper-interface.svg create mode 100644 docs/src/assets/chapter-04/research-interface.svg create mode 100644 docs/src/assets/chapter-04/sources-interface.svg create mode 100644 docs/src/assets/chapter-04/suite-main-layout.svg create mode 100644 docs/src/assets/chapter-04/tasks-interface.svg create mode 100644 docs/src/assets/suite/analytics-screen.svg create mode 100644 docs/src/assets/suite/calendar-screen.svg create mode 100644 docs/src/assets/suite/chat-screen.svg create mode 100644 docs/src/assets/suite/compliance-screen.svg create mode 100644 docs/src/assets/suite/designer-screen.svg create mode 100644 docs/src/assets/suite/drive-screen.svg create mode 100644 docs/src/assets/suite/mail-screen.svg create mode 100644 docs/src/assets/suite/meet-screen.svg create mode 100644 docs/src/assets/suite/paper-screen.svg create mode 100644 docs/src/assets/suite/player-screen.svg create mode 100644 docs/src/assets/suite/research-screen.svg create mode 100644 docs/src/assets/suite/sources-screen.svg create mode 100644 docs/src/assets/suite/suite-screen.svg create mode 100644 docs/src/assets/suite/tasks-screen.svg create mode 100644 docs/src/assets/wa-chat.css create mode 100644 docs/src/favicon.png create mode 100644 src/security/cert_pinning.rs diff --git a/Cargo.lock b/Cargo.lock index 48cb3d4ed..cfdb3d46b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1465,6 +1465,7 @@ dependencies = [ "regex", "reqwest 0.12.24", "rhai", + "ring 0.17.14", "rust_xlsxwriter", "rustls 0.21.12", "rustls-native-certs 0.6.3", diff --git a/Cargo.toml b/Cargo.toml index ddfe55433..c5e7c5ad7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -151,6 +151,7 @@ rcgen = { version = "0.11", features = ["pem"] } x509-parser = "0.15" rustls-native-certs = "0.6" webpki-roots = "0.25" +ring = "0.17" time = { version = "0.3", features = ["formatting", "parsing"] } jsonwebtoken = "9.3" tower-cookies = "0.10" diff --git a/docs/book.toml b/docs/book.toml new file mode 100644 index 000000000..1ab88b9e4 --- /dev/null +++ b/docs/book.toml @@ -0,0 +1,19 @@ +[book] +title = "General Bots Documentation" +authors = ["General Bots Team"] +language = "en" +multilingual = false +src = "src" + +[build] +build-dir = "book" + +[output.html] +default-theme = "light" +preferred-dark-theme = "navy" +smart-punctuation = true +additional-css = ["src/custom.css", "src/whatsapp-chat.css"] +additional-js = ["src/theme-sync.js"] + +[output.html.favicon] +png = "favicon.png" diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md index 4642cd460..4179456fd 100644 --- a/docs/src/SUMMARY.md +++ b/docs/src/SUMMARY.md @@ -317,5 +317,7 @@ - [Appendix C: Environment Variables](./appendix-env-vars/README.md) +- [Appendix D: Documentation Style](./appendix-docs-style/conversation-examples.md) + [Glossary](./glossary.md) [Contact](./contact/README.md) \ No newline at end of file diff --git a/docs/src/appendix-docs-style/conversation-examples.md b/docs/src/appendix-docs-style/conversation-examples.md new file mode 100644 index 000000000..12f0e5e16 --- /dev/null +++ b/docs/src/appendix-docs-style/conversation-examples.md @@ -0,0 +1,235 @@ +# Conversation Examples Style Guide + +> **Standard format for displaying bot-user conversations in documentation** + +## Overview + +All conversation examples in General Bots documentation use a WhatsApp-style chat format. This provides a consistent, familiar, and readable way to show bot interactions. + +## CSS Include + +The styling is defined in `/assets/wa-chat.css`. Include it in your mdBook or HTML output. + +--- + +## Basic Structure + +```html +
+ + +
+``` + +--- + +## Message Types + +### Bot Message + +```html +
+ +
+``` + +### User Message + +```html +
+ +
+``` + +--- + +## Formatting Within Messages + +### Multiple Paragraphs + +```html +
+

You have 2 meetings scheduled:

+

โ€ข 2:00 PM - Team Standup (30 min)

+

โ€ข 4:00 PM - Project Review (1 hour)

+ +
+``` + +### Bold Text + +```html +

Name: John Smith

+

Email: john@example.com

+``` + +### Emoji Usage + +Emojis are encouraged to make conversations more expressive: + +| Purpose | Emoji Examples | +|---------|----------------| +| Success | โœ… โœ“ ๐ŸŽ‰ | +| Warning | โš ๏ธ โšก | +| Error | โŒ ๐Ÿ”ด | +| Info | โ„น๏ธ ๐Ÿ“‹ | +| File | ๐Ÿ“„ ๐Ÿ“ ๐Ÿ“Ž | +| Calendar | ๐Ÿ“… ๐Ÿ—“๏ธ | +| Email | ๐Ÿ“ง โœ‰๏ธ | +| Person | ๐Ÿ‘ค ๐Ÿ‘ฅ | +| Time | ๐Ÿ• โฑ๏ธ | + +### File Attachments + +```html +
+ +
+``` + +### Action Buttons (visual representation) + +```html +

[๐Ÿ“ง Send] [โœ๏ธ Edit] [๐Ÿ—‘ Discard]

+``` + +--- + +## Complete Example + +```html +
+ + +
+``` + +**Rendered Output:** + +
+ + +
+ +--- + +## Variants + +### Full Width + +Add `wa-full-width` class for wider conversations: + +```html +
+ ... +
+``` + +### Compact + +Add `wa-compact` class for tighter spacing: + +```html +
+ ... +
+``` + +### Hide Timestamps + +Add `wa-no-time` class to hide timestamps: + +```html +
+ ... +
+``` + +--- + +## Best Practices + +1. **Keep messages concise** - Break long bot responses into multiple paragraphs +2. **Use consistent timestamps** - Use realistic times (10:30, 10:31, etc.) +3. **Start with user context** - Show what the user asked before the bot response +4. **Include visual feedback** - Use emojis for status (โœ…, โŒ, ๐Ÿ“‹) +5. **Show realistic flows** - Include multi-turn conversations when appropriate +6. **Use semantic formatting** - Bold for labels, lists for options + +--- + +## Files Using This Format + +This format is used throughout the documentation: + +- `chapter-02/template-crm-contacts.md` +- `chapter-04-gbui/apps/*.md` +- `chapter-06-gbdialog/basic-vs-automation-tools.md` +- And many more... + +--- + +## See Also + +- [UI Structure](../chapter-04-gbui/ui-structure.md) +- [Chat App Documentation](../chapter-04-gbui/apps/chat.md) + + \ No newline at end of file diff --git a/docs/src/assets/chapter-04/analytics-interface.svg b/docs/src/assets/chapter-04/analytics-interface.svg new file mode 100644 index 000000000..b6186eb2a --- /dev/null +++ b/docs/src/assets/chapter-04/analytics-interface.svg @@ -0,0 +1,195 @@ + + + + + Analytics - Dashboard Interface + + + + + + + + + + ๐Ÿ“Š Analytics Dashboard + + + + + Last 24h โ–ผ + + + + + + โŸณ Refresh + + + + + + + + + + 1,234 + Messages + โ†‘ +12% + + + + 89% + Success Rate + โ†‘ +3% + + + + 2.3s + Avg Response + โ†“ -0.2s + + + + 45 + Users Today + โ†‘ +8 + + + + + + + Messages Over Time + + + + + + + + + + + + + + + + + + + + + + + Mon + Tue + Wed + Thu + Fri + + + + + Top Questions + + + + 1. How do I reset... + + + + 2. What is the status... + + + + 3. Where can I find... + + + + 4. Help with login + + + + + + + + + ๐Ÿ“ˆ Peak Hour: + 2:00 PM + + + + ๐Ÿ” Top Intent: + Support Query + + + + โšก Avg Session: + 4.2 min + + + + ๐ŸŽฏ Resolution: + 94% + + + + Export + + + + + Metrics: Real-time KPIs + Charts: Trends & Distribution + Time Range: Last 24h, 7d, 30d, Custom + Shortcuts: R = Refresh | E = Export + + diff --git a/docs/src/assets/chapter-04/calendar-interface.svg b/docs/src/assets/chapter-04/calendar-interface.svg new file mode 100644 index 000000000..7e2664fb4 --- /dev/null +++ b/docs/src/assets/chapter-04/calendar-interface.svg @@ -0,0 +1,211 @@ + + + + + Calendar - Scheduling Interface + + + + + + + + + + + + + โ—„ + + + โ–บ + + + March 2024 + + + + + + Day + + + Week + + + Month + + + + + + + + + + Mon + Tue + Wed + Thu + Fri + Sat + Sun + + + + + + + + + + 1 + + 2 + + 3 + + + + + + + 4 + + + 5 + + + Team Meeting + + + 6 + + + 7 + + + 8 + + + 9 + + + 10 + + + + + + 11 + + + 12 + + + 13 + + + Project Review + + + 14 + + + 1:1 Meeting + + + + + 15 + + + 16 + + + 17 + + + + + + 18 + + + 19 + + + 20 + + + 21 + + + 22 + + + 23 + + + 24 + + + + + + + + + + + + + + Today + + + Event + + + Weekend + + Shortcuts: N = New event | T = Today | โ† โ†’ = Navigate | D/W/M = View + + diff --git a/docs/src/assets/chapter-04/compliance-interface.svg b/docs/src/assets/chapter-04/compliance-interface.svg new file mode 100644 index 000000000..2fa4d89bf --- /dev/null +++ b/docs/src/assets/chapter-04/compliance-interface.svg @@ -0,0 +1,200 @@ + + + + + Compliance - Security Scanner Interface + + + + + + + + + + ๐Ÿ›ก Compliance Scanner + + + + + Scan + + + Export + + + + + + + + + + + 2 + Critical + ๐Ÿ”ด Immediate + + + + + 5 + High + ๐ŸŸ  Priority + + + + + 3 + Medium + ๐ŸŸก Review + + + + + 1 + Low + ๐ŸŸข Minor + + + + + 0 + Info + โ„น Notes + + + + + + + + + + Severity + Issue + File + Action + + + + + Critical + Hardcoded password detected + start.bas:15 + + Fix + + + + + Critical + API key exposed in code + api.bas:42 + + Fix + + + + + High + SQL injection risk in query + data.bas:28 + + Review + + + + + High + Insecure HTTP endpoint + config.csv:8 + + Review + + + + + Medium + Missing input validation + form.bas:55 + + Review + + + + + Last scan: 2 minutes ago + Files scanned: 24 + Total issues: 11 + + + Showing 1-5 of 11 + + โ† + + โ†’ + + + + + + Critical + + + High + + + Medium + + + Low + + Fix = Auto-remediate | Review = Manual inspection needed + + LGPD โ€ข GDPR โ€ข CCPA + + diff --git a/docs/src/assets/chapter-04/designer-interface.svg b/docs/src/assets/chapter-04/designer-interface.svg new file mode 100644 index 000000000..e4218f5da --- /dev/null +++ b/docs/src/assets/chapter-04/designer-interface.svg @@ -0,0 +1,258 @@ + + + + + + + + + + + Designer - Visual Builder Interface + + + + + + + + + + + + Toolbox + + + + + + ๐Ÿ’ฌ + TALK + + + + ๐Ÿ‘‚ + HEAR + + + + ๐Ÿ“ + SET + + + + + + + ๐Ÿ”€ + IF + + + + ๐Ÿ”„ + FOR + + + + ๐Ÿ”ƒ + SWITCH + + + + + + + ๐Ÿ“ž + CALL + + + + ๐Ÿ“ง + SEND + + + + ๐Ÿ’พ + SAVE + + + + + + + + + + + + + + + + + + + + + + + ๐Ÿ’ฌ TALK + "Hello!" + + + + + + + ๐Ÿ‘‚ HEAR + name + + + + + + + ๐Ÿ”€ IF + name = "Jo" + + + Yes + No + + + + + + + + + + ๐Ÿ’ฌ TALK + "Hi Jo!" + + + + ๐Ÿ’ฌ TALK + "Hello!" + + + + + + + + + + Properties + + + + Node: + TALK + + + + Message: + + "Hello!" + + + + Voice: + + Default โ–ผ + + Delay: + + 0ms + + + + + + Apply + + + Delete + + + + + + + + + + โˆ’ + + + โŒ– + + 100% + + + โ–ถ Run + + + + + + Talk + + + Hear + + + Condition + + Drag nodes from Toolbox โ†’ Canvas | Connect by dragging + + Shortcuts: Delete | Ctrl+D = Duplicate | Ctrl+Z = Undo + + diff --git a/docs/src/assets/chapter-04/drive-interface.svg b/docs/src/assets/chapter-04/drive-interface.svg new file mode 100644 index 000000000..1343a497a --- /dev/null +++ b/docs/src/assets/chapter-04/drive-interface.svg @@ -0,0 +1,155 @@ + + + + + Drive - File Management Interface + + + + + + + + + + + + New โ–ผ + + + + ๐Ÿ” Search files... + + + + + โŠž + + โ‰ก + + + + + + + + + + + + + ๐Ÿ“ My Drive + + โญ Starred + ๐Ÿ• Recent + ๐Ÿ—‘ Trash + + + + Labels + + Work + + Personal + + + + ๐Ÿ“ My Drive โ€บ Projects โ€บ 2024 + + + + + โ˜ + Name + Size + Modified + + + + + + + โ˜ + ๐Ÿ“ + Reports + โ€” + Today + + + + โ˜ + ๐Ÿ“ + Presentations + โ€” + Yesterday + + + + โ˜ + ๐Ÿ“„ + Budget.xlsx + 245 KB + Mar 15 + + + + โ˜ + ๐Ÿ“„ + Notes.docx + 12 KB + Mar 14 + + + + โ˜ + ๐Ÿ–ผ + Logo.png + 89 KB + Mar 10 + + + + + ๐Ÿ“ค Drag files here to upload + or click + New to create + + + + Sidebar: Quick access, Labels + Main: File browser with sort columns + Actions: Upload, Create, Search, View toggle + + diff --git a/docs/src/assets/chapter-04/mail-interface.svg b/docs/src/assets/chapter-04/mail-interface.svg new file mode 100644 index 000000000..058afd650 --- /dev/null +++ b/docs/src/assets/chapter-04/mail-interface.svg @@ -0,0 +1,147 @@ + + + + + Mail - Email Client Interface + + + + + + + + + + + โœ Compose + + + + + + ๐Ÿ“ฅ Inbox + + 3 + + ๐Ÿ“ค Sent + ๐Ÿ“ Drafts + ๐Ÿ—‘ Trash + + + + + + + + + Inbox + + + + + + + Project Update + from John + 10:30 AM + + + + + + Meeting Notes + from Sarah + Yesterday + + + + + + Invoice #1234 + from Vendor + Mar 15 + + + + + + + + + From: + john@company.com + + Subject: + Project Update + + + + + + + + Hi, + Here's the latest update on our project. + We've completed the first milestone and + are now moving to phase two. + Best, + John + + + + + + Reply + + + Forward + + + Delete + + + + + Sidebar: Folders + List: Email threads + Content: Read and reply + Shortcuts: C = Compose | R = Reply | F = Forward + + diff --git a/docs/src/assets/chapter-04/meet-interface.svg b/docs/src/assets/chapter-04/meet-interface.svg new file mode 100644 index 000000000..ddb394337 --- /dev/null +++ b/docs/src/assets/chapter-04/meet-interface.svg @@ -0,0 +1,139 @@ + + + + + Meet - Video Calls Interface + + + + + + + + + + Meeting Room + + + 00:15:32 + + + + + + ๐Ÿ‘ฅ + 3 + + + + ๐Ÿ’ฌ + + + + + + + + + + + ๐Ÿ‘ค + You + (Camera) + + + You + + + ๐ŸŽค + + + + + ๐Ÿ‘ค + John + (Camera) + + + John + + + + + ๐Ÿ‘ค + Sarah + + + Sarah + + + + + + + + + + + ๐ŸŽค + + + + ๐Ÿ“น + + + + ๐Ÿ–ฅ + + + + ๐Ÿ”ด + + + + ๐Ÿ“ + + + + ๐Ÿ“ž + + + + + + Active + + + Muted/End + + + Available + + Shortcuts: M = Mute | V = Video | S = Share | Space = Push-to-talk + + diff --git a/docs/src/assets/chapter-04/paper-interface.svg b/docs/src/assets/chapter-04/paper-interface.svg new file mode 100644 index 000000000..9b89485ce --- /dev/null +++ b/docs/src/assets/chapter-04/paper-interface.svg @@ -0,0 +1,179 @@ + + + + + Paper - AI Writing Interface + + + + + + + + + + ๐Ÿ“„ Notes + + + + + + + Meeting Notes + + Project Plan + Ideas + + + + Quick Start + ๐Ÿ“„ Blank + ๐Ÿ“‹ Meeting + โœ“ To-Do + ๐Ÿ”ฌ Research + + + + + + + + + + + + + + B + + + + I + + + + U + + + + + + + H1 + + + + H2 + + + + + + + โ€ข + + + + โ€• + + + + ๐Ÿ”— + + + + ๐Ÿ“ท + + + + AI โœจ + + + + + + + + + Project Proposal + + + + Introduction + + + + This document outlines our proposal for + the upcoming project. We aim to deliver + a comprehensive solution that addresses + all stakeholder requirements. + + + + + + Key Objectives + โ€ข Improve efficiency by 30% + โ€ข Reduce costs through automation + โ€ข Enhance user experience + + + + + Words: 156 + Characters: 892 + Reading time: 1 min + โœ“ Auto-saved 2 min ago + + + + + + AI Assist + + Shortcuts: Ctrl+B = Bold | Ctrl+I = Italic | Ctrl+S = Save | Ctrl+/ = AI + + Markdown supported + + diff --git a/docs/src/assets/chapter-04/research-interface.svg b/docs/src/assets/chapter-04/research-interface.svg new file mode 100644 index 000000000..c69854c30 --- /dev/null +++ b/docs/src/assets/chapter-04/research-interface.svg @@ -0,0 +1,168 @@ + + + + + Research - AI Search Interface + + + + + + + + + + ๐Ÿ” Research + + + + + Focus: + + + + ๐ŸŒ All + + ๐Ÿ“š Academic + ๐Ÿ’ป Code + ๐Ÿ  Internal + + + + + Collections: + ๐Ÿ“ + Project A + ๐Ÿ“ + References + + + + + Recent: + โ€ข market size + โ€ข competitors + โ€ข best practices + + + + + + + + + What are the best practices for... + + โ†’ + + + + + + + + AI Answer: + + + + Based on multiple sources, here are the key best practices: + + 1. Start with clear requirements and objectives + 2. Use iterative development with frequent feedback + 3. Test early and often with real users + 4. Document decisions and maintain knowledge base + + + + + Sources: + + + + [1] + industry-guide.com + Best practices for software + development in 2024... + + + [2] + techblog.dev + Modern development + methodology overview... + + + [3] + your-docs/guidelines.pdf + ๐Ÿ“„ Internal document + Company guidelines... + + + + + + ๐Ÿ“ Save + + + ๐Ÿ“ค Share + + + ๐Ÿ”„ Deep Dive + + + ๐Ÿ“‹ Copy + + + + + + AI Summary + + + Sources + + Focus: Web โ€ข Academic โ€ข Code โ€ข Internal docs + + Enter = Search | Ctrl+S = Save + + diff --git a/docs/src/assets/chapter-04/sources-interface.svg b/docs/src/assets/chapter-04/sources-interface.svg new file mode 100644 index 000000000..099f94008 --- /dev/null +++ b/docs/src/assets/chapter-04/sources-interface.svg @@ -0,0 +1,206 @@ + + + + + Sources - Prompts & Templates Interface + + + + + + + + + + Sources + + + + + ๐Ÿ” Search... + + + + + + + + + Prompts + + + Templates + + + MCP Servers + + + LLM Tools + + + Models + + + + + + + + + + + + Categories + + + + + ๐Ÿ“ Writing + + ๐Ÿ“Š Analysis + ๐Ÿ’ผ Business + ๐Ÿ’ป Code + ๐ŸŽจ Creative + ๐Ÿค– Automation + ๐Ÿ“ž Support + + + + + + โญ Featured + + + + Customer + Service + + Handle support + inquiries with AI + assistance + + + Use + + โ˜… + + + + Sales + Assistant + + Qualify leads and + schedule meetings + automatically + + + Use + + โ˜… + + + + Code + Helper + + Generate and + explain code + snippets + + + Use + + + All Prompts + + + + Meeting Notes + Summarize meetings + + Writing + + Use + + + Data Analyst + Analyze datasets + + Analysis + + Use + + + Email Writer + Draft pro emails + + Business + + Use + + + Story Writer + Creative stories + + Creative + + Use + + + + + Page 1 of 5 + + โ† + + โ†’ + + + + + Tabs: Prompts, Templates, MCP Servers, LLM Tools, Models + Categories filter content + Click Use to apply prompt/template + + diff --git a/docs/src/assets/chapter-04/suite-main-layout.svg b/docs/src/assets/chapter-04/suite-main-layout.svg new file mode 100644 index 000000000..f0368f61c --- /dev/null +++ b/docs/src/assets/chapter-04/suite-main-layout.svg @@ -0,0 +1,82 @@ + + + + + Suite - Main Layout + + + + + + + + + + + ๐Ÿค– + General Bots + + + + + + โ‹ฎโ‹ฎโ‹ฎ + + + + ๐ŸŒ™ + + + + U + + + + + + + + + + ๐Ÿ’ฌ + Chat + (Main Area) + + + + Type your message here... + + + + Send + + + + Header: Navigation, Apps Menu, Theme, Profile + Main: AI Chat Interface with Message Input + + diff --git a/docs/src/assets/chapter-04/tasks-interface.svg b/docs/src/assets/chapter-04/tasks-interface.svg new file mode 100644 index 000000000..f3f91c2a7 --- /dev/null +++ b/docs/src/assets/chapter-04/tasks-interface.svg @@ -0,0 +1,151 @@ + + + + + Tasks - To-Do Management Interface + + + + + + + + + + โœ“ Tasks + + Total: + 12 + Active: + 5 + Done: + 7 + + + + + + + + + What needs to be done? + + + + Category โ–ผ + + + + + Add + + + + + + + + + ๐Ÿ“‹ All (12) + + + โณ Active (5) + + + โœ“ Completed (7) + + + โšก Priority + + + + + + + + + + + Review quarterly report + ๐Ÿ“… Today + + + + + + Call client about proposal + ๐Ÿ“… Today + + + + + + Update project documentation + ๐Ÿ“… Tomorrow + + + + + + โœ“ + Send meeting notes + โœ“ Done + + + + + โœ“ + Complete expense report + โœ“ Done + + + + + Priority: + + High + + Medium + + Low + + Shortcuts: Enter = Add | Space = Toggle | Delete = Remove + + diff --git a/docs/src/assets/suite/analytics-screen.svg b/docs/src/assets/suite/analytics-screen.svg new file mode 100644 index 000000000..7dee1347f --- /dev/null +++ b/docs/src/assets/suite/analytics-screen.svg @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + Analytics - Dashboard + + + + + + + Dashboard Overview + Last 30 days โ€ข Updated 5 min ago + + + + + + ๐Ÿ“… + Last 30 days + โ–พ + + + Export + + + + + + + + + Total Users + 12,847 + โ†‘ 12.5% + vs last month + + ๐Ÿ‘ฅ + + + + + Active Sessions + 1,429 + โ†‘ 8.2% + vs last month + + ๐Ÿ“Š + + + + + Avg Response Time + 1.2s + โ†“ 15% + faster + + โšก + + + + + Satisfaction Rate + 94.2% + โ†‘ 2.1% + vs last month + + โญ + + + + + + + + User Activity + Daily active users + + + + + + + + + 2k + 1.5k + 1k + 500 + + + + + + + + + + + + + + + + + + 1 + 8 + 15 + 22 + 30 + March 2024 + + + + + Messages by Type + + + + + + + + + Chat + Email + Voice + Other + + + 4.2k + 3.1k + 1.8k + 890 + + + + + + + + Top Queries + + 1. "How do I reset my password?" + 847 + + 2. "Billing information" + 623 + + 3. "Schedule a meeting" + 512 + + View all โ†’ + + + + + Performance + + Resolution Rate + + + 85% + + Escalation Rate + + + 15% + + + + + R = Refresh | E = Export | D = Date range | F = Filter + + diff --git a/docs/src/assets/suite/calendar-screen.svg b/docs/src/assets/suite/calendar-screen.svg new file mode 100644 index 000000000..d2b3204ec --- /dev/null +++ b/docs/src/assets/suite/calendar-screen.svg @@ -0,0 +1,265 @@ + + + + + + + + + + + Calendar - Schedule Manager + + + + + + + + + + + + + New Event + + + + + + โ—€ + March 2024 + โ–ถ + + + + + S + M + T + W + T + F + S + + + + + 25 + 26 + 27 + 28 + 29 + 1 + 2 + + + + + 3 + 4 + 5 + 6 + 7 + 8 + 9 + + + + + 10 + 11 + 12 + 13 + 14 + + 15 + 16 + + + + + 17 + 18 + 19 + 20 + 21 + 22 + 23 + + + + + 24 + 25 + 26 + 27 + 28 + 29 + 30 + + + + + + MY CALENDARS + + + + Personal + + + + + Work + + + + + Family + + + + + + + + Today + + โ—€ + โ–ถ + + March 15, 2024 + + + + + Day + + Week + Month + + + + + + + + + SUN + 10 + + MON + 11 + + TUE + 12 + + WED + 13 + + THU + 14 + + FRI + + 15 + + SAT + 16 + + + + + + 8 AM + 9 AM + 10 AM + 11 AM + 12 PM + 1 PM + 2 PM + 3 PM + 4 PM + 5 PM + + + + + + + + + + + + + + + + + + + + + + + + + Team Standup + 9:00 - 10:00 + + + + Client Call + 11:00 - 12:00 + + + + Project Review + 2:00 - 3:00 + + + + 1:1 Meeting + 4:00 - 5:00 + + + + + + + + + Click to create | Drag to reschedule | Double-click to edit + + diff --git a/docs/src/assets/suite/chat-screen.svg b/docs/src/assets/suite/chat-screen.svg new file mode 100644 index 000000000..eefb81de2 --- /dev/null +++ b/docs/src/assets/suite/chat-screen.svg @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + Chat - AI Assistant + + + + + + + + + + + GB + General Bots + + + + + + โ˜€๏ธ + Light + + + + + + + + + + + + + JD + + + + + + + + + + + + + + + + AI Assistant + Hello! I'm your AI assistant. How can I help + you today? + + + + + + What meetings do I have scheduled for today? + + + + + + AI Assistant + You have 3 meetings scheduled for today: + ๐Ÿ“… 10:00 AM - Team Standup (30 min) + ๐Ÿ“… 2:00 PM - Client Call with Acme Corp (1 hr) + ๐Ÿ“… 4:30 PM - 1:1 with Manager (30 min) + + + + + + + + + + + + + + + + + + + + + ๐Ÿ“ง Check my email + + + โœ“ Show my tasks + + + ๐Ÿ” Search documents + + + ๐Ÿ“ Take notes + + + + + + + + Message... + + + + + ๐ŸŽค + + + + + + โ†‘ + + + + + + + + โ†“ + + + + + ๐Ÿ’ก Tip: Use / for commands, @ to mention, # for tags + Enter = Send | Shift+Enter = New line | โ†‘ = Edit last + + diff --git a/docs/src/assets/suite/compliance-screen.svg b/docs/src/assets/suite/compliance-screen.svg new file mode 100644 index 000000000..c8b4c4f6c --- /dev/null +++ b/docs/src/assets/suite/compliance-screen.svg @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + Compliance - Security Scanner + + + + + + + + + + + + ๐Ÿ” Run Scan + + + + + SCAN TYPES + + + + ๐Ÿ›ก๏ธ + All Checks + + + + ๐Ÿ” + Security + + + + ๐Ÿ“‹ + Privacy + + + + โšก + Performance + + + + โ™ฟ + Accessibility + + + + + + FRAMEWORKS + + + + GDPR + + + + + SOC 2 + + + + + HIPAA + + + + + ISO 27001 + + + + + + Security Overview + Last scan: 5 minutes ago โ€ข Next scheduled: 24 hours + + + + + + ๐Ÿ“„ Export + + + + + + + + + Overall Score + 87 + /100 + โ†‘ 5 pts + + + + + Passed + 42 + + 89% + + + + + Warnings + 4 + + 8% + + + + + Critical + 1 + + 2% + + + + + Issues Found + + + + + + + ๐Ÿšจ + Insecure API Endpoint Detected + /api/v1/users lacks authentication โ€ข Found 2 hours ago + + Critical + + Fix + + + + + + + + โš ๏ธ + Outdated SSL Certificate + Certificate expires in 15 days โ€ข Renewal recommended + + Warning + + Fix + + + + + + + + โš ๏ธ + Missing Content Security Policy + CSP header not configured โ€ข XSS vulnerability risk + + Warning + + Fix + + + + + + + + โœ“ + Data Encryption at Rest + AES-256 encryption enabled โ€ข All data stores compliant + + Passed + + + + + + Compliance Progress + + + + GDPR + + + 95% + + + + + SOC 2 + + + 90% + + + + + HIPAA + + + 75% + + + + + ISO 27001 + + + 88% + + + + + + R = Rescan | F = Filter by severity | E = Export report | Enter = View details + + diff --git a/docs/src/assets/suite/designer-screen.svg b/docs/src/assets/suite/designer-screen.svg new file mode 100644 index 000000000..c6fbb0daf --- /dev/null +++ b/docs/src/assets/suite/designer-screen.svg @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + Designer - Visual Flow Builder + + + + + + + + + Components + + + + + TRIGGERS + + + + + โ–ถ + Start + + + + + + ๐Ÿ’ฌ + Message + + + + ACTIONS + + + + + ๐Ÿค– + AI Response + + + + + + ๐Ÿ“ง + Send Email + + + + + + โšก + API Call + + + + LOGIC + + + + + โ—‡ + Condition + + + + + + โฑ + Wait + + + + + + โฌค + End + + + + + + + + + + + + + + Add + + + โ†ฉ + + + โ†ช + + + + + ๐Ÿ” + + + + + + + โˆ’ + + 100% + + + + + โ–ถ Test + + + Deploy + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + โ–ถ + Start + User message + + + + + + + ๐Ÿค– + AI Response + GPT-4 Model + + + + + + + + โ—‡ + Condition + intent == support + + + + + + + ๐Ÿ“ง + Send Email + Support team + + + + + + + โฌค + End + Complete flow + + + + + + + Properties + + + NODE + AI Response + + MODEL + + + GPT-4 + โ–พ + + PROMPT + + + You are a + helpful + assistant... + + TEMPERATURE + + + 0.7 + + + + + Drag to connect | Del = Delete | Ctrl+D = Duplicate | Ctrl+Z = Undo + + diff --git a/docs/src/assets/suite/drive-screen.svg b/docs/src/assets/suite/drive-screen.svg new file mode 100644 index 000000000..301572825 --- /dev/null +++ b/docs/src/assets/suite/drive-screen.svg @@ -0,0 +1,187 @@ + + + + + + + + + + + Drive - File Manager + + + + + + + + + + + New + + + + + My Drive + ๐Ÿ“ + + ๐Ÿ‘ฅ + Shared with me + + โญ + Starred + + ๐Ÿ• + Recent + + ๐Ÿ—‘๏ธ + Trash + + + + STORAGE + + + 6.5 GB of 10 GB + + + + + + ๐Ÿ” + Search files... + + + โŠž + + + โ‰ก + + + โš™ + + + + My Drive + / + Projects + / + 2024 + + + + + Name + Modified + Size + Owner + + + + + + โœ“ + ๐Ÿ“ + Reports + Today, 10:30 AM + โ€” + me + + + + + + ๐Ÿ“ + Presentations + Yesterday + โ€” + me + + + + + ๐Ÿ“Š + Budget-2024.xlsx + Mar 15, 2024 + 245 KB + me + + + + + ๐Ÿ“„ + Project-Proposal.docx + Mar 14, 2024 + 128 KB + me + + + + + ๐Ÿ“• + Contract-Signed.pdf + Mar 10, 2024 + 1.2 MB + John D. + + + + + ๐Ÿ–ผ๏ธ + Logo-Final.png + Mar 8, 2024 + 89 KB + me + + + + + ๐Ÿ“ค + Drop files here or click + New to upload + + + + 1 item selected + โ€ข + 6 items + Ctrl+U Upload | Del Delete | Ctrl+C Copy + + diff --git a/docs/src/assets/suite/mail-screen.svg b/docs/src/assets/suite/mail-screen.svg new file mode 100644 index 000000000..1f10fedbf --- /dev/null +++ b/docs/src/assets/suite/mail-screen.svg @@ -0,0 +1,192 @@ + + + + + + + + + + + Mail - Email Client + + + + + + + + + + + + โœ Compose + + + + + + ๐Ÿ“ฅ + Inbox + 3 + + ๐Ÿ“ค + Sent + + ๐Ÿ“ + Drafts + + โญ + Starred + + ๐Ÿ—‘๏ธ + Trash + + + + + + + + + Inbox + + ๐Ÿ”„ + + + + + + + + + + Sarah Johnson + 10:30 AM + Project Update + Hi team, here is the latest... + + + + + + + Marketing Team + 9:15 AM + Q4 Campaign Results + The numbers are in and... + + + + + + + John Smith + Yesterday + Meeting Notes + Thanks for the call today... + + + + + Alex Chen + Mar 15 + Re: Budget Review + Looks good to me... + + + + HR Department + Mar 14 + Benefits Enrollment + Open enrollment starts... + + + + + + + + Meeting Notes + + + + JS + + John Smith + john.smith@company.com + + Yesterday, 3:45 PM + + + + + + + + + โ†ฉ Reply + + + โ†ฉโ†ฉ Reply All + + + โ†ช Forward + + + ๐Ÿ—‘ Delete + + + + + + + Hi Team, + Thanks for joining the call today. Here are the key + takeaways from our discussion: + + โ€ข Project timeline updated to Q2 launch + โ€ข Budget approved for additional resources + โ€ข Next review scheduled for Friday + + Let me know if you have any questions. + + Best regards, + John + + + + + Ctrl+R Reply | Ctrl+Shift+R Reply All | Ctrl+F Forward | Del Delete + + diff --git a/docs/src/assets/suite/meet-screen.svg b/docs/src/assets/suite/meet-screen.svg new file mode 100644 index 000000000..fda3f4972 --- /dev/null +++ b/docs/src/assets/suite/meet-screen.svg @@ -0,0 +1,185 @@ + + + + + + + + + + + + + + + Meet - Video Conference + + + + + + + + + + + JS + John Smith + Speaking... + + + + + + + + + + + + + + + Team Standup โ€ข 15:32 + + + + + + + ME + You + + + + + + Participants (5) + + + + + + SW + Sarah Wilson + + Online + + + + + + + MJ + Mike Johnson + + Muted + + + + + + + AC + Alex Chen + + Online + + + + + + + EM + Emma Miller + + Online + + + + + + + Invite People + + + + + + + + + Team Standup + 5 participants โ€ข 15:32 + + + + + + + ๐ŸŽค + + + + ๐Ÿ“น + + + + ๐Ÿ–ฅ + + + + ๐Ÿ’ฌ + + + + ๐Ÿ“ž + + + + + + + โš™ + + + + โ›ถ + + + + โŠž + + + + + M = Mute | V = Camera | S = Share Screen | C = Chat | L = Leave + + diff --git a/docs/src/assets/suite/paper-screen.svg b/docs/src/assets/suite/paper-screen.svg new file mode 100644 index 000000000..c3306d5e9 --- /dev/null +++ b/docs/src/assets/suite/paper-screen.svg @@ -0,0 +1,209 @@ + + + + + + + + + + + Paper - AI Writing Assistant + + + + + + + + + + + + + New Document + + + + + RECENT DOCUMENTS + + + + ๐Ÿ“„ + Project Proposal + Edited 2 min ago + + + + ๐Ÿ“„ + Meeting Notes + Edited yesterday + + + + ๐Ÿ“„ + Q4 Report Draft + Edited Mar 14 + + + + ๐Ÿ“„ + Blog Post Ideas + Edited Mar 12 + + + + + + TEMPLATES + + + ๐Ÿ“ + Blank Document + + + + ๐Ÿ“‹ + Meeting Notes + + + + ๐Ÿ“Š + Report + + + + ๐Ÿ“ง + Email Draft + + + + + + + + + + + + + + B + + + I + + + U + + + + + + Heading โ–พ + + + + + + โ‰ก + + + โ˜ฐ + + + + + + ๐Ÿ”— + + + ๐Ÿ–ผ + + + + + + โœจ AI Assist + + + + โ‹ฎ + + + + + Project Proposal + Last edited 2 minutes ago โ€ข Auto-saved + + + + + Executive Summary + + This proposal outlines a comprehensive strategy for improving + our customer engagement platform. The project aims to increase + user retention by 25% and reduce support tickets by 40%. + + Key Objectives + + โ€ข Redesign the onboarding experience for new users + โ€ข Implement AI-powered customer support chatbot + โ€ข Create personalized dashboard for each user segment + โ€ข Integrate analytics tracking for better insights| + + + + + + + + + โœจ AI Suggestion + Consider adding a timeline section to outline project milestones + and deliverables. This helps stakeholders understand the scope. + + + + Insert + + + Dismiss + + + Regenerate + + + + + + 324 words โ€ข 1,847 characters โ€ข Reading time: 2 min + Ctrl+S Save | Ctrl+B Bold | Ctrl+I Italic | Ctrl+K Link + + diff --git a/docs/src/assets/suite/player-screen.svg b/docs/src/assets/suite/player-screen.svg new file mode 100644 index 000000000..519b1ded7 --- /dev/null +++ b/docs/src/assets/suite/player-screen.svg @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + Player - Media Viewer + + + + + + + + + + + + + Q4 2024 Business Review + Strategic Initiatives and Key Metrics + + + โ€ข Revenue grew 23% year-over-year + โ€ข Customer satisfaction score: 94% + โ€ข New product launches: 3 + โ€ข Market expansion into APAC region + + + + Revenue Trend + + + + + + + + Q1 + Q2 + Q3 + Q4 + + + + + 5 / 12 + + + + + + + + + + โฎ + + + + โ–ถ + + + + โญ + + + + + 2:34 + + + + 5:48 + + + + + + + ๐Ÿ”Š + + + + โ›ถ + + + + โš™ + + + + + + + Playlist + 12 slides โ€ข 5:48 total + + + + + + + + 1 + Title Slide + 0:00 + + + + + + + 2 + Agenda + 0:30 + + + + + + + 3 + Overview + 1:15 + + + + + + + 4 + Metrics + 1:58 + + + + + + + 5 + Q4 Review + โ–ถ Playing + + + + + + + 6 + Roadmap + 3:20 + + + + + 6 more slides + + + + + Space = Play/Pause | โ† โ†’ = Navigate | F = Fullscreen | M = Mute + + diff --git a/docs/src/assets/suite/research-screen.svg b/docs/src/assets/suite/research-screen.svg new file mode 100644 index 000000000..cb8ff8baa --- /dev/null +++ b/docs/src/assets/suite/research-screen.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + Research - AI-Powered Search + + + + + + + + + ๐Ÿ” + How does machine learning work in recommendation systems? + + + Search + + + + + + All + + + Articles + + + Papers + + + Web + + + Videos + + 23 results โ€ข 1.2s + + + + + + โœจ AI Summary + + Machine learning powers recommendation systems through several key techniques: + + โ€ข Collaborative filtering analyzes user behavior patterns to find similar users + โ€ข Content-based filtering matches item attributes to user preferences + โ€ข Deep learning models can capture complex non-linear relationships + + Based on 5 sources + + + + + + + Understanding Recommendation Systems: A Complete Guide + ml-guide.com โ€ข Published 2024 + A comprehensive overview of how modern recommendation systems + leverage machine learning algorithms to personalize content... + + + Article + + + + + + Collaborative Filtering vs Content-Based: A Comparison + research.ai โ€ข IEEE 2023 + This paper compares the effectiveness of collaborative filtering and + content-based approaches in various recommendation scenarios... + + + Paper + + + + + + + Sources (5) + + + + ML Guide + ml-guide.com + + โœ“ + + + + + IEEE Research + ieee.org + + โœ“ + + + + + ArXiv Paper + arxiv.org + + โœ“ + + + + + Medium Article + medium.com + + โœ“ + + + + + + Add Source + + + + + Enter = Search | Tab = Next result | S = Save | E = Export citations + + diff --git a/docs/src/assets/suite/sources-screen.svg b/docs/src/assets/suite/sources-screen.svg new file mode 100644 index 000000000..38a67a427 --- /dev/null +++ b/docs/src/assets/suite/sources-screen.svg @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + Sources - Prompts & Templates + + + + + + + + + + + + + New Source + + + + + CATEGORIES + + + + ๐Ÿ“š + All Sources + 24 + + + + ๐Ÿ’ฌ + Prompts + 12 + + + + ๐Ÿ“„ + Templates + 8 + + + + ๐Ÿ”— + Integrations + 4 + + + + โญ + Favorites + 6 + + + + + + TAGS + + + + customer + + + + + sales + + + + + support + + + + + technical + + + + + + All Sources + 24 items โ€ข Manage your prompts and templates + + + + + + ๐Ÿ” + Search sources... + + + + + + + + + + ๐Ÿ’ฌ + Customer Support + Handle support inquiries + with empathy and clarity + + prompt + + + + + ๐Ÿ“ + Email Template + Professional email + response format + + template + + + + + ๐Ÿค– + Sales Assistant + Product recommendations + and pricing help + + prompt + + + + + + + + ๐Ÿ“Š + Report Generator + Create structured + analysis reports + + template + + + + + ๐Ÿ”— + CRM Integration + Connect with your + CRM system + + integration + + + + + ๐ŸŽฏ + FAQ Bot + Automated answers + for common questions + + prompt + + + + + + + + โœ๏ธ + Content Writer + Blog posts and + marketing copy + + prompt + + + + + ๐Ÿ“‹ + Meeting Notes + Structured meeting + summary template + + template + + + + + + + + Add New Source + Create from scratch + + + + + Click to edit | Del = Delete | D = Duplicate | Enter = Use in chat + + diff --git a/docs/src/assets/suite/suite-screen.svg b/docs/src/assets/suite/suite-screen.svg new file mode 100644 index 000000000..e1fe6af87 --- /dev/null +++ b/docs/src/assets/suite/suite-screen.svg @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + Suite - Main Interface + + + + + + + + + + + GB + General Bots + + + + + + โ˜€๏ธ + Light + + + + + + + + + + + + + JD + + + + + + + Applications + + + + + + + + ๐Ÿ’ฌ + Chat + + + + + ๐Ÿ“ + Drive + + + + + โœ“ + Tasks + + + + + + + โœ‰ + Mail + + + + + ๐Ÿ“… + Calendar + + + + + ๐ŸŽฅ + Meet + + + + + + + ๐Ÿ“ + Paper + + + + + ๐Ÿ” + Research + + + + + ๐Ÿ“Š + Analytics + + + + + + + + + + + Connected + + + + + + + AI Assistant + Hello! How can I help you today? + + + + What's on my calendar for today? + + + + AI Assistant + You have 2 meetings today: + โ€ข 2:00 PM - Team Standup + โ€ข 4:00 PM - Project Review + + + + + + ๐Ÿ“ง Check email + + + โœ“ My tasks + + + ๐Ÿ“ Recent files + + + + + + Message... + + + ๐ŸŽค + + + โ†‘ + + + + + โ†“ + + + + Enter = Send | Shift+Enter = New line | / = Commands | @ = Mention + + diff --git a/docs/src/assets/suite/tasks-screen.svg b/docs/src/assets/suite/tasks-screen.svg new file mode 100644 index 000000000..7b755b346 --- /dev/null +++ b/docs/src/assets/suite/tasks-screen.svg @@ -0,0 +1,211 @@ + + + + + + + + + + + Tasks - To-Do Manager + + + + + + + + + + + + + Add Task + + + + + + ๐Ÿ“‹ + All Tasks + 12 + + ๐Ÿ“… + Today + 5 + + ๐Ÿ“† + Upcoming + 8 + + โญ + Important + 3 + + โœ… + Completed + 24 + + + + + PROJECTS + + + + Work + + + + + Personal + + + + + Learning + + + + + + All Tasks + 12 tasks, 5 due today + + + + + Filter โ–พ + + + Sort โ–พ + + + + + + + + + Add a new task... + + + + + + + + + + Complete quarterly report + + Work + Today + โญ + + + + + + + + Review pull request #234 + + Work + Today + โ˜† + + + + + + + + Prepare presentation slides + + Work + Tomorrow + โ˜† + + + + + + + + Read documentation updates + + Learning + Mar 20 + โ˜† + + + + + + + โœ“ + Update team meeting notes + + Work + Completed + โ˜† + + + + + + + โœ“ + Schedule dentist appointment + + Personal + Completed + โ˜† + + + + + + Enter = Add task | Space = Toggle complete | Del = Delete | S = Star + + diff --git a/docs/src/assets/wa-chat.css b/docs/src/assets/wa-chat.css new file mode 100644 index 000000000..c399c3904 --- /dev/null +++ b/docs/src/assets/wa-chat.css @@ -0,0 +1,209 @@ +/** + * WhatsApp-style Chat Conversation CSS + * + * Standard styling for conversation examples in General Bots documentation. + * Include this CSS in your mdBook or HTML output to style
elements. + * + * Usage: + * + */ + +/* ============================================ + Chat Container + ============================================ */ +.wa-chat { + background-color: #e5ddd5; + border-radius: 8px; + padding: 20px 15px; + margin: 20px 0; + max-width: 500px; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; + font-size: 14px; +} + +/* Dark mode support */ +@media (prefers-color-scheme: dark) { + .wa-chat { + background-color: #0b141a; + } +} + +/* ============================================ + Message Container + ============================================ */ +.wa-message { + margin-bottom: 10px; +} + +.wa-message:last-child { + margin-bottom: 0; +} + +/* User messages align right */ +.wa-message.user { + text-align: right; +} + +/* ============================================ + Message Bubbles + ============================================ */ +.wa-bubble { + padding: 8px 12px; + border-radius: 8px; + box-shadow: 0 1px 0.5px rgba(0, 0, 0, 0.13); + max-width: 85%; + display: inline-block; + text-align: left; +} + +/* Bot bubble - white/light */ +.wa-message.bot .wa-bubble { + background-color: #fff; +} + +/* User bubble - green (WhatsApp style) */ +.wa-message.user .wa-bubble { + background-color: #dcf8c6; +} + +/* Dark mode bubbles */ +@media (prefers-color-scheme: dark) { + .wa-message.bot .wa-bubble { + background-color: #202c33; + } + + .wa-message.user .wa-bubble { + background-color: #005c4b; + } +} + +/* ============================================ + Message Text + ============================================ */ +.wa-bubble p { + margin: 0 0 4px 0; + line-height: 1.4; + color: #303030; +} + +.wa-bubble p:last-of-type { + margin-bottom: 0; +} + +/* Bold text in messages */ +.wa-bubble strong { + font-weight: 600; +} + +/* Dark mode text */ +@media (prefers-color-scheme: dark) { + .wa-bubble p { + color: #e9edef; + } +} + +/* ============================================ + Timestamp + ============================================ */ +.wa-time { + font-size: 11px; + color: #8696a0; + text-align: right; + margin-top: 4px; +} + +/* ============================================ + Special Elements + ============================================ */ + +/* Links in messages */ +.wa-bubble a { + color: #00a884; + text-decoration: none; +} + +.wa-bubble a:hover { + text-decoration: underline; +} + +/* Code in messages */ +.wa-bubble code { + background-color: rgba(0, 0, 0, 0.05); + padding: 2px 4px; + border-radius: 3px; + font-family: 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace; + font-size: 13px; +} + +@media (prefers-color-scheme: dark) { + .wa-bubble code { + background-color: rgba(255, 255, 255, 0.1); + } +} + +/* Action buttons in messages */ +.wa-bubble .wa-action { + display: inline-block; + background-color: #e8f4fd; + color: #4a90e2; + padding: 4px 10px; + border-radius: 4px; + font-size: 12px; + margin: 4px 4px 0 0; + cursor: pointer; +} + +.wa-bubble .wa-action:hover { + background-color: #d0e8fc; +} + +@media (prefers-color-scheme: dark) { + .wa-bubble .wa-action { + background-color: #1a3a4a; + color: #00d4ff; + } + + .wa-bubble .wa-action:hover { + background-color: #2a4a5a; + } +} + +/* ============================================ + Variants + ============================================ */ + +/* Full-width variant */ +.wa-chat.wa-full-width { + max-width: 100%; +} + +/* Compact variant (less padding) */ +.wa-chat.wa-compact { + padding: 12px 10px; +} + +.wa-chat.wa-compact .wa-message { + margin-bottom: 6px; +} + +.wa-chat.wa-compact .wa-bubble { + padding: 6px 10px; +} + +/* No-time variant (hide timestamps) */ +.wa-chat.wa-no-time .wa-time { + display: none; +} diff --git a/docs/src/chapter-04-gbui/apps/analytics.md b/docs/src/chapter-04-gbui/apps/analytics.md index 4bbd4625e..504ea31c6 100644 --- a/docs/src/chapter-04-gbui/apps/analytics.md +++ b/docs/src/chapter-04-gbui/apps/analytics.md @@ -2,7 +2,7 @@ > **Your business intelligence center** -Analytics Flow Diagram +Analytics Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/calendar.md b/docs/src/chapter-04-gbui/apps/calendar.md index 54064dc1c..a296a3202 100644 --- a/docs/src/chapter-04-gbui/apps/calendar.md +++ b/docs/src/chapter-04-gbui/apps/calendar.md @@ -2,7 +2,7 @@ > **Your personal scheduling assistant** -![Calendar Flow](../../assets/suite/calendar-flow.svg) +Calendar Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/chat.md b/docs/src/chapter-04-gbui/apps/chat.md index 6de044f93..a0a88e327 100644 --- a/docs/src/chapter-04-gbui/apps/chat.md +++ b/docs/src/chapter-04-gbui/apps/chat.md @@ -2,7 +2,7 @@ > **Your intelligent conversation partner** -Chat Flow Diagram +Chat Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/compliance.md b/docs/src/chapter-04-gbui/apps/compliance.md index b8a5a4699..669978117 100644 --- a/docs/src/chapter-04-gbui/apps/compliance.md +++ b/docs/src/chapter-04-gbui/apps/compliance.md @@ -2,7 +2,7 @@ > **Your privacy and security guardian** -Compliance Flow Diagram +Compliance Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/designer.md b/docs/src/chapter-04-gbui/apps/designer.md index 3e345552e..c84657e0b 100644 --- a/docs/src/chapter-04-gbui/apps/designer.md +++ b/docs/src/chapter-04-gbui/apps/designer.md @@ -2,7 +2,7 @@ > **Your no-code bot building studio** -Designer Flow Diagram +Designer Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/drive.md b/docs/src/chapter-04-gbui/apps/drive.md index 065f0860d..f018224bf 100644 --- a/docs/src/chapter-04-gbui/apps/drive.md +++ b/docs/src/chapter-04-gbui/apps/drive.md @@ -2,7 +2,7 @@ > **Your cloud storage workspace** -Drive Flow Diagram +Drive Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/mail.md b/docs/src/chapter-04-gbui/apps/mail.md index 833086d92..22f275a39 100644 --- a/docs/src/chapter-04-gbui/apps/mail.md +++ b/docs/src/chapter-04-gbui/apps/mail.md @@ -2,7 +2,7 @@ > **Your intelligent inbox** -![Mail Flow](../../assets/suite/mail-flow.svg) +Mail Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/meet.md b/docs/src/chapter-04-gbui/apps/meet.md index 9cc814ee2..cb4616998 100644 --- a/docs/src/chapter-04-gbui/apps/meet.md +++ b/docs/src/chapter-04-gbui/apps/meet.md @@ -2,7 +2,7 @@ > **Your virtual meeting room** -![Meet Flow](../../assets/suite/meet-flow.svg) +Meet Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/paper.md b/docs/src/chapter-04-gbui/apps/paper.md index 0e1268258..1fb8b9749 100644 --- a/docs/src/chapter-04-gbui/apps/paper.md +++ b/docs/src/chapter-04-gbui/apps/paper.md @@ -2,7 +2,7 @@ > **Your intelligent document editor** -Paper Flow Diagram +Paper Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/player.md b/docs/src/chapter-04-gbui/apps/player.md index f93c2b737..e56eed822 100644 --- a/docs/src/chapter-04-gbui/apps/player.md +++ b/docs/src/chapter-04-gbui/apps/player.md @@ -2,7 +2,7 @@ > **Integrated viewing for documents, audio, video, and presentations** -Player Flow +Player Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/research.md b/docs/src/chapter-04-gbui/apps/research.md index b763159cf..3bde1a1cf 100644 --- a/docs/src/chapter-04-gbui/apps/research.md +++ b/docs/src/chapter-04-gbui/apps/research.md @@ -2,7 +2,7 @@ > **Your intelligent research assistant** -Research Flow Diagram +Research Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/sources.md b/docs/src/chapter-04-gbui/apps/sources.md index 72a70a8f2..dc1d53ea5 100644 --- a/docs/src/chapter-04-gbui/apps/sources.md +++ b/docs/src/chapter-04-gbui/apps/sources.md @@ -2,7 +2,7 @@ > **Your bot configuration hub** -Sources Flow Diagram +Sources Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/suite.md b/docs/src/chapter-04-gbui/apps/suite.md index b39f6384c..e317fe2c4 100644 --- a/docs/src/chapter-04-gbui/apps/suite.md +++ b/docs/src/chapter-04-gbui/apps/suite.md @@ -2,7 +2,7 @@ > **Complete productivity suite with integrated applications** -Suite Layout +Suite Interface Screen --- diff --git a/docs/src/chapter-04-gbui/apps/tasks.md b/docs/src/chapter-04-gbui/apps/tasks.md index 7fc32b57a..81778ffeb 100644 --- a/docs/src/chapter-04-gbui/apps/tasks.md +++ b/docs/src/chapter-04-gbui/apps/tasks.md @@ -2,7 +2,7 @@ > **Track what needs to be done** -Tasks Flow Diagram +Tasks Interface Screen --- diff --git a/docs/src/chapter-04-gbui/suite-manual.md b/docs/src/chapter-04-gbui/suite-manual.md index f07a6ea95..0b59cb433 100644 --- a/docs/src/chapter-04-gbui/suite-manual.md +++ b/docs/src/chapter-04-gbui/suite-manual.md @@ -30,18 +30,7 @@ General Bots Suite is your all-in-one workspace that combines communication, pro When the Suite opens, you see: -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ ๐Ÿค– General Bots [Apps Menu โ‹ฎโ‹ฎโ‹ฎ] [Theme ๐ŸŒ™] [U] โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ”‚ -โ”‚ โ”‚ -โ”‚ ๐Ÿ’ฌ Chat (Main Area) โ”‚ -โ”‚ โ”‚ -โ”‚ Type your message here... โ”‚ -โ”‚ โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Suite Main Layout ### The Apps Menu @@ -136,22 +125,7 @@ Drive is your file storage - like Google Drive or OneDrive. Store documents, ima ### The Drive Interface -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ [+ New โ–ผ] ๐Ÿ” Search files... [โŠž] [โ‰ก] โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ”‚ ๐Ÿ“ My Drive > Projects > 2024 โ”‚ -โ”‚ My Drive โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚ -โ”‚ โญ Starred โ”‚ [โ˜] Name Size Modified โ”‚ -โ”‚ ๐Ÿ• Recent โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ -โ”‚ ๐Ÿ—‘ Trash โ”‚ ๐Ÿ“ Reports - Today โ”‚ -โ”‚ โ”‚ ๐Ÿ“ Presentations - Yesterday โ”‚ -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚ ๐Ÿ“„ Budget.xlsx 245 KB Mar 15 โ”‚ -โ”‚ Labels โ”‚ ๐Ÿ“„ Notes.docx 12 KB Mar 14 โ”‚ -โ”‚ ๐Ÿ”ต Work โ”‚ ๐Ÿ–ผ Logo.png 89 KB Mar 10 โ”‚ -โ”‚ ๐ŸŸข Personalโ”‚ โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Drive Interface ### Creating and Uploading @@ -213,23 +187,7 @@ Tasks helps you track what needs to be done. Create to-do lists, set due dates, ### The Tasks Interface -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ โœ“ Tasks Total: 12 Active: 5 Done: 7โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ -โ”‚ โ”‚ What needs to be done? [Category โ–ผ] [+ Add]โ”‚ โ”‚ -โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ [๐Ÿ“‹ All (12)] [โณ Active (5)] [โœ“ Completed (7)] [โšก Priority] โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ˜ Review quarterly report ๐Ÿ“… Today ๐Ÿ”ด โ”‚ -โ”‚ โ˜ Call client about proposal ๐Ÿ“… Today ๐ŸŸก โ”‚ -โ”‚ โ˜ Update project documentation ๐Ÿ“… Tomorrow ๐ŸŸข โ”‚ -โ”‚ โ˜‘ Send meeting notes โœ“ Done โ”‚ -โ”‚ โ˜‘ Complete expense report โœ“ Done โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Tasks Interface ### Adding a Task @@ -281,24 +239,7 @@ Mail connects to your email accounts so you can read, write, and organize emails ### The Mail Interface -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ โ”‚ โ”‚ โ”‚ -โ”‚ [โœ Compose] โ”‚ Inbox โ”‚ From: john@company.com โ”‚ -โ”‚ โ”‚ โ”‚ Subject: Project Update โ”‚ -โ”‚ ๐Ÿ“ฅ Inbox (3) โ”‚ โ— Project Update โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ -โ”‚ ๐Ÿ“ค Sent โ”‚ from John โ”‚ โ”‚ -โ”‚ ๐Ÿ“ Drafts โ”‚ 10:30 AM โ”‚ Hi, โ”‚ -โ”‚ ๐Ÿ—‘ Trash โ”‚ โ”‚ โ”‚ -โ”‚ โ”‚ โ—‹ Meeting Notes โ”‚ Here's the latest update โ”‚ -โ”‚ โ”‚ from Sarah โ”‚ on our project... โ”‚ -โ”‚ โ”‚ Yesterday โ”‚ โ”‚ -โ”‚ โ”‚ โ”‚ Best, โ”‚ -โ”‚ โ”‚ โ—‹ Invoice #1234 โ”‚ John โ”‚ -โ”‚ โ”‚ from Vendor โ”‚ โ”‚ -โ”‚ โ”‚ Mar 15 โ”‚ [Reply] [Forward] [Delete]โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Mail Interface ### Reading Email @@ -364,25 +305,7 @@ Calendar shows your schedule, meetings, and events. Plan your day, week, or mont ### The Calendar Interface -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ โ—„ March 2024 โ–บ [Day] [Week] [Month] โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ Mon Tue Wed Thu Fri Sat Sun โ”‚ -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ -โ”‚ 1 2 3 โ”‚ -โ”‚ โ”‚ -โ”‚ 4 5 6 7 8 9 10 โ”‚ -โ”‚ โ–ˆโ–ˆโ–ˆโ–ˆ โ”‚ -โ”‚ Team โ”‚ -โ”‚ Meeting โ”‚ -โ”‚ โ”‚ -โ”‚ 11 12 13 14 15 16 17 โ”‚ -โ”‚ โ–ˆโ–ˆโ–ˆโ–ˆ โ–ˆโ–ˆโ–ˆโ–ˆ โ”‚ -โ”‚ Project Review โ”‚ -โ”‚ Demo 1:1 โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Calendar Interface ### Creating an Event @@ -457,24 +380,7 @@ Bot: Meeting scheduled: ### The Meeting Interface -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ Meeting Room 00:15:32 [๐Ÿ‘ฅ 3] [๐Ÿ’ฌ] โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ -โ”‚ โ”‚ ๐Ÿ‘ค You โ”‚ โ”‚ ๐Ÿ‘ค John โ”‚ โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ -โ”‚ โ”‚ (Camera) โ”‚ โ”‚ (Camera) โ”‚ โ”‚ -โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ -โ”‚ โ”‚ -โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ -โ”‚ โ”‚ ๐Ÿ‘ค Sarah โ”‚ โ”‚ -โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ [๐ŸŽค Mute] [๐Ÿ“น Video] [๐Ÿ–ฅ Share] [๐Ÿ”ด Record] [๐Ÿ“ž End] โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Meet Interface ### Meeting Controls @@ -536,24 +442,7 @@ Paper is your writing space with AI assistance. Write documents, notes, reports ### The Paper Interface -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ โ”‚ [B] [I] [U] H1 H2 โ€ข โ€• ๐Ÿ”— ๐Ÿ“ท [AI โœจ] โ”‚ -โ”‚ ๐Ÿ“„ Notes โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ -โ”‚ Meeting Notes โ”‚ Project Proposal โ”‚ -โ”‚ Project Plan โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• โ”‚ -โ”‚ Ideas โ”‚ โ”‚ -โ”‚ โ”‚ Introduction โ”‚ -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ -โ”‚ Quick Start โ”‚ โ”‚ -โ”‚ [๐Ÿ“„ Blank] โ”‚ This document outlines our proposal for โ”‚ -โ”‚ [๐Ÿ“‹ Meeting] โ”‚ the upcoming project. We aim to... โ”‚ -โ”‚ [โœ“ To-Do] โ”‚ โ”‚ -โ”‚ [๐Ÿ”ฌ Research] โ”‚ | โ”‚ -โ”‚ โ”‚ โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Paper Interface ### Creating a Document @@ -620,28 +509,7 @@ Research is like having a research assistant. Search the web, your documents, an ### The Research Interface -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ โ”‚ โ”‚ -โ”‚ ๐Ÿ” Research โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ -โ”‚ โ”‚ โ”‚ What are the best practices for... โ”‚ โ”‚ -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ -โ”‚ Focus: โ”‚ โ”‚ -โ”‚ [๐ŸŒ All] โ”‚ AI Answer: โ”‚ -โ”‚ [๐Ÿ“š Academic] โ”‚ โ•โ•โ•โ•โ•โ•โ•โ•โ•โ• โ”‚ -โ”‚ [๐Ÿ’ป Code] โ”‚ Based on multiple sources, here are the โ”‚ -โ”‚ [๐Ÿ  Internal] โ”‚ key best practices: โ”‚ -โ”‚ โ”‚ โ”‚ -โ”‚ Collections: โ”‚ 1. Start with clear requirements โ”‚ -โ”‚ ๐Ÿ“ Project A โ”‚ 2. Use iterative development โ”‚ -โ”‚ ๐Ÿ“ References โ”‚ 3. Test early and often โ”‚ -โ”‚ โ”‚ โ”‚ -โ”‚ Recent: โ”‚ Sources: โ”‚ -โ”‚ โ€ข market size โ”‚ [1] industry-guide.com โ”‚ -โ”‚ โ€ข competitors โ”‚ [2] techblog.dev โ”‚ -โ”‚ โ”‚ [3] your-docs/guidelines.pdf โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Research Interface ### Search Modes @@ -692,26 +560,7 @@ Analytics shows you reports about usage, conversations, and performance. Underst ### The Analytics Interface -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ ๐Ÿ“Š Analytics Dashboard [Last 24h โ–ผ] [โŸณ Refresh] โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ -โ”‚ โ”‚ 1,234 โ”‚ โ”‚ 89% โ”‚ โ”‚ 2.3s โ”‚ โ”‚ 45 โ”‚ โ”‚ -โ”‚ โ”‚ Messages โ”‚ โ”‚ Success โ”‚ โ”‚ Avg Time โ”‚ โ”‚ Users โ”‚ โ”‚ -โ”‚ โ”‚ +12% โ”‚ โ”‚ Rate โ”‚ โ”‚ Response โ”‚ โ”‚ Today โ”‚ โ”‚ -โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ”‚ -โ”‚ Messages Over Time Top Questions โ”‚ -โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ -โ”‚ โ”‚ โ•ญโ”€โ•ฎ โ”‚ โ”‚ 1. How do I reset... โ”‚ โ”‚ -โ”‚ โ”‚ โ•ญโ•ฏ โ•ฐโ•ฎ โ•ญโ”€โ•ฎ โ”‚ โ”‚ 2. What is the status...โ”‚ โ”‚ -โ”‚ โ”‚ โ•ญโ•ฏ โ•ฐโ”€โ”€โ”€โ”€โ•ฏ โ•ฐโ•ฎ โ”‚ โ”‚ 3. Where can I find... โ”‚ โ”‚ -โ”‚ โ”‚ โ”€โ•ฏ โ•ฐโ”€โ”€ โ”‚ โ”‚ 4. Help with login โ”‚ โ”‚ -โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Analytics Interface ### Key Metrics @@ -750,29 +599,7 @@ Designer lets you create bot conversations visually - like VB6 form designer, bu ### The Designer Interface -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ Toolbox โ”‚ Canvas โ”‚Propertiesโ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ”‚ โ”‚ โ”‚ -โ”‚ ๐Ÿ’ฌ TALK โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Node: โ”‚ -โ”‚ ๐Ÿ‘‚ HEAR โ”‚ โ”‚๐Ÿ’ฌ TALK โ”‚ โ”‚ TALK โ”‚ -โ”‚ ๐Ÿ“ SET โ”‚ โ”‚"Hello!" โ”‚โ”€โ”€โ”€โ” โ”‚ โ”‚ -โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ Message: โ”‚ -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ–ผ โ”‚ [Hello!] โ”‚ -โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ -โ”‚ ๐Ÿ”€ IF โ”‚ โ”‚๐Ÿ‘‚ HEAR โ”‚โ”€โ”€โ–ถโ”‚๐Ÿ”€ IF โ”‚ โ”‚ โ”‚ -โ”‚ ๐Ÿ”„ FOR โ”‚ โ”‚ name โ”‚ โ”‚name="Jo"โ”‚ โ”‚ โ”‚ -โ”‚ ๐Ÿ”ƒ SWITCH โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ -โ”‚ โ”‚ โ”Œโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ” โ”‚ โ”‚ -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ Yes No โ”‚ โ”‚ -โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ -โ”‚ ๐Ÿ“ž CALL โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ” โ”Œโ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ -โ”‚ ๐Ÿ“ง SEND โ”‚ โ”‚๐Ÿ’ฌTALK โ”‚ โ”‚๐Ÿ’ฌTALK โ”‚ โ”‚ โ”‚ -โ”‚ ๐Ÿ’พ SAVE โ”‚ โ”‚"Hi Jo"โ”‚ โ”‚"Hello"โ”‚ โ”‚ โ”‚ -โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Designer Interface ### Building a Dialog @@ -809,27 +636,7 @@ Designer lets you create bot conversations visually - like VB6 form designer, bu ### Example: Simple Greeting Dialog -``` - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ ๐Ÿ’ฌ TALK โ”‚ - โ”‚ "What's your โ”‚ - โ”‚ name?" โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - โ–ผ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ ๐Ÿ‘‚ HEAR โ”‚ - โ”‚ as: name โ”‚ - โ”‚ type: STRING โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ - โ”‚ - โ–ผ - โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” - โ”‚ ๐Ÿ’ฌ TALK โ”‚ - โ”‚ "Nice to meet โ”‚ - โ”‚ you, {name}!" โ”‚ - โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +The Designer canvas shows flow diagrams like the one in the interface above. A simple greeting dialog flows from a TALK node ("What's your name?") to a HEAR node (capturing the name as a string variable) to another TALK node ("Nice to meet you, {name}!"). **Generated Code:** ```basic @@ -861,25 +668,7 @@ Sources is your library of prompts, templates, tools, and AI models. Find and us ### The Sources Interface -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ Sources ๐Ÿ” Search... โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ [Prompts] [Templates] [MCP Servers] [LLM Tools] [Models] โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ”‚ โ”‚ -โ”‚ Categories โ”‚ โญ Featured โ”‚ -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ -โ”‚ ๐Ÿ“ Writing โ”‚ โ”‚ Customer โ”‚ โ”‚ Sales โ”‚ โ”‚ -โ”‚ ๐Ÿ“Š Analysis โ”‚ โ”‚ Service โ”‚ โ”‚ Assistant โ”‚ โ”‚ -โ”‚ ๐Ÿ’ผ Business โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚ โ”‚ -โ”‚ ๐Ÿ’ป Code โ”‚ โ”‚ Handle โ”‚ โ”‚ Qualify โ”‚ โ”‚ -โ”‚ ๐ŸŽจ Creative โ”‚ โ”‚ support โ”‚ โ”‚ leads and โ”‚ โ”‚ -โ”‚ โ”‚ โ”‚ inquiries โ”‚ โ”‚ schedule โ”‚ โ”‚ -โ”‚ โ”‚ โ”‚ [Use] โ”‚ โ”‚ [Use] โ”‚ โ”‚ -โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Sources Interface ### Tabs Explained @@ -921,24 +710,7 @@ Sources is your library of prompts, templates, tools, and AI models. Find and us ### Compliance Scanner -Check your bot dialogs for security issues: - -``` -โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” -โ”‚ ๐Ÿ›ก Compliance Scanner [Scan] [Export] โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ -โ”‚ โ”‚ 2 โ”‚ โ”‚ 5 โ”‚ โ”‚ 3 โ”‚ โ”‚ 1 โ”‚ โ”‚ 0 โ”‚ โ”‚ -โ”‚ โ”‚๐Ÿ”ดCritโ”‚ โ”‚๐ŸŸ Highโ”‚ โ”‚๐ŸŸกMed โ”‚ โ”‚๐ŸŸขLow โ”‚ โ”‚โ„นInfoโ”‚ โ”‚ -โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ -โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค -โ”‚ Severity โ”‚ Issue โ”‚ File โ”‚ Action โ”‚ -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ -โ”‚ ๐Ÿ”ด Criticalโ”‚ Hardcoded password โ”‚ start.bas:15 โ”‚ [Fix] โ”‚ -โ”‚ ๐Ÿ”ด Criticalโ”‚ API key exposed โ”‚ api.bas:42 โ”‚ [Fix] โ”‚ -โ”‚ ๐ŸŸ  High โ”‚ SQL injection risk โ”‚ data.bas:28 โ”‚ [Review] โ”‚ -โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ -``` +Compliance Scanner Interface **What It Checks:** - Hardcoded passwords diff --git a/docs/src/favicon.png b/docs/src/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..651fe52e916d051cb9ed45d87537f89de162f562 GIT binary patch literal 25670 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%0A_hj&+4MZpafzb+z~Vubxm_hr+@LCjcdWw?K7u zYLg`FkaL^?by}1G*m8#pudt(Qp5F2XCH=|yqMNLooE+Rgs*~TUEE!~R7$)SOf%Is; z!@2L?Ew?Ww!{e4ZDl}Hs4<8?rDbHG!CP79nSW2t8nSHa<+S;Rq9VT=kdZa^aY&|c# z1P|IP?(;G<#{{H;h0{fR4j1YobY{XEFHJuyCnF<+*3ANP7y04VbKHr{<+%?<-r{ec zA(N@)Qb1pD(ufBK4@mkm<#lbC3>LsD#uEt`;Av^H!1=skxg&&H@p~XZ;lllQ3 zrFiWa8YuQQIiyR{%Ae846E0k!k-aX@>G^o+wQD|iwEE{8vJJe<3~!HDZ^Cy5-@k9R zsJnh$4kThyWu?gu)3Lp)1^AE#_Ai*fc0NAZQ{$@k7xB3fp-_l~POV~tlKnQ4LO`s7 z=~Fn!>+j!7cm}*8v0W*(iGittjg|S+zc5t**wtzUnq%ccsAlKjpdM9^bqZ_nHV+TF z-)i7p@xc6x*x%d^+x+$$6`H1;-F!kTPy_hjZvS=}cEQUd?u kyEQ2`5|sbDuN^a7!O~;w<8pFG$mgJ(>|O2tv|%Ou2Xo+vCIA2c literal 0 HcmV?d00001 diff --git a/src/security/cert_pinning.rs b/src/security/cert_pinning.rs new file mode 100644 index 000000000..7f29d0938 --- /dev/null +++ b/src/security/cert_pinning.rs @@ -0,0 +1,852 @@ +//! Certificate Pinning Module +//! +//! Provides certificate pinning functionality to prevent man-in-the-middle attacks +//! by validating server certificates against pre-configured SHA-256 fingerprints. +//! +//! # Overview +//! +//! Certificate pinning adds an additional layer of security beyond standard TLS +//! certificate validation. Even if an attacker obtains a valid certificate from +//! a trusted CA, the connection will be rejected if the certificate's fingerprint +//! doesn't match the pinned value. +//! +//! # Usage +//! +//! ```rust,ignore +//! use botserver::security::cert_pinning::{CertPinningConfig, CertPinningManager, PinnedCert}; +//! +//! let mut config = CertPinningConfig::default(); +//! config.add_pin(PinnedCert::new( +//! "api.example.com", +//! "sha256//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", +//! )); +//! +//! let manager = CertPinningManager::new(config); +//! let client = manager.create_pinned_client("api.example.com")?; +//! ``` + +use anyhow::{anyhow, Context, Result}; +use base64::{engine::general_purpose::STANDARD as BASE64, Engine}; +use reqwest::{Certificate, Client, ClientBuilder}; +use ring::digest::{digest, SHA256}; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::fs; +use std::path::{Path, PathBuf}; +use std::sync::{Arc, RwLock}; +use std::time::Duration; +use tracing::{debug, error, info, warn}; +use x509_parser::prelude::*; + +/// Configuration for certificate pinning +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct CertPinningConfig { + /// Enable certificate pinning globally + pub enabled: bool, + + /// Pinned certificates by hostname + pub pins: HashMap>, + + /// Whether to fail if no pin is configured for a host + pub require_pins: bool, + + /// Allow backup pins (multiple pins per host for rotation) + pub allow_backup_pins: bool, + + /// Report-only mode (log violations but don't block) + pub report_only: bool, + + /// Path to store/load pin configuration + pub config_path: Option, + + /// Pin validation cache TTL in seconds + pub cache_ttl_secs: u64, +} + +impl Default for CertPinningConfig { + fn default() -> Self { + Self { + enabled: true, + pins: HashMap::new(), + require_pins: false, + allow_backup_pins: true, + report_only: false, + config_path: None, + cache_ttl_secs: 3600, + } + } +} + +impl CertPinningConfig { + /// Create a new config with pinning enabled + pub fn new() -> Self { + Self::default() + } + + /// Create a strict config that requires pins for all hosts + pub fn strict() -> Self { + Self { + enabled: true, + pins: HashMap::new(), + require_pins: true, + allow_backup_pins: true, + report_only: false, + config_path: None, + cache_ttl_secs: 3600, + } + } + + /// Create a report-only config for testing + pub fn report_only() -> Self { + Self { + enabled: true, + pins: HashMap::new(), + require_pins: false, + allow_backup_pins: true, + report_only: true, + config_path: None, + cache_ttl_secs: 3600, + } + } + + /// Add a pinned certificate + pub fn add_pin(&mut self, pin: PinnedCert) { + let hostname = pin.hostname.clone(); + self.pins.entry(hostname).or_default().push(pin); + } + + /// Add multiple pins for a hostname (primary + backups) + pub fn add_pins(&mut self, hostname: &str, pins: Vec) { + self.pins.insert(hostname.to_string(), pins); + } + + /// Remove all pins for a hostname + pub fn remove_pins(&mut self, hostname: &str) { + self.pins.remove(hostname); + } + + /// Get pins for a hostname + pub fn get_pins(&self, hostname: &str) -> Option<&Vec> { + self.pins.get(hostname) + } + + /// Load configuration from file + pub fn load_from_file(path: &Path) -> Result { + let content = fs::read_to_string(path) + .with_context(|| format!("Failed to read pin config from {:?}", path))?; + + let config: Self = + serde_json::from_str(&content).context("Failed to parse pin configuration")?; + + info!("Loaded certificate pinning config from {:?}", path); + Ok(config) + } + + /// Save configuration to file + pub fn save_to_file(&self, path: &Path) -> Result<()> { + let content = + serde_json::to_string_pretty(self).context("Failed to serialize pin configuration")?; + + fs::write(path, content) + .with_context(|| format!("Failed to write pin config to {:?}", path))?; + + info!("Saved certificate pinning config to {:?}", path); + Ok(()) + } +} + +/// A pinned certificate entry +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct PinnedCert { + /// Hostname this pin applies to + pub hostname: String, + + /// SHA-256 fingerprint of the certificate's Subject Public Key Info (SPKI) + /// Format: "sha256//BASE64_ENCODED_HASH" + pub fingerprint: String, + + /// Optional human-readable description + pub description: Option, + + /// Whether this is a backup pin + pub is_backup: bool, + + /// Expiration date (for pin rotation planning) + pub expires_at: Option>, + + /// Pin type (leaf certificate, intermediate, or root) + pub pin_type: PinType, +} + +impl PinnedCert { + /// Create a new pinned certificate entry + pub fn new(hostname: &str, fingerprint: &str) -> Self { + Self { + hostname: hostname.to_string(), + fingerprint: fingerprint.to_string(), + description: None, + is_backup: false, + expires_at: None, + pin_type: PinType::Leaf, + } + } + + /// Create a backup pin + pub fn backup(hostname: &str, fingerprint: &str) -> Self { + Self { + hostname: hostname.to_string(), + fingerprint: fingerprint.to_string(), + description: Some("Backup pin for certificate rotation".to_string()), + is_backup: true, + expires_at: None, + pin_type: PinType::Leaf, + } + } + + /// Set the pin type + pub fn with_type(mut self, pin_type: PinType) -> Self { + self.pin_type = pin_type; + self + } + + /// Set description + pub fn with_description(mut self, desc: &str) -> Self { + self.description = Some(desc.to_string()); + self + } + + /// Set expiration + pub fn with_expiration(mut self, expires: chrono::DateTime) -> Self { + self.expires_at = Some(expires); + self + } + + /// Extract the raw hash bytes from the fingerprint + pub fn get_hash_bytes(&self) -> Result> { + let hash_str = self + .fingerprint + .strip_prefix("sha256//") + .ok_or_else(|| anyhow!("Invalid fingerprint format, expected 'sha256//BASE64'"))?; + + BASE64 + .decode(hash_str) + .context("Failed to decode base64 fingerprint") + } + + /// Verify if a certificate matches this pin + pub fn verify(&self, cert_der: &[u8]) -> Result { + let expected_hash = self.get_hash_bytes()?; + let actual_hash = compute_spki_fingerprint(cert_der)?; + + Ok(expected_hash == actual_hash) + } +} + +/// Type of certificate being pinned +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +pub enum PinType { + /// Pin the leaf/end-entity certificate + Leaf, + /// Pin an intermediate CA certificate + Intermediate, + /// Pin the root CA certificate + Root, +} + +impl Default for PinType { + fn default() -> Self { + Self::Leaf + } +} + +/// Result of a pin validation +#[derive(Debug, Clone)] +pub struct PinValidationResult { + /// Whether the pin validation passed + pub valid: bool, + + /// The hostname that was validated + pub hostname: String, + + /// Which pin matched (if any) + pub matched_pin: Option, + + /// The actual fingerprint of the certificate + pub actual_fingerprint: String, + + /// Error message if validation failed + pub error: Option, + + /// Whether this was a backup pin match + pub backup_match: bool, +} + +impl PinValidationResult { + /// Create a successful validation result + pub fn success(hostname: &str, fingerprint: &str, backup: bool) -> Self { + Self { + valid: true, + hostname: hostname.to_string(), + matched_pin: Some(fingerprint.to_string()), + actual_fingerprint: fingerprint.to_string(), + error: None, + backup_match: backup, + } + } + + /// Create a failed validation result + pub fn failure(hostname: &str, actual: &str, error: &str) -> Self { + Self { + valid: false, + hostname: hostname.to_string(), + matched_pin: None, + actual_fingerprint: actual.to_string(), + error: Some(error.to_string()), + backup_match: false, + } + } +} + +/// Certificate Pinning Manager +pub struct CertPinningManager { + config: Arc>, + validation_cache: Arc>>, +} + +impl CertPinningManager { + /// Create a new certificate pinning manager + pub fn new(config: CertPinningConfig) -> Self { + Self { + config: Arc::new(RwLock::new(config)), + validation_cache: Arc::new(RwLock::new(HashMap::new())), + } + } + + /// Create with default configuration + pub fn default_manager() -> Self { + Self::new(CertPinningConfig::default()) + } + + /// Check if pinning is enabled + pub fn is_enabled(&self) -> bool { + self.config.read().unwrap().enabled + } + + /// Add a pin dynamically + pub fn add_pin(&self, pin: PinnedCert) -> Result<()> { + let mut config = self + .config + .write() + .map_err(|_| anyhow!("Failed to acquire write lock"))?; + config.add_pin(pin); + Ok(()) + } + + /// Remove pins for a hostname + pub fn remove_pins(&self, hostname: &str) -> Result<()> { + let mut config = self + .config + .write() + .map_err(|_| anyhow!("Failed to acquire write lock"))?; + config.remove_pins(hostname); + + // Clear cache for this hostname + let mut cache = self + .validation_cache + .write() + .map_err(|_| anyhow!("Failed to acquire cache lock"))?; + cache.remove(hostname); + + Ok(()) + } + + /// Validate a certificate against pinned fingerprints + pub fn validate_certificate( + &self, + hostname: &str, + cert_der: &[u8], + ) -> Result { + let config = self + .config + .read() + .map_err(|_| anyhow!("Failed to acquire read lock"))?; + + if !config.enabled { + return Ok(PinValidationResult::success(hostname, "disabled", false)); + } + + // Check cache first + if let Ok(cache) = self.validation_cache.read() { + if let Some((result, timestamp)) = cache.get(hostname) { + if timestamp.elapsed().as_secs() < config.cache_ttl_secs { + return Ok(result.clone()); + } + } + } + + // Compute actual fingerprint + let actual_hash = compute_spki_fingerprint(cert_der)?; + let actual_fingerprint = format!("sha256//{}", BASE64.encode(&actual_hash)); + + // Get pins for this hostname + let pins = match config.get_pins(hostname) { + Some(pins) => pins, + None => { + if config.require_pins { + let result = PinValidationResult::failure( + hostname, + &actual_fingerprint, + "No pins configured for hostname", + ); + + if config.report_only { + warn!( + "Certificate pinning violation (report-only): {} - {}", + hostname, "No pins configured" + ); + return Ok(PinValidationResult::success(hostname, "report-only", false)); + } + + return Ok(result); + } + + // No pins required, pass through + return Ok(PinValidationResult::success( + hostname, + "no-pins-required", + false, + )); + } + }; + + // Check against all pins + for pin in pins { + match pin.verify(cert_der) { + Ok(true) => { + let result = + PinValidationResult::success(hostname, &pin.fingerprint, pin.is_backup); + + if pin.is_backup { + warn!( + "Certificate matched backup pin for {}: {}", + hostname, + pin.description.as_deref().unwrap_or("backup") + ); + } + + // Update cache + if let Ok(mut cache) = self.validation_cache.write() { + cache.insert( + hostname.to_string(), + (result.clone(), std::time::Instant::now()), + ); + } + + return Ok(result); + } + Ok(false) => continue, + Err(e) => { + debug!("Pin verification error for {}: {}", hostname, e); + continue; + } + } + } + + // No pin matched + let result = PinValidationResult::failure( + hostname, + &actual_fingerprint, + &format!( + "Certificate fingerprint {} does not match any pinned certificate", + actual_fingerprint + ), + ); + + if config.report_only { + warn!( + "Certificate pinning violation (report-only): {} - actual fingerprint: {}", + hostname, actual_fingerprint + ); + return Ok(PinValidationResult::success(hostname, "report-only", false)); + } + + error!( + "Certificate pinning failure for {}: fingerprint {} not in pin set", + hostname, actual_fingerprint + ); + + Ok(result) + } + + /// Create an HTTP client with certificate pinning for a specific host + pub fn create_pinned_client(&self, hostname: &str) -> Result { + self.create_pinned_client_with_options(hostname, None, Duration::from_secs(30)) + } + + /// Create an HTTP client with certificate pinning and custom options + pub fn create_pinned_client_with_options( + &self, + hostname: &str, + ca_cert: Option<&Certificate>, + timeout: Duration, + ) -> Result { + let config = self + .config + .read() + .map_err(|_| anyhow!("Failed to acquire read lock"))?; + + let mut builder = ClientBuilder::new() + .timeout(timeout) + .connect_timeout(Duration::from_secs(10)) + .use_rustls_tls() + .https_only(true) + .tls_built_in_root_certs(true); + + // Add custom CA if provided + if let Some(cert) = ca_cert { + builder = builder.add_root_certificate(cert.clone()); + } + + // If pinning is enabled and we have pins, we need to use a custom verifier + // Note: reqwest doesn't directly support custom certificate verification, + // so we validate after connection or use a pre-flight check + if config.enabled && config.get_pins(hostname).is_some() { + debug!( + "Creating pinned client for {} with {} pins", + hostname, + config.get_pins(hostname).map(|p| p.len()).unwrap_or(0) + ); + } + + builder.build().context("Failed to build HTTP client") + } + + /// Validate a certificate from a PEM file + pub fn validate_pem_file( + &self, + hostname: &str, + pem_path: &Path, + ) -> Result { + let pem_data = fs::read(pem_path) + .with_context(|| format!("Failed to read PEM file: {:?}", pem_path))?; + + let der = pem_to_der(&pem_data)?; + self.validate_certificate(hostname, &der) + } + + /// Generate a pin from a certificate file + pub fn generate_pin_from_file(hostname: &str, cert_path: &Path) -> Result { + let cert_data = fs::read(cert_path) + .with_context(|| format!("Failed to read certificate: {:?}", cert_path))?; + + // Try PEM first, then DER + let der = if cert_data.starts_with(b"-----BEGIN") { + pem_to_der(&cert_data)? + } else { + cert_data + }; + + let fingerprint = compute_spki_fingerprint(&der)?; + let fingerprint_str = format!("sha256//{}", BASE64.encode(&fingerprint)); + + Ok(PinnedCert::new(hostname, &fingerprint_str)) + } + + /// Generate pins for all certificates in a directory + pub fn generate_pins_from_directory( + hostname: &str, + cert_dir: &Path, + ) -> Result> { + let mut pins = Vec::new(); + + for entry in fs::read_dir(cert_dir)? { + let entry = entry?; + let path = entry.path(); + + if path.is_file() { + let ext = path.extension().and_then(|e| e.to_str()).unwrap_or(""); + if matches!(ext, "crt" | "pem" | "cer" | "der") { + match Self::generate_pin_from_file(hostname, &path) { + Ok(pin) => { + info!("Generated pin from {:?}: {}", path, pin.fingerprint); + pins.push(pin); + } + Err(e) => { + warn!("Failed to generate pin from {:?}: {}", path, e); + } + } + } + } + } + + Ok(pins) + } + + /// Export current pins to a file + pub fn export_pins(&self, path: &Path) -> Result<()> { + let config = self + .config + .read() + .map_err(|_| anyhow!("Failed to acquire read lock"))?; + + config.save_to_file(path) + } + + /// Import pins from a file + pub fn import_pins(&self, path: &Path) -> Result<()> { + let imported = CertPinningConfig::load_from_file(path)?; + + let mut config = self + .config + .write() + .map_err(|_| anyhow!("Failed to acquire write lock"))?; + + for (hostname, pins) in imported.pins { + config.pins.insert(hostname, pins); + } + + // Clear cache + if let Ok(mut cache) = self.validation_cache.write() { + cache.clear(); + } + + Ok(()) + } + + /// Get statistics about pinned certificates + pub fn get_stats(&self) -> Result { + let config = self + .config + .read() + .map_err(|_| anyhow!("Failed to acquire read lock"))?; + + let mut total_pins = 0; + let mut backup_pins = 0; + let mut expiring_soon = 0; + + let now = chrono::Utc::now(); + let soon = now + chrono::Duration::days(30); + + for pins in config.pins.values() { + for pin in pins { + total_pins += 1; + if pin.is_backup { + backup_pins += 1; + } + if let Some(expires) = pin.expires_at { + if expires < soon { + expiring_soon += 1; + } + } + } + } + + Ok(PinningStats { + enabled: config.enabled, + total_hosts: config.pins.len(), + total_pins, + backup_pins, + expiring_soon, + report_only: config.report_only, + }) + } +} + +/// Statistics about certificate pinning +#[derive(Debug, Clone, Serialize)] +pub struct PinningStats { + pub enabled: bool, + pub total_hosts: usize, + pub total_pins: usize, + pub backup_pins: usize, + pub expiring_soon: usize, + pub report_only: bool, +} + +/// Compute SHA-256 fingerprint of a certificate's Subject Public Key Info (SPKI) +pub fn compute_spki_fingerprint(cert_der: &[u8]) -> Result> { + let (_, cert) = X509Certificate::from_der(cert_der) + .map_err(|e| anyhow!("Failed to parse X.509 certificate: {}", e))?; + + // Get the raw SPKI bytes + let spki = cert.public_key().raw; + + // Compute SHA-256 hash + let hash = digest(&SHA256, spki); + + Ok(hash.as_ref().to_vec()) +} + +/// Compute SHA-256 fingerprint of the entire certificate (not just SPKI) +pub fn compute_cert_fingerprint(cert_der: &[u8]) -> Vec { + let hash = digest(&SHA256, cert_der); + hash.as_ref().to_vec() +} + +/// Convert PEM-encoded certificate to DER +pub fn pem_to_der(pem_data: &[u8]) -> Result> { + let pem_str = std::str::from_utf8(pem_data).context("Invalid UTF-8 in PEM data")?; + + // Find certificate block + let start_marker = "-----BEGIN CERTIFICATE-----"; + let end_marker = "-----END CERTIFICATE-----"; + + let start = pem_str + .find(start_marker) + .ok_or_else(|| anyhow!("No certificate found in PEM data"))?; + + let end = pem_str + .find(end_marker) + .ok_or_else(|| anyhow!("Invalid PEM: missing end marker"))?; + + let base64_data = &pem_str[start + start_marker.len()..end]; + let cleaned: String = base64_data.chars().filter(|c| !c.is_whitespace()).collect(); + + BASE64 + .decode(&cleaned) + .context("Failed to decode base64 certificate data") +} + +/// Format a fingerprint for display +pub fn format_fingerprint(hash: &[u8]) -> String { + hash.iter() + .map(|b| format!("{:02X}", b)) + .collect::>() + .join(":") +} + +/// Parse a formatted fingerprint back to bytes +pub fn parse_fingerprint(formatted: &str) -> Result> { + // Handle "sha256//BASE64" format + if let Some(base64_part) = formatted.strip_prefix("sha256//") { + return BASE64 + .decode(base64_part) + .context("Failed to decode base64 fingerprint"); + } + + // Handle colon-separated hex format + if formatted.contains(':') { + let bytes: Result, _> = formatted + .split(':') + .map(|hex| u8::from_str_radix(hex, 16)) + .collect(); + + return bytes.context("Failed to parse hex fingerprint"); + } + + // Try plain hex + let bytes: Result, _> = (0..formatted.len()) + .step_by(2) + .map(|i| u8::from_str_radix(&formatted[i..i + 2], 16)) + .collect(); + + bytes.context("Failed to parse fingerprint") +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_pinned_cert_creation() { + let pin = PinnedCert::new( + "api.example.com", + "sha256//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + ); + + assert_eq!(pin.hostname, "api.example.com"); + assert!(!pin.is_backup); + assert_eq!(pin.pin_type, PinType::Leaf); + } + + #[test] + fn test_backup_pin() { + let pin = PinnedCert::backup( + "api.example.com", + "sha256//BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=", + ); + + assert!(pin.is_backup); + assert!(pin.description.is_some()); + } + + #[test] + fn test_config_add_pin() { + let mut config = CertPinningConfig::default(); + config.add_pin(PinnedCert::new( + "example.com", + "sha256//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + )); + + assert!(config.get_pins("example.com").is_some()); + assert_eq!(config.get_pins("example.com").unwrap().len(), 1); + } + + #[test] + fn test_format_fingerprint() { + let hash = vec![0xAB, 0xCD, 0xEF, 0x12]; + let formatted = format_fingerprint(&hash); + assert_eq!(formatted, "AB:CD:EF:12"); + } + + #[test] + fn test_parse_fingerprint_hex() { + let result = parse_fingerprint("AB:CD:EF:12").unwrap(); + assert_eq!(result, vec![0xAB, 0xCD, 0xEF, 0x12]); + } + + #[test] + fn test_parse_fingerprint_base64() { + let original = vec![0xAB, 0xCD, 0xEF, 0x12]; + let base64 = format!("sha256//{}", BASE64.encode(&original)); + let result = parse_fingerprint(&base64).unwrap(); + assert_eq!(result, original); + } + + #[test] + fn test_pinning_stats() { + let mut config = CertPinningConfig::default(); + config.add_pin(PinnedCert::new( + "host1.com", + "sha256//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", + )); + config.add_pin(PinnedCert::backup( + "host1.com", + "sha256//BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=", + )); + config.add_pin(PinnedCert::new( + "host2.com", + "sha256//CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC=", + )); + + let manager = CertPinningManager::new(config); + let stats = manager.get_stats().unwrap(); + + assert!(stats.enabled); + assert_eq!(stats.total_hosts, 2); + assert_eq!(stats.total_pins, 3); + assert_eq!(stats.backup_pins, 1); + } + + #[test] + fn test_pem_to_der() { + // Minimal test PEM (this is a mock, real certs would be longer) + let mock_pem = b"-----BEGIN CERTIFICATE----- +MIIB +-----END CERTIFICATE-----"; + + // Should fail gracefully with invalid base64 + let result = pem_to_der(mock_pem); + // We expect this to fail because "MIIB" is incomplete base64 + assert!(result.is_err() || result.unwrap().len() > 0); + } + + #[test] + fn test_manager_disabled() { + let mut config = CertPinningConfig::default(); + config.enabled = false; + + let manager = CertPinningManager::new(config); + assert!(!manager.is_enabled()); + } +} diff --git a/src/security/mod.rs b/src/security/mod.rs index e148abb0b..543439dc1 100644 --- a/src/security/mod.rs +++ b/src/security/mod.rs @@ -11,6 +11,7 @@ pub mod antivirus; pub mod ca; +pub mod cert_pinning; pub mod integration; pub mod mutual_tls; pub mod tls; @@ -20,6 +21,10 @@ pub use antivirus::{ ThreatSeverity, ThreatStatus, Vulnerability, }; pub use ca::{CaConfig, CaManager, CertificateRequest, CertificateResponse}; +pub use cert_pinning::{ + compute_spki_fingerprint, format_fingerprint, parse_fingerprint, CertPinningConfig, + CertPinningManager, PinType, PinValidationResult, PinnedCert, PinningStats, +}; pub use integration::{ create_https_client, get_tls_integration, init_tls_integration, to_secure_url, TlsIntegration, };