Skip to content

fix(oauth): MCP /mcp returns 401 (not 500) for invalid/expired tokens #219

fix(oauth): MCP /mcp returns 401 (not 500) for invalid/expired tokens

fix(oauth): MCP /mcp returns 401 (not 500) for invalid/expired tokens #219

Workflow file for this run

name: CI
on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev]
workflow_dispatch:
env:
NODE_VERSION: "22"
# Opt into Node.js 24 runner for JavaScript actions ahead of the June 2026 default.
# See: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
jobs:
typecheck:
name: TypeScript Compile
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
- run: npm ci
- run: npx tsc --noEmit
test:
name: Unit + Integration Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
- run: npm ci
- name: Run Vitest (ephemeral server, in-memory DB, RM_TEST_MODE=1)
run: npm test
security:
name: Security Checks
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Verify .env files are gitignored
run: |
if ! grep -q '\.env' .gitignore 2>/dev/null; then
echo "::error::.env is not in .gitignore"
exit 1
fi
- name: Verify no sensitive files are tracked
run: |
SENSITIVE=(.env .env.local .env.production credentials.json serviceAccountKey.json)
for f in "${SENSITIVE[@]}"; do
if git ls-files --error-unmatch "$f" 2>/dev/null; then
echo "::error::Sensitive file '${f}' is tracked by git -- remove it and rotate credentials"
exit 1
fi
done
- name: Scan for hardcoded secrets
run: |
PATTERNS=(
'AKIA[0-9A-Z]{16}'
'sk-[a-zA-Z0-9]{20,}'
'sk_live_[a-zA-Z0-9]{20,}'
'rk_live_[a-zA-Z0-9]{20,}'
'ghp_[a-zA-Z0-9]{36}'
'gho_[a-zA-Z0-9]{36}'
'github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59}'
'glpat-[a-zA-Z0-9\-]{20,}'
'xox[bpors]-[a-zA-Z0-9\-]+'
'SG\.[a-zA-Z0-9_-]{22}\.[a-zA-Z0-9_-]{43}'
'rm_live_[a-f0-9]{48}'
)
FAILED=0
for pattern in "${PATTERNS[@]}"; do
MATCHES=$(grep -rEn "$pattern" \
--include='*.ts' --include='*.js' --include='*.mjs' \
--include='*.json' --include='*.yml' --include='*.yaml' \
--include='*.md' --include='*.env.*' \
--exclude-dir=node_modules --exclude-dir=dist \
--exclude-dir=.git --exclude='package-lock.json' \
--exclude='ci.yml' --exclude='security.yml' \
. 2>/dev/null || true)
if [ -n "$MATCHES" ]; then
echo "::error::Potential secret matching: ${pattern:0:20}..."
echo "$MATCHES" | head -5
FAILED=1
fi
done
if [ "$FAILED" -eq 1 ]; then
exit 1
fi
audit:
name: Dependency Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
- run: npm ci
# Temporarily allow moderate until vuln fix PR lands (tracked in TEST_PLAN.md phase 7).
# Critical/high still block.
- run: npm audit --production --audit-level=high