@rehearsal-db/core 1.0.0 → 1.0.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/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ### Platform compatibility
9
+
10
+ - Keep macOS Intel/Apple Silicon and Linux execution distinct from Windows desktop
11
+ access through WSL 2. Require the WSL project's Linux filesystem; document the
12
+ preview's actual component and runtime limits rather than claiming every OS works.
13
+ - Verify installed package version/discovery on real desktop OS runners and exercise
14
+ PostgreSQL/dependent targets in an owned Windows 2025 WSL2 Ubuntu distribution.
15
+ Provision checksum-verified official Node and signed Docker Engine packages without
16
+ Docker Desktop, a daemon TCP endpoint or new branch-protection requirements.
17
+ - Document native Windows runtime refusal and the Linux/Remote-WSL setup path; version,
18
+ help and project discovery remain distinct from database-runtime support.
19
+
8
20
  ## [1.0.0] - 2026-10-17
9
21
 
10
22
  ### Stable compatibility
package/COMPATIBILITY.md CHANGED
@@ -32,6 +32,49 @@ default and the release-build runtime. End-of-life and odd-numbered Node.js rele
32
32
  not supported. A future release may remove a Node.js line after its upstream end-of-life
33
33
  date, with that change called out in the changelog.
34
34
 
35
+ ## Operating systems and execution location
36
+
37
+ Core 1.0.1's platform boundary distinguishes the computer running VS Code from the
38
+ operating system actually executing Node, Docker and Rehearsal. The corresponding editor
39
+ changes are delivered with extension 0.1.21. A Windows desktop connected to WSL is not native
40
+ Windows execution.
41
+
42
+ | Execution environment | Runtime boundary |
43
+ | ---------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
44
+ | macOS, Intel or Apple Silicon | POSIX runtime; supported Node and a local Docker-compatible engine required |
45
+ | Linux | POSIX runtime; Ubuntu 24.04 is the primary PostgreSQL/Supabase fixture environment |
46
+ | Windows with WSL 2 | Run Linux Node and Docker inside the distribution, with the project on its Linux filesystem; compatibility preview |
47
+ | Native Windows Node, PowerShell or Command Prompt | Version, help and read-only project discovery remain available; runtime/setup/database operations refuse with WSL guidance |
48
+ | WSL 1, a WSL project on `/mnt/c` or another Windows-mounted filesystem | Not a supported database-runtime environment |
49
+ | SSH, Dev Containers, Codespaces or browser-only VS Code | No end-to-end support claim; different host, filesystem and port-forwarding boundaries need their own verification |
50
+ | iOS, iPadOS, Android, BSD and other unlisted systems | Not supported; installing a JavaScript package does not establish a compatible database engine or desktop extension host |
51
+
52
+ Do not bypass native Windows refusal with permission bits or a shell wrapper. Native
53
+ Windows ACLs, process-tree retirement and baseline filesystem behavior are not certified
54
+ by Linux tests. Keep keys, baselines and working files in the WSL Linux home filesystem,
55
+ not a Windows share. The package does not move an existing project automatically.
56
+ See [Windows and WSL setup](docs/getting-started.md#windows-use-a-wsl-2-linux-workspace).
57
+
58
+ ### What platform verification proves
59
+
60
+ The separate `Platform compatibility` workflow preserves existing release/check names.
61
+ Desktop jobs install the packed package and exercise version/discovery from a path with
62
+ spaces and Unicode on real Linux, macOS and Windows runners. Windows also checks the
63
+ intentional runtime refusal; a passing Windows job is not a working Windows database.
64
+ The Windows 2025 WSL job provisions its own Ubuntu 24.04 distribution, verifies Linux
65
+ execution and filesystem location, then runs the existing real PostgreSQL/dependent-target
66
+ fixtures against a local Unix-socket Docker Engine. It does not install Docker Desktop
67
+ or expose the daemon over TCP. Node uses the official release checksum; Docker packages
68
+ use its signed apt repository. These integrity checks are not independent publisher
69
+ authentication.
70
+
71
+ A configured workflow is not passing evidence. Reports identify actual OS, architecture,
72
+ installed artifact and exercised boundary. The WSL fixture does not certify native
73
+ Windows runtime, WSL Supabase/Auth/Storage, a native Remote-WSL VS Code session, all Linux
74
+ distributions, assistive technology or every architecture. Editor Node/controller tests
75
+ are separate from real extension-host and browser walkthroughs. Intel/ARM labels and
76
+ Windows/WSL are never interchangeable evidence.
77
+
35
78
  The npm install hook may create project scaffolding only when it proves one application
36
79
  root. Ordinary npm application installs are covered. A workspace is automatic only when
37
80
  one declaring consumer is already visible in its manifest or lockfile; npm can save a
package/README.md CHANGED
@@ -16,6 +16,7 @@
16
16
  <p align="center">
17
17
  <a href="https://ddupasquier.github.io/rehearsal-db/">Read the documentation</a> ·
18
18
  <a href="https://www.npmjs.com/package/@rehearsal-db/core">View on npm</a> ·
19
+ <a href="https://ddupasquier.github.io/rehearsal-db/vscode/">Free VS Code Starter</a> ·
19
20
  <a href="https://github.com/Ddupasquier/rehearsal-db">Source on GitHub</a> ·
20
21
  <a href="https://github.com/Ddupasquier/rehearsal-db/issues">Report a problem</a>
21
22
  </p>
@@ -45,8 +46,14 @@ it through a reviewed privacy policy, and retire the access again. It is never p
45
46
  `run`, `reset`, `migrate`, or application launch. Rehearsal is not a backup system or a
46
47
  production deployment tool.
47
48
 
48
- > **Pre-1.0 safety note:** use Rehearsal on a branch and keep a working backup of your
49
- > project.
49
+ The CLI is free and MIT-licensed, with stable releases on
50
+ [npm](https://www.npmjs.com/package/@rehearsal-db/core). This guide targets **1.0.1**;
51
+ install only a version actually published there. Prefer a visual workflow?
52
+ [Install the free VS Code Starter preview](docs/vscode.md). Its included features are
53
+ free indefinitely for personal or commercial development—no account, card, or trial.
54
+
55
+ Work on a branch and keep a working backup of your project. Rehearsal's local safety
56
+ boundaries do not replace version control or backups.
50
57
 
51
58
  ## What you need
52
59
 
@@ -62,6 +69,12 @@ your migration is intended to change.
62
69
 
63
70
  ## Quick start
64
71
 
72
+ Prefer OS-specific files? Use the [Windows / WSL 2](installers/windows/README.md),
73
+ [macOS](installers/macos/README.md) or [Linux](installers/linux/README.md) setup folder.
74
+ These readable helpers require existing Node.js 24 or 26 and check prerequisites by
75
+ default; installation is an explicit option. They do not install OS tools or start a
76
+ database. See [their exact behavior and release availability](installers/README.md).
77
+
65
78
  From your project directory:
66
79
 
67
80
  ```bash
@@ -157,18 +170,24 @@ loads.
157
170
 
158
171
  ## Supported today
159
172
 
160
- | Environment | Support |
161
- | ------------------------------------------------ | ---------------------- |
162
- | Supabase CLI projects | Supported |
163
- | Ordinary PostgreSQL in local Docker | Supported |
164
- | macOS and Linux | Supported |
165
- | WSL | Experimental |
166
- | Native Windows | Not yet supported |
167
- | Hosted database URLs | Intentionally rejected |
168
- | Optional read-only PostgreSQL source preparation | Explicit opt-in beta |
169
- | MySQL, MongoDB, and other database families | Not yet supported |
173
+ | Environment | Support |
174
+ | ------------------------------------------------ | ---------------------------- |
175
+ | Supabase CLI projects | Supported |
176
+ | Ordinary PostgreSQL in local Docker | Supported |
177
+ | macOS and Linux | Supported |
178
+ | Windows via WSL 2 on its Linux filesystem | Compatibility preview |
179
+ | Native Windows runtime | Not yet supported; use WSL 2 |
180
+ | Hosted database URLs | Intentionally rejected |
181
+ | Optional read-only PostgreSQL source preparation | Explicit opt-in beta |
182
+ | MySQL, MongoDB, and other database families | Not yet supported |
170
183
 
171
184
  See [COMPATIBILITY.md](COMPATIBILITY.md) for the exact support contract.
185
+ Native Windows metadata commands are not database-runtime support. For Windows, follow
186
+ the [WSL 2 setup path](docs/getting-started.md#windows-use-a-wsl-2-linux-workspace):
187
+ Linux Node, project files and Docker must live in the Linux execution environment.
188
+ Core 1.0.1 and editor 0.1.21 add explicit platform guidance/refusal; older immutable
189
+ releases retain their original behavior. Mobile, browser-only and unlisted systems are
190
+ not implied by desktop or Linux compatibility.
172
191
 
173
192
  ## Documentation
174
193
 
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rehearsal-db/core",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "private": false,
5
5
  "description": "Catch PostgreSQL and Supabase migrations that pass on empty databases but fail on real data—before deploy.",
6
6
  "repository": {
@@ -78,7 +78,7 @@
78
78
  "test:fixture:resources": "npm run build && node scripts/verification/run_scenario.mjs resources",
79
79
  "release:verify": "npm run build && node scripts/verification/release_gate.mjs",
80
80
  "check": "npm run check:syntax && npm run typecheck && npm run test && npm run docs:build && npm run format:check && npm run package:audit",
81
- "check:syntax": "find scripts tests -type f -name '*.mjs' -exec node --check {} +",
81
+ "check:syntax": "node scripts/verification/check_syntax.mjs",
82
82
  "typecheck": "npm run build && tsc --project tsconfig.json",
83
83
  "format": "prettier --write .",
84
84
  "format:check": "prettier --check .",
@@ -2,10 +2,17 @@
2
2
  /** Create safe project-root Rehearsal scaffolding during a local install. */
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { createInstalledRehearsalScaffold, renderInstalledRehearsalScaffold, } from "../../src/project/install_scaffold.mjs";
5
+ import { inspectHostPlatform } from "../../src/shared/host_platform.mjs";
5
6
  const packageRoot = fileURLToPath(new URL("../../..", import.meta.url));
6
7
  try {
7
- const result = await createInstalledRehearsalScaffold({ packageRoot });
8
- console.log(renderInstalledRehearsalScaffold(result));
8
+ const host = await inspectHostPlatform();
9
+ if (!host.supported) {
10
+ console.log(`Rehearsal installed without creating project files. ${host.remediation}`);
11
+ }
12
+ else {
13
+ const result = await createInstalledRehearsalScaffold({ packageRoot });
14
+ console.log(renderInstalledRehearsalScaffold(result));
15
+ }
9
16
  }
10
17
  catch (error) {
11
18
  const message = error instanceof Error ? error.message : String(error);
@@ -22,6 +22,7 @@ import { buildRefreshWorkflowPlan, createRefreshWorkflow, } from "./source_comma
22
22
  import { installGuidedExitShortcut, useStyledPrompts } from "./terminal.mjs";
23
23
  import { runWithOperationCancellation, supportsOperationCancellation, } from "../shared/cancellation.mjs";
24
24
  import { withOperationProgress } from "../shared/operation_progress.mjs";
25
+ import { assertSupportedHostPlatform } from "../shared/host_platform.mjs";
25
26
  const packageRoot = fileURLToPath(new URL("../../..", import.meta.url));
26
27
  const projectRoot = process.cwd();
27
28
  const managerPath = join(packageRoot, "dist/scripts/runtime/manage_database.mjs");
@@ -94,8 +95,17 @@ const main = async () => {
94
95
  !flags.json &&
95
96
  process.stdin.isTTY &&
96
97
  process.stdout.isTTY;
97
- const guided = command === "guide" || wantsAutomaticGuide;
98
- const mutating = commandMutatesProject({ command, flags, guided });
98
+ const guided = !flags.help &&
99
+ !flags.version &&
100
+ (command === "guide" || wantsAutomaticGuide);
101
+ if (!flags.help &&
102
+ !flags.version &&
103
+ (guided || !["help", "version", "discover", "doctor"].includes(command))) {
104
+ await assertSupportedHostPlatform({ projectRoot });
105
+ }
106
+ const mutating = !flags.help &&
107
+ !flags.version &&
108
+ commandMutatesProject({ command, flags, guided });
99
109
  const operation = mutating
100
110
  ? await acquireProjectOperation({
101
111
  projectRoot,
@@ -14,6 +14,7 @@ import { RehearsalError, normalizeRehearsalError, redactDiagnosticValue, } from
14
14
  import { assertInstalledPackageFingerprint } from "../shared/operation_guard.mjs";
15
15
  import { getOperationCancellationSignal, throwIfOperationCancelled, } from "../shared/cancellation.mjs";
16
16
  import { runOwnedProcess } from "../shared/owned_process.mjs";
17
+ import { createCleanProcessEnvironment } from "../shared/process_environment.mjs";
17
18
  import { getOwnedOperationProgressId, trackOperationStage, } from "../shared/operation_progress.mjs";
18
19
  import { buildRuntimeManagerArguments } from "../targets/target.mjs";
19
20
  import { parseRuntimeStatusSnapshot, renderRuntimeStatusSnapshot, } from "../runtime/status.mjs";
@@ -55,23 +56,7 @@ const parseCommand = (source) => {
55
56
  throw new Error("Application proof command is empty.");
56
57
  return values;
57
58
  };
58
- const projectCommandEnvironment = (additional = {}) => ({
59
- ...Object.fromEntries([
60
- "CI",
61
- "COLORTERM",
62
- "FORCE_COLOR",
63
- "HOME",
64
- "LANG",
65
- "LC_ALL",
66
- "NO_COLOR",
67
- "PATH",
68
- "SHELL",
69
- "TERM",
70
- "TMPDIR",
71
- "USER",
72
- ].flatMap((key) => process.env[key] === undefined ? [] : [[key, process.env[key]]])),
73
- ...additional,
74
- });
59
+ const projectCommandEnvironment = (additional = {}) => createCleanProcessEnvironment({ overrides: additional });
75
60
  const RUNTIME_STARTUP_FAILURE_PATTERN = /container\b.*\b(?:is not ready|starting|unhealthy)|health(?:check)?\b.*\b(?:failed|starting|unhealthy)|out of memory|\boom\b|no space left|resource temporarily unavailable/iu;
76
61
  export const classifyManagerFailure = ({ action, output, inferredCategory, }) => {
77
62
  if (RUNTIME_STARTUP_FAILURE_PATTERN.test(output) ||
@@ -1,6 +1,7 @@
1
1
  import { buildRehearsalPlan, runRehearsalDoctor } from "../runtime/plan.mjs";
2
2
  import { inspectRuntimeTopologyCandidates, loadRuntimeTopology, } from "../runtime/topology.mjs";
3
3
  import { redactDiagnosticValue } from "../shared/diagnostics.mjs";
4
+ import { inspectHostPlatform } from "../shared/host_platform.mjs";
4
5
  const errorMessage = (error) => error instanceof Error ? error.message : String(error);
5
6
  export const buildRuntimeStackPlan = async (planOptions) => {
6
7
  const topology = await loadRuntimeTopology(planOptions);
@@ -52,6 +53,11 @@ export const buildRuntimeStackPlan = async (planOptions) => {
52
53
  };
53
54
  };
54
55
  export const runRuntimeStackDoctor = async (planOptions) => {
56
+ const host = await inspectHostPlatform({
57
+ projectRoot: planOptions.projectRoot ?? process.cwd(),
58
+ });
59
+ if (!host.supported)
60
+ return runRehearsalDoctor(planOptions);
55
61
  let topology;
56
62
  try {
57
63
  topology = await loadRuntimeTopology(planOptions);
@@ -6,6 +6,7 @@ import { access, readFile, readdir, stat } from "node:fs/promises";
6
6
  import { isAbsolute, join, relative, resolve, sep } from "node:path";
7
7
  import { applyRehearsalSetup, planRehearsalSetup } from "./setup.mjs";
8
8
  import { findRehearsalConfigPath, inspectDetectedProject, loadRehearsalConfig, } from "./configuration.mjs";
9
+ import { inspectHostPlatform } from "../shared/host_platform.mjs";
9
10
  const PACKAGE_NAME = "@rehearsal-db/core";
10
11
  const DEPENDENCY_GROUPS = Object.freeze([
11
12
  "dependencies",
@@ -224,6 +225,12 @@ export const createInstalledRehearsalScaffold = async ({ packageRoot, environmen
224
225
  });
225
226
  if (resolution.status !== "resolved")
226
227
  return resolution;
228
+ const host = await inspectHostPlatform({
229
+ projectRoot: resolution.projectRoot,
230
+ });
231
+ if (!host.supported) {
232
+ return skip(`${host.detail} ${host.remediation}`.replace(/\.$/u, ""));
233
+ }
227
234
  const detected = await inspectDetectedProject({
228
235
  projectRoot: resolution.projectRoot,
229
236
  });
@@ -7,6 +7,7 @@ import { lstat, readFile, readdir } from "node:fs/promises";
7
7
  import { basename, join, relative, resolve, sep } from "node:path";
8
8
  import { promisify } from "node:util";
9
9
  import { CONFIG_FILENAMES } from "./configuration_discovery.mjs";
10
+ import { createCleanProcessEnvironment } from "../shared/process_environment.mjs";
10
11
  const MAX_METADATA_BYTES = 1024 * 1024;
11
12
  const execFileAsync = promisify(execFile);
12
13
  const inside = (root, path) => {
@@ -112,17 +113,14 @@ export const probeContainerEngineWithoutStarting = async () => {
112
113
  await execFileAsync("docker", ["info", "--format", "{{.ServerVersion}}"], {
113
114
  timeout: 2_000,
114
115
  maxBuffer: 64 * 1024,
115
- env: Object.fromEntries([
116
- "COLIMA_HOME",
117
- "DOCKER_CONFIG",
118
- "DOCKER_CONTEXT",
119
- "DOCKER_HOST",
120
- "HOME",
121
- "PATH",
122
- "USER",
123
- ]
124
- .map((key) => [key, process.env[key]])
125
- .filter((entry) => Boolean(entry[1]))),
116
+ env: createCleanProcessEnvironment({
117
+ passthroughKeys: [
118
+ "COLIMA_HOME",
119
+ "DOCKER_CONFIG",
120
+ "DOCKER_CONTEXT",
121
+ "DOCKER_HOST",
122
+ ],
123
+ }),
126
124
  });
127
125
  return "running";
128
126
  }
@@ -21,6 +21,8 @@ import { readRehearsalServiceEnvironment } from "./service_environment.mjs";
21
21
  import { readBoundRuntimeSanitizationPolicy, validateRuntimeSanitizationPolicy, } from "../baseline/sanitization_policy.mjs";
22
22
  import { buildAuthenticationReview, buildBaselineScopeReview, } from "./project_review.mjs";
23
23
  import { readVerifiedBaselineShapeEvidence } from "../source/shape_files.mjs";
24
+ import { inspectHostPlatform } from "../shared/host_platform.mjs";
25
+ import { createCleanProcessEnvironment } from "../shared/process_environment.mjs";
24
26
  const errorMessage = (error) => error instanceof Error ? error.message : String(error);
25
27
  const hasErrorCode = (error, code) => typeof error === "object" &&
26
28
  error !== null &&
@@ -29,7 +31,7 @@ const hasErrorCode = (error, code) => typeof error === "object" &&
29
31
  const commandAvailable = (command, args = ["--version"]) => {
30
32
  const result = spawnSync(command, args, {
31
33
  encoding: "utf8",
32
- env: Object.fromEntries(["HOME", "LANG", "LC_ALL", "PATH", "SHELL", "TMPDIR"].flatMap((key) => process.env[key] === undefined ? [] : [[key, process.env[key]]])),
34
+ env: createCleanProcessEnvironment(),
33
35
  stdio: ["ignore", "pipe", "pipe"],
34
36
  });
35
37
  return {
@@ -378,6 +380,23 @@ export const inspectRehearsalMigrations = async (options = {}) => {
378
380
  };
379
381
  };
380
382
  export const runRehearsalDoctor = async (options = {}) => {
383
+ const host = await inspectHostPlatform({
384
+ projectRoot: options.projectRoot ?? process.cwd(),
385
+ });
386
+ if (!host.supported) {
387
+ return {
388
+ state: "NOT READY",
389
+ checks: [
390
+ {
391
+ id: "operating-system",
392
+ label: "Operating-system support",
393
+ status: "fail",
394
+ detail: host.detail,
395
+ remediation: host.remediation,
396
+ },
397
+ ],
398
+ };
399
+ }
381
400
  let loaded;
382
401
  try {
383
402
  loaded = await loadRehearsalConfig(options);
@@ -426,12 +445,9 @@ export const runRehearsalDoctor = async (options = {}) => {
426
445
  id: "operating-system",
427
446
  label: "Operating-system support",
428
447
  run: async () => {
429
- if (!["darwin", "linux"].includes(process.platform)) {
430
- throw new Error(`${process.platform} is not supported by the version-1 contract.`);
431
- }
432
- return `${process.platform} is in the supported matrix`;
448
+ return host.detail;
433
449
  },
434
- remediation: "Use macOS or Linux; WSL and native Windows require separate proof before support.",
450
+ remediation: host.remediation,
435
451
  },
436
452
  {
437
453
  id: "package-manager",
@@ -594,9 +610,7 @@ export const runRehearsalDoctor = async (options = {}) => {
594
610
  ], {
595
611
  cwd: projectRoot,
596
612
  encoding: "utf8",
597
- env: Object.fromEntries(["HOME", "LANG", "LC_ALL", "PATH", "SHELL", "TMPDIR"].flatMap((key) => process.env[key] === undefined
598
- ? []
599
- : [[key, process.env[key]]])),
613
+ env: createCleanProcessEnvironment(),
600
614
  stdio: ["ignore", "pipe", "pipe"],
601
615
  });
602
616
  if (status.status !== 0 ||
@@ -614,12 +628,9 @@ export const runRehearsalDoctor = async (options = {}) => {
614
628
  const status = spawnSync("supabase", ["status", "-o", "env", "--workdir", paths.runtimeWorkdir], {
615
629
  cwd: projectRoot,
616
630
  encoding: "utf8",
617
- env: {
618
- ...Object.fromEntries(["HOME", "LANG", "LC_ALL", "PATH", "SHELL", "TMPDIR"].flatMap((key) => process.env[key] === undefined
619
- ? []
620
- : [[key, process.env[key]]])),
621
- ...serviceEnvironment,
622
- },
631
+ env: createCleanProcessEnvironment({
632
+ overrides: serviceEnvironment,
633
+ }),
623
634
  stdio: ["ignore", "pipe", "pipe"],
624
635
  });
625
636
  if (status.status !== 0 ||
@@ -0,0 +1,16 @@
1
+ export declare const NATIVE_WINDOWS_REMEDIATION = "Use WSL2, not a native Windows terminal: run wsl --install -d Ubuntu in PowerShell and confirm version 2 with wsl --list --verbose (upgrade with wsl --set-version Ubuntu 2 if needed). Enable Docker Desktop Settings > Resources > WSL integration for that distribution. Keep the project in its Linux home filesystem (for example ~/projects, not /mnt/c), install a supported Linux Node.js version and project tools there, open it with VS Code Remote - WSL, then rerun rehearsal doctor inside WSL2.";
2
+ export interface HostPlatformInspection {
3
+ readonly kind: "macos" | "linux" | "wsl2" | "wsl-unverified" | "windows" | "other";
4
+ readonly supported: boolean;
5
+ readonly detail: string;
6
+ readonly remediation: string;
7
+ }
8
+ export interface HostPlatformOptions {
9
+ readonly projectRoot?: string;
10
+ readonly platform?: NodeJS.Platform;
11
+ readonly kernelRelease?: string;
12
+ readonly readKernelRelease?: () => Promise<string>;
13
+ readonly inspectFilesystem?: (path: string) => Promise<number>;
14
+ }
15
+ export declare const inspectHostPlatform: ({ projectRoot, platform, kernelRelease, readKernelRelease, inspectFilesystem, }?: HostPlatformOptions) => Promise<HostPlatformInspection>;
16
+ export declare const assertSupportedHostPlatform: (options?: HostPlatformOptions) => Promise<void>;
@@ -0,0 +1,109 @@
1
+ /** Read-only host capability checks; never substitute environment hints for proof. */
2
+ import { open, statfs } from "node:fs/promises";
3
+ import { release } from "node:os";
4
+ import { RehearsalError } from "./diagnostics.mjs";
5
+ export const NATIVE_WINDOWS_REMEDIATION = "Use WSL2, not a native Windows terminal: run wsl --install -d Ubuntu in PowerShell and confirm version 2 with wsl --list --verbose (upgrade with wsl --set-version Ubuntu 2 if needed). Enable Docker Desktop Settings > Resources > WSL integration for that distribution. Keep the project in its Linux home filesystem (for example ~/projects, not /mnt/c), install a supported Linux Node.js version and project tools there, open it with VS Code Remote - WSL, then rerun rehearsal doctor inside WSL2.";
6
+ const readProcKernelRelease = async () => {
7
+ const file = await open("/proc/sys/kernel/osrelease", "r");
8
+ try {
9
+ const buffer = Buffer.alloc(512);
10
+ const { bytesRead } = await file.read(buffer, 0, buffer.length, 0);
11
+ return buffer.subarray(0, bytesRead).toString("utf8");
12
+ }
13
+ finally {
14
+ await file.close();
15
+ }
16
+ };
17
+ // WSL's Windows drive mounts do not provide the private modes and atomic symlink
18
+ // contract used by baselines. Accept proven Linux filesystem types, not paths.
19
+ const WSL_POSIX_FILESYSTEM_TYPES = new Set([
20
+ 0xef53, // ext2/ext3/ext4 (WSL2 distribution filesystem)
21
+ 0x58465342, // XFS
22
+ 0x9123683e, // Btrfs
23
+ ]);
24
+ export const inspectHostPlatform = async ({ projectRoot = process.cwd(), platform = process.platform, kernelRelease = release(), readKernelRelease = readProcKernelRelease, inspectFilesystem = async (path) => (await statfs(path)).type, } = {}) => {
25
+ if (platform === "darwin") {
26
+ return {
27
+ kind: "macos",
28
+ supported: true,
29
+ detail: "macOS is in the supported host matrix; project readiness checks still apply.",
30
+ remediation: "Resolve the remaining project readiness checks on macOS.",
31
+ };
32
+ }
33
+ if (platform === "win32") {
34
+ return {
35
+ kind: "windows",
36
+ supported: false,
37
+ detail: "Native Windows runtime and preparation operations are unsupported: POSIX private-file, process-group, and atomic baseline-pointer guarantees have not been established.",
38
+ remediation: NATIVE_WINDOWS_REMEDIATION,
39
+ };
40
+ }
41
+ if (platform !== "linux") {
42
+ return {
43
+ kind: "other",
44
+ supported: false,
45
+ detail: "This operating system is outside the verified macOS/Linux runtime contract.",
46
+ remediation: "Use a supported macOS or Linux environment. Windows users should use WSL2 with the project on its Linux home filesystem and Docker Desktop WSL integration.",
47
+ };
48
+ }
49
+ let procRelease = "";
50
+ try {
51
+ procRelease = (await readKernelRelease()).slice(0, 512);
52
+ }
53
+ catch {
54
+ // os.release() is independent kernel evidence when procfs is unavailable.
55
+ }
56
+ const evidence = `${kernelRelease.slice(0, 512)}\n${procRelease}`;
57
+ if (!/microsoft|\bwsl2?\b/iu.test(evidence)) {
58
+ return {
59
+ kind: "linux",
60
+ supported: true,
61
+ detail: "Linux is in the supported host matrix; project readiness checks still apply.",
62
+ remediation: "Resolve the remaining project readiness checks on Linux.",
63
+ };
64
+ }
65
+ if (!/microsoft-standard|\bwsl2\b/iu.test(evidence)) {
66
+ return {
67
+ kind: "wsl-unverified",
68
+ supported: false,
69
+ detail: "A WSL kernel was detected, but WSL2 kernel capabilities were not proven. WSL1 is unsupported.",
70
+ remediation: NATIVE_WINDOWS_REMEDIATION,
71
+ };
72
+ }
73
+ let filesystemType = null;
74
+ try {
75
+ filesystemType = await inspectFilesystem(projectRoot);
76
+ }
77
+ catch {
78
+ // Unknown filesystem evidence must not be interpreted as POSIX capability.
79
+ }
80
+ if (filesystemType === null ||
81
+ !WSL_POSIX_FILESYSTEM_TYPES.has(filesystemType)) {
82
+ return {
83
+ kind: "wsl2",
84
+ supported: false,
85
+ detail: "WSL2 was detected, but this project is not on a proven Linux filesystem. Windows drive mounts and unknown filesystem types are unsupported for private baseline data.",
86
+ remediation: NATIVE_WINDOWS_REMEDIATION,
87
+ };
88
+ }
89
+ return {
90
+ kind: "wsl2",
91
+ supported: true,
92
+ detail: "WSL2 kernel and a Linux project filesystem were detected. Run in VS Code Remote - WSL with Linux tools and Docker Desktop WSL integration; the remaining readiness and private-file checks still apply.",
93
+ remediation: NATIVE_WINDOWS_REMEDIATION,
94
+ };
95
+ };
96
+ export const assertSupportedHostPlatform = async (options = {}) => {
97
+ const inspection = await inspectHostPlatform(options);
98
+ if (inspection.supported)
99
+ return;
100
+ throw new RehearsalError({
101
+ category: "unsafe_environment",
102
+ code: "HOST_PLATFORM_UNSUPPORTED",
103
+ message: inspection.detail,
104
+ expected: "A supported macOS/Linux runtime with its existing safety guarantees.",
105
+ actual: inspection.kind,
106
+ refused: "No project configuration, child process, or runtime operation was started.",
107
+ suggestions: [inspection.remediation],
108
+ });
109
+ };
@@ -8,8 +8,9 @@ export interface CleanProcessEnvironmentOptions {
8
8
  inheritedEnvironment?: ProcessEnvironment;
9
9
  overrides?: ProcessEnvironment;
10
10
  passthroughKeys?: readonly string[];
11
+ platform?: NodeJS.Platform;
11
12
  }
12
13
  export declare const isLoopbackUrl: (value: string) => boolean;
13
14
  export declare const assertLoopbackUrl: (label: string, value: string) => void;
14
15
  export declare const pickEnvironmentVariables: (source: ProcessEnvironment, keys: readonly string[]) => Record<string, string>;
15
- export declare const createCleanProcessEnvironment: ({ inheritedEnvironment, overrides, passthroughKeys, }?: CleanProcessEnvironmentOptions) => Record<string, string>;
16
+ export declare const createCleanProcessEnvironment: ({ inheritedEnvironment, overrides, passthroughKeys, platform, }?: CleanProcessEnvironmentOptions) => Record<string, string>;
@@ -21,6 +21,17 @@ const SAFE_SYSTEM_ENVIRONMENT_KEYS = Object.freeze([
21
21
  "TEMP",
22
22
  "USER",
23
23
  ]);
24
+ // Windows resolves environment names case-insensitively. Keep only infrastructure
25
+ // needed to locate executables and user configuration, never ambient credentials.
26
+ const SAFE_WINDOWS_ENVIRONMENT_KEYS = Object.freeze([
27
+ "SystemRoot",
28
+ "WINDIR",
29
+ "ComSpec",
30
+ "PATHEXT",
31
+ "USERPROFILE",
32
+ "APPDATA",
33
+ "LOCALAPPDATA",
34
+ ]);
24
35
  const LOOPBACK_HOSTNAMES = new Set(["127.0.0.1", "::1", "[::1]", "localhost"]);
25
36
  export const isLoopbackUrl = (value) => {
26
37
  try {
@@ -41,10 +52,41 @@ export const pickEnvironmentVariables = (source, keys) => Object.fromEntries(key
41
52
  const value = source[key];
42
53
  return value === undefined ? [] : [[key, value]];
43
54
  }));
44
- export const createCleanProcessEnvironment = ({ inheritedEnvironment = process.env, overrides = {}, passthroughKeys = [], } = {}) => ({
45
- ...pickEnvironmentVariables(inheritedEnvironment, [
55
+ const pickWindowsEnvironmentVariables = (source, keys) => {
56
+ const selected = {};
57
+ const seen = new Set();
58
+ for (const key of keys) {
59
+ const normalized = key.toUpperCase();
60
+ if (seen.has(normalized))
61
+ continue;
62
+ seen.add(normalized);
63
+ const sourceKey = source[key] !== undefined
64
+ ? key
65
+ : Object.keys(source).find((candidate) => candidate.toUpperCase() === normalized &&
66
+ source[candidate] !== undefined);
67
+ if (sourceKey !== undefined)
68
+ selected[key] = source[sourceKey];
69
+ }
70
+ return selected;
71
+ };
72
+ export const createCleanProcessEnvironment = ({ inheritedEnvironment = process.env, overrides = {}, passthroughKeys = [], platform = process.platform, } = {}) => {
73
+ const keys = [
46
74
  ...SAFE_SYSTEM_ENVIRONMENT_KEYS,
75
+ ...(platform === "win32" ? SAFE_WINDOWS_ENVIRONMENT_KEYS : []),
47
76
  ...passthroughKeys,
48
- ]),
49
- ...pickEnvironmentVariables(overrides, Object.keys(overrides)),
50
- });
77
+ ];
78
+ if (platform !== "win32") {
79
+ return {
80
+ ...pickEnvironmentVariables(inheritedEnvironment, keys),
81
+ ...pickEnvironmentVariables(overrides, Object.keys(overrides)),
82
+ };
83
+ }
84
+ const environment = pickWindowsEnvironmentVariables(inheritedEnvironment, keys);
85
+ for (const [key, value] of Object.entries(overrides)) {
86
+ if (value === undefined)
87
+ continue;
88
+ const existing = Object.keys(environment).find((candidate) => candidate.toUpperCase() === key.toUpperCase());
89
+ environment[existing ?? key] = value;
90
+ }
91
+ return environment;
92
+ };
@@ -5,6 +5,54 @@ your computer. Normal setup and rehearsal commands never connect to a hosted dat
5
5
 
6
6
  Want to experiment first? Use the [safe hands-on tutorial](tutorial.md).
7
7
 
8
+ ## OS-specific setup files (optional)
9
+
10
+ Separate setup folders are available for
11
+ [Windows / WSL 2](https://github.com/Ddupasquier/rehearsal-db/tree/main/installers/windows),
12
+ [macOS](https://github.com/Ddupasquier/rehearsal-db/tree/main/installers/macos) and
13
+ [Linux](https://github.com/Ddupasquier/rehearsal-db/tree/main/installers/linux).
14
+ They are readable helpers, not native executables or bundled Node/Docker installers.
15
+ Existing Node.js 24 or 26 is required. The default only checks an existing project;
16
+ installation needs an explicit option and does not start a database. Review the
17
+ [shared behavior and release availability](https://github.com/Ddupasquier/rehearsal-db/blob/main/installers/README.md)
18
+ before choosing an install option. An exact core 1.0.1 install requires that version to
19
+ be published; a checked-in helper is not proof of publication.
20
+
21
+ ### Windows: use a WSL 2 Linux workspace
22
+
23
+ The Windows compatibility route is Linux execution inside **WSL 2**, not a native
24
+ PowerShell/Command Prompt database runtime. Core 1.0.1 and extension 0.1.21 make that
25
+ boundary explicit; native Windows version/help/discovery do not authorize runtime work.
26
+
27
+ 1. Follow Microsoft's [WSL installation guide](https://learn.microsoft.com/en-us/windows/wsl/install)
28
+ to prepare a WSL 2 Linux distribution, such as Ubuntu 24.04. Do not use WSL 1.
29
+ 2. Clone or open the project inside the distribution's Linux home directory, such as
30
+ `/home/your-name/projects/app`. Do not keep the runtime project under `/mnt/c`, a
31
+ Windows share or a Windows-mounted drive. Rehearsal does not relocate your files.
32
+ 3. Install a supported **Linux** Node/npm and a Docker-compatible Linux engine in that
33
+ environment. Docker Engine in WSL or an already configured Docker Desktop WSL
34
+ integration are user-controlled setup choices; Rehearsal does not install or license
35
+ Docker Desktop for you. In the Linux terminal, check:
36
+
37
+ ```bash
38
+ node -p "process.platform"
39
+ pwd
40
+ docker info --format '{{.OSType}}'
41
+ ```
42
+
43
+ Both platform results must be `linux`, and `pwd` must be in the Linux filesystem.
44
+
45
+ 4. For editor use, install Microsoft's **WSL** extension, then run `code .` from that
46
+ Linux project directory. Confirm the VS Code window says **WSL** in its remote
47
+ indicator, and install Rehearsal into **WSL**, not only the Windows-side extension host.
48
+ 5. Continue below from that Linux terminal. Keep the existing baseline, approval and
49
+ local-only checks; do not substitute a hosted database to make setup pass.
50
+
51
+ WSL is a compatibility preview. A real WSL PostgreSQL fixture and a native Remote-WSL
52
+ editor walkthrough are different evidence; do not infer the latter from Linux unit
53
+ tests. Supabase/Auth/Storage in WSL and other remote hosts remain unclaimed until their
54
+ own checks pass. See the [complete platform boundary](https://github.com/Ddupasquier/rehearsal-db/blob/main/COMPATIBILITY.md#operating-systems-and-execution-location).
55
+
8
56
  ## 1. Check the required tools
9
57
 
10
58
  You need Node.js 22, 24, or 26, npm, and a running Docker-compatible engine. Node.js 24
package/docs/index.md CHANGED
@@ -12,6 +12,11 @@ Rehearsal catches those problems before deployment. It restores a reviewed, sani
12
12
  baseline into a disposable local PostgreSQL or Supabase environment, applies only the
13
13
  exact migrations you approve, and runs your application's own proof.
14
14
 
15
+ The [CLI is free and MIT-licensed](https://www.npmjs.com/package/@rehearsal-db/core).
16
+ Prefer clicks to commands? [Install the free VS Code Starter preview](vscode.md).
17
+ All features included in its Starter-licensed releases are free indefinitely, with no
18
+ account, payment card, or trial period.
19
+
15
20
  | Empty-database tests miss… | Rehearsal exercises… |
16
21
  | ------------------------------------------------- | --------------------------------------------------------- |
17
22
  | old rows and edge cases | a reviewed, production-shaped baseline |
@@ -23,15 +28,16 @@ exact migrations you approve, and runs your application's own proof.
23
28
  You do not need to read everything before your first rehearsal. Start with the outcome
24
29
  you want, then follow the links when a term or safety check is new.
25
30
 
26
- | I want to… | Go here |
27
- | --------------------------------------- | ----------------------------------------------------------------- |
28
- | Set up my own project | [Getting started](getting-started.md) |
29
- | Try Rehearsal without touching my app | [Hands-on tutorial](tutorial.md) |
30
- | Understand what makes a copy safe | [Baselines](baselines.md) and [Sanitization](sanitization.md) |
31
- | Look up a command or setting | [CLI commands](commands.md) and [Configuration](configuration.md) |
32
- | Reduce Docker and Supabase resource use | [Container runtime lifecycle](runtime-lifecycle.md) |
33
- | Add editor and compiler type checks | [TypeScript](typescript.md) |
34
- | Fix something that did not work | [Troubleshooting](troubleshooting.md) |
31
+ | I want to… | Go here |
32
+ | ---------------------------------------- | ----------------------------------------------------------------- |
33
+ | Set up my own project | [Getting started](getting-started.md) |
34
+ | Use the free visual workbench in VS Code | [Install VS Code Starter](vscode.md) |
35
+ | Try Rehearsal without touching my app | [Hands-on tutorial](tutorial.md) |
36
+ | Understand what makes a copy safe | [Baselines](baselines.md) and [Sanitization](sanitization.md) |
37
+ | Look up a command or setting | [CLI commands](commands.md) and [Configuration](configuration.md) |
38
+ | Reduce Docker and Supabase resource use | [Container runtime lifecycle](runtime-lifecycle.md) |
39
+ | Add editor and compiler type checks | [TypeScript](typescript.md) |
40
+ | Fix something that did not work | [Troubleshooting](troubleshooting.md) |
35
41
 
36
42
  ## The short version
37
43
 
package/docs/releasing.md CHANGED
@@ -95,23 +95,27 @@ than seven days or in the future. Public fields and timestamps must still match
95
95
  bypass metadata is hidden; an explicitly malformed or nonempty bypass list always
96
96
  refuses publication.
97
97
 
98
- The prepare job prints an exact approval comment in its summary. Independently check
99
- the live no-bypass settings and accepted artifact checksum, then paste the comment into
100
- **Review deployments → npm** and approve manually. Before publishing or repairing
101
- tags, the workflow reads GitHub's actual approval history and requires the configured
102
- owner's authenticated review for that npm environment. The comment binds the operation,
103
- run ID, run attempt, source commit, artifact SHA-256 and settings-record SHA-256.
104
- GitHub may store the form's line breaks as CRLF instead of LF. The checker treats
105
- those two encodings as equivalent; it does not trim whitespace or change any field.
106
- An approval copied from another artifact, run or attempt is refused. Rerun the whole
107
- workflow after failure so preparation prints a new attempt-bound comment; do not reuse
108
- an earlier comment when rerunning only the mutation job.
109
-
110
- The record alone is never authorization. This mechanism relies on the owner's fresh
111
- settings review and GitHub's reported timestamps; timestamps are not cryptographic
112
- proof of every hidden setting change. No settings check eliminates a subsequent
113
- administrator change or check-to-use race. Keep the npm environment's no-bypass human
114
- gate enforced. See [GitHub's ruleset metadata boundary](https://docs.github.com/en/rest/repos/rules#get-a-repository-ruleset)
98
+ The prepare job displays the exact package version, SHA-256, source commit and run
99
+ in its summary. Review the candidate and passed checks, then choose **Review
100
+ deployments → npm → Approve and deploy**. That ordinary GitHub approval is the
101
+ publication authorization: no separate chat approval, secret phrase or pasted block
102
+ is required. Comments are optional.
103
+
104
+ GitHub's enforced, no-bypass `npm` environment admits the publishing job only after
105
+ its protection rules pass. The workflow also reads this run's actual review history
106
+ to corroborate the configured human owner's approval for the exact npm environment.
107
+ That history does not identify an approval's run attempt or verify artifact bytes;
108
+ the workflow independently checks the prepared tarball's hashes before publication,
109
+ and freshly downloads/checks registry bytes before tag repair. Reruns keep the same
110
+ source/ref and remain subject to GitHub's environment controls; old review text is
111
+ never presented as proof of new bytes or a fresh attempt.
112
+
113
+ The unsigned settings record remains a bounded drift check, not authorization or
114
+ cryptographic proof of current hidden bypass settings. Refresh its owner observation
115
+ when stale or changed; never advance its timestamp without reading the settings.
116
+ No settings check eliminates a later administrator change or check-to-use race.
117
+ See [GitHub's deployment review](https://docs.github.com/en/actions/how-tos/deploy/configure-and-manage-deployments/review-deployments),
118
+ [ruleset metadata boundary](https://docs.github.com/en/rest/repos/rules#get-a-repository-ruleset)
115
119
  and [workflow approval history](https://docs.github.com/en/rest/actions/workflow-runs#get-the-review-history-for-a-workflow-run).
116
120
 
117
121
  Keep customer evidence, credentials, runtime data and the internal tracker out of public
@@ -137,11 +141,12 @@ release-source migration.
137
141
  5. Change `private` to `false` only in the reviewed release change.
138
142
  6. Record the exact tarball filename, SHA-1, SHA-256, allowlisted files, unpacked size,
139
143
  executable, declared runtime dependency inventory, and dependency audit result.
140
- 7. Obtain explicit publication authorization for that exact version and artifact.
141
- 8. Merge the approved release commit through protected `main` and create the exact
144
+ 7. Review the release change and its exact artifact evidence.
145
+ 8. Merge the reviewed release commit through protected `main` and create the exact
142
146
  `v<package-version>` tag and GitHub release.
143
- 9. Review and approve the protected `npm` deployment only after its prepare job matches
144
- the approved version and checksum, using its exact approval comment.
147
+ 9. Authorize publication once, in the protected `npm` deployment review, after its
148
+ prepare job matches the tested version and checksum. No comment or chat approval
149
+ is required.
145
150
  10. Verify public visibility, ownership, provenance, registry SHA-1, README rendering,
146
151
  exact-version clean installation, CLI execution, signatures, and the unrelated
147
152
  installed Docker fixture. Allow up to six minutes for a first package to propagate
@@ -199,6 +204,5 @@ package or select a different version. The `npm` environment must supply the ver
199
204
  human approval gate; a workflow reference to that environment is not sufficient.
200
205
 
201
206
  Creating the repository, passing CI, extracting the engine, merging a release branch,
202
- or creating a tag does not authorize npm publication. Publication requires explicit
203
- authorization for the exact packed artifact, and the protected GitHub environment
204
- supplies the final human gate.
207
+ or creating a tag does not authorize npm publication. The protected GitHub deployment
208
+ review supplies the single human authorization for the exact displayed artifact.
package/docs/roadmap.md CHANGED
@@ -1,8 +1,13 @@
1
1
  # Next steps
2
2
 
3
- Rehearsal supports guided Supabase and ordinary PostgreSQL migration rehearsals. The
4
- current development track removes the need for consumer-owned Rehearsal engines while
5
- keeping application meaning and privacy decisions project-owned.
3
+ Rehearsal core **1.0.0 is available on
4
+ [npm](https://www.npmjs.com/package/@rehearsal-db/core)** for guided Supabase and
5
+ ordinary PostgreSQL migration rehearsals. The [free VS Code Starter preview](vscode.md)
6
+ adds a visual workbench. Neither requires a purchase or account.
7
+
8
+ The standalone workflow keeps the rehearsal engine in the package while application
9
+ meaning and privacy decisions remain project-owned. The sequence below explains its
10
+ dependencies, not a list of features withheld from the published release.
6
11
 
7
12
  ## Standalone workflow
8
13
 
package/docs/stability.md CHANGED
@@ -1,7 +1,10 @@
1
1
  # Stability and the first stable release
2
2
 
3
- Rehearsal leaves beta when the workflow it already promises is dependable. Stable
4
- `1.0.0` does not require every planned database, desktop interface, or paid feature.
3
+ Rehearsal core **1.0.0 is published** on
4
+ [npm](https://www.npmjs.com/package/@rehearsal-db/core). This page defines its
5
+ compatibility promise and the verification policy for releases; it is not an
6
+ unfinished launch checklist. Stable core does not require every planned database,
7
+ editor interface, or paid feature.
5
8
 
6
9
  ## What becomes a compatibility promise
7
10
 
@@ -63,8 +66,9 @@ ready. The sequence below is policy, not a claim that its checks have passed.
63
66
  do not relabel old or unavailable manual checks as new results. No minimum number
64
67
  of calendar days replaces these checks.
65
68
  6. Publish `1.0.0` only when no blocking issue remains and the exact tarball has passed
66
- the required release checks, consumer acceptance, exact-artifact authorization and
67
- protected human publication approval.
69
+ the required release checks and consumer acceptance. The protected GitHub npm
70
+ review is the single human authorization for its displayed exact version and
71
+ checksum; no separate chat approval or pasted phrase is required.
68
72
  7. Independently verify registry bytes, provenance, signatures and channels, then
69
73
  confirm the published package in the real consumer. Promotion is complete only
70
74
  when the published artifact matches the tested tarball and these checks pass.
package/docs/vscode.md CHANGED
@@ -4,6 +4,22 @@ The Rehearsal extension turns the local CLI into a project-aware database-change
4
4
  workbench. It is for developers who want the safety of exact migration plans and disposable
5
5
  local runtimes without memorizing every command.
6
6
 
7
+ This guide targets **Free Starter 0.1.21**, named **Rehearsal DB** on
8
+ [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=rehearsal-db.rehearsal-db),
9
+ with a [reviewed GitHub VSIX](https://github.com/Ddupasquier/rehearsal-vscode/releases/tag/v0.1.21)
10
+ for direct installation. The canonical extension ID is **`rehearsal-db.rehearsal-db`**,
11
+ published by **`rehearsal-db`**. The workbench and commands retain the **Rehearsal** brand.
12
+ All included features are free indefinitely for personal or commercial development.
13
+ No account, payment card, purchase, trial period, or license activation is required.
14
+ The CLI is separately available on [npm](https://www.npmjs.com/package/@rehearsal-db/core)
15
+ under the MIT license. There is no paid CLI tier.
16
+ Confirm the target version appears in its official channel before installing. A guide
17
+ or checked-in version does not mean that publication has completed.
18
+
19
+ Already using the GitHub preview through 0.1.18? Follow the
20
+ [one-time migration steps](#move-from-a-preview-through-0118) before installing the new
21
+ identity. This is not an automatic rename or uninstall.
22
+
7
23
  ## What you can do
8
24
 
9
25
  - See what Rehearsal detected, what it suggests, and what still needs your decision.
@@ -14,6 +30,11 @@ local runtimes without memorizing every command.
14
30
  - Export a privacy-safe verification report and review bounded local activity.
15
31
  - Keep the sidebar and open workbench current when another terminal changes the project's
16
32
  Rehearsal package, lockfile, manifest, or known configuration.
33
+ - Browse resource inventories in independent pages of 5, 10 or 25 cards, rather than
34
+ one unbounded list.
35
+ - Read a configuration diff before choosing **Apply changes** or **Cancel**, then
36
+ return to the project from the saved result.
37
+ - Choose independent, initially off automatic-update options for the extension and CLI.
17
38
 
18
39
  The extension does not become a second database engine. Rehearsal core still owns data
19
40
  boundaries, baselines, migration digests, runtime isolation, locks, rollback, and cleanup.
@@ -22,6 +43,11 @@ boundaries, baselines, migration digests, runtime isolation, locks, rollback, an
22
43
 
23
44
  Use desktop VS Code 1.101 or newer on macOS or Linux and a supported Node.js release
24
45
  (22, 24, or 26). You do not need the extension source repository or Test Lab.
46
+ For a Windows desktop, use the [WSL 2 Linux-workspace setup](getting-started.md#windows-use-a-wsl-2-linux-workspace).
47
+ With editor 0.1.21, native Windows inspection and foreground actions refuse before launching a child
48
+ process and directs you to Remote-WSL. Install the extension into the Linux extension
49
+ host and keep the project on its Linux filesystem. WSL compatibility remains a preview;
50
+ real WSL core fixtures do not certify a native Remote-WSL editor walkthrough.
25
51
 
26
52
  1. Open your application's folder in VS Code—the one containing `package.json` and
27
53
  your migrations. Install Rehearsal there if it is missing:
@@ -30,31 +56,154 @@ Use desktop VS Code 1.101 or newer on macOS or Linux and a supported Node.js rel
30
56
  npm install --save-dev @rehearsal-db/core
31
57
  ```
32
58
 
33
- 2. Open the [reviewed GitHub prereleases](https://github.com/Ddupasquier/rehearsal-vscode/releases).
34
- Download the chosen release's `.vsix` and `SHA256SUMS`. Compare the file's SHA-256
35
- with that release's checksum; do not substitute an unreviewed rebuild.
36
- 3. In VS Code, open **Extensions → … → Install from VSIX…** and choose that file.
37
- Reload the extension host if VS Code asks.
38
- 4. Review Workspace Trust, then open the Command Palette and choose
59
+ 2. Open **Extensions** and search **`@id:rehearsal-db.rehearsal-db`**, or open the
60
+ [official Rehearsal DB listing](https://marketplace.visualstudio.com/items?itemName=rehearsal-db.rehearsal-db).
61
+ Confirm publisher **`rehearsal-db`** and the full extension ID, then choose **Install**.
62
+ The similar-looking legacy ID `rehearsal-db.rehearsal` is not the canonical package.
63
+ If you prefer a direct download, use the verified GitHub VSIX instructions below.
64
+ 3. Review Workspace Trust, then open the Command Palette and choose
39
65
  **Rehearsal: Open Dashboard**. The Rehearsal sidebar also has a dashboard button.
40
- 5. Follow **Next best step**. Review the detected project and active configuration;
66
+ 4. Follow **Next best step**. Review the detected project and active configuration;
41
67
  setup, source access, migration execution and cleanup keep their own confirmations.
42
68
 
43
- The extension needs `@rehearsal-db/core@0.1.0-rc.4` or newer. A project that is not ready
44
- should show setup guidance, not require you to build the extension. Use
69
+ The release pairing described here is core **1.0.1** with Starter **0.1.21**.
70
+ Install it once both versions appear in their official release channels.
71
+ The extension's minimum core is `0.1.0-rc.4`. A project that is not ready should show
72
+ setup guidance, not require you to build the extension. Opening the dashboard does not
73
+ start a database or run a migration. Use
45
74
  [Getting started](getting-started.md) for the CLI and safe baseline inputs.
46
75
 
47
- ## Updates
48
-
49
- GitHub VSIX installations do not auto-update. Download and verify the next reviewed
50
- release, then use **Install from VSIX…** again. Keep the previous reviewed file for
51
- rollback. See the extension's [installation guide](https://github.com/Ddupasquier/rehearsal-vscode#install-and-open-your-project)
52
- for checksum commands and the optional command-line installer.
53
-
54
- Updating the project's core package is separate: its manifest, lockfile and installed
55
- metadata trigger a narrow read-only refresh automatically. You do not reload the VS Code
56
- window after an ordinary core-package update. Replacing the VSIX may require VS Code's
57
- one-time extension-host reload so the new extension code becomes active.
76
+ Native Windows inspection refusal is not database-runtime support. Browser-based
77
+ VS Code, Codespaces, SSH and Dev Containers have no end-to-end support claim.
78
+ Native Windows means the Windows Node/extension host, not a Windows desktop
79
+ connected to WSL. iOS/iPadOS, Android, BSD and unlisted systems are not
80
+ supported by this desktop/local-runtime release. Consult the
81
+ [platform matrix](https://github.com/Ddupasquier/rehearsal-db/blob/main/COMPATIBILITY.md#operating-systems-and-execution-location) for the
82
+ distinction between desktop OS, extension host, architecture and actual database proof.
83
+
84
+ ### Direct GitHub installation
85
+
86
+ The verified GitHub VSIX is an alternative to Marketplace. Open the
87
+ [Starter 0.1.21 release](https://github.com/Ddupasquier/rehearsal-vscode/releases/tag/v0.1.21).
88
+ Under **Assets**, download `rehearsal-db-0.1.21.vsix` and `SHA256SUMS`. In a terminal,
89
+ run `shasum -a 256 /path/to/rehearsal-db-0.1.21.vsix` on macOS or
90
+ `sha256sum /path/to/rehearsal-db-0.1.21.vsix` on Linux. Compare the result with that
91
+ release's `SHA256SUMS`; stop if they differ. Do not substitute a local rebuild.
92
+ Then open **Extensions → … → Install from VSIX…** and choose the verified file.
93
+ Save your work and reload only if VS Code asks.
94
+
95
+ ### Move from a preview through 0.1.18
96
+
97
+ Earlier GitHub previews use `rehearsal-db.rehearsal`, a separate VS Code identity.
98
+ Their released 0.1.18 bytes, tag and checksum remain available and unchanged. Its updater
99
+ looks for `rehearsal-<version>.vsix`, so it ignores the canonical
100
+ `rehearsal-db-<version>.vsix` family instead of silently switching identities.
101
+
102
+ 1. Finish Rehearsal commands in all open project windows. If a sandbox app is open,
103
+ press **Ctrl+C** once in its owning terminal and wait for its normal shell prompt
104
+ and configured lifecycle result. Save your work.
105
+ 2. Explicitly uninstall the legacy extension: in **Extensions**, search
106
+ **`@id:rehearsal-db.rehearsal`**, then use its gear menu → **Uninstall**.
107
+ 3. Save remaining files and run **Developer: Reload Window**. Ensure the old extension
108
+ is no longer installed in each profile where you will use the canonical version.
109
+ 4. Install **Rehearsal DB**, ID **`rehearsal-db.rehearsal-db`**, using Marketplace or the
110
+ verified canonical VSIX above. Reload if asked, reopen the dashboard and review your
111
+ update preferences.
112
+
113
+ The canonical extension refuses activation whenever VS Code still reports the legacy ID.
114
+ Not currently active is not proof that an installed extension is disabled; uninstalling
115
+ and reloading is the supported route. The extension does not automatically uninstall,
116
+ disable or rename your existing installation, interrupt a command or force a reload.
117
+
118
+ This identity change does not reset or modify databases, Storage, project configuration,
119
+ keys or baselines. Private per-extension view state, activity history and metadata-check
120
+ consent are not copied to the new identity; re-select views and review consent there.
121
+ Shared VS Code user settings, including `rehearsal.automaticUpdates`, retain your existing
122
+ values. Review or disable those flags before migration if desired. Do not run database
123
+ cleanup or **Reset Saved Editor State** as a migration step.
124
+
125
+ ## Everyday editor workflow
126
+
127
+ Use **Overview** for the next safe step, **Migrations** to review the complete ordered
128
+ candidate set, and **Environments** for local resource inventory. Filters and sorting
129
+ apply to the full inventory before pagination. Each list has its own **Previous/Next**
130
+ controls and **5/10/25** page size. Paging preserves drafts and selections; bulk image
131
+ selection selects safe candidates on the current page only. Off-page selections remain
132
+ counted and can be cleared before the exact cleanup review. Display filters never narrow
133
+ database cleanup ownership or the required migration set.
134
+
135
+ For configuration, change only the values you intend to change, then choose
136
+ **Review exact configuration diff** or **Review name & protection**. The review tab
137
+ keeps the full diff readable. **Cancel** makes no changes; **Apply changes** saves the
138
+ reviewed change. Wait for **Saved**, then choose **Return to project**. Concurrent edits
139
+ refuse safely instead of overwriting someone else's work; a saved confirmation is tied
140
+ to the exact bytes read back from disk, not merely a completed write request.
141
+
142
+ Commands reuse the same Rehearsal terminal for a project only after its previous command
143
+ has a confirmed exit and its directory still matches. A running sandbox or manually
144
+ entered foreground command is never interrupted to make room for another action. If
145
+ shell integration or completion evidence is unavailable, finish the command and close
146
+ that terminal before retrying. An idle database lock is not proof that a terminal is free.
147
+
148
+ **Open sandbox** is a persistent hands-on session, not a task that should finish while
149
+ you browse. Overview distinguishes **Opening sandbox**, **Sandbox running** and
150
+ **Closing sandbox** from core phase evidence. Missing evidence says **Sandbox session
151
+ open**, not ready. Project inspection waits for that session; the app itself is not
152
+ paused. Use the local address shown by the owning terminal. **Open application** opens
153
+ that address without running another CLI command. Press **Ctrl+C** once in the owning
154
+ terminal when done, then wait for its shell prompt and the configured lifecycle result.
155
+
156
+ ## Optional automatic updates
157
+
158
+ Open **Rehearsal: Check for Updates** from the Command Palette, or use the dashboard's
159
+ **Check for updates** action. The prompt has two independent, initially unchecked choices:
160
+
161
+ - **Automatically keep the Rehearsal extension up to date**
162
+ - **Automatically keep Rehearsal CLI dependencies up to date**
163
+
164
+ Check the options you want, then choose **Save preferences**. Checking a box alone does
165
+ not save consent: **Later**, **Skip versions**, or closing the tab do not opt you in.
166
+ These choices are stored only in machine-scoped VS Code user settings, not your
167
+ repository or Settings Sync. A project cannot authorize automatic installation. You can
168
+ also edit the user setting directly:
169
+
170
+ ```json
171
+ "rehearsal.automaticUpdates": { "extension": true, "cli": false }
172
+ ```
173
+
174
+ Extension updates download only the official GitHub release, verify the checksum,
175
+ package identity and engine compatibility, and hand the local VSIX to VS Code's
176
+ installer. Rehearsal never forces a window reload; VS Code may ask you to reload when
177
+ you are ready to activate installed code. Keep the previous reviewed VSIX for rollback.
178
+ Canonical automatic updates require `rehearsal-db-<version>.vsix` and embedded identity
179
+ `rehearsal-db.rehearsal-db`; they do not automatically import or replace a legacy package.
180
+
181
+ CLI updates require the separate CLI opt-in. They update compatible registry-backed npm
182
+ dependencies in trusted, idle projects, preserve the dependency group, pin the exact
183
+ checked version and update the lockfile with install scripts disabled. Busy or
184
+ unknown-completion terminals, dirty dependency files, another window's update, offline
185
+ services and unverifiable artifacts defer the update rather than guessing. Breaking
186
+ upgrades, unsupported package managers and local/candidate provenance remain manual.
187
+ No migration, database lifecycle action or forced editor reload is requested.
188
+
189
+ Enabled automatic options check at project opening and daily while the editor stays
190
+ open; there is no separate background daemon. npm/GitHub receive ordinary connection
191
+ information and requested public releases, not project files, database data, credentials
192
+ or installed-version reports. Metadata-only advisory checks keep their separate consent.
193
+
194
+ Turn either option off to revoke its future automatic work. **Rehearsal: Configure
195
+ Update Checks → Disable updates** turns both automatic options off on this computer and
196
+ stops this project's release checks. Existing installations are not rolled back. An
197
+ interrupted package-manager update with unknown completion requires the support recovery
198
+ route; do not delete its coordination lock while a package manager may still be running.
199
+
200
+ Manual updating stays available: download and verify the next reviewed VSIX, then repeat
201
+ **Install from VSIX…**. See the release's
202
+ [installation guide](https://github.com/Ddupasquier/rehearsal-vscode/blob/v0.1.21/README.md#install-and-open-your-project).
203
+ An ordinary core-package update is detected from its manifest, lockfile and installed
204
+ metadata without reloading VS Code. The header shows loaded extension and core versions
205
+ separately; installed → newest appears only after a successful release check. Unknown or
206
+ offline availability is not proof that you are up to date.
58
207
 
59
208
  ## Privacy boundary
60
209
 
@@ -63,28 +212,37 @@ database access, or account. It does not read environment files, credentials, pr
63
212
  baseline contents, or project source. User-approved package operations and external links
64
213
  may use their own services.
65
214
 
66
- ## Licensing and planned editions
67
-
68
- The approved direction is a complete free MIT CLI, a useful free VS Code Starter, and
69
- optional paid Pro editor workflows. The [extension's edition guide](https://github.com/Ddupasquier/rehearsal-vscode/blob/main/docs/commercial-readiness.md)
70
- owns that planned split. Database and safety capabilities stay in the free CLI.
71
-
72
- The split is not implemented yet: current preview artifacts retain their bundled 14-day
73
- evaluation and per-user license, without a technical trial countdown or feature paywall.
74
- GitHub VSIX installations do not auto-update, so each reviewed delivery includes its exact
75
- version, compatible core range, checksum, privacy statement, license, and support policy.
76
-
77
- Technical GitHub prereleases are already public; they are not a Marketplace listing or
78
- an announcement of paid availability. A development candidate is not a released artifact
79
- merely because it has the same version number. Read the release's license, privacy and
80
- support documents before evaluation.
81
-
82
- Starter/Pro license terms and Marketplace distribution still need approval. Paid Pro
83
- availability also needs reviewed seller identity, checkout/refund arrangements and support
84
- ownership. Do not send payment based on an unofficial download or message. Native Windows,
85
- browser-based VS Code, Codespaces, SSH and Dev Containers are not yet claimed as supported.
215
+ ## License, support and future Pro
216
+
217
+ Starter 0.1.21 carries the same
218
+ [free Starter license](https://github.com/Ddupasquier/rehearsal-vscode/blob/v0.1.21/LICENSE).
219
+ Its current review, configuration, comparison and reporting tools are included; they
220
+ are not a timed evaluation or a paid feature gate. Free use does not mean the extension
221
+ is MIT-licensed: its bundled terms govern copying and redistribution. Core remains MIT.
222
+
223
+ Future optional Pro editor workflows must be separately identified. They cannot
224
+ retroactively remove Starter rights already granted for a received version. Pro pricing,
225
+ billing and entitlements are not implemented; no payment is needed to use Starter.
226
+ Database and safety capabilities stay in the free CLI. The
227
+ [edition guide](https://github.com/Ddupasquier/rehearsal-vscode/blob/v0.1.21/docs/commercial-readiness.md)
228
+ owns the detailed boundary.
229
+
230
+ Preview describes stability, not a trial countdown. Support is best effort, with no
231
+ service-level agreement, database hosting, backups or production support. Before use,
232
+ read the release's [privacy statement](https://github.com/Ddupasquier/rehearsal-vscode/blob/v0.1.21/PRIVACY.md)
233
+ and [support policy](https://github.com/Ddupasquier/rehearsal-vscode/blob/v0.1.21/SUPPORT.md).
234
+ Report editor problems in the
235
+ [Rehearsal issue tracker](https://github.com/Ddupasquier/rehearsal-db/issues), as
236
+ described in the support policy.
237
+ Use its [private security process](https://github.com/Ddupasquier/rehearsal-vscode/blob/v0.1.21/SECURITY.md)
238
+ for vulnerabilities; never post credentials, private rows or baseline files publicly.
239
+
240
+ Historical VSIX files retain their bundled terms. Choose a reviewed release carrying
241
+ the Starter license; a development candidate is not released merely because its version
242
+ number matches. The [release list](https://github.com/Ddupasquier/rehearsal-vscode/releases)
243
+ is the authority for downloadable artifacts and their checksums.
86
244
 
87
245
  ## Try the free engine first
88
246
 
89
247
  Start with [Getting started](getting-started.md). A successful CLI rehearsal proves the
90
- project and local runtime are compatible before you evaluate the visual workflow.
248
+ project and local runtime are compatible before you use the visual workflow.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rehearsal-db/core",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "private": false,
5
5
  "description": "Catch PostgreSQL and Supabase migrations that pass on empty databases but fail on real data—before deploy.",
6
6
  "repository": {
@@ -78,7 +78,7 @@
78
78
  "test:fixture:resources": "npm run build && node scripts/verification/run_scenario.mjs resources",
79
79
  "release:verify": "npm run build && node scripts/verification/release_gate.mjs",
80
80
  "check": "npm run check:syntax && npm run typecheck && npm run test && npm run docs:build && npm run format:check && npm run package:audit",
81
- "check:syntax": "find scripts tests -type f -name '*.mjs' -exec node --check {} +",
81
+ "check:syntax": "node scripts/verification/check_syntax.mjs",
82
82
  "typecheck": "npm run build && tsc --project tsconfig.json",
83
83
  "format": "prettier --write .",
84
84
  "format:check": "prettier --check .",