Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,63 @@
## ADDED Requirements
### Requirement: Default network sandboxing
`createE2ETestConfig()` SHALL default to blocking external origins via a per-test `page.route('**/*')` handler that aborts requests with `'blockedbyclient'` unless their origin is allow-listed. The auto-allowed set SHALL include `localhost`, `127.0.0.1`, and the configured testbed origin (read from the `TESTBED_ORIGIN` env var, falling back to the factory's `baseURL`). The factory SHALL accept an `allowedOrigins: string[]` option (default `[]`) which lifts the block per-origin. Origin matching SHALL be performed via `URL` constructor parsing on full origin (`<scheme>://<host>:<port>`), never substring or regex matching.
#### Scenario: External origin blocked by default
- **WHEN** a spec configured by `createE2ETestConfig({ baseURL: 'http://localhost:3200' })` issues a request to `https://example.com/data`
- **THEN** the request is aborted with reason `'blockedbyclient'` AND the assertion library surfaces the abort as a network failure
#### Scenario: localhost auto-allowed
- **WHEN** a spec under the same config issues a request to `http://localhost:3200/api/users` or `http://127.0.0.1:9000/`
- **THEN** the request proceeds normally AND no abort is raised
#### Scenario: Testbed origin auto-allowed
- **WHEN** `TESTBED_ORIGIN=https://testbed.internal:8443` is set in the environment
- **THEN** requests to that exact origin proceed normally
#### Scenario: allowedOrigins lifts the block
- **WHEN** `createE2ETestConfig({ allowedOrigins: ['https://api.partner.test'] })` is used and a spec issues `GET https://api.partner.test/v1/foo`
- **THEN** the request proceeds normally AND requests to any other external origin remain blocked
#### Scenario: Origin matching is exact
- **WHEN** `allowedOrigins: ['https://api.partner.test']` is set and a spec issues `GET https://evil.api.partner.test.attacker.example/`
- **THEN** the request is blocked AND the substring overlap does NOT lift the block
### Requirement: Spec-level escape hatch with warning
The package SHALL expose a `test.use({ allowExternalNetwork: true })` Playwright fixture extension that disables the default block for the enclosing spec only. Use of this escape hatch SHALL emit a warning at suite start naming the offending spec file path, encouraging migration to explicit `allowedOrigins`. The escape hatch MUST be implemented as a Playwright `test.extend` fixture and MUST NOT mutate other specs' route handlers.
#### Scenario: Escape hatch lifts the block locally
- **WHEN** a spec declares `test.use({ allowExternalNetwork: true })` and issues a request to `https://example.com/`
- **THEN** the request proceeds normally AND no abort is raised within that spec
#### Scenario: Escape-hatch warning emitted
- **WHEN** the suite starts and at least one spec opts into `allowExternalNetwork: true`
- **THEN** a warning line is written to stderr naming each offending spec file path AND the warning persists in the test report
#### Scenario: Escape hatch is spec-local
- **WHEN** spec A declares `test.use({ allowExternalNetwork: true })` and spec B does not
- **THEN** spec B's external requests are still blocked AND spec A's opt-in does not leak across
### Requirement: Origin-matching algorithm is documented and tested
The origin-matching algorithm used by the network sandbox SHALL be exported as a pure function (e.g. `isOriginAllowed(url, allowedOrigins, autoAllowed)`) so it is testable in isolation. The function MUST: parse `url` via the `URL` constructor and reject inputs that fail to parse with `TESTING_E2E.NETWORK.URL_INVALID`; compare on the `<scheme>://<host>:<port>` triple, treating the default port for the scheme as equivalent to an explicit port; return a boolean. fast-check property tests SHALL cover round-trip parsing and the substring-attack scenario above.
#### Scenario: Default-port equivalence
- **WHEN** `isOriginAllowed('https://api.partner.test/', ['https://api.partner.test:443'], [])` is called
- **THEN** the function returns `true`
#### Scenario: Invalid URL rejected
- **WHEN** `isOriginAllowed('not a url', [], [])` is called
- **THEN** the function throws `TESTING_E2E.NETWORK.URL_INVALID`