Skip to content

Commit afe2dd7

Browse files
Bill LeoutsakosBill Leoutsakos
authored andcommitted
Harden E2E persona orchestration and remove deferred cleanup
Generate runtime secrets per run, close lifecycle and acceptance gaps, and remove the unused exact-ID cleanup module until retained-stack support has a real consumer.
1 parent f7d10c7 commit afe2dd7

45 files changed

Lines changed: 2167 additions & 624 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/test-build.yml

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -300,14 +300,6 @@ jobs:
300300
key: ${{ github.repository }}-playwright-browsers-${{ github.event_name }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}
301301
path: ~/.cache/ms-playwright
302302

303-
- name: Restore E2E Next.js build cache
304-
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
305-
with:
306-
path: ./apps/sim/.next/cache
307-
key: ${{ runner.os }}-nextjs-e2e-hosted-billing-${{ hashFiles('bun.lock') }}-${{ github.sha }}
308-
restore-keys: |
309-
${{ runner.os }}-nextjs-e2e-hosted-billing-${{ hashFiles('bun.lock') }}-
310-
311303
- name: Install dependencies
312304
run: bun install --frozen-lockfile
313305

@@ -327,7 +319,7 @@ jobs:
327319
run: bun run test:e2e
328320

329321
- name: Upload E2E diagnostics
330-
if: failure() || cancelled()
322+
if: failure()
331323
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
332324
with:
333325
name: settings-e2e-${{ github.run_id }}
@@ -336,6 +328,8 @@ jobs:
336328
apps/sim/test-results/
337329
apps/sim/e2e/.runs/
338330
!apps/sim/e2e/.runs/**/auth/**
331+
!apps/sim/e2e/.runs/**/private/**
332+
!apps/sim/e2e/.runs/**/homes/**
339333
if-no-files-found: ignore
340334
include-hidden-files: true
341335
retention-days: 7

apps/sim/e2e/README.md

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,18 @@ Stripe fake and realtime, builds and starts Next.js, seeds the validated persona
5454
world through production APIs plus narrow trusted arrangements, captures each
5555
persona through the real login UI, runs Playwright on Node 22, then stops
5656
services and drops only that guarded database.
57+
Server telemetry currently shares the strict loopback Stripe-fake process; the
58+
generic modular fake-service refactor remains scoped to the roadmap's
59+
`e2e/06b-enterprise-integrations` phase.
60+
An exclusive checkout-level orchestrator lock prevents concurrent runs from
61+
racing on `.next`, the shared build cache, or the fixed app/realtime ports.
5762

5863
On interruption, the runner launches a detached cleanup supervisor before
5964
exiting. It terminates managed process groups, force-drops the guarded database,
6065
and removes temporary auth/cloud-config directories even if another Ctrl-C
6166
terminates the foreground package runner.
67+
Cleanup failures retain the lock and require the reported resources to be
68+
inspected and cleaned before manually removing `e2e/.cache/orchestrator.lock`.
6269

6370
Pass Playwright arguments after `--`:
6471

@@ -67,6 +74,19 @@ bun run test:e2e -- --project=hosted-billing-chromium-navigation
6774
bun run test:e2e -- --grep "unauthenticated"
6875
```
6976

77+
Projects form a dependency chain to keep shared boundaries serialized. Selecting
78+
the personas project therefore also runs navigation and workflows by default,
79+
and an upstream failure skips its dependents. For focused local iteration,
80+
`--no-deps` is explicitly supported:
81+
82+
```bash
83+
bun run test:e2e -- --project=hosted-billing-chromium-personas --no-deps
84+
```
85+
86+
`--no-deps` requires exactly one explicit canonical project. It skips only
87+
Playwright project dependencies; the guarded one-shot stack still performs full
88+
seed and auth setup. Do not use it for full verification; the runner rejects it in CI.
89+
7090
For a local follow-up run, reuse only a verified build while still creating a
7191
new database, Stripe fake, app, realtime process, and browser run:
7292

@@ -77,8 +97,12 @@ bun run test:e2e -- --reuse-build --project=hosted-billing-chromium-navigation
7797
The cache lives under ignored `e2e/.cache/builds/`. A hit requires matching
7898
source contents (including uncommitted/untracked files), build/public profile,
7999
Node/Bun/Next versions, platform, `BUILD_ID`, and the cached artifact checksum.
80-
Any mismatch performs and caches a fresh build. CI rejects `--reuse-build`.
81-
`--skip-build` remains unsupported.
100+
Any mismatch performs and caches a fresh local build; only the most recent cache
101+
entry is retained because this application's production artifact is several
102+
gigabytes. CI rejects `--reuse-build` and does not copy or hash a disposable
103+
cache artifact. Plain local runs also skip cache identity computation,
104+
multi-gigabyte copying, and cache population; only an explicit `--reuse-build`
105+
request pays those costs. `--skip-build` remains unsupported.
82106

83107
Keep-stack/rerun supervision is intentionally unavailable. The initial safety
84108
experiment requires descriptor ownership, mutation observation, state snapshots,
@@ -92,15 +116,17 @@ safe because they do not execute tests.
92116

93117
Sharding is supported only for the navigation project. The runner rejects
94118
`--shard` for workflows, persona contracts, and the dedicated two-worker
95-
cross-world isolation project.
119+
cross-world isolation project. Project dependencies serialize navigation,
120+
workflows, and persona contracts before the isolation project opens its
121+
two-worker pool.
96122

97123
## Diagnostics
98124

99125
- HTML report: `playwright-report/`
100126
- Traces and screenshots: `test-results/`
101127
- App, realtime, migration, seed, auth-capture, and fake logs:
102128
`e2e/.runs/<runId>/logs/`
103-
- Non-secret persona manifest and post-login auth-capture screenshots:
129+
- Non-secret persona manifest and auth-capture failure screenshots:
104130
`e2e/.runs/<runId>/`
105131

106132
Open the report:
@@ -123,12 +149,34 @@ non-secret manifest and storage-state directory, never passwords, the admin API
123149
key, or the database URL. Next build/start shadow
124150
keys found in local `.env*` files, while children that cannot load those files
125151
omit denied keys entirely. Developer credentials are not used as test state or
126-
written to reports. Synthetic persona passwords live in a private run-home file
127-
and are removed with the auth/cloud-config directory during teardown.
128-
129-
E2E builds verify the reviewed sandbox-bundle source/dependency/output
130-
fingerprint and never regenerate committed `.cjs` files. Regeneration remains an
131-
explicit repository maintenance operation.
152+
written to reports. Named persona credentials and a separate all-synthetic-user
153+
canary list live outside every child `HOME` in a private run directory. Auth
154+
capture receives only the persona file, which is deleted immediately after
155+
capture; storage states are mode `0600` and excluded from CI artifacts. Captured
156+
passwords are loaded into orchestrator memory, then both secret files are
157+
deleted before Playwright starts. After managed processes stop and logs flush,
158+
the in-memory canary scans the manifest, logs, report files, and trace archives
159+
and fails if a synthetic password, invitation token, or runtime secret escaped
160+
the excluded private directories. Cancelled CI runs do not upload unscanned
161+
diagnostics. Storage-state session cookies are intentionally not canaried
162+
because authenticated Playwright traces contain them by design; they are
163+
synthetic and invalid once the run database is dropped.
164+
Fresh-session recapture is deliberately deferred. Future membership-mutation
165+
coverage must explicitly restore a private credential handoff and re-review its
166+
access boundary rather than assuming credentials persist through Playwright.
167+
168+
E2E builds verify the pinned Bun executable plus reviewed sandbox-bundle
169+
source, direct dependency, and output fingerprints and never regenerate
170+
committed `.cjs` files.
171+
`bun run build:sandbox-bundles:integrity` is the explicit maintenance command
172+
that regenerates bundles and their reviewed integrity manifest together.
173+
Unrelated monorepo lockfile changes do not invalidate the bundle fingerprint;
174+
the committed output hashes still detect any transitive change that alters a
175+
bundle.
176+
177+
Reset/reseed cleanup remains deferred with keep-stack supervision. Ordinary
178+
runs own a unique guarded database and remove it wholesale rather than carrying
179+
untested row-level deletion code.
132180

133181
Provider log scans are diagnostic tripwires, not proof of zero egress. The
134182
primary boundaries are the default-deny child environment, provider disabling,

apps/sim/e2e/fakes/stripe/server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const STRIPE_FAKE_ENDPOINTS = {
66
health: '/health',
77
requestLog: '/__control/requests',
88
reset: '/__control/reset',
9+
// Co-locate the only other server-side external boundary so the E2E stack needs one loopback fake.
910
telemetry: '/v1/traces',
1011
} as const
1112

apps/sim/e2e/fixtures/cleanup.ts

Lines changed: 0 additions & 172 deletions
This file was deleted.

0 commit comments

Comments
 (0)