diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 406fc328f..222ed401d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,11 +5,14 @@ on:
branches: [ "main", "remediation/*", "feature/mvp-complete" ]
pull_request:
branches: [ "main", "feature/mvp-complete" ]
- workflow_dispatch: # Allow manual trigger
+ workflow_dispatch:
jobs:
- backend-go:
- name: Backend (Go)
+ # ===========================================================================
+ # TMT Vital — Backend (Go)
+ # ===========================================================================
+ vital-backend:
+ name: TMT Vital — Backend (Go)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
@@ -28,75 +31,37 @@ jobs:
fi
fi
- - name: Set up Node
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
- with:
- node-version: '20'
- cache: 'npm'
-
- name: Set up Go
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v5.3.0
with:
go-version: '1.24'
cache: true
- - name: Install dependencies
- run: npm ci
-
- - name: Run govulncheck
+ - name: Install Go tools
run: |
- cd veza-backend-api
go install golang.org/x/vuln/cmd/govulncheck@latest
- govulncheck ./...
+ go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
- - name: Vet
- run: |
- cd veza-backend-api
- go vet ./...
+ - name: Install TMT
+ run: pip install tmt
- - name: Install golangci-lint
- run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
+ - name: Run TMT Vital Backend
+ run: tmt --root tmt run plan --name /vital-backend
- - name: Lint
- run: npx turbo run lint --filter=veza-backend-api
-
- - name: Test with coverage
- run: |
- cd veza-backend-api
- go test ./internal/handlers/... ./internal/services/... -short -coverprofile=coverage.out -covermode=atomic
- COVERAGE=$(go tool cover -func=coverage.out | tail -1 | awk '{print $3}' | tr -d '%')
- echo "Coverage: ${COVERAGE}%"
- echo "coverage=${COVERAGE}" >> $GITHUB_OUTPUT
- if awk -v c="$COVERAGE" -v t=60 'BEGIN {exit !(c+0>=t)}'; then
- echo "Coverage gate passed (>= 60%)"
- else
- echo "Coverage $COVERAGE% is below threshold 60%"
- exit 1
- fi
-
- - name: Build
- run: npx turbo run build --filter=veza-backend-api
-
- rust-services:
- name: Rust Services (Stream)
+ # ===========================================================================
+ # TMT Vital — Rust Services (Stream)
+ # ===========================================================================
+ vital-services:
+ name: TMT Vital — Rust Services
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- - name: Set up Node
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
- with:
- node-version: '20'
- cache: 'npm'
-
- name: Set up Rust
uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
with:
components: rustfmt, clippy
- - name: Install dependencies
- run: npm ci
-
- name: Cache Cargo registry
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
@@ -109,26 +74,21 @@ jobs:
- name: Install cargo-audit
run: cargo install cargo-audit
- - name: Auditing Stream Server
- run: |
- cd veza-stream-server
- cargo audit
+ - name: Install TMT
+ run: pip install tmt
- - name: Lint
- run: npx turbo run lint --filter=veza-stream-server
+ - name: Run TMT Vital Services
+ run: tmt --root tmt run plan --name /vital-services
- - name: Build
- run: npx turbo run build --filter=veza-stream-server
-
- - name: Test
- run: npx turbo run test --filter=veza-stream-server
-
- frontend:
- name: Frontend (Web)
+ # ===========================================================================
+ # TMT Vital — Frontend (Web)
+ # ===========================================================================
+ vital-frontend:
+ name: TMT Vital — Frontend (Web)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-
+
- name: Use Node.js
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
@@ -139,9 +99,6 @@ jobs:
- name: Install Dependencies
run: npm ci
- - name: Security audit (npm)
- run: npm audit --audit-level=critical
-
- name: Cache Generated Types
uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0
with:
@@ -150,46 +107,15 @@ jobs:
restore-keys: |
${{ runner.os }}-generated-types-
- - name: Generate Types from OpenAPI
- run: |
- cd apps/web
- chmod +x scripts/generate-types.sh
- ./scripts/generate-types.sh
- continue-on-error: false
- # This step ensures types are generated before typecheck
- # Cache keyed on openapi.yaml hash, so types regenerate when spec changes
+ - name: Install TMT
+ run: pip install tmt
- - name: Check types sync with OpenAPI spec
- run: |
- if ! git diff --exit-code apps/web/src/types/generated/; then
- echo "::error::Types are out of sync with openapi.yaml. Run 'make openapi' then 'cd apps/web && ./scripts/generate-types.sh' and commit the updated types."
- exit 1
- fi
-
- - name: Lint
- run: npx turbo run lint --filter=veza-frontend
-
- - name: Format Check
- run: |
- cd apps/web
- npm run format:check --if-present
-
- - name: Type Check
- run: |
- cd apps/web
- npm run typecheck
-
- - name: Test with coverage
- run: npx turbo run test --filter=veza-frontend -- --run --coverage
-
- - name: Contrast Tests
- run: |
- cd apps/web
- npm run test -- --run src/__tests__/contrast.test.ts
-
- - name: Build
- run: npx turbo run build --filter=veza-frontend
+ - name: Run TMT Vital Frontend
+ run: tmt --root tmt run plan --name /vital-frontend
+ # ===========================================================================
+ # Storybook Audit (kept outside TMT — tier 3 candidate)
+ # ===========================================================================
storybook:
name: Storybook Audit
runs-on: ubuntu-latest
@@ -224,6 +150,9 @@ jobs:
npm run test:storybook
working-directory: apps/web
+ # ===========================================================================
+ # E2E (Playwright) — kept outside TMT (complex infra setup)
+ # ===========================================================================
e2e:
name: E2E (Playwright)
runs-on: ubuntu-latest
@@ -324,9 +253,12 @@ jobs:
path: apps/web/playwright-report/
retention-days: 7
+ # ===========================================================================
+ # Notify on failure
+ # ===========================================================================
notify-failure:
name: Notify on failure
- needs: [backend-go, rust-services, frontend, storybook, e2e]
+ needs: [vital-backend, vital-services, vital-frontend, storybook, e2e]
if: failure()
runs-on: ubuntu-latest
steps:
diff --git a/apps/web/src/features/feed/components/SuggestionsWidget.tsx b/apps/web/src/features/feed/components/SuggestionsWidget.tsx
index c09770194..ccd39cae8 100644
--- a/apps/web/src/features/feed/components/SuggestionsWidget.tsx
+++ b/apps/web/src/features/feed/components/SuggestionsWidget.tsx
@@ -45,7 +45,7 @@ export function SuggestionsWidget() {
- Suggested Accounts
+ {t('feed.suggestedAccounts')}
diff --git a/make/test.mk b/make/test.mk
index 9a7a9359d..4bb28bf60 100644
--- a/make/test.mk
+++ b/make/test.mk
@@ -2,7 +2,8 @@
# TEST & QUALITY (unit tests, lint, format)
# ==============================================================================
-.PHONY: test test-tmt lint fmt status test-web test-backend-api test-stream-server
+.PHONY: test test-tmt test-tmt-backend test-tmt-frontend test-tmt-services lint fmt status test-web test-backend-api test-stream-server
+.PHONY: test-e2e test-e2e-critical
.PHONY: load-test-smoke load-test-backend load-test-all
.PHONY: lint-web lint-backend-api lint-stream-server
@@ -25,15 +26,38 @@ test: infra-up ## [MID] Run All Tests (Fastest strategy)
@(cd $(ROOT)/$(SERVICE_DIR_web) && npm run test -- --run)
@$(ECHO_CMD) "${GREEN}✅ All tests passed.${NC}"
-test-tmt: ## [MID] Run Unified TMT Pipeline
- @$(ECHO_CMD) "${BLUE}🧪 Running TMT Pipeline...${NC}"
+test-tmt: ## [MID] Run Unified TMT Pipeline (all vital tests)
+ @$(ECHO_CMD) "${BLUE}🧪 Running TMT Vital Pipeline...${NC}"
@command -v tmt >/dev/null 2>&1 || { $(ECHO_CMD) "${RED}❌ tmt is missing! Install with 'pip install tmt'${NC}"; exit 1; }
- @tmt run
+ @tmt --root tmt run plan --name /vital
+
+test-tmt-backend: ## [MID] Run TMT Backend tests only
+ @$(ECHO_CMD) "${BLUE}🧪 Running TMT Backend...${NC}"
+ @command -v tmt >/dev/null 2>&1 || { $(ECHO_CMD) "${RED}❌ tmt is missing! Install with 'pip install tmt'${NC}"; exit 1; }
+ @tmt --root tmt run plan --name /vital-backend
+
+test-tmt-frontend: ## [MID] Run TMT Frontend tests only
+ @$(ECHO_CMD) "${BLUE}🧪 Running TMT Frontend...${NC}"
+ @command -v tmt >/dev/null 2>&1 || { $(ECHO_CMD) "${RED}❌ tmt is missing! Install with 'pip install tmt'${NC}"; exit 1; }
+ @tmt --root tmt run plan --name /vital-frontend
+
+test-tmt-services: ## [MID] Run TMT Rust Services tests only
+ @$(ECHO_CMD) "${BLUE}🧪 Running TMT Services...${NC}"
+ @command -v tmt >/dev/null 2>&1 || { $(ECHO_CMD) "${RED}❌ tmt is missing! Install with 'pip install tmt'${NC}"; exit 1; }
+ @tmt --root tmt run plan --name /vital-services
test-web: ## [MID] Run Web tests only
@$(ECHO_CMD) "${BLUE}🧪 Running Web tests...${NC}"
@(cd $(ROOT)/$(SERVICE_DIR_web) && npm run test -- --run)
+test-e2e: ## [MID] Run Playwright E2E tests (Chromium, requires backend running)
+ @$(ECHO_CMD) "${BLUE}🧪 Running E2E tests (Playwright)...${NC}"
+ @(cd $(ROOT)/tests/e2e && npx playwright test --project=chromium)
+
+test-e2e-critical: ## [MID] Run only @critical E2E tests (fast smoke)
+ @$(ECHO_CMD) "${BLUE}🧪 Running Critical E2E tests...${NC}"
+ @(cd $(ROOT)/tests/e2e && npx playwright test --project=chromium --grep "@critical")
+
test-backend-api: infra-up ## [MID] Run Go backend tests only
@$(ECHO_CMD) "${BLUE}🧪 Running Backend API tests...${NC}"
@(cd $(ROOT)/$(SERVICE_DIR_backend-api) && \
@@ -48,9 +72,9 @@ test-stream-server: ## [MID] Run Stream server tests only
lint: ## [MID] Lint everything
@$(ECHO_CMD) "${BLUE}🔍 Linting Codebase...${NC}"
- @(cd $(ROOT)/$(SERVICE_DIR_stream-server) && cargo clippy -- -D warnings) || true
- @(cd $(ROOT)/$(SERVICE_DIR_backend-api) && golangci-lint run ./...) || true
- @(cd $(ROOT)/$(SERVICE_DIR_web) && npm run lint) || true
+ @(cd $(ROOT)/$(SERVICE_DIR_stream-server) && cargo clippy -- -D warnings)
+ @(cd $(ROOT)/$(SERVICE_DIR_backend-api) && golangci-lint run ./...)
+ @(cd $(ROOT)/$(SERVICE_DIR_web) && npm run lint)
lint-web: ## [MID] Lint web app only
@(cd $(ROOT)/$(SERVICE_DIR_web) && npm run lint)
diff --git a/tests/e2e/01-auth.spec.ts b/tests/e2e/01-auth.spec.ts
index 77523fc98..1a0833e4e 100644
--- a/tests/e2e/01-auth.spec.ts
+++ b/tests/e2e/01-auth.spec.ts
@@ -14,96 +14,87 @@ test.describe('AUTH — Inscription', () => {
test('02. Inscription avec email + mot de passe valides', async ({ page }) => {
test.setTimeout(60_000);
await navigateTo(page, '/register');
- await page.getByTestId('register-form').waitFor({ state: 'visible', timeout: 10_000 });
+ await expect(page.getByTestId('register-form')).toBeVisible({ timeout: 10_000 });
const uniqueSuffix = Date.now();
const uniqueEmail = `e2e-${uniqueSuffix}@veza.test`;
- const usernameInput = page.locator('#register-username');
- await usernameInput.waitFor({ state: 'visible', timeout: 5_000 });
- await usernameInput.fill(`e2e-user-${uniqueSuffix}`);
+ await page.locator('#register-username').fill(`e2e-user-${uniqueSuffix}`);
await page.locator('#register-email').fill(uniqueEmail);
await page.locator('#register-password').fill('SecurePass123!@#');
await page.locator('#register-password_confirm').fill('SecurePass123!@#');
- // Accept terms — Radix Checkbox renders a visible