@rehearsal-db/core 0.1.0-beta.1 → 0.1.0-beta.2

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,24 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## [0.1.0-beta.2] - 2026-09-15
9
+
10
+ ### Fixed
11
+
12
+ - Generate `rehearsal.config.mjs` so first-time initialization works in both CommonJS
13
+ and ESM projects instead of failing when a fresh npm project declares CommonJS.
14
+ - Report the exact table and represented-migration counts after creating a synthetic
15
+ baseline instead of rendering missing result fields as `undefined`.
16
+ - Keep the copyable getting-started migration bytes identical to its migration-ledger
17
+ example so the documented runtime replay passes exact-history verification.
18
+ - Install the current prerelease through npm's `beta` tag so new projects do not resolve
19
+ the superseded bootstrap release from npm's historical `latest` tag.
20
+
21
+ ### Security
22
+
23
+ - Removed the completed first-package bootstrap credential path. All future publication
24
+ uses the package's trusted GitHub Actions OIDC publisher and cannot read an npm token.
25
+
8
26
  ## [0.1.0-beta.1] - 2026-09-14
9
27
 
10
28
  ### Changed
@@ -54,6 +72,7 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
54
72
  publication uses short-lived trusted OIDC, and every release tag must already exist on
55
73
  protected `main`.
56
74
 
57
- [Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.1...HEAD
75
+ [Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.2...HEAD
76
+ [0.1.0-beta.2]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.1...v0.1.0-beta.2
58
77
  [0.1.0-beta.1]: https://github.com/Ddupasquier/rehearsal-db/releases/tag/v0.1.0-beta.1
59
78
  [0.1.0-beta.0]: https://github.com/Ddupasquier/rehearsal-db/releases/tag/v0.1.0-beta.0
package/README.md CHANGED
@@ -77,7 +77,7 @@ invariants. Reset restores and reproves the exact starting data.
77
77
  Install the current beta from npm:
78
78
 
79
79
  ```bash
80
- npm install --save-dev @rehearsal-db/core
80
+ npm install --save-dev @rehearsal-db/core@beta
81
81
  ```
82
82
 
83
83
  Contributors testing an unreleased change can use `npm link` or install the tarball
@@ -102,9 +102,10 @@ npx rehearsal stop
102
102
  npx rehearsal discard
103
103
  ```
104
104
 
105
- `init` previews a typed `rehearsal.config.ts`; it writes only with `--write` and never
106
- overwrites an existing file. Review all detected values. Rehearsal intentionally does
107
- not detect, copy, or enable a hosted project.
105
+ `init` previews a type-aware ESM `rehearsal.config.mjs`; it writes only with `--write`
106
+ and never overwrites an existing file. The explicit `.mjs` extension makes the generated
107
+ configuration executable in both CommonJS and ESM projects. Review all detected values.
108
+ Rehearsal intentionally does not detect, copy, or enable a hosted project.
108
109
 
109
110
  `doctor` must end with `READY` before execution. `explain` and `run --dry-run` use the
110
111
  same immutable planner and perform no state-changing operations. If migrations are
@@ -1,6 +1,8 @@
1
1
  # Configuration reference
2
2
 
3
- `rehearsal.config.ts` is executable configuration with a strict versioned schema.
3
+ `rehearsal.config.mjs` is executable configuration with a strict versioned schema. The
4
+ initializer uses an explicit ESM extension so the same generated file works in CommonJS
5
+ and ESM projects.
4
6
  Unknown fields and unknown schema versions are errors, not warnings.
5
7
 
6
8
  ```ts
@@ -35,7 +35,7 @@ its labeled local runtime. It does not need a hosted Supabase project or credent
35
35
  ## 1. Install and initialize
36
36
 
37
37
  ```bash
38
- npm install --save-dev @rehearsal-db/core
38
+ npm install --save-dev @rehearsal-db/core@beta
39
39
  npx rehearsal init
40
40
  ```
41
41
 
@@ -53,7 +53,7 @@ until the next section's files exist.
53
53
 
54
54
  ## 2. Add the project-owned inputs
55
55
 
56
- Create the paths named by `rehearsal.config.ts`:
56
+ Create the paths named by `rehearsal.config.mjs`:
57
57
 
58
58
  - a dedicated local Supabase `config.toml`;
59
59
  - a sanitization policy describing every exported field;
@@ -68,7 +68,7 @@ cp supabase/config.toml infrastructure/rehearsal/supabase/config.toml
68
68
  ```
69
69
 
70
70
  Edit the copied Supabase config. Give it the same unique `project_id`, API port, database
71
- port, and Studio port used by `rehearsal.config.ts`. Disable services your proof does
71
+ port, and Studio port used by `rehearsal.config.mjs`. Disable services your proof does
72
72
  not need. This must remain an unlinked local config; never run `supabase link` from it.
73
73
 
74
74
  Also replace the generated `application.startCommand`, `application.proofCommand`, and
@@ -83,9 +83,9 @@ Historical migration `supabase/migrations/20260101000000_create_widgets.sql`:
83
83
 
84
84
  ```sql
85
85
  create table public.widgets (
86
- id bigint generated by default as identity primary key,
87
- name text not null,
88
- created_at timestamptz not null default now()
86
+ id bigint generated by default as identity primary key,
87
+ name text not null,
88
+ created_at timestamptz not null default now()
89
89
  );
90
90
 
91
91
  insert into storage.buckets (id, name, public)
@@ -238,7 +238,8 @@ stops only this project's runtime.
238
238
 
239
239
  ## Generated files
240
240
 
241
- - `rehearsal.config.ts` is written only by `init --write`.
241
+ - `rehearsal.config.mjs` is written only by `init --write`. Its explicit ESM extension
242
+ works whether the consuming project's `package.json` uses CommonJS or ESM.
242
243
  - `.rehearsal/generations/<id>/` contains one immutable baseline generation.
243
244
  - `.rehearsal/current` selects the active generation atomically.
244
245
  - `.rehearsal/runtime/` contains the disposable local Supabase project and receipts.
@@ -22,7 +22,7 @@ never row bodies.
22
22
 
23
23
  ## What not to do
24
24
 
25
- - Do not point `rehearsal.config.ts` at a hosted URL.
25
+ - Do not point `rehearsal.config.mjs` at a hosted URL.
26
26
  - Do not put a production connection string in `.rehearsal/runtime.env`.
27
27
  - Do not grant table-wide access merely because a view is inconvenient.
28
28
  - Do not commit sanitized baselines; sanitized data is still data.
package/docs/releasing.md CHANGED
@@ -5,48 +5,27 @@ environment. The workflow builds and hashes the candidate before the environment
5
5
  approval gate, then publishes those exact bytes with npm provenance. A local working
6
6
  tree is never the release source.
7
7
 
8
- The initial publishable `0.1.0-beta.1` release branch is the first change allowed to set
9
- `"private": false`. Publication still requires the exact protected-main tag, prerelease
10
- flag, artifact checks, and protected `npm` environment gate described below.
11
-
12
8
  `0.1.0-beta.0` was prepared under the unavailable `@rehearsal` npm scope and was never
13
9
  published. `0.1.0-beta.1` supersedes that candidate under `@rehearsal-db/core` without
14
10
  rewriting the earlier Git tag or GitHub prerelease.
15
11
 
16
- ## One-time first-package bootstrap
12
+ ## Trusted publication boundary
17
13
 
18
- npm trusted publishing and staged publishing are package-level settings, so they cannot
19
- be configured until `@rehearsal-db/core` exists in the registry. The first public version has
20
- a deliberately narrower bootstrap path:
14
+ `@rehearsal-db/core` trusts only the GitHub Actions publisher for repository
15
+ `Ddupasquier/rehearsal-db`, workflow `publish.yml`, and environment `npm`. The publish job
16
+ requests a short-lived GitHub OIDC identity after the protected environment approval;
17
+ it does not read an npm token or retain a registry credential. Package publishing access
18
+ requires 2FA and disallows bypass tokens.
21
19
 
22
- 1. The npm owner enables 2FA and creates or confirms the public `@rehearsal-db` organization
23
- scope. Do not send a password, OTP, recovery code, or access token to another person.
24
- 2. After the reviewed release change reaches protected `main`, the owner creates the
25
- exact `v0.1.0-beta.1` GitHub release and marks it as a prerelease. The prepare job runs without npm credentials,
26
- packs the tag, and uploads its versioned tarball plus SHA-1 and SHA-256 metadata. The
27
- publish job waits at the protected environment and cannot run yet.
28
- 3. The owner downloads or inspects that prepared artifact, confirms its version and
29
- checksum, and explicitly authorizes those exact bytes.
30
- 4. Only then, the owner creates a short-lived granular npm token with read/write access
31
- limited to the `@rehearsal-db` scope and **Bypass 2FA** enabled. npm requires that bypass
32
- for a non-interactive first publish; the environment approval remains the human
33
- release gate. Store the token only as the `NPM_TOKEN` secret in the protected GitHub
34
- `npm` environment.
35
- 5. The owner approves the waiting `npm` deployment. GitHub Actions publishes the exact
36
- uploaded tarball with provenance. The workflow
37
- refuses to use the bootstrap secret for any version other than `0.1.0-beta.1`.
38
- 6. Immediately after the registry verification passes, the owner deletes the GitHub
39
- environment secret and revokes the temporary npm token.
40
- 7. From the new package's npm settings, configure the trusted GitHub Actions publisher
41
- for repository `Ddupasquier/rehearsal-db`, workflow `publish.yml`, and environment
42
- `npm`. Allow direct `npm publish` for this workflow because the protected GitHub
43
- environment supplies the human gate. A later switch to npm staged publication must
44
- change and prove the workflow before narrowing the trusted publisher permission.
45
- 8. Set package publishing access to require 2FA and disallow traditional tokens.
20
+ The initial `0.1.0-beta.1` package creation required a one-time bootstrap credential
21
+ because npm cannot configure a trusted publisher before a package exists. That
22
+ credential is not part of the maintained release architecture: it was deleted from the
23
+ GitHub environment after publication, must remain revoked at npm, and cannot be consumed
24
+ by this workflow.
46
25
 
47
- This bootstrap token is a one-release compromise imposed by npm's package-creation
48
- boundary. It is never committed, printed, copied into a ticket, or retained for later
49
- versions.
26
+ Direct `npm publish` is allowed only for this trusted publisher because the protected
27
+ GitHub `npm` environment supplies the human gate. A later switch to npm staged
28
+ publication must change and prove the workflow before narrowing that permission.
50
29
 
51
30
  ## Every release candidate
52
31
 
@@ -66,7 +45,9 @@ versions.
66
45
  the approved version and checksum.
67
46
  10. Verify public visibility, ownership, provenance, registry SHA-1, README rendering,
68
47
  exact-version clean installation, CLI execution, signatures, and the unrelated
69
- installed Docker fixture.
48
+ installed Docker fixture. Allow up to six minutes for a first package to propagate
49
+ through the public registry before classifying a missing packument as a release
50
+ failure.
70
51
  11. Replace consuming projects' temporary Git/archive references only on their own
71
52
  protected integration branches and rerun their complete verification.
72
53
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rehearsal-db/core",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0-beta.2",
4
4
  "private": false,
5
5
  "description": "Safely rehearse Supabase migrations against sanitized, production-shaped PostgreSQL data.",
6
6
  "repository": {
@@ -148,8 +148,8 @@ export const createSyntheticBaselineFromFiles = async ({
148
148
  return {
149
149
  generationId,
150
150
  migrationCutoff: baseline.migrationCutoff,
151
- migrationCount: baseline.migrationCount,
151
+ migrationCount: Object.keys(baseline.migrations).length,
152
152
  rowCount: baseline.rowCount,
153
- tableCount: baseline.tableCount,
153
+ tableCount: Object.keys(baseline.tableCounts).length,
154
154
  };
155
155
  };
@@ -515,9 +515,8 @@ export const inspectDetectedProject = async ({
515
515
  };
516
516
  };
517
517
 
518
- export const renderDetectedConfig = (
519
- detected,
520
- ) => `import { defineRehearsalConfig } from "@rehearsal-db/core";
518
+ export const renderDetectedConfig = (detected) => `// @ts-check
519
+ import { defineRehearsalConfig } from "@rehearsal-db/core";
521
520
 
522
521
  export default defineRehearsalConfig({
523
522
  schemaVersion: 1,
@@ -7,7 +7,7 @@
7
7
  import { createHash } from "node:crypto";
8
8
 
9
9
  export const REHEARSAL_RESULT_VERSION = 1;
10
- export const REHEARSAL_VERSION = "0.1.0-beta.1";
10
+ export const REHEARSAL_VERSION = "0.1.0-beta.2";
11
11
 
12
12
  export const REHEARSAL_EXIT_CODES = Object.freeze({
13
13
  success: 0,
@@ -362,7 +362,7 @@ const runApplicationProof = async (planOptions) => {
362
362
  const runInit = async ({ flags }) => {
363
363
  const detected = await inspectDetectedProject({ projectRoot });
364
364
  const source = renderDetectedConfig(detected);
365
- const destination = join(projectRoot, "rehearsal.config.ts");
365
+ const destination = join(projectRoot, "rehearsal.config.mjs");
366
366
  let existingPath = null;
367
367
  try {
368
368
  existingPath = await findRehearsalConfigPath({ projectRoot });