diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0e599809..e115cf47 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -6,3 +6,9 @@ # Nest.js backend – backend team reviews all changes under backend/ /backend/ @MyFanss/backend + +# Next.js frontend – frontend team reviews all changes under frontend/ +/frontend/ @MyFanss/frontend + +# Release docs including smoke test matrix – frontend team owns these +/docs/release/ @MyFanss/frontend diff --git a/.github/workflows/abi-snapshot.yml b/.github/workflows/abi-snapshot.yml index c9c2df80..0ec808d2 100644 --- a/.github/workflows/abi-snapshot.yml +++ b/.github/workflows/abi-snapshot.yml @@ -20,15 +20,15 @@ jobs: working-directory: contract steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Set up Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@3c5f7ea28cd621ae0bf5283f0e981fb97b8a7af9 # stable with: targets: wasm32-unknown-unknown - name: Cache Rust dependencies - uses: Swatinem/rust-cache@v2 + uses: Swatinem/rust-cache@42dc69e1aa15d09112580998cf2ef0119e2e91ae # v2 with: workspaces: contract diff --git a/.github/workflows/audit-check.yml b/.github/workflows/audit-check.yml index f876ea06..515e41fd 100644 --- a/.github/workflows/audit-check.yml +++ b/.github/workflows/audit-check.yml @@ -18,10 +18,10 @@ jobs: steps: - name: 📥 Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: 🟢 Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: "20" @@ -58,6 +58,8 @@ jobs: echo "::error::High vulnerabilities in backend: $HIGH" exit 1 fi + + - name: 📦 Check frontend audits id: frontend-audit working-directory: ./frontend run: | @@ -89,9 +91,11 @@ jobs: echo "❌ **HIGH vulnerabilities detected**" >> $GITHUB_STEP_SUMMARY echo "::error::High vulnerabilities in frontend: $HIGH" exit 1 - fi with audit summary + fi + + - name: 💬 Comment on PR with audit summary if: github.event_name == 'pull_request' && always() - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: >- diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index e8b0682b..15fb011a 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -16,13 +16,13 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: fetch-depth: 0 token: ${{ secrets.GITHUB_TOKEN }} - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '20' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbd76d89..2395d0c9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,9 +48,9 @@ jobs: SOROBAN_RPC_URL: https://soroban-testnet.stellar.org steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: ${{ matrix.node }} cache: 'npm' @@ -102,9 +102,9 @@ jobs: NODE_ENV: test steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '20' cache: 'npm' @@ -143,9 +143,9 @@ jobs: node: ['20', '22'] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: ${{ matrix.node }} cache: 'npm' @@ -198,9 +198,9 @@ jobs: NODE_ENV: test steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - - uses: actions/setup-node@v4 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '20' cache: 'npm' @@ -226,10 +226,10 @@ jobs: timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: Cache Cargo registry - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: | ~/.cargo/registry/index @@ -241,7 +241,7 @@ jobs: ${{ runner.os }}-cargo-registry- - name: Cache Cargo target directory - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: contract/target key: ${{ runner.os }}-contract-target-${{ hashFiles('contract/**/Cargo.lock') }} @@ -266,4 +266,4 @@ jobs: - name: Build run: cargo build --release - working-directory: contract \ No newline at end of file + working-directory: contract diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 15e88cb2..12f967f9 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -10,12 +10,12 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 with: fetch-depth: 0 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: node-version: '20' diff --git a/.github/workflows/contract-release.yml b/.github/workflows/contract-release.yml index 35a77aae..586bd4ca 100644 --- a/.github/workflows/contract-release.yml +++ b/.github/workflows/contract-release.yml @@ -26,10 +26,10 @@ jobs: steps: - name: 📥 Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: 🦀 Cache Cargo registry - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: | ~/.cargo/registry/index @@ -41,7 +41,7 @@ jobs: ${{ runner.os }}-cargo-registry- - name: 🏗️ Cache Cargo target - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: contract/target key: ${{ runner.os }}-contract-target-${{ hashFiles('contract/Cargo.lock') }} @@ -211,7 +211,7 @@ jobs: - name: 📝 Comment on PR with checklist summary if: github.event_name == 'pull_request' && always() - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index f0b0eb07..7d9c4ff5 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -9,6 +9,6 @@ jobs: runs-on: ubuntu-latest steps: - name: 'Checkout Repository' - uses: actions/checkout@v4 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - name: 'Dependency Review' - uses: actions/dependency-review-action@v4 \ No newline at end of file + uses: actions/dependency-review-action@a6993e2c61fd5dc440b409aa1d6904921c5e1894 # v4 diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml new file mode 100644 index 00000000..ca9e1d61 --- /dev/null +++ b/.github/workflows/sbom.yml @@ -0,0 +1,86 @@ +name: SBOM Generation + +on: + push: + branches: [main, develop] + paths: + - 'frontend/Dockerfile' + - 'frontend/package*.json' + - 'backend/Dockerfile' + - 'backend/package*.json' + - '.github/workflows/sbom.yml' + pull_request: + branches: [main, develop] + paths: + - 'frontend/Dockerfile' + - 'frontend/package*.json' + - 'backend/Dockerfile' + - 'backend/package*.json' + - '.github/workflows/sbom.yml' + workflow_dispatch: + +permissions: + contents: read + +jobs: + sbom-frontend: + name: SBOM – Frontend container + runs-on: ubuntu-latest + timeout-minutes: 20 + + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Build frontend Docker image + run: | + docker build \ + --file frontend/Dockerfile \ + --tag myfans/frontend:ci \ + frontend/ + + - name: Generate SBOM (SPDX JSON) + uses: anchore/sbom-action@df80a981bc6edbc4e220a492d3cbe9f5547a6e75 # v0.17.9 + with: + image: myfans/frontend:ci + format: spdx-json + artifact-name: sbom-frontend.spdx.json + output-file: sbom-frontend.spdx.json + + - name: Upload SBOM artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: sbom-frontend + path: sbom-frontend.spdx.json + retention-days: 90 + + sbom-backend: + name: SBOM – Backend container + runs-on: ubuntu-latest + timeout-minutes: 20 + + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + + - name: Build backend Docker image + run: | + docker build \ + --file backend/Dockerfile \ + --tag myfans/backend:ci \ + backend/ + + - name: Generate SBOM (SPDX JSON) + uses: anchore/sbom-action@df80a981bc6edbc4e220a492d3cbe9f5547a6e75 # v0.17.9 + with: + image: myfans/backend:ci + format: spdx-json + artifact-name: sbom-backend.spdx.json + output-file: sbom-backend.spdx.json + + - name: Upload SBOM artifact + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: sbom-backend + path: sbom-backend.spdx.json + retention-days: 90 diff --git a/docs/release/SMOKE_TEST_MATRIX.md b/docs/release/SMOKE_TEST_MATRIX.md index ff0554cd..a21f468a 100644 --- a/docs/release/SMOKE_TEST_MATRIX.md +++ b/docs/release/SMOKE_TEST_MATRIX.md @@ -7,22 +7,30 @@ Run this matrix twice for every release: Mark each row as `Pass`, `Fail`, or `N/A` and record follow-up tickets for anything that does not pass cleanly. +## Team Ownership + +| Team | Responsible for | +| --- | --- | +| `@MyFanss/frontend` | Auth, Discovery, Creator pages, Gated content, Settings, Dashboard, Error handling, Responsive QA | +| `@MyFanss/backend` | Backend API health checks across all areas | +| `@MyFanss/contract` | Subscriptions, Payments (contract-backed flows) | + ## Test Matrix -| Area | Scenario | Viewport / Browser | Dependencies | Expected Result | Staging | Production | Notes | -| --- | --- | --- | --- | --- | --- | --- | --- | -| Auth | Sign up or first-time onboarding entry point | Desktop + mobile, Chrome | Backend auth/session APIs | User can start account flow without blocking errors | [ ] | [ ] | `...` | -| Auth | Login and session restore | Desktop + mobile, Chrome + Firefox | Backend auth/session APIs | User can sign in or restore an existing session without redirect loops | [ ] | [ ] | `...` | -| Auth | Logout | Desktop, Chrome | Backend auth/session APIs | Session clears and protected routes no longer show authenticated state | [ ] | [ ] | `...` | -| Discovery | Home page and discover/creator listing views | Desktop + mobile, Chrome + Safari | Backend creator APIs | Pages render, data loads, and empty/loading states look correct | [ ] | [ ] | `...` | -| Creator pages | Open a creator profile and inspect pricing/content preview | Desktop + mobile, Chrome | Backend creator/profile APIs | Creator metadata, plans, and preview content render correctly | [ ] | [ ] | `...` | -| Subscriptions | Start a subscription checkout flow | Desktop, Chrome + Firefox | Backend checkout APIs + contract configuration | Plan details, pricing, and transaction preview are correct | [ ] | [ ] | `...` | -| Payments | Complete or simulate contract-backed payment | Desktop, Chrome | Backend checkout APIs + contract calls | Payment state updates in UI and resulting subscription state is reflected | [ ] | [ ] | `...` | -| Gated content | Access content after successful subscription | Desktop + mobile, Chrome | Backend access checks + contract/subscription status | Eligible users see content and ineligible users get graceful fallback UI | [ ] | [ ] | `...` | -| Settings | Update user or creator settings | Desktop, Chrome | Backend settings/profile APIs | Validation works, save succeeds, and persisted values reload correctly | [ ] | [ ] | `...` | -| Dashboard | Open dashboard pages relevant to the release | Desktop, Chrome + Firefox | Backend dashboard APIs | Metrics, tables, loading states, and empty states render correctly | [ ] | [ ] | `...` | -| Error handling | Trigger a known recoverable failure path | Desktop + mobile, Chrome | Backend error responses | Error UI is understandable and does not leave the app stuck | [ ] | [ ] | `...` | -| Responsive QA | Re-check changed screens on mobile and desktop | Mobile Safari + desktop Chrome | Frontend only | Layout, spacing, navigation, and primary interactions remain usable | [ ] | [ ] | `...` | +| Area | Scenario | Viewport / Browser | Dependencies | Expected Result | Owner | Staging | Production | Notes | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | +| Auth | Sign up or first-time onboarding entry point | Desktop + mobile, Chrome | Backend auth/session APIs | User can start account flow without blocking errors | `@MyFanss/frontend` | [ ] | [ ] | `...` | +| Auth | Login and session restore | Desktop + mobile, Chrome + Firefox | Backend auth/session APIs | User can sign in or restore an existing session without redirect loops | `@MyFanss/frontend` | [ ] | [ ] | `...` | +| Auth | Logout | Desktop, Chrome | Backend auth/session APIs | Session clears and protected routes no longer show authenticated state | `@MyFanss/frontend` | [ ] | [ ] | `...` | +| Discovery | Home page and discover/creator listing views | Desktop + mobile, Chrome + Safari | Backend creator APIs | Pages render, data loads, and empty/loading states look correct | `@MyFanss/frontend` | [ ] | [ ] | `...` | +| Creator pages | Open a creator profile and inspect pricing/content preview | Desktop + mobile, Chrome | Backend creator/profile APIs | Creator metadata, plans, and preview content render correctly | `@MyFanss/frontend` | [ ] | [ ] | `...` | +| Subscriptions | Start a subscription checkout flow | Desktop, Chrome + Firefox | Backend checkout APIs + contract configuration | Plan details, pricing, and transaction preview are correct | `@MyFanss/contract` | [ ] | [ ] | `...` | +| Payments | Complete or simulate contract-backed payment | Desktop, Chrome | Backend checkout APIs + contract calls | Payment state updates in UI and resulting subscription state is reflected | `@MyFanss/contract` | [ ] | [ ] | `...` | +| Gated content | Access content after successful subscription | Desktop + mobile, Chrome | Backend access checks + contract/subscription status | Eligible users see content and ineligible users get graceful fallback UI | `@MyFanss/frontend` | [ ] | [ ] | `...` | +| Settings | Update user or creator settings | Desktop, Chrome | Backend settings/profile APIs | Validation works, save succeeds, and persisted values reload correctly | `@MyFanss/frontend` | [ ] | [ ] | `...` | +| Dashboard | Open dashboard pages relevant to the release | Desktop, Chrome + Firefox | Backend dashboard APIs | Metrics, tables, loading states, and empty states render correctly | `@MyFanss/frontend` | [ ] | [ ] | `...` | +| Error handling | Trigger a known recoverable failure path | Desktop + mobile, Chrome | Backend error responses | Error UI is understandable and does not leave the app stuck | `@MyFanss/frontend` | [ ] | [ ] | `...` | +| Responsive QA | Re-check changed screens on mobile and desktop | Mobile Safari + desktop Chrome | Frontend only | Layout, spacing, navigation, and primary interactions remain usable | `@MyFanss/frontend` | [ ] | [ ] | `...` | ## Cross-browser Coverage