fix(projects): pin the ListProjects status wire contract, "active" included #3179
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Security | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| schedule: | |
| # Weekly scan on Monday at 6am UTC | |
| - cron: '0 6 * * 1' | |
| workflow_dispatch: | |
| permissions: {} | |
| jobs: | |
| trivy-go: | |
| name: Trivy (Go SDK) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| # Full-severity SARIF for Security-tab visibility; the gate step below enforces policy. | |
| # (In SARIF mode the action reports all severities unless limit-severities-for-sarif is set.) | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: './go' | |
| ignore-unfixed: true | |
| format: 'sarif' | |
| output: 'trivy-go-results.sarif' | |
| - name: Upload Trivy scan results to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 | |
| if: always() | |
| continue-on-error: true # Requires GitHub Advanced Security | |
| with: | |
| sarif_file: 'trivy-go-results.sarif' | |
| category: 'trivy-go' | |
| # Table mode passes the severity filter through, so this gates on HIGH/CRITICAL only. | |
| - name: Fail on HIGH/CRITICAL vulnerabilities | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| env: | |
| TRIVY_SKIP_DB_UPDATE: true | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: './go' | |
| severity: 'HIGH,CRITICAL' | |
| exit-code: '1' | |
| ignore-unfixed: true | |
| format: 'table' | |
| skip-setup-trivy: true | |
| cache: 'false' | |
| # Ground truth, and the authoritative check: the static parser predicts | |
| # that nothing writes a lockfile, this observes whether anything did. A CI | |
| # checkout starts pristine, so the committed tree is the baseline. Catches | |
| # a manifest that was modified AND one CREATED where none was tracked, and | |
| # runs on failure too, so a job cannot fail and hide what it dirtied. | |
| - name: Dependency manifests unchanged by this job | |
| if: always() | |
| working-directory: . | |
| run: ./scripts/assert-lockfiles-unchanged --verify-clean | |
| trivy-typescript: | |
| name: Trivy (TypeScript SDK) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| # Full-severity SARIF for Security-tab visibility; the gate step below enforces policy. | |
| # (In SARIF mode the action reports all severities unless limit-severities-for-sarif is set.) | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: './typescript' | |
| ignore-unfixed: true | |
| format: 'sarif' | |
| output: 'trivy-ts-results.sarif' | |
| - name: Upload Trivy scan results to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 | |
| if: always() | |
| continue-on-error: true # Requires GitHub Advanced Security | |
| with: | |
| sarif_file: 'trivy-ts-results.sarif' | |
| category: 'trivy-typescript' | |
| # Table mode passes the severity filter through, so this gates on HIGH/CRITICAL only. | |
| - name: Fail on HIGH/CRITICAL vulnerabilities | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| env: | |
| TRIVY_SKIP_DB_UPDATE: true | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: './typescript' | |
| severity: 'HIGH,CRITICAL' | |
| exit-code: '1' | |
| ignore-unfixed: true | |
| format: 'table' | |
| skip-setup-trivy: true | |
| cache: 'false' | |
| # Ground truth, and the authoritative check: the static parser predicts | |
| # that nothing writes a lockfile, this observes whether anything did. A CI | |
| # checkout starts pristine, so the committed tree is the baseline. Catches | |
| # a manifest that was modified AND one CREATED where none was tracked, and | |
| # runs on failure too, so a job cannot fail and hide what it dirtied. | |
| - name: Dependency manifests unchanged by this job | |
| if: always() | |
| working-directory: . | |
| run: ./scripts/assert-lockfiles-unchanged --verify-clean | |
| govulncheck: | |
| name: Go Vulnerability Check | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: go | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Go | |
| uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version-file: 'go/go.mod' | |
| cache-dependency-path: 'go/go.sum' | |
| # Scan against the newest 1.26.x, not whatever patch the runner has cached. | |
| check-latest: true | |
| - name: Install govulncheck | |
| run: go install golang.org/x/vuln/cmd/govulncheck@latest | |
| - name: Run govulncheck | |
| run: govulncheck ./... | |
| # Ground truth, and the authoritative check: the static parser predicts | |
| # that nothing writes a lockfile, this observes whether anything did. A CI | |
| # checkout starts pristine, so the committed tree is the baseline. Catches | |
| # a manifest that was modified AND one CREATED where none was tracked, and | |
| # runs on failure too, so a job cannot fail and hide what it dirtied. | |
| - name: Dependency manifests unchanged by this job | |
| if: always() | |
| working-directory: . | |
| run: ./scripts/assert-lockfiles-unchanged --verify-clean | |
| gosec: | |
| name: Go Security Checker | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| security-events: write | |
| defaults: | |
| run: | |
| working-directory: go | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Go | |
| uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version-file: 'go/go.mod' | |
| cache-dependency-path: 'go/go.sum' | |
| - name: Install gosec | |
| run: go install github.com/securego/gosec/v2/cmd/gosec@v2.23.0 | |
| - name: Run gosec | |
| run: gosec -severity high -exclude-dir=pkg/generated -fmt sarif -out gosec-results.sarif ./... | |
| - name: Upload gosec results | |
| uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 | |
| if: always() | |
| continue-on-error: true | |
| with: | |
| sarif_file: 'go/gosec-results.sarif' | |
| category: 'gosec' | |
| # Ground truth, and the authoritative check: the static parser predicts | |
| # that nothing writes a lockfile, this observes whether anything did. A CI | |
| # checkout starts pristine, so the committed tree is the baseline. Catches | |
| # a manifest that was modified AND one CREATED where none was tracked, and | |
| # runs on failure too, so a job cannot fail and hide what it dirtied. | |
| - name: Dependency manifests unchanged by this job | |
| if: always() | |
| working-directory: . | |
| run: ./scripts/assert-lockfiles-unchanged --verify-clean | |
| npm-audit: | |
| name: npm Audit (TypeScript SDK) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: typescript | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Node.js | |
| uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: '24' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run npm audit | |
| run: npm audit --audit-level=high | |
| # Ground truth, and the authoritative check: the static parser predicts | |
| # that nothing writes a lockfile, this observes whether anything did. A CI | |
| # checkout starts pristine, so the committed tree is the baseline. Catches | |
| # a manifest that was modified AND one CREATED where none was tracked, and | |
| # runs on failure too, so a job cannot fail and hide what it dirtied. | |
| - name: Dependency manifests unchanged by this job | |
| if: always() | |
| working-directory: . | |
| run: ./scripts/assert-lockfiles-unchanged --verify-clean | |
| trivy-ruby: | |
| name: Trivy (Ruby SDK) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| # Full-severity SARIF for Security-tab visibility; the gate step below enforces policy. | |
| # (In SARIF mode the action reports all severities unless limit-severities-for-sarif is set.) | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: './ruby' | |
| ignore-unfixed: true | |
| format: 'sarif' | |
| output: 'trivy-ruby-results.sarif' | |
| - name: Upload Trivy scan results to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 | |
| if: always() | |
| continue-on-error: true | |
| with: | |
| sarif_file: 'trivy-ruby-results.sarif' | |
| category: 'trivy-ruby' | |
| # Table mode passes the severity filter through, so this gates on HIGH/CRITICAL only. | |
| - name: Fail on HIGH/CRITICAL vulnerabilities | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| env: | |
| TRIVY_SKIP_DB_UPDATE: true | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: './ruby' | |
| severity: 'HIGH,CRITICAL' | |
| exit-code: '1' | |
| ignore-unfixed: true | |
| format: 'table' | |
| skip-setup-trivy: true | |
| cache: 'false' | |
| # Ground truth, and the authoritative check: the static parser predicts | |
| # that nothing writes a lockfile, this observes whether anything did. A CI | |
| # checkout starts pristine, so the committed tree is the baseline. Catches | |
| # a manifest that was modified AND one CREATED where none was tracked, and | |
| # runs on failure too, so a job cannot fail and hide what it dirtied. | |
| - name: Dependency manifests unchanged by this job | |
| if: always() | |
| working-directory: . | |
| run: ./scripts/assert-lockfiles-unchanged --verify-clean | |
| trivy-python: | |
| name: Trivy (Python SDK) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| security-events: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| # Full-severity SARIF for Security-tab visibility; the gate step below enforces policy. | |
| # (In SARIF mode the action reports all severities unless limit-severities-for-sarif is set.) | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: './python' | |
| ignore-unfixed: true | |
| format: 'sarif' | |
| output: 'trivy-python-results.sarif' | |
| - name: Upload Trivy scan results to GitHub Security tab | |
| uses: github/codeql-action/upload-sarif@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 | |
| if: always() | |
| continue-on-error: true | |
| with: | |
| sarif_file: 'trivy-python-results.sarif' | |
| category: 'trivy-python' | |
| # Table mode passes the severity filter through, so this gates on HIGH/CRITICAL only. | |
| - name: Fail on HIGH/CRITICAL vulnerabilities | |
| uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0 | |
| env: | |
| TRIVY_SKIP_DB_UPDATE: true | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: './python' | |
| severity: 'HIGH,CRITICAL' | |
| exit-code: '1' | |
| ignore-unfixed: true | |
| format: 'table' | |
| skip-setup-trivy: true | |
| cache: 'false' | |
| # Ground truth, and the authoritative check: the static parser predicts | |
| # that nothing writes a lockfile, this observes whether anything did. A CI | |
| # checkout starts pristine, so the committed tree is the baseline. Catches | |
| # a manifest that was modified AND one CREATED where none was tracked, and | |
| # runs on failure too, so a job cannot fail and hide what it dirtied. | |
| - name: Dependency manifests unchanged by this job | |
| if: always() | |
| working-directory: . | |
| run: ./scripts/assert-lockfiles-unchanged --verify-clean | |
| bundler-audit: | |
| name: Bundler Audit (Ruby SDK) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: ruby | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Ruby | |
| uses: ruby/setup-ruby@95ef2b042f9d7a56d8268cba8559e2842e2ad01b # v1.321.0 | |
| with: | |
| ruby-version: '3.3' | |
| bundler-cache: true | |
| working-directory: ruby | |
| - name: Install bundler-audit | |
| run: gem install bundler-audit # zizmor: ignore[adhoc-packages] -- bundler-audit is the auditing tool itself; adding it to the SDK's Gemfile would make the gem under audit depend on its own auditor | |
| - name: Update vulnerability database | |
| run: bundle-audit update | |
| - name: Run bundler-audit | |
| run: bundle-audit check | |
| # Ground truth, and the authoritative check: the static parser predicts | |
| # that nothing writes a lockfile, this observes whether anything did. A CI | |
| # checkout starts pristine, so the committed tree is the baseline. Catches | |
| # a manifest that was modified AND one CREATED where none was tracked, and | |
| # runs on failure too, so a job cannot fail and hide what it dirtied. | |
| - name: Dependency manifests unchanged by this job | |
| if: always() | |
| working-directory: . | |
| run: ./scripts/assert-lockfiles-unchanged --verify-clean | |
| gradle-dependency-check: | |
| name: Gradle Dependency Check (Kotlin SDK) | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: kotlin | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Java | |
| uses: actions/setup-java@b6effb05e454b25005698d916606bdc6ffcbf961 # v5.7.0 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '17' | |
| - name: Setup Gradle | |
| uses: gradle/actions/setup-gradle@9c971963bec38e04b3d30dcc455b5382be2fdbfb # v6.3.0 | |
| with: | |
| cache-provider: basic | |
| - name: Run dependency verification | |
| run: ./gradlew :basecamp-sdk:dependencies --scan | |
| - name: Check for known vulnerabilities | |
| run: ./gradlew :basecamp-sdk:dependencyInsight --dependency org.jetbrains.kotlin --scan || true | |
| # Ground truth, and the authoritative check: the static parser predicts | |
| # that nothing writes a lockfile, this observes whether anything did. A CI | |
| # checkout starts pristine, so the committed tree is the baseline. Catches | |
| # a manifest that was modified AND one CREATED where none was tracked, and | |
| # runs on failure too, so a job cannot fail and hide what it dirtied. | |
| - name: Dependency manifests unchanged by this job | |
| if: always() | |
| working-directory: . | |
| run: ./scripts/assert-lockfiles-unchanged --verify-clean | |
| swift-audit: | |
| name: Swift Dependency Audit | |
| runs-on: macos-15 | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: swift | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Audit Swift dependencies | |
| run: | | |
| swift package show-dependencies --format json > deps.json | |
| echo "Swift package dependencies:" | |
| cat deps.json | python3 -c " | |
| import json, sys | |
| deps = json.load(sys.stdin) | |
| def walk(dep, depth=0): | |
| name = dep.get('identity', dep.get('name', 'unknown')) | |
| version = dep.get('version', 'unknown') | |
| print(f\"{' ' * depth}{name}@{version}\") | |
| for d in dep.get('dependencies', []): | |
| walk(d, depth + 1) | |
| walk(deps) | |
| " | |
| rm -f deps.json | |
| # Ground truth, and the authoritative check: the static parser predicts | |
| # that nothing writes a lockfile, this observes whether anything did. A CI | |
| # checkout starts pristine, so the committed tree is the baseline. Catches | |
| # a manifest that was modified AND one CREATED where none was tracked, and | |
| # runs on failure too, so a job cannot fail and hide what it dirtied. | |
| - name: Dependency manifests unchanged by this job | |
| if: always() | |
| working-directory: . | |
| run: ./scripts/assert-lockfiles-unchanged --verify-clean | |
| secrets: | |
| name: Secret Scanning | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Install and run gitleaks | |
| env: | |
| GITLEAKS_VERSION: '8.22.0' | |
| run: | | |
| TARBALL="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" | |
| curl -sSfL -O "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/${TARBALL}" | |
| curl -sSfL -O "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_checksums.txt" | |
| sha256sum --check --ignore-missing "gitleaks_${GITLEAKS_VERSION}_checksums.txt" | |
| tar xzf "${TARBALL}" gitleaks | |
| ./gitleaks detect --source . --no-git -v | |
| dependency-review: | |
| name: Dependency Review | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'pull_request' | |
| continue-on-error: true # Requires GitHub Advanced Security | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 |