Skip to content

Conversation

@0xrinegade
Copy link
Member

@0xrinegade 0xrinegade commented May 23, 2025

…search document

This commit adds a standalone offline book website that displays the comprehensive research on Solana Protocol Design for Agent and MCP Server Registries. The implementation includes a single HTML file that loads markdown content directly from the same folder, with a responsive 90s ASCII grayscale theme design.

Summary by Sourcery

Transform the static report into a standalone offline book website with responsive 90s ASCII grayscale design, dynamic markdown content loading, and enhanced navigation features.

New Features:

  • Implement a dynamic offline book reader that loads markdown chapters into a single HTML page
  • Add navigable chapter sidebar, mobile menu toggle, and keyboard-based chapter navigation
  • Enable PDF download and print support directly from the book interface

Enhancements:

  • Replace static content and Chart.js visuals with a 90s-style ASCII grayscale theme using Tailwind CSS
  • Introduce loading spinner, error handling UI, and simplified responsive layout for improved user experience
  • Streamline navigation links with reduced padding and sharp 90s monospace styling

Documentation:

  • Add comprehensive markdown research documents covering Solana Protocol Design chapters for Agent and MCP Server Registries

…search document

This commit adds a standalone offline book website that displays the comprehensive research on Solana Protocol Design for Agent and MCP Server Registries. The implementation includes a single HTML file that loads markdown content directly from the same folder, with a responsive 90s ASCII grayscale theme design.
@netlify
Copy link

netlify bot commented May 23, 2025

Deploy Preview for aeamcp ready!

Name Link
🔨 Latest commit 299dd61
🔍 Latest deploy log https://app.netlify.com/projects/aeamcp/deploys/6830e0d01885ce0008e943e9
😎 Deploy Preview https://deploy-preview-1--aeamcp.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@sourcery-ai
Copy link

sourcery-ai bot commented May 23, 2025

Reviewer's Guide

This PR transforms the static HTML report into a standalone, single-page offline book site: it dynamically loads markdown chapters with marked.js, applies a responsive 90s ASCII-grayscale monospace theme, introduces mobile-friendly navigation and PDF/print controls, and adds graceful loading, ASCII diagram support, and error messaging—all while removing legacy static content and Chart.js.

Sequence Diagram for Dynamic Chapter Loading

sequenceDiagram
    actor User
    participant B as Browser (index.html + JS)
    participant M as marked.js
    participant FS as Local Filesystem

    User->>B: Clicks chapter link (e.g., "Chapter 2")
    B->>B: Calls loadChapter(2)
    B->>User: Shows loading spinner in #markdown-content
    B->>FS: fetch("research_draft_part2.md")
    FS-->>B: Returns Markdown content for Chapter 2
    B->>M: marked.parse(markdownContent)
    M-->>B: Returns HTML content
    B->>B: Updates #markdown-content with HTML
    B->>B: Calls addNavigation(2) to update prev/next buttons
    B->>B: Calls processAsciiDiagrams() to style <pre> tags
    B->>User: Hides loading spinner
    B->>User: Displays formatted Chapter 2 content
Loading

Class Diagram for index.html Structure and Key JavaScript Functions

classDiagram
    class OfflineBookPage {
        +String currentChapterId
        +Map<String, String> chapterFiles
        +HTMLElement header
        +HTMLElement mainNav
        +HTMLButtonElement mobileMenuButton
        +HTMLElement bookSidebar
        +HTMLButtonElement mobileSidebarButton
        +HTMLElement chapterLinksContainer
        +HTMLElement bookContentArea
        +HTMLElement markdownDisplayArea
        +HTMLElement navigationControlsArea
        +HTMLElement footer

        +loadChapter(chapterNum) void
        +toggleMenu() void
        +toggleSidebar() void
        +addNavigation(currentChapter) void
        +processAsciiDiagrams() void
        +downloadPDF() void
        +printPage() void
        +handleKeydown(event) void
        +handleResize() void
        +initializeBook() void
    }
    OfflineBookPage "1" -- "1" HTMLElement : Renders In
    OfflineBookPage -- "*" MarkdownFile : Loads
    OfflineBookPage -- "1" MarkedJS : Uses for Parsing

    class HTMLElement {
        <<HTML Element>>
    }
    class HTMLButtonElement {
        <<HTML Element>>
    }
    class MarkdownFile {
        +String path
        +String content
    }
    class MarkedJS {
        <<External Library>>
        +parse(markdownText) String
    }

    note for OfflineBookPage "Represents index.html and its associated JavaScript logic."
Loading

State Diagram for Chapter Content Area

stateDiagram-v2
    [*] --> Initializing
    Initializing --> LoadingChapter : Load default chapter (Chapter 1)
    LoadingChapter --> ChapterLoaded : Markdown fetched & parsed successfully
    LoadingChapter --> ChapterLoadError : Error fetching or parsing markdown
    ChapterLoaded --> LoadingChapter : User selects another chapter
    ChapterLoadError --> LoadingChapter : User selects another chapter (retry)
    ChapterLoaded : Displaying chapter content
    ChapterLoadError : Displaying error message
Loading

File-Level Changes

Change Details Files
Implement dynamic chapter loading and navigation
  • Load chapters on demand by fetching local markdown files
  • Show a loading spinner and parse content via marked.js
  • Gracefully handle fetch errors with user-friendly messages
  • Highlight active chapter link and support keyboard arrow navigation
  • Process and style ASCII diagrams within
     blocks
index.html
Revamp UI/navigation for mobile and PDF/print
  • Replace static nav with collapsible sidebar Table of Contents
  • Add mobile menu and sidebar toggle buttons
  • Include Download PDF and Print controls in header
  • Ensure sidebar sticks and toggles on small screens
index.html
Overhaul styling to a retro 90s ASCII-grayscale theme
  • Replace old card/info-box styles with .book-container, .book-sidebar, and .book-content layouts
  • Define monospace typography and neutral color palette
  • Add markdown element styles (h1–h4, lists, blockquotes, tables)
  • Include responsive and print-optimized CSS rules
index.html
Add research content and remove legacy static sections
  • Add fourteen markdown chapter files covering Solana protocol research
  • Remove unused static HTML sections and Chart.js references
  • Eliminate legacy inline content and static diagrams
index.html
research_draft_part2.md
research_draft_part3.md
research_draft_part4.md
research_draft_part5.md
research_draft_part6.md
research_draft_part7.md
research_draft_part8.md
research_draft_part9.md
research_draft_part14.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @0xrinegade - I've reviewed your changes and found some issues that need to be addressed.

Blocking issues:

  • Using marked without sanitization can introduce XSS risks (link)

General comments:

  • Extract the massive inline CSS and JavaScript from index.html into separate stylesheet and JS module files to make the page more maintainable and easier to navigate.
  • Implement a simple caching layer for fetched markdown chapters so users don’t re-download the same file when navigating back and forth.
  • Generate the table of contents and navigation links dynamically from your chapter list instead of hard-coding each link to reduce duplication and simplify future updates.
Here's what I looked at during the review
  • 🟡 General issues: 15 issues found
  • 🟢 Security: all looks good
  • 🟢 Review instructions: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

index.html Outdated
- CONFIRMATION: NO SVG graphics used. NO Mermaid JS used. -->
<title>Solana AI Registries: A Corporate Technical Overview (90s Monospace)</title>
<title>Solana Protocol Design for Agent and MCP Server Registries</title>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 issue (security): Using marked without sanitization can introduce XSS risks

Sanitize the Markdown output (e.g., with DOMPurify or marked's sanitization) before inserting it into innerHTML to prevent XSS vulnerabilities.

index.html Outdated
const content = await response.text();

// Render markdown content
document.getElementById('markdown-content').innerHTML = marked.parse(content);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 issue (security): Direct innerHTML assignment of parsed Markdown is unsafe

Sanitize the output of marked.parse() before assigning it to innerHTML to prevent script injection.

Comment on lines 506 to 515
function processAsciiDiagrams() {
const preElements = document.querySelectorAll('pre');
preElements.forEach(pre => {
// Check if this looks like an ASCII diagram
const content = pre.textContent;
if (content.includes('+---') || (content.includes('|') && content.includes('-'))) {
pre.classList.add('ascii-diagram');
}
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): ASCII diagram detection logic may misclassify code blocks

The current heuristic may incorrectly identify regular code as diagrams. Using a dedicated Markdown fence (e.g., ```ascii) or explicit metadata would improve accuracy.

Suggested change
function processAsciiDiagrams() {
const preElements = document.querySelectorAll('pre');
preElements.forEach(pre => {
// Check if this looks like an ASCII diagram
const content = pre.textContent;
if (content.includes('+---') || (content.includes('|') && content.includes('-'))) {
pre.classList.add('ascii-diagram');
}
});
}
function processAsciiDiagrams() {
// Only select <pre><code class="language-ascii">...</code></pre>
const asciiPreElements = document.querySelectorAll('pre > code.language-ascii');
asciiPreElements.forEach(code => {
const pre = code.parentElement;
if (pre) {
pre.classList.add('ascii-diagram');
}
});
}

index.html Outdated
<h3>Error Loading Chapter</h3>
<p>Please ensure all markdown files are in the same directory as this HTML file.</p>
<p>Expected file: ${chapterFiles[chapterNum]}</p>
<p>Error details: ${error.message}</p>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 issue (security): Exposing raw error.message to users may leak internals

Consider displaying a generic error to users and logging the detailed message elsewhere to avoid exposing internal information.

index.html Outdated
Comment on lines 563 to 573
// Handle keyboard navigation
document.addEventListener('keydown', function(e) {
// Left arrow key for previous chapter
if (e.key === 'ArrowLeft' && currentChapter > 1) {
loadChapter(currentChapter - 1);
}
// Right arrow key for next chapter
else if (e.key === 'ArrowRight' && currentChapter < Object.keys(chapterFiles).length) {
loadChapter(currentChapter + 1);
}
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Global arrow key handling may conflict with other components

Scoping the listener to only activate when the book container is focused or when not inside text inputs will help avoid interfering with default browser or input behaviors.

Suggested change
// Handle keyboard navigation
document.addEventListener('keydown', function(e) {
// Left arrow key for previous chapter
if (e.key === 'ArrowLeft' && currentChapter > 1) {
loadChapter(currentChapter - 1);
}
// Right arrow key for next chapter
else if (e.key === 'ArrowRight' && currentChapter < Object.keys(chapterFiles).length) {
loadChapter(currentChapter + 1);
}
});
// Handle keyboard navigation, but only when not inside input, textarea, or contenteditable
document.addEventListener('keydown', function(e) {
const tag = e.target.tagName.toLowerCase();
const isEditable = e.target.isContentEditable;
if (
tag === 'input' ||
tag === 'textarea' ||
isEditable
) {
return; // Don't handle navigation if typing in an input, textarea, or contenteditable
}
// Optionally, scope to a specific container (uncomment and adjust if needed)
// const bookContainer = document.getElementById('book-container');
// if (document.activeElement !== bookContainer) {
// return;
// }
// Left arrow key for previous chapter
if (e.key === 'ArrowLeft' && currentChapter > 1) {
loadChapter(currentChapter - 1);
}
// Right arrow key for next chapter
else if (e.key === 'ArrowRight' && currentChapter < Object.keys(chapterFiles).length) {
loadChapter(currentChapter + 1);
}
});

// Operational Parameters
pub rate_limit_requests: Option<u32>,
pub rate_limit_tokens: Option<u32>,
pub pricing_info_uri: Option<String>, // Max MAX_PRICING_URI_LEN
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Missing #[max_len] for pricing_info_uri

Add the #[max_len(MAX_PRICING_URI_LEN)] annotation to ensure InitSpace allocates the correct size for pricing_info_uri.

Suggested change
pub pricing_info_uri: Option<String>, // Max MAX_PRICING_URI_LEN
#[max_len(MAX_PRICING_URI_LEN)]
pub pricing_info_uri: Option<String>, // Max MAX_PRICING_URI_LEN

pub service_endpoints: Vec<ServiceEndpoint>,

// Off-chain Extension
pub extended_metadata_uri: Option<String>, // Max MAX_EXTENDED_URI_LEN
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Missing #[max_len] for extended_metadata_uri in MCPServerRegistryEntryV1

Please add the #[max_len(MAX_EXTENDED_URI_LEN)] annotation to ensure correct sizing of extended_metadata_uri.

Suggested implementation:

    // Off-chain Extension

    #[max_len(MAX_EXTENDED_URI_LEN)]
    pub extended_metadata_uri: Option<String>, // Max MAX_EXTENDED_URI_LEN


**Example: Owner Index Traversal**

Let's consider an owner index for the Agent Registry, where index accounts map an owner's public key to the `agent_id`s they own:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (typo): Typo in 'agent_id`s'

'agent_ids' is used elsewhere in this section; update for consistency.

Suggested change
Let's consider an owner index for the Agent Registry, where index accounts map an owner's public key to the `agent_id`s they own:
Let's consider an owner index for the Agent Registry, where index accounts map an owner's public key to the `agent_ids` they own:

Comment on lines +397 to +406
3. **Denial of Service (DoS) via Large Data**: While `InitSpace` and `#[max_len]` help prevent excessively large accounts during initialization, update instructions need to validate the size of incoming variable-length data (`String`, `Vec`) to prevent attempts to store data exceeding reasonable limits or causing excessive computation during deserialization/validation.

4. **Complex Enum Deserialization**: Borsh handles enums, but complex enum structures or changes in enum variants across program versions require careful handling during upgrades.

5. **IDL Discrepancies**: If the program's IDL (used by clients) gets out of sync with the actual on-chain program's data structures, clients might serialize instruction data incorrectly, leading to deserialization failures.

**Mitigation Strategies:**

1. **Use Anchor Types**: Rely on Anchor's `Account<T>`, `Program<T>`, `Signer`, etc., as they handle much of the underlying deserialization and validation securely.
2. **Strict Validation**: Implement the input validation checks discussed previously (lengths, formats) to catch invalid data before or during deserialization.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Clarify 'InitSpace' and '#[max_len]' terminology

These terms are not standard in Anchor or Rust. Please clarify if they are custom, or use standard Anchor syntax and terminology to prevent confusion.

It's possible to generate program keypairs whose public keys start with a specific prefix (vanity address) using tools like `solana-keygen grind`. This can improve recognizability but offers no security benefit.
```bash
# Example: Find a keypair whose public key starts with
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Incomplete example comment.

Please complete the example or remove the incomplete line if it's just a placeholder.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants