diff --git a/.github/workflows/pr-to-slack-codex.yml b/.github/workflows/pr-to-slack-codex.yml deleted file mode 100644 index 789eb2a86..000000000 --- a/.github/workflows/pr-to-slack-codex.yml +++ /dev/null @@ -1,207 +0,0 @@ -name: PR → Codex review → Slack - -on: - pull_request: - types: [opened, reopened, ready_for_review] - -jobs: - codex_review: - # Run only for trusted contributors - if: ${{ contains(fromJSON('["OWNER","MEMBER","COLLABORATOR","CONTRIBUTOR"]'), github.event.pull_request.author_association) }} - - runs-on: ubuntu-latest - timeout-minutes: 15 - permissions: - contents: read - pull-requests: write - - steps: - - name: Checkout PR HEAD (full history) - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - - uses: actions/setup-node@v4 - with: - node-version: '22' - - - name: Install Codex CLI - run: npm i -g @openai/codex - - - name: Codex login - env: - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - run: | - set -euo pipefail - echo "$OPENAI_API_KEY" | codex login --with-api-key - - - name: Compute merge-base diff (compact) - run: | - set -euo pipefail - BASE_REF='${{ github.event.pull_request.base.ref }}' - git fetch --no-tags origin "$BASE_REF":"refs/remotes/origin/$BASE_REF" - MB=$(git merge-base "origin/$BASE_REF" HEAD) - git diff --unified=0 "$MB"..HEAD > pr.diff - git --no-pager diff --stat "$MB"..HEAD > pr.stat || true - - - name: Build prompt and run Codex (guard + fallback) - env: - PR_URL: ${{ github.event.pull_request.html_url }} - PR_NUMBER: ${{ github.event.pull_request.number }} - run: | - set -euo pipefail - MAX=${MAX_DIFF_BYTES:-900000} # ~0.9MB ceiling; override via env if needed - - BYTES=$(wc -c < pr.diff || echo 0) - echo "pr.diff size: $BYTES bytes (limit: $MAX)" - - # Common prelude for AppSec review - { - echo "You are a skilled AppSec reviewer. Analyze this PR for:" - echo "bugs, vulnerabilities, loss of funds issues, crypto attack vectors, signature vulnerability, replay attacks etc.." - echo "Think deeply. Prioritize the *changed hunks* in pr.diff, but open any other files" - echo "in the checkout as needed for context." - echo - echo "Return a tight executive summary, then bullets with:" - echo "- severity (high/med/low)" - echo "- file:line pointers" - echo "- concrete fixes & example patches" - echo '- if N/A, say "No significant issues found."' - echo - echo "PR URL: $PR_URL" - echo - echo "Formatting requirements:" - echo "- Output MUST be GitHub-flavored Markdown (GFM)." - echo "- Start with '## Executive summary' (one short paragraph)." - echo "- Then '## Findings and fixes' as a bullet list." - echo "- Use fenced code blocks for patches/configs with language tags (diff, yaml, etc.)." - echo "- Use inline code for file:line and identifiers." - } > prompt.txt - - if [ "$BYTES" -le "$MAX" ] && [ "$BYTES" -gt 0 ]; then - echo "Using embedded diff path (<= $MAX bytes)" - { - echo "Unified diff (merge-base vs HEAD):" - echo '```diff' - cat pr.diff - echo '```' - } >> prompt.txt - - echo "---- prompt head ----"; head -n 40 prompt.txt >&2 - echo "---- prompt size ----"; wc -c prompt.txt >&2 - - # Run Codex with a scrubbed env: only OPENAI_API_KEY, PATH, HOME - env -i OPENAI_API_KEY="${{ secrets.OPENAI_API_KEY }}" PATH="$PATH" HOME="$HOME" \ - codex --model gpt-5-codex --ask-for-approval never exec \ - --sandbox read-only \ - --output-last-message review.md \ - < prompt.txt \ - > codex.log 2>&1 - - else - echo "Large diff – switching to fallback that lets Codex fetch the .diff URL" - # Recompute merge-base and HEAD for clarity in the prompt - BASE_REF='${{ github.event.pull_request.base.ref }}' - git fetch --no-tags origin "$BASE_REF":"refs/remotes/origin/$BASE_REF" - MB=$(git merge-base "origin/$BASE_REF" HEAD) - HEAD_SHA=$(git rev-parse HEAD) - DIFF_URL="${PR_URL}.diff" - - { - echo "The diff is too large to embed safely in this CI run." - echo "Please fetch and analyze the diff from this URL:" - echo "$DIFF_URL" - echo - echo "Commit range (merge-base...HEAD):" - echo "merge-base: $MB" - echo "head: $HEAD_SHA" - echo - echo "For quick orientation, here is the diffstat:" - echo '```' - cat pr.stat || true - echo '```' - echo - echo "After fetching the diff, continue with the same review instructions above." - } >> prompt.txt - - echo "---- fallback prompt head ----"; head -n 80 prompt.txt >&2 - echo "---- fallback prompt size ----"; wc -c prompt.txt >&2 - - # Network-enabled only for this large-diff case; still scrub env - env -i OPENAI_API_KEY="${{ secrets.OPENAI_API_KEY }}" PATH="$PATH" HOME="$HOME" \ - codex --model gpt-5-codex --ask-for-approval never exec \ - --sandbox danger-full-access \ - --output-last-message review.md \ - < prompt.txt \ - > codex.log 2>&1 - fi - - # Defensive: ensure later steps don't explode - if [ ! -s review.md ]; then - echo "_Codex produced no output._" > review.md - fi - - - name: Post parent message in Slack (blocks) - id: post_parent - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} - run: | - resp=$(curl -s -X POST https://slack.com/api/chat.postMessage \ - -H "Authorization: Bearer $SLACK_BOT_TOKEN" \ - -H 'Content-type: application/json; charset=utf-8' \ - --data "$(jq -n \ - --arg ch "$SLACK_CHANNEL_ID" \ - --arg n "${{ github.event.pull_request.number }}" \ - --arg t "${{ github.event.pull_request.title }}" \ - --arg a "${{ github.event.pull_request.user.login }}" \ - --arg u "${{ github.event.pull_request.html_url }}" \ - '{ - channel: $ch, - text: ("PR #" + $n + ": " + $t), - blocks: [ - { "type":"section", "text":{"type":"mrkdwn","text":("*PR #"+$n+":* "+$t)} }, - { "type":"section", "text":{"type":"mrkdwn","text":("• Author: "+$a)} }, - { "type":"section", "text":{"type":"mrkdwn","text":("• Link: <"+$u+">")} } - ], - unfurl_links:false, unfurl_media:false - }')" ) - echo "ts=$(echo "$resp" | jq -r '.ts')" >> "$GITHUB_OUTPUT" - - - name: Thread reply with review (upload via Slack external upload API) - env: - SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} - SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }} - TS: ${{ steps.post_parent.outputs.ts }} - run: | - set -euo pipefail - - # robust byte count (works on Linux & macOS) - BYTES=$( (stat -c%s review.md 2>/dev/null || stat -f%z review.md 2>/dev/null) ) - BYTES=${BYTES:-$(wc -c < review.md | tr -d '[:space:]')} - - ticket=$(curl -sS -X POST https://slack.com/api/files.getUploadURLExternal \ - -H "Authorization: Bearer $SLACK_BOT_TOKEN" \ - -H "Content-type: application/x-www-form-urlencoded" \ - --data-urlencode "filename=codex_review.md" \ - --data "length=$BYTES" \ - --data "snippet_type=markdown") - echo "$ticket" - upload_url=$(echo "$ticket" | jq -r '.upload_url') - file_id=$(echo "$ticket" | jq -r '.file_id') - test "$upload_url" != "null" -a "$file_id" != "null" || { echo "getUploadURLExternal failed: $ticket" >&2; exit 1; } - - curl -sS -X POST "$upload_url" \ - -F "filename=@review.md;type=text/markdown" \ - > /dev/null - - payload=$(jq -n --arg fid "$file_id" --arg ch "$SLACK_CHANNEL_ID" --arg ts "$TS" \ - --arg title "Codex Security Review" --arg ic "Automated Codex review attached." \ - '{files:[{id:$fid, title:$title}], channel_id:$ch, thread_ts:$ts, initial_comment:$ic}') - resp=$(curl -sS -X POST https://slack.com/api/files.completeUploadExternal \ - -H "Authorization: Bearer $SLACK_BOT_TOKEN" \ - -H "Content-type: application/json; charset=utf-8" \ - --data "$payload") - echo "$resp" - test "$(echo "$resp" | jq -r '.ok')" = "true" || { echo "files.completeUploadExternal failed: $resp" >&2; exit 1; } diff --git a/.github/workflows/uci-stale-check.yml b/.github/workflows/uci-stale-check.yml index a6c5f4b6d..1a7510988 100644 --- a/.github/workflows/uci-stale-check.yml +++ b/.github/workflows/uci-stale-check.yml @@ -10,8 +10,10 @@ permissions: contents: read concurrency: - group: ${{ github.workflow }}-${{ github.sha }} - cancel-in-progress: true + # A sweep is cheap and idempotent, but cancelling one part-way leaves the triage + # half-applied, so queue behind a running sweep instead of superseding it. + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false jobs: stale: @@ -26,3 +28,7 @@ jobs: uses: sei-protocol/uci/.github/workflows/stale-check.yml@65901242783550521f25a19199a6b10e54550b97 with: days-before-pr-stale: 28 + # Disable both paths: -1 stops new stale labels, while the close setting + # protects issues that already carry the stale label. + days-before-issue-stale: -1 + days-before-issue-close: -1 diff --git a/.gitignore b/.gitignore index 86ca8e9ae..974a2afc3 100644 --- a/.gitignore +++ b/.gitignore @@ -25,11 +25,7 @@ node_modules *.sublime-workspace # IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json +.vscode/ # misc /.sass-cache diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 2c0f4932e..000000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["nrwl.angular-console", "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", "firsttris.vscode-jest-runner"] -} diff --git a/.windsurf/rules/docs.md b/.windsurf/rules/docs.md deleted file mode 100644 index 989a4acb0..000000000 --- a/.windsurf/rules/docs.md +++ /dev/null @@ -1,368 +0,0 @@ ---- -trigger: model_decision -description: When writing any Mintlify docs for any package. These docs are located in the /docs folder ---- - ---- -description: Mintlify writing assistant guidelines -type: always ---- -# Mintlify technical writing assistant - -You are an AI writing assistant specialized in creating exceptional technical documentation using Mintlify components and following industry-leading technical writing practices. - -## Core writing principles - -### Language and style requirements -- Use clear, direct language appropriate for technical audiences -- Write in second person ("you") for instructions and procedures -- Use active voice over passive voice -- Employ present tense for current states, future tense for outcomes -- Maintain consistent terminology throughout all documentation -- Keep sentences concise while providing necessary context -- Use parallel structure in lists, headings, and procedures - -### Content organization standards -- Lead with the most important information (inverted pyramid structure) -- Use progressive disclosure: basic concepts before advanced ones -- Break complex procedures into numbered steps -- Include prerequisites and context before instructions -- Provide expected outcomes for each major step -- End sections with next steps or related information -- Use descriptive, keyword-rich headings for navigation and SEO - -### User-centered approach -- Focus on user goals and outcomes rather than system features -- Anticipate common questions and address them proactively -- Include troubleshooting for likely failure points -- Provide multiple pathways when appropriate (beginner vs advanced), but offer an opinionated path for people to follow to avoid overwhelming with options - -## Mintlify component reference - -### Callout components - -#### Note - Additional helpful information - - -Supplementary information that supports the main content without interrupting flow - - -#### Tip - Best practices and pro tips - - -Expert advice, shortcuts, or best practices that enhance user success - - -#### Warning - Important cautions - - -Critical information about potential issues, breaking changes, or destructive actions - - -#### Info - Neutral contextual information - - -Background information, context, or neutral announcements - - -#### Check - Success confirmations - - -Positive confirmations, successful completions, or achievement indicators - - -### Code components - -#### Single code block - -```javascript config.js -const apiConfig = { -baseURL: 'https://api.example.com', -timeout: 5000, -headers: { - 'Authorization': `Bearer ${process.env.API_TOKEN}` -} -}; -``` - -#### Code group with multiple languages - - -```javascript Node.js -const response = await fetch('/api/endpoint', { - headers: { Authorization: `Bearer ${apiKey}` } -}); -``` - -```python Python -import requests -response = requests.get('/api/endpoint', - headers={'Authorization': f'Bearer {api_key}'}) -``` - -```curl cURL -curl -X GET '/api/endpoint' \ - -H 'Authorization: Bearer YOUR_API_KEY' -``` - - -#### Request/Response examples - - -```bash cURL -curl -X POST 'https://api.example.com/users' \ - -H 'Content-Type: application/json' \ - -d '{"name": "John Doe", "email": "john@example.com"}' -``` - - - -```json Success -{ - "id": "user_123", - "name": "John Doe", - "email": "john@example.com", - "created_at": "2024-01-15T10:30:00Z" -} -``` - - -### Structural components - -#### Steps for procedures - - - - Run `npm install` to install required packages. - - - Verify installation by running `npm list`. - - - - - Create a `.env` file with your API credentials. - - ```bash - API_KEY=your_api_key_here - ``` - - - Never commit API keys to version control. - - - - -#### Tabs for alternative content - - - - ```bash - brew install node - npm install -g package-name - ``` - - - - ```powershell - choco install nodejs - npm install -g package-name - ``` - - - - ```bash - sudo apt install nodejs npm - npm install -g package-name - ``` - - - -#### Accordions for collapsible content - - - - - **Firewall blocking**: Ensure ports 80 and 443 are open - - **Proxy configuration**: Set HTTP_PROXY environment variable - - **DNS resolution**: Try using 8.8.8.8 as DNS server - - - - ```javascript - const config = { - performance: { cache: true, timeout: 30000 }, - security: { encryption: 'AES-256' } - }; - ``` - - - -### API documentation components - -#### Parameter fields - - -Unique identifier for the user. Must be a valid UUID v4 format. - - - -User's email address. Must be valid and unique within the system. - - - -Maximum number of results to return. Range: 1-100. - - - -Bearer token for API authentication. Format: `Bearer YOUR_API_KEY` - - -#### Response fields - - -Unique identifier assigned to the newly created user. - - - -ISO 8601 formatted timestamp of when the user was created. - - - -List of permission strings assigned to this user. - - -#### Expandable nested fields - - -Complete user object with all associated data. - - - - User profile information including personal details. - - - - User's first name as entered during registration. - - - - URL to user's profile picture. Returns null if no avatar is set. - - - - - - -### Interactive components - -#### Cards for navigation - - -Complete walkthrough from installation to your first API call in under 10 minutes. - - - - - Learn how to authenticate requests using API keys or JWT tokens. - - - - Understand rate limits and best practices for high-volume usage. - - - -### Media and advanced components - -#### Frames for images - -Wrap all images in frames. - - -Main dashboard showing analytics overview - - - -Analytics dashboard with charts - - -#### Tooltips and updates - - -API - - - -## New features -- Added bulk user import functionality -- Improved error messages with actionable suggestions - -## Bug fixes -- Fixed pagination issue with large datasets -- Resolved authentication timeout problems - - -## Required page structure - -Every documentation page must begin with YAML frontmatter: - -```yaml ---- -title: "Clear, specific, keyword-rich title" -description: "Concise description explaining page purpose and value" ---- -``` - -## Content quality standards - -### Code examples requirements -- Always include complete, runnable examples that users can copy and execute -- Show proper error handling and edge case management -- Use realistic data instead of placeholder values -- Include expected outputs and results for verification -- Test all code examples thoroughly before publishing -- Specify language and include filename when relevant -- Add explanatory comments for complex logic - -### API documentation requirements -- Document all parameters including optional ones with clear descriptions -- Show both success and error response examples with realistic data -- Include rate limiting information with specific limits -- Provide authentication examples showing proper format -- Explain all HTTP status codes and error handling -- Cover complete request/response cycles - -### Accessibility requirements -- Include descriptive alt text for all images and diagrams -- Use specific, actionable link text instead of "click here" -- Ensure proper heading hierarchy starting with H2 -- Provide keyboard navigation considerations -- Use sufficient color contrast in examples and visuals -- Structure content for easy scanning with headers and lists - -## AI assistant instructions - -### Component selection logic -- Use **Steps** for procedures, tutorials, setup guides, and sequential instructions -- Use **Tabs** for platform-specific content or alternative approaches -- Use **CodeGroup** when showing the same concept in multiple languages -- Use **Accordions** for supplementary information that might interrupt flow -- Use **Cards and CardGroup** for navigation, feature overviews, and related resources -- Use **RequestExample/ResponseExample** specifically for API endpoint documentation -- Use **ParamField** for API parameters, **ResponseField** for API responses -- Use **Expandable** for nested object properties or hierarchical information - -### Quality assurance checklist -- Verify all code examples are syntactically correct and executable -- Test all links to ensure they are functional and lead to relevant content -- Validate Mintlify component syntax with all required properties -- Confirm proper heading hierarchy with H2 for main sections, H3 for subsections -- Ensure content flows logically from basic concepts to advanced topics -- Check for consistency in terminology, formatting, and component usage - -### Error prevention strategies -- Always include realistic error handling in code examples -- Provide dedicated troubleshooting sections for complex procedures -- Explain prerequisites clearly before beginning instructions -- Include verification and testing steps with expected outcomes -- Add appropriate warnings for destructive or security-sensitive actions -- Validate all technical information through testing before publication \ No newline at end of file diff --git a/REVIEW.md b/REVIEW.md index c50f13788..bde73246a 100644 --- a/REVIEW.md +++ b/REVIEW.md @@ -37,10 +37,6 @@ overridable through `MAINNET_RPC_URL` / `TESTNET_RPC_URL` / `DEVNET_RPC_URL` in `src/core/config.ts` and must never reach a log line, an error message, or a tool response. -Note that `.github/workflows/pr-to-slack-codex.yml` already runs a separate -AppSec pass to Slack. Overlapping findings are expected; don't suppress a real -issue because you assume the other reviewer caught it. - ## 2. Precompile addresses and ABIs are hand-maintained source `packages/precompiles/src/precompiles/*.ts` is not generated — there is no @@ -78,15 +74,19 @@ defect. path reachable from stdio breaks the transport. - **The CORS middleware sets no `Access-Control-Allow-Origin`.** `createCorsMiddleware()` answers preflights with a bare 204 and no CORS - headers. That is deny-by-default: a browser treats the missing header as a - failure and blocks the request. It is not an oversight and not a permissive - wildcard. + headers. The *absence of a permissive wildcard* is deliberate, so don't file + it as a misconfiguration. Note the limit of that guarantee: it only binds + browsers that honour the missing header. Neither `http-sse.ts` nor + `streamable-http.ts` validates `Origin` or `Host`, so a non-browser client or + a DNS-rebinding attack still reaches the tool surface — that gap is a + separate question and is fair to raise. - **`process.exit(1)` inside `validateSecurityConfig()`.** Failing closed at startup is the intent. Do not ask for a thrown error the caller might swallow. - **`packages/registry/chain-registry` and `.../community-assetlist` are missing from the tree.** Both are git submodules (`.gitmodules`) and are - listed in `.gitignore`; they are populated by the `registry` package's - `postinstall` and by CI's submodule checkout. Their JSON is vendored + listed in `.gitignore`. Only `release.yml` checks them out with + `submodules: recursive`; the PR gate in `checks.yml` does a plain checkout + and relies on the `registry` package's `postinstall`. Their JSON is vendored upstream — review the TypeScript wrappers, not the data. - **Biome findings are not enforced anywhere.** `biome.json` configures tabs, 160-column lines, single quotes and no trailing commas, but no package