Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .github/workflows/accessibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,23 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Least-privilege permissions (#462)
permissions:
contents: read

jobs:
accessibility:
name: accessibility
runs-on: namespace-profile-nursca
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- uses: pnpm/action-setup@v4
with:
version: '9.0.0'

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
Expand All @@ -37,7 +41,7 @@ jobs:

- name: Upload accessibility test results
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: accessibility-results
path: |
Expand Down
10 changes: 7 additions & 3 deletions .github/workflows/contract-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,23 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Least-privilege permissions (#462)
permissions:
contents: read

jobs:
contract-tests:
name: Mocked Stellar SDK Contract Tests
runs-on: namespace-profile-nursca
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- uses: pnpm/action-setup@v4
with:
version: '9.0.0'

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
Expand Down Expand Up @@ -75,7 +79,7 @@ jobs:

- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: contract-coverage
path: coverage/
Expand Down
12 changes: 8 additions & 4 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,22 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Least-privilege permissions (#462)
permissions:
contents: read

jobs:
e2e:
timeout-minutes: 30
runs-on: namespace-profile-nursca
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- uses: pnpm/action-setup@v4
with:
version: '9.0.0'

- uses: actions/setup-node@v4
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
cache: "pnpm"
Expand All @@ -39,15 +43,15 @@ jobs:

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: playwright-report
path: playwright-report/
retention-days: 30

- name: Upload test videos on failure
if: failure()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: e2e-test-videos
path: test-results/playwright/
Expand Down
48 changes: 48 additions & 0 deletions .github/workflows/license-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: License Compatibility Check

on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]

# Least-privilege permissions (#462)
permissions:
contents: read

jobs:
license-check:
name: Dependency License Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '22'

- name: Install dependencies
run: npm ci

- name: Install license-checker
run: npm install --no-save license-checker@25.0.1

# Fail if any dependency uses a license outside the allowlist.
# The allowlist is defined in .license-checker.json at the repo root.
# See docs/ci-cd.md for the triage process for exceptions.
- name: Check dependency licenses
run: |
npx license-checker \
--production \
--onlyAllow "$(node -e "const c=require('./.license-checker.json'); console.log(c.allowedLicenses.join(';'))")" \
--excludePrivatePackages \
--out license-report.txt

- name: Upload license report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: license-report
path: license-report.txt
retention-days: 14
12 changes: 9 additions & 3 deletions .github/workflows/lighthouse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,25 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Least-privilege permissions (#462)
# statuses: write is required for LHCI to post commit status checks
permissions:
contents: read
statuses: write

jobs:
lighthouse:
name: Lighthouse CI
runs-on: namespace-profile-nursca
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- uses: pnpm/action-setup@v4
with:
version: '9.0.0'

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
Expand All @@ -43,7 +49,7 @@ jobs:

- name: Upload Lighthouse reports
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: lighthouse-reports
path: .lighthouseci/
Expand Down
39 changes: 39 additions & 0 deletions .github/workflows/security-audit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: Security Audit

on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
schedule:
# Run every Monday at 08:00 UTC to catch newly published CVEs
- cron: '0 8 * * 1'

# Least-privilege permissions (#462)
permissions:
contents: read

jobs:
audit:
name: npm audit security gate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: '22'

- name: Install dependencies
run: npm ci

# Fail on high and critical severity vulnerabilities.
# Moderate vulnerabilities are reported but do not block the build.
# See docs/ci-cd.md for the triage / allowlist process.
- name: Run security audit (high+critical gate)
run: npm audit --audit-level=high

# Separate informational step for moderate findings — never blocks CI.
- name: Report moderate vulnerabilities (informational)
run: npm audit --audit-level=moderate || true
12 changes: 8 additions & 4 deletions .github/workflows/visual-regression.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

# Least-privilege permissions (#462)
permissions:
contents: read

jobs:
chromatic:
if: ${{ secrets.CHROMATIC_PROJECT_TOKEN != '' }}
name: Chromatic Visual Regression
runs-on: namespace-profile-nursca
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
fetch-depth: 0

Expand All @@ -25,7 +29,7 @@ jobs:
version: '9.0.0'

- name: Setup Node.js
uses: actions/setup-node@v4
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
cache: 'pnpm'
Expand All @@ -39,7 +43,7 @@ jobs:
NODE_OPTIONS: '--max_old_space_size=4096'

- name: Run Chromatic
uses: chromaui/action@latest
uses: chromaui/action@14cfaef73576e69f95f47f60058063f46ca38719 # v18.1.0
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
storybookBuildDir: storybook-static
Expand All @@ -51,7 +55,7 @@ jobs:

- name: Upload Storybook build
if: always()
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: storybook-static
path: storybook-static/
Expand Down
10 changes: 5 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
!.yarn/releases
!.yarn/versions

# testing
# testing — generated artifacts, never commit these
/coverage
/test-results
/playwright-report
Expand All @@ -23,9 +23,12 @@
# production
/build

# lighthouse CI
# lighthouse CI — generated reports, never commit these
/.lighthouseci

# storybook static output
/storybook-static

# misc
.DS_Store
*.pem
Expand Down Expand Up @@ -66,9 +69,6 @@ useWallet_SUMMARY.md
useWallet_QUICK_REFERENCE.md
docs/pr_description.md

# storybook static output
/storybook-static

# turbo cache
.turbo

Expand Down
19 changes: 19 additions & 0 deletions .license-checker.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"allowedLicenses": [
"MIT",
"MIT-0",
"Apache-2.0",
"BSD-2-Clause",
"BSD-3-Clause",
"ISC",
"CC0-1.0",
"CC-BY-3.0",
"CC-BY-4.0",
"0BSD",
"BlueOak-1.0.0",
"Python-2.0",
"Unlicense",
"WTFPL"
],
"comment": "Allowlist of OSI-compatible, permissive licenses. Copyleft licenses (GPL, LGPL, AGPL, MPL, EUPL) are NOT permitted. To request an exception for a specific package, add it to the 'excludePackages' list in .license-checker.json and document the rationale in docs/ci-cd.md."
}
20 changes: 20 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,26 @@ export const Variant: Story = {
- Regenerate all baselines after major updates
- Update this documentation as needed

## Security Audit (CI Gate)

A `npm audit --audit-level=high` step runs in CI on every push and PR (see `.github/workflows/security-audit.yml`). The build **fails** on high or critical severity vulnerabilities.

### When the audit fails

1. Run `npm audit` locally to see the full report.
2. Apply available patches: `npm audit fix` (or `npm audit fix --force` for breaking-change patches — review the diff carefully).
3. If no fix is available and the finding is a confirmed false positive for this project, open a tracking issue and follow the triage process in [docs/ci-cd.md](docs/ci-cd.md#security-audit-gate-issue-459).

## License Compatibility Check

All production dependencies must use permissive OSI-approved licenses. The allowed list is in `.license-checker.json`. CI checks this on every push and PR (see `.github/workflows/license-check.yml`).

### When the license check fails

1. Identify which new dependency introduced the non-allowed license.
2. Look for a permissive-licensed alternative.
3. If no alternative exists, follow the exception process in [docs/ci-cd.md](docs/ci-cd.md#license-compatibility-check-issue-460).

## Getting Help

If you need help:
Expand Down
Loading
Loading