diff --git a/.claude/skills/emulate/SKILL.md b/.claude/skills/emulate/SKILL.md index 8814a64aa..f8e3515b5 100644 --- a/.claude/skills/emulate/SKILL.md +++ b/.claude/skills/emulate/SKILL.md @@ -5,15 +5,18 @@ description: Use the @executor-js/emulate service emulators (GitHub, Google, Str # Emulate: production-fidelity service emulators -`@executor-js/emulate` (our fork of Vercel Labs' emulate, developed in -`vendor/emulate` but ALWAYS consumed as the published npm package — never -import from `vendor/`) provides stateful, wire-level emulators for 16 -services: `github vercel google okta microsoft spotify slack apple aws -resend stripe mongoatlas clerk x workos autumn`. These are not mocks: real -SDKs and real product code run against them unmodified — the cloud e2e -target points the actual WorkOS SDK (sealed sessions, JWKS, hosted AuthKit -login) and Autumn billing at emulators and exercises the product's real -auth code. +`@executor-js/emulate` (our fork of Vercel Labs' emulate) provides stateful, +wire-level emulators for 16 services: `github vercel google okta microsoft +spotify slack apple aws resend stripe mongoatlas clerk x workos autumn`. +These are not mocks: real SDKs and real product code run against them +unmodified — the cloud e2e target points the actual WorkOS SDK (sealed +sessions, JWKS, hosted AuthKit login) and Autumn billing at emulators and +exercises the product's real auth code. + +**This repo only consumes the published npm package.** There is no +`vendor/emulate` submodule — everything imports `@executor-js/emulate` from +npm. The emulator _source_ is its own standalone project; to change or deploy +an emulator, see "Changing or deploying an emulator" at the bottom. ## Two ways to get one @@ -83,6 +86,40 @@ before `createEmulator` so minted MCP access tokens carry the right audience. app's real dev stack (recipe in `e2e/setup/cloud.boot.ts`), fronted with tailscale HTTPS. +## Changing or deploying an emulator + +The emulators live in their own repo — **not** in executor and **not** a +submodule: `github.com/UsefulSoftwareCo/emulate` (clone it as a sibling of +executor). It's a pnpm + turbo monorepo on node ≥ 24 — a different toolchain +from executor's bun, which is exactly why it's standalone rather than +vendored here. + +You have full autonomy over it: **work directly on `main`, and commit, push, +publish, and deploy without asking.** The loop: + +1. Edit in the emulate repo, then **rebuild the package you changed.** It + resolves through built `dist`, so a source-only edit does nothing until you + build it — this is the single most common mistake. `@emulators/*` packages + are a `workspace:*` graph, so adding or renaming one needs an install + + rebuild too. +2. Publish a version bump of `@executor-js/emulate` to npm. +3. Deploy the hosted Cloudflare emulators (the `emulate-hosts` worker behind + `*.emulators.dev`) when behavior the hosted instances serve has changed. +4. Back in executor, bump the `@executor-js/emulate` dependency to the version + you just published. Never point a consumer at a local checkout to ship — + publish, then bump. + +The emulate repo's own `AGENTS.md` / `README.md` carry the current build, +publish, and deploy commands (npm + Cloudflare creds are in 1Password). Read +them there rather than memorizing flags here — they move. + +**A hot deploy can redden other people's e2e.** `*.emulators.dev` service +hosts are shared infrastructure; a control-plane regression there has failed +unrelated PRs' suites before. When a scenario needs isolation or a behavior +that isn't deployed yet, pin to a published package version or mint a private +per-run instance (`POST /_emulate/instances`) instead of mutating the shared +service host. + ## Gotchas - **Secure cookies need HTTPS off-localhost.** Browser-driven flows work on diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 2d0fb0c20..000000000 --- a/.gitmodules +++ /dev/null @@ -1,9 +0,0 @@ -[submodule "integrationsdotsh"] - path = integrationsdotsh - url = https://github.com/RhysSullivan/integrationsdotsh.git -[submodule "vendor/emulate"] - path = vendor/emulate - url = https://github.com/UsefulSoftwareCo/emulate.git -[submodule "vendor/mcporter"] - path = vendor/mcporter - url = https://github.com/UsefulSoftwareCo/mcporter.git diff --git a/.oxfmtrc.json b/.oxfmtrc.json index 795e7bb76..d92df54ec 100644 --- a/.oxfmtrc.json +++ b/.oxfmtrc.json @@ -7,7 +7,6 @@ "dist", "vendor", "e2e/runs", - "integrationsdotsh", "node_modules", "packages/core/fumadb", "bun.lock", diff --git a/.oxlintrc.jsonc b/.oxlintrc.jsonc index a117a09ec..53839c4bb 100644 --- a/.oxlintrc.jsonc +++ b/.oxlintrc.jsonc @@ -153,7 +153,6 @@ "vendor/", "emulators/", "e2e/runs/", - "integrationsdotsh/", "node_modules/", "packages/core/fumadb/", "packages/core/sdk/src/vendor/json-schema-to-typescript/", diff --git a/AGENTS.md b/AGENTS.md index 901b9eb33..6e6aeecc3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -61,6 +61,12 @@ with zero setup. See the `emulate` skill (`.claude/skills/emulate/SKILL.md`) for the control-plane reference and recipes. +The emulators are a standalone project (`github.com/UsefulSoftwareCo/emulate`), +not vendored here — this repo only consumes the published `@executor-js/emulate` +package. You have full autonomy to change, publish, and deploy the emulators, +working directly on their `main`; the skill covers the loop. Don't re-introduce +a `vendor/` submodule for them. + ## Attribution Do not add any AI assistant, Claude, Anthropic, or Co-Authored-By diff --git a/README.md b/README.md index e848bd4af..1974fb7bc 100644 --- a/README.md +++ b/README.md @@ -134,8 +134,7 @@ bun run test:e2e # full-stack e2e: boots the cloud and self-host apps and driv ``` The browser e2e scenarios need Playwright's Chromium once per machine: -`bunx playwright install chromium`. The git submodules under `vendor/` are -optional — see [vendor/README.md](vendor/README.md). +`bunx playwright install chromium`. ## Community diff --git a/RUNNING.md b/RUNNING.md index 4c4b55238..55c1c6fba 100644 --- a/RUNNING.md +++ b/RUNNING.md @@ -15,11 +15,13 @@ artifacts dev servers fail without) plus Playwright chromium. A fresh worktree that skips it dies with "Failed to resolve entry for package '@executor-js/vite-plugin'". -The `vendor/` submodules (emulate, mcporter) are NOT required — nothing -imports from `vendor/` at runtime; those packages come from npm -(`@executor-js/emulate`, `@executor-js/mcporter`). `bun run bootstrap ---forks` inits them only when deliberately developing a fork (see -`vendor/README.md`). +Our two upstream forks — `@executor-js/emulate` (service emulators) and +`@executor-js/mcporter` (headless MCP client) — are consumed purely as +published npm packages; nothing in this repo references them by path. There +are no `vendor/` submodules. Each fork is its own standalone repo +(`github.com/UsefulSoftwareCo/emulate`, `github.com/UsefulSoftwareCo/mcporter`): +develop on its `main`, publish a bump, then bump the dependency here. The +`emulate` skill covers the emulator publish/deploy loop. ## Dev servers diff --git a/e2e/src/surfaces/mcp.ts b/e2e/src/surfaces/mcp.ts index 1c3848546..aa89a828e 100644 --- a/e2e/src/surfaces/mcp.ts +++ b/e2e/src/surfaces/mcp.ts @@ -1,6 +1,7 @@ -// MCP surface: our mcporter fork (@executor-js/mcporter on npm; develop it in -// the vendor/mcporter submodule) as a programmatic MCP client, with headless -// OAuth via the target's consent strategy. Session methods are Effects; +// MCP surface: our mcporter fork (@executor-js/mcporter on npm; developed in +// its own repo, github.com/UsefulSoftwareCo/mcporter) as a programmatic MCP +// client, with headless OAuth via the target's consent strategy. Session +// methods are Effects; // mcporter itself is promise-native underneath. Assertions are vitest's job. import { createHash, randomBytes, randomUUID } from "node:crypto"; import { mkdtempSync, writeFileSync } from "node:fs"; diff --git a/scripts/bootstrap.ts b/scripts/bootstrap.ts index be34a42dc..923d868d7 100644 --- a/scripts/bootstrap.ts +++ b/scripts/bootstrap.ts @@ -3,10 +3,9 @@ // Playwright browser the e2e suite drives. Idempotent and safe to re-run; // each step prints what it is doing. // -// The vendor/ submodules are intentionally NOT initialized: nothing imports -// from vendor/ at runtime — those forks are consumed as published npm -// packages (see vendor/README.md). Pass --forks only when deliberately -// developing a fork. +// There are no fork submodules: our upstream forks (@executor-js/emulate, +// @executor-js/mcporter) are consumed purely as published npm packages and +// developed in their own standalone repos. Nothing to init here. import { execFileSync } from "node:child_process"; import { existsSync } from "node:fs"; import { resolve } from "node:path"; @@ -19,10 +18,6 @@ const run = (label: string, cmd: string, args: ReadonlyArray) => { execFileSync(cmd, [...args], { cwd: repoRoot, stdio: "inherit" }); }; -if (process.argv.includes("--forks")) { - run("vendor fork submodules", "git", ["submodule", "update", "--init", "--recursive"]); -} - // `bun install` runs the workspace prepare hook, which builds // @executor-js/vite-plugin and @executor-js/react — the two artifacts the // apps' vite dev servers fail without in a fresh worktree. diff --git a/scripts/migrate-schema-class.ts b/scripts/migrate-schema-class.ts index ed5d8c0ec..6eb10c46b 100644 --- a/scripts/migrate-schema-class.ts +++ b/scripts/migrate-schema-class.ts @@ -30,7 +30,6 @@ const IGNORE_DIRS = new Set([ "build", ".local", ".changeset", - "integrationsdotsh", ]); // Files we intentionally leave alone — they contain `Schema.Class` strings as diff --git a/vendor/README.md b/vendor/README.md deleted file mode 100644 index 765e01f7c..000000000 --- a/vendor/README.md +++ /dev/null @@ -1,34 +0,0 @@ -# vendor/ — fork submodules (optional) - -These are git submodules holding our forks of upstream projects. **Nothing in -the repo imports from `vendor/` at runtime** — code consumes the published -packages from npm — so a fresh clone works without initializing submodules. -They exist so the forks can be developed alongside the code that uses them. - -| Submodule | Published as | Used by | -| --- | --- | --- | -| `vendor/mcporter` | `@executor-js/mcporter` | `e2e/` (headless MCP client with `cookieConsentStrategy`) | -| `vendor/emulate` | `@executor-js/emulate` | `e2e/` (wire-level WorkOS/Autumn emulators the real SDKs are pointed at) | - -## Developing a fork - -```bash -git submodule update --init vendor/mcporter -cd vendor/mcporter -pnpm install && pnpm build -``` - -To test local fork changes against the repo before publishing, point the -consumer at the submodule build with a temporary `file:` override (or -`bun link`), then revert once the new version is published: - -```jsonc -// e2e/package.json (temporary, do not commit) -"@executor-js/mcporter": "file:../vendor/mcporter" -``` - -## Releasing a fork - -Bump the fork's `package.json` version, publish from the submodule -(`npm publish --access public`), push the fork branch, bump the consumer's -dependency here, and commit the new submodule pointer. diff --git a/vendor/emulate b/vendor/emulate deleted file mode 160000 index 894206f09..000000000 --- a/vendor/emulate +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 894206f09681d77f1d9d708a8d49f1c7dc72fa1f diff --git a/vendor/mcporter b/vendor/mcporter deleted file mode 160000 index 8f3e44926..000000000 --- a/vendor/mcporter +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8f3e44926e76ba19387885b83f7bb554658d2804