start-vibing 4.4.0 → 4.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/template/.claude/commands/e2e-audit.md +16 -0
- package/template/.claude/hooks/e2e-audit-session-start.sh +4 -0
- package/template/.claude/settings.json +4 -0
- package/template/.claude/skills/e2e-audit/SKILL.md +216 -660
- package/template/.claude/skills/e2e-audit/findings.schema.json +98 -0
- package/template/.claude/skills/e2e-audit/references/api-contract-playbook.md +66 -0
- package/template/.claude/skills/e2e-audit/references/auth-setup-playbook.md +78 -0
- package/template/.claude/skills/e2e-audit/references/coverage-gap-playbook.md +95 -0
- package/template/.claude/skills/e2e-audit/references/post-run-feedback-playbook.md +80 -0
- package/template/.claude/skills/e2e-audit/scripts/detect-stack.sh +205 -0
- package/template/.claude/skills/e2e-audit/scripts/detect-uncovered.sh +137 -0
- package/template/.claude/skills/e2e-audit/scripts/discover-api-surface.sh +242 -0
- package/template/.claude/skills/e2e-audit/scripts/discover-routes.sh +163 -0
- package/template/.claude/skills/e2e-audit/scripts/inventory-existing-tests.sh +161 -0
- package/template/.claude/skills/e2e-audit/scripts/verify-audit.sh +88 -0
- package/template/.claude/skills/e2e-audit/templates/auth-setup.ts.tpl +24 -0
- package/template/.claude/skills/e2e-audit/templates/base-fixture.ts.tpl +75 -0
- package/template/.claude/skills/e2e-audit/templates/findings-report.md.tpl +54 -0
- package/template/.claude/skills/e2e-audit/templates/post-run-feedback.md.tpl +36 -0
- package/template/.claude/skills/e2e-audit/DESIGN.md +0 -294
- package/template/.claude/skills/e2e-audit/e2e/fixtures/auth.setup.ts +0 -70
- package/template/.claude/skills/e2e-audit/e2e/fixtures/auth.ts +0 -21
- package/template/.claude/skills/e2e-audit/e2e/fixtures/base.ts +0 -90
- package/template/.claude/skills/e2e-audit/e2e/fixtures/storage/.gitkeep +0 -0
- package/template/.claude/skills/e2e-audit/e2e/fixtures/storage/admin.json +0 -50
- package/template/.claude/skills/e2e-audit/e2e/fixtures/storage/manager.json +0 -50
- package/template/.claude/skills/e2e-audit/e2e/fixtures/storage/member.json +0 -50
- package/template/.claude/skills/e2e-audit/e2e/fixtures/storage/owner.json +0 -50
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-admin.page.ts +0 -141
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-billing.page.ts +0 -47
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-chat.page.ts +0 -35
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-home.page.ts +0 -134
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-integrations.page.ts +0 -334
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-knowledge.page.ts +0 -30
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-ontology.page.ts +0 -71
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-profile.page.ts +0 -38
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-teams.page.ts +0 -123
- package/template/.claude/skills/e2e-audit/e2e/pages/dashboard-transcripts.page.ts +0 -109
- package/template/.claude/skills/e2e-audit/e2e/specs/auth/login.spec.ts +0 -59
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-admin.spec.ts +0 -233
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-billing.spec.ts +0 -44
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-chat.spec.ts +0 -50
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-home.spec.ts +0 -243
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-integrations.spec.ts +0 -472
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-knowledge.spec.ts +0 -57
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-ontology.spec.ts +0 -72
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-profile.spec.ts +0 -48
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-teams.spec.ts +0 -247
- package/template/.claude/skills/e2e-audit/e2e/specs/dashboard-transcripts.spec.ts +0 -122
- package/template/.claude/skills/e2e-audit/e2e/specs/security/headers.spec.ts +0 -39
- package/template/.claude/skills/e2e-audit/e2e/specs/security/rbac.spec.ts +0 -92
- package/template/.claude/skills/e2e-audit/e2e/specs/security/xss.spec.ts +0 -74
- package/template/.claude/skills/e2e-audit/e2e/utils/console-collector.ts +0 -89
- package/template/.claude/skills/e2e-audit/e2e/utils/security-helpers.ts +0 -114
- package/template/.claude/skills/e2e-audit/e2e/utils/test-data.ts +0 -64
- package/template/.claude/skills/e2e-audit/runbook.md +0 -115
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
import { type Page, expect } from '@playwright/test'
|
|
2
|
-
|
|
3
|
-
export const XSS_PAYLOADS = [
|
|
4
|
-
'<script>alert("xss")</script>',
|
|
5
|
-
'<img src=x onerror=alert("xss")>',
|
|
6
|
-
'"><script>alert("xss")</script>',
|
|
7
|
-
"javascript:alert('xss')",
|
|
8
|
-
'<svg onload=alert("xss")>',
|
|
9
|
-
"'; DROP TABLE users; --",
|
|
10
|
-
'{{constructor.constructor("return this")()}}',
|
|
11
|
-
'${7*7}',
|
|
12
|
-
]
|
|
13
|
-
|
|
14
|
-
export const REQUIRED_SECURITY_HEADERS = [
|
|
15
|
-
'x-frame-options',
|
|
16
|
-
'x-content-type-options',
|
|
17
|
-
'referrer-policy',
|
|
18
|
-
]
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Test XSS payloads against a text input.
|
|
22
|
-
* Fills each payload and verifies no dialog (alert/confirm/prompt) fires.
|
|
23
|
-
*/
|
|
24
|
-
export async function testXssOnInput(
|
|
25
|
-
page: Page,
|
|
26
|
-
inputLocator: ReturnType<Page['getByRole']>,
|
|
27
|
-
) {
|
|
28
|
-
const dialogFired: string[] = []
|
|
29
|
-
const handler = (dialog: { message: () => string; dismiss: () => Promise<void> }) => {
|
|
30
|
-
dialogFired.push(dialog.message())
|
|
31
|
-
void dialog.dismiss()
|
|
32
|
-
}
|
|
33
|
-
page.on('dialog', handler)
|
|
34
|
-
|
|
35
|
-
for (const payload of XSS_PAYLOADS) {
|
|
36
|
-
await inputLocator.clear()
|
|
37
|
-
await inputLocator.fill(payload)
|
|
38
|
-
// Trigger potential execution (blur, submit)
|
|
39
|
-
await inputLocator.press('Tab')
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
page.off('dialog', handler)
|
|
43
|
-
|
|
44
|
-
if (dialogFired.length > 0) {
|
|
45
|
-
throw new Error(
|
|
46
|
-
`XSS detected! Dialog(s) fired with: ${dialogFired.join(', ')}`,
|
|
47
|
-
)
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Verify required security headers are present on a response.
|
|
53
|
-
*/
|
|
54
|
-
export async function assertSecurityHeaders(page: Page, url: string) {
|
|
55
|
-
const response = await page.goto(url)
|
|
56
|
-
if (!response) throw new Error(`No response for ${url}`)
|
|
57
|
-
|
|
58
|
-
const headers = response.headers()
|
|
59
|
-
|
|
60
|
-
for (const header of REQUIRED_SECURITY_HEADERS) {
|
|
61
|
-
expect(
|
|
62
|
-
headers[header],
|
|
63
|
-
`Missing security header: ${header}`,
|
|
64
|
-
).toBeDefined()
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// X-Content-Type-Options should be nosniff
|
|
68
|
-
if (headers['x-content-type-options']) {
|
|
69
|
-
expect(headers['x-content-type-options']).toBe('nosniff')
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Verify that error responses don't contain stack traces.
|
|
75
|
-
*/
|
|
76
|
-
export async function assertNoStackTraceInResponse(page: Page) {
|
|
77
|
-
const content = await page.content()
|
|
78
|
-
const stackTraceIndicators = [
|
|
79
|
-
'at Object.',
|
|
80
|
-
'at Module.',
|
|
81
|
-
'at Function.',
|
|
82
|
-
'node_modules/',
|
|
83
|
-
'.js:',
|
|
84
|
-
'webpack-internal',
|
|
85
|
-
'__next',
|
|
86
|
-
]
|
|
87
|
-
|
|
88
|
-
for (const indicator of stackTraceIndicators) {
|
|
89
|
-
expect(content).not.toContain(indicator)
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Test RBAC by navigating to a URL and checking if access is denied.
|
|
95
|
-
*/
|
|
96
|
-
export async function assertAccessDenied(
|
|
97
|
-
page: Page,
|
|
98
|
-
url: string,
|
|
99
|
-
expectedRedirect?: string,
|
|
100
|
-
) {
|
|
101
|
-
await page.goto(url)
|
|
102
|
-
const currentUrl = page.url()
|
|
103
|
-
|
|
104
|
-
if (expectedRedirect) {
|
|
105
|
-
expect(currentUrl).toContain(expectedRedirect)
|
|
106
|
-
} else {
|
|
107
|
-
// Should redirect to /unauthorized or /auth
|
|
108
|
-
const denied =
|
|
109
|
-
currentUrl.includes('/unauthorized') ||
|
|
110
|
-
currentUrl.includes('/auth') ||
|
|
111
|
-
currentUrl.includes('/login')
|
|
112
|
-
expect(denied).toBe(true)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared test data constants for E2E tests.
|
|
3
|
-
* Keep this minimal — only data used across multiple test files.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export const ROUTES = {
|
|
7
|
-
// Dashboard (authenticated)
|
|
8
|
-
home: '/dashboard/home',
|
|
9
|
-
knowledge: '/dashboard/knowledge',
|
|
10
|
-
knowledgeDetail: (id: string) => `/dashboard/knowledge/${id}`,
|
|
11
|
-
chat: '/dashboard/chat',
|
|
12
|
-
integrations: '/dashboard/integrations',
|
|
13
|
-
integrationDetail: (id: string) => `/dashboard/integrations/${id}`,
|
|
14
|
-
integrationsNew: '/dashboard/integrations/new',
|
|
15
|
-
integrationsSuccess: '/dashboard/integrations/success',
|
|
16
|
-
teams: '/dashboard/teams',
|
|
17
|
-
profile: '/dashboard/profile',
|
|
18
|
-
admin: '/dashboard/admin',
|
|
19
|
-
billing: '/dashboard/billing',
|
|
20
|
-
ontology: '/dashboard/ontology',
|
|
21
|
-
transcripts: '/dashboard/transcripts',
|
|
22
|
-
transcriptDetail: (id: string) => `/dashboard/transcripts/${id}`,
|
|
23
|
-
transcriptDocument: (id: string) => `/dashboard/transcripts/documents/${id}`,
|
|
24
|
-
|
|
25
|
-
// Auth
|
|
26
|
-
root: '/',
|
|
27
|
-
authDesktop: '/auth/desktop',
|
|
28
|
-
authError: '/auth/error',
|
|
29
|
-
logout: '/auth/logout',
|
|
30
|
-
popupCallback: '/auth/popup-callback',
|
|
31
|
-
integrationCallbackSuccess: '/auth/integration/callback/success',
|
|
32
|
-
integrationCallbackError: '/auth/integration/callback/error',
|
|
33
|
-
|
|
34
|
-
// Other
|
|
35
|
-
unauthorized: '/unauthorized',
|
|
36
|
-
freeTrial: '/freetrial',
|
|
37
|
-
} as const
|
|
38
|
-
|
|
39
|
-
export const RBAC_ROUTES = {
|
|
40
|
-
/** Routes accessible only by ADMIN+ */
|
|
41
|
-
admin: [ROUTES.admin],
|
|
42
|
-
/** Routes accessible only by OWNER */
|
|
43
|
-
owner: [ROUTES.billing],
|
|
44
|
-
/** Routes accessible only by MANAGER+ */
|
|
45
|
-
manager: [ROUTES.integrationsNew],
|
|
46
|
-
/** Routes accessible by any authenticated user */
|
|
47
|
-
member: [
|
|
48
|
-
ROUTES.home,
|
|
49
|
-
ROUTES.knowledge,
|
|
50
|
-
ROUTES.chat,
|
|
51
|
-
ROUTES.integrations,
|
|
52
|
-
ROUTES.teams,
|
|
53
|
-
ROUTES.profile,
|
|
54
|
-
ROUTES.ontology,
|
|
55
|
-
ROUTES.transcripts,
|
|
56
|
-
],
|
|
57
|
-
} as const
|
|
58
|
-
|
|
59
|
-
export const TIMEOUTS = {
|
|
60
|
-
navigation: 30_000,
|
|
61
|
-
action: 10_000,
|
|
62
|
-
toast: 5_000,
|
|
63
|
-
animation: 500,
|
|
64
|
-
} as const
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
# E2E Audit Runbook
|
|
2
|
-
|
|
3
|
-
## Setup
|
|
4
|
-
|
|
5
|
-
### 1. Install Playwright
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
bun add -D @playwright/test
|
|
9
|
-
bunx playwright install chromium
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
### 2. Start the dev server
|
|
13
|
-
|
|
14
|
-
```bash
|
|
15
|
-
bun run dev
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
### 3. Run tests
|
|
19
|
-
|
|
20
|
-
```bash
|
|
21
|
-
# All E2E tests
|
|
22
|
-
bun run test:e2e
|
|
23
|
-
|
|
24
|
-
# With UI mode (visual debugger)
|
|
25
|
-
bunx playwright test --ui
|
|
26
|
-
|
|
27
|
-
# Specific test file
|
|
28
|
-
bunx playwright test tests/e2e/specs/dashboard-home.spec.ts
|
|
29
|
-
|
|
30
|
-
# By tag
|
|
31
|
-
bunx playwright test --grep @smoke
|
|
32
|
-
bunx playwright test --grep @security
|
|
33
|
-
bunx playwright test --grep @ux
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
## Test Organization
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
tests/e2e/
|
|
40
|
-
├── fixtures/ # Auth + base fixtures
|
|
41
|
-
│ ├── auth.ts # Per-role authentication setup
|
|
42
|
-
│ ├── base.ts # Extended test fixture (authenticatedPage)
|
|
43
|
-
│ └── storage/ # Generated auth state files (gitignored)
|
|
44
|
-
├── pages/ # Page Object Models (1 per page)
|
|
45
|
-
├── specs/ # Test specs (1 per page + security/)
|
|
46
|
-
│ └── security/ # Cross-cutting security tests
|
|
47
|
-
└── utils/ # Shared helpers
|
|
48
|
-
├── console-collector.ts # Console message interceptor
|
|
49
|
-
├── security-helpers.ts # XSS, header, RBAC helpers
|
|
50
|
-
└── test-data.ts # Routes, timeouts, test constants
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
## Adding Tests for a New Page
|
|
54
|
-
|
|
55
|
-
1. **Create Page Object** in `tests/e2e/pages/{page-name}.page.ts`
|
|
56
|
-
2. **Create Test Spec** in `tests/e2e/specs/{page-name}.spec.ts`
|
|
57
|
-
3. **Create Page Spec** in `docs/e2e-audit/page-specs/{page-name}.md`
|
|
58
|
-
4. **Run and fix**: `bunx playwright test tests/e2e/specs/{page-name}.spec.ts`
|
|
59
|
-
5. **Update master audit** in `docs/e2e-audit/reports/master-audit.md`
|
|
60
|
-
|
|
61
|
-
## Updating Tests After App Changes
|
|
62
|
-
|
|
63
|
-
1. Run the e2e-audit skill to re-discover elements on changed pages
|
|
64
|
-
2. Compare new page spec with existing
|
|
65
|
-
3. Update POM, test spec, and page spec
|
|
66
|
-
4. Run tests: `bun run test:e2e`
|
|
67
|
-
5. Fix failures
|
|
68
|
-
|
|
69
|
-
## Auth Setup
|
|
70
|
-
|
|
71
|
-
Tests use `storageState` for pre-authenticated sessions. The auth fixture at
|
|
72
|
-
`tests/e2e/fixtures/auth.ts` needs real login flows implemented per role.
|
|
73
|
-
|
|
74
|
-
For local development with OAuth, you may need to:
|
|
75
|
-
1. Use the Cloudflare tunnel (`https://dev.hakutaku.ai`)
|
|
76
|
-
2. Set `BASE_URL=https://dev.hakutaku.ai` when running tests
|
|
77
|
-
3. Or mock auth via direct cookie/session injection
|
|
78
|
-
|
|
79
|
-
## CI Integration
|
|
80
|
-
|
|
81
|
-
```yaml
|
|
82
|
-
# Example GitHub Actions step
|
|
83
|
-
- name: E2E Tests
|
|
84
|
-
run: |
|
|
85
|
-
bunx playwright install chromium
|
|
86
|
-
bun run test:e2e
|
|
87
|
-
env:
|
|
88
|
-
BASE_URL: http://localhost:3000
|
|
89
|
-
```
|
|
90
|
-
|
|
91
|
-
## Debugging Failed Tests
|
|
92
|
-
|
|
93
|
-
```bash
|
|
94
|
-
# View trace from failed test
|
|
95
|
-
bunx playwright show-trace test-results/{test-name}/trace.zip
|
|
96
|
-
|
|
97
|
-
# Run with headed browser
|
|
98
|
-
bunx playwright test --headed
|
|
99
|
-
|
|
100
|
-
# Run with slow motion
|
|
101
|
-
bunx playwright test --headed --slow-mo 500
|
|
102
|
-
|
|
103
|
-
# Debug specific test
|
|
104
|
-
bunx playwright test --debug tests/e2e/specs/dashboard-home.spec.ts
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## Tags Reference
|
|
108
|
-
|
|
109
|
-
| Tag | Purpose | When to run |
|
|
110
|
-
|-----|---------|-------------|
|
|
111
|
-
| `@smoke` | Critical paths | Every PR |
|
|
112
|
-
| `@regression` | Full suite | Main merges |
|
|
113
|
-
| `@security` | Security tests | Weekly + before release |
|
|
114
|
-
| `@a11y` | Accessibility | Weekly |
|
|
115
|
-
| `@ux` | UX/UI validation | After UI changes |
|