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.
-
-
-
-
-
-
-
-
-
-#### 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