rescript-openapi 0.1.0

Generate type-safe ReScript clients from OpenAPI specifications
Documentation
# SPDX-License-Identifier: PMPL-1.0-or-later
# Hypatia Neurosymbolic CI/CD Security Scan
name: Hypatia Security Scan

on:
  push:
    branches: [ main, master, develop ]
  pull_request:
    branches: [ main, master ]
  schedule:
    - cron: '0 0 * * 0'  # Weekly on Sunday
  workflow_dispatch:

permissions: read-all

jobs:
  scan:
    name: Hypatia Neurosymbolic Analysis
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
        with:
          fetch-depth: 0  # Full history for better pattern analysis

      - name: Setup Elixir for Hypatia scanner
        uses: erlef/setup-beam@2f0cc07b4b9bea248ae098aba9e1a8a1de5ec24c # v1.18.2
        with:
          elixir-version: '1.19.4'
          otp-version: '28.3'

      - name: Clone Hypatia
        run: |
          if [ ! -d "$HOME/hypatia" ]; then
            git clone https://github.com/hyperpolymath/hypatia.git "$HOME/hypatia"
          fi

      - name: Build Hypatia scanner (if needed)
        working-directory: ${{ env.HOME }}/hypatia
        run: |
          if [ ! -f hypatia-v2 ]; then
            echo "Building hypatia-v2 scanner..."
            cd scanner
            mix deps.get
            mix escript.build
            mv hypatia ../hypatia-v2
          fi

      - name: Run Hypatia scan
        id: scan
        run: |
          echo "Scanning repository: ${{ github.repository }}"

          # Run scanner
          HYPATIA_FORMAT=json "$HOME/hypatia/hypatia-cli.sh" scan . > hypatia-findings.json

          # Count findings
          FINDING_COUNT=$(jq '. | length' hypatia-findings.json 2>/dev/null || echo 0)
          echo "findings_count=$FINDING_COUNT" >> $GITHUB_OUTPUT

          # Extract severity counts
          CRITICAL=$(jq '[.[] | select(.severity == "critical")] | length' hypatia-findings.json)
          HIGH=$(jq '[.[] | select(.severity == "high")] | length' hypatia-findings.json)
          MEDIUM=$(jq '[.[] | select(.severity == "medium")] | length' hypatia-findings.json)

          echo "critical=$CRITICAL" >> $GITHUB_OUTPUT
          echo "high=$HIGH" >> $GITHUB_OUTPUT
          echo "medium=$MEDIUM" >> $GITHUB_OUTPUT

          echo "## Hypatia Scan Results" >> $GITHUB_STEP_SUMMARY
          echo "- Total findings: $FINDING_COUNT" >> $GITHUB_STEP_SUMMARY
          echo "- Critical: $CRITICAL" >> $GITHUB_STEP_SUMMARY
          echo "- High: $HIGH" >> $GITHUB_STEP_SUMMARY
          echo "- Medium: $MEDIUM" >> $GITHUB_STEP_SUMMARY

      - name: Upload findings artifact
        uses: actions/upload-artifact@65c79d7f54e76e4e3c7a8f34db0f4ac8b515c478 # v4
        with:
          name: hypatia-findings
          path: hypatia-findings.json
          retention-days: 90

      - name: Submit findings to gitbot-fleet (Phase 2)
        if: steps.scan.outputs.findings_count > 0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          GITHUB_REPOSITORY: ${{ github.repository }}
          GITHUB_SHA: ${{ github.sha }}
        run: |
          echo "📤 Submitting ${{ steps.scan.outputs.findings_count }} findings to gitbot-fleet..."

          # Clone gitbot-fleet to temp directory
          FLEET_DIR="/tmp/gitbot-fleet-$$"
          git clone https://github.com/hyperpolymath/gitbot-fleet.git "$FLEET_DIR"

          # Run submission script
          bash "$FLEET_DIR/scripts/submit-finding.sh" hypatia-findings.json

          # Cleanup
          rm -rf "$FLEET_DIR"

          echo "✅ Finding submission complete"

      - name: Check for critical issues
        if: steps.scan.outputs.critical > 0
        run: |
          echo "⚠️  Critical security issues found!"
          echo "Review hypatia-findings.json for details"
          # Don't fail the build yet - just warn
          # exit 1

      - name: Generate scan report
        run: |
          cat << EOF > hypatia-report.md
          # Hypatia Security Scan Report

          **Repository:** ${{ github.repository }}
          **Scan Date:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")
          **Commit:** ${{ github.sha }}

          ## Summary

          | Severity | Count |
          |----------|-------|
          | Critical | ${{ steps.scan.outputs.critical }} |
          | High     | ${{ steps.scan.outputs.high }} |
          | Medium   | ${{ steps.scan.outputs.medium }} |
          | **Total**| ${{ steps.scan.outputs.findings_count }} |

          ## Next Steps

          1. Review findings in the artifact: hypatia-findings.json
          2. Auto-fixable issues will be addressed by robot-repo-automaton (Phase 3)
          3. Manual review required for complex issues

          ## Learning

          These findings feed Hypatia's learning engine to improve future rules.

          ---
          *Powered by [Hypatia](https://github.com/hyperpolymath/hypatia) - Neurosymbolic CI/CD Intelligence*
          EOF

          cat hypatia-report.md >> $GITHUB_STEP_SUMMARY

      - name: Comment on PR with findings
        if: github.event_name == 'pull_request' && steps.scan.outputs.findings_count > 0
        uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
        with:
          script: |
            const fs = require('fs');
            const findings = JSON.parse(fs.readFileSync('hypatia-findings.json', 'utf8'));

            const critical = findings.filter(f => f.severity === 'critical').length;
            const high = findings.filter(f => f.severity === 'high').length;

            let comment = `## 🔍 Hypatia Security Scan\n\n`;
            comment += `**Findings:** ${findings.length} issues detected\n\n`;
            comment += `| Severity | Count |\n|----------|-------|\n`;
            comment += `| 🔴 Critical | ${critical} |\n`;
            comment += `| 🟠 High | ${high} |\n`;
            comment += `| 🟡 Medium | ${findings.length - critical - high} |\n\n`;

            if (critical > 0) {
              comment += `⚠️ **Action Required:** Critical security issues found!\n\n`;
            }

            comment += `<details><summary>View findings</summary>\n\n`;
            comment += `\`\`\`json\n${JSON.stringify(findings.slice(0, 10), null, 2)}\n\`\`\`\n`;
            comment += `</details>\n\n`;
            comment += `*Powered by Hypatia Neurosymbolic CI/CD Intelligence*`;

            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: comment
            });