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

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,58 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## [0.1.0-beta.3] - 2026-10-01
9
+
10
+ ### Added
11
+
12
+ - A state-aware interactive home screen that guides setup, baseline preparation,
13
+ migration review, runtime management, verification, and cleanup without requiring
14
+ users to memorize commands.
15
+ - A safe `setup` workflow that previews and creates a dedicated local Supabase config,
16
+ chooses an available port block, updates protective ignore rules, and summarizes
17
+ readiness without overwriting project files.
18
+ - A schema-only `baseline prepare` workflow that generates a fail-closed policy draft
19
+ with explicit `REVIEW REQUIRED` decisions and never prints source row values.
20
+ - Interactive confirmation of the exact candidate migration set plus friendly progress
21
+ and timing while a rehearsal runs.
22
+
23
+ ### Changed
24
+
25
+ - Human output now recommends the next useful action, uses compact first-run readiness
26
+ summaries, respects `NO_COLOR` and `--plain`, and renders singular counts correctly.
27
+ - Bare `rehearsal` opens the guide only in a terminal and remains noninteractive and
28
+ script-safe when standard input or output is redirected.
29
+
30
+ ### Fixed
31
+
32
+ - Setup detects unsupported Node.js versions before writing, ignores ports occupied by
33
+ Docker or SSH forwarding, and rechecks its selected ports immediately before commit.
34
+ - Generated project identifiers are bounded to values accepted by the local runtime.
35
+
36
+ ### Security
37
+
38
+ - Reviewed sanitization policy bytes are checksum-bound to the active baseline and are
39
+ revalidated during planning and runtime restore.
40
+ - Draft or incomplete sanitization policies cannot be activated as baselines.
41
+
42
+ ## [0.1.0-beta.2] - 2026-09-15
43
+
44
+ ### Fixed
45
+
46
+ - Generate `rehearsal.config.mjs` so first-time initialization works in both CommonJS
47
+ and ESM projects instead of failing when a fresh npm project declares CommonJS.
48
+ - Report the exact table and represented-migration counts after creating a synthetic
49
+ baseline instead of rendering missing result fields as `undefined`.
50
+ - Keep the copyable getting-started migration bytes identical to its migration-ledger
51
+ example so the documented runtime replay passes exact-history verification.
52
+ - Install the current prerelease through npm's `beta` tag so new projects do not resolve
53
+ the superseded bootstrap release from npm's historical `latest` tag.
54
+
55
+ ### Security
56
+
57
+ - Removed the completed first-package bootstrap credential path. All future publication
58
+ uses the package's trusted GitHub Actions OIDC publisher and cannot read an npm token.
59
+
8
60
  ## [0.1.0-beta.1] - 2026-09-14
9
61
 
10
62
  ### Changed
@@ -54,6 +106,8 @@ a Changelog, and versions will follow Semantic Versioning after the package exis
54
106
  publication uses short-lived trusted OIDC, and every release tag must already exist on
55
107
  protected `main`.
56
108
 
57
- [Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.1...HEAD
109
+ [Unreleased]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.3...HEAD
110
+ [0.1.0-beta.3]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.2...v0.1.0-beta.3
111
+ [0.1.0-beta.2]: https://github.com/Ddupasquier/rehearsal-db/compare/v0.1.0-beta.1...v0.1.0-beta.2
58
112
  [0.1.0-beta.1]: https://github.com/Ddupasquier/rehearsal-db/releases/tag/v0.1.0-beta.1
59
113
  [0.1.0-beta.0]: https://github.com/Ddupasquier/rehearsal-db/releases/tag/v0.1.0-beta.0
package/README.md CHANGED
@@ -77,15 +77,20 @@ 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
84
84
  produced by `npm pack` from a local checkout. In a consuming project, the commands are:
85
85
 
86
86
  ```bash
87
+ npx rehearsal
88
+ npx rehearsal setup
89
+ npx rehearsal setup --write
87
90
  npx rehearsal init
88
91
  npx rehearsal init --write
92
+ npx rehearsal baseline prepare --records=<safe.ndjson> --ledger=<ledger.json>
93
+ npx rehearsal baseline prepare --records=<safe.ndjson> --ledger=<ledger.json> --write
89
94
  npx rehearsal baseline create --records=<safe.ndjson> --ledger=<ledger.json>
90
95
  npx rehearsal doctor
91
96
  npx rehearsal explain
@@ -102,13 +107,32 @@ npx rehearsal stop
102
107
  npx rehearsal discard
103
108
  ```
104
109
 
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.
110
+ Running `npx rehearsal` in a terminal opens a state-aware guide that shows completed
111
+ setup steps and recommends available actions. The explicit commands remain the stable
112
+ interface for automation and CI.
113
+
114
+ `setup` previews a conservative first-run scaffold: the Rehearsal configuration, a
115
+ dedicated local-only Supabase configuration on an available port block, and protective
116
+ `.gitignore` entries. It writes only with `--write`, never overwrites project files, and
117
+ does not copy enabled external providers from the application's Supabase configuration.
118
+ After writing, it runs the same readiness checks as `doctor` and shows the remaining
119
+ project-owned inputs. Use `init` when you want to create only the configuration file
120
+ manually.
121
+
122
+ `baseline prepare` inspects only the shape of explicit local synthetic records and writes
123
+ a fail-closed sanitization-policy draft. Every column remains `REVIEW REQUIRED` until a
124
+ human classifies its sanitization action, generated/identity behavior, and foreign key.
125
+ Drafts cannot be activated, and a reviewed policy is checksum-bound to its baseline.
126
+
127
+ `init` previews a type-aware ESM `rehearsal.config.mjs`; it writes only with `--write`
128
+ and never overwrites an existing file. The explicit `.mjs` extension makes the generated
129
+ configuration executable in both CommonJS and ESM projects. Review all detected values.
130
+ Rehearsal intentionally does not detect, copy, or enable a hosted project.
108
131
 
109
132
  `doctor` must end with `READY` before execution. `explain` and `run --dry-run` use the
110
- same immutable planner and perform no state-changing operations. If migrations are
111
- pending, execution requires the exact candidate digest printed by the plan:
133
+ same immutable planner and perform no state-changing operations. In a terminal,
134
+ `rehearsal run` displays and confirms the exact candidate set before touching the local
135
+ runtime. Automation supplies the digest explicitly:
112
136
 
113
137
  ```bash
114
138
  npx rehearsal run --confirm-candidates=<sha256>
package/docs/commands.md CHANGED
@@ -6,8 +6,13 @@ values or credentials.
6
6
 
7
7
  | Command | Mutates local state | Purpose |
8
8
  | ------------------------------------------------------------ | ------------------- | --------------------------------------------------------- |
9
+ | `rehearsal` or `rehearsal guide` | No by default | Open the guided, state-aware interactive home screen. |
10
+ | `rehearsal setup` | No | Preview safe config, local runtime, and ignore files. |
11
+ | `rehearsal setup --write` | Project files | Create the previewed first-run scaffolding. |
9
12
  | `rehearsal init` | No | Preview safe starter configuration. |
10
13
  | `rehearsal init --write` | Config only | Create config without overwriting. |
14
+ | `rehearsal baseline prepare --records= --ledger=` | No | Preview a fail-closed policy draft from local shape. |
15
+ | `rehearsal baseline prepare --records= --ledger= --write` | Policy only | Write the draft without exposing row values. |
11
16
  | `rehearsal baseline create --records=<path> --ledger=<path>` | Artifact only | Activate a baseline from explicit safe local inputs. |
12
17
  | `rehearsal doctor` | No | Check dependencies, inputs, and safety barriers. |
13
18
  | `rehearsal explain` | No | Print the immutable execution plan. |
@@ -24,12 +29,30 @@ values or credentials.
24
29
  | `rehearsal stop` | Runtime only | Stop this project's local services. |
25
30
  | `rehearsal discard` | Yes, local only | Remove only this project's disposable runtime and volume. |
26
31
 
27
- `run` requires the digest from the current candidate set. Any added, removed, reordered,
28
- or edited migration changes the digest and invalidates the confirmation.
32
+ In an interactive terminal, `run` and `migrate` display the candidate files and ask for
33
+ confirmation before touching the runtime. In automation, they require the digest from
34
+ the current candidate set. Any added, removed, reordered, or edited migration changes
35
+ the digest and invalidates either form of confirmation.
29
36
 
30
37
  `baseline create` never extracts data. The NDJSON and migration-ledger files must already
31
38
  exist inside the project and be safe to retain. Add `--assets=<manifest.json>` to include
32
39
  bounded local Storage bytes; every manifest `file` must also remain inside the project.
40
+ The guided home screen can ask for these paths so they do not need to be supplied as
41
+ flags.
42
+
43
+ `baseline prepare` reads only table and column names from the NDJSON records; row values
44
+ are never included in its result. Its generated policy deliberately marks every column
45
+ decision `REVIEW REQUIRED` and cannot be activated until a human completes the metadata
46
+ and removes the `draft` marker. Rehearsal binds the reviewed policy checksum to the
47
+ baseline and rejects later policy changes during planning and restore.
33
48
 
34
49
  Automation should use `--json` and inspect both exit status and the versioned envelope.
35
50
  Exit-code meanings are documented in the root README. Scripts must not parse human text.
51
+ When standard input or output is not an interactive terminal, bare `rehearsal` prints
52
+ help instead of prompting. Use `--plain` to disable decorative terminal styling.
53
+
54
+ `setup` chooses an available local port block and generates a conservative Supabase
55
+ configuration with hosted access and optional networked services disabled. It does not
56
+ overwrite an existing Rehearsal config, dedicated Supabase config, or concurrently
57
+ changed `.gitignore`. After writing, it includes a Doctor readiness summary. `init`
58
+ remains available for config-only/manual onboarding.
@@ -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
@@ -34,18 +34,30 @@ its labeled local runtime. It does not need a hosted Supabase project or credent
34
34
 
35
35
  ## 1. Install and initialize
36
36
 
37
+ Confirm this shell is running the supported Node.js major before installing:
38
+
39
+ ```bash
40
+ node --version # v24.x
41
+ ```
42
+
37
43
  ```bash
38
- npm install --save-dev @rehearsal-db/core
39
- npx rehearsal init
44
+ npm install --save-dev @rehearsal-db/core@beta
45
+ npx rehearsal
40
46
  ```
41
47
 
42
- `init` is a preview. Read the generated configuration, then explicitly write it:
48
+ Choose **Set up Rehearsal** in the guide. It previews a versioned configuration, a
49
+ dedicated local-only Supabase configuration using available ports, and protective
50
+ `.gitignore` entries before asking permission to write.
51
+
52
+ The same flow is available noninteractively as an explicit preview and write:
43
53
 
44
54
  ```bash
45
- npx rehearsal init --write
55
+ npx rehearsal setup
56
+ npx rehearsal setup --write
46
57
  ```
47
58
 
48
- Rehearsal never overwrites an existing configuration.
59
+ Rehearsal never overwrites an existing configuration. For config-only/manual setup, use
60
+ `npx rehearsal init` followed by `npx rehearsal init --write`.
49
61
 
50
62
  The generated configuration is intentionally incomplete until you review its ports,
51
63
  project ID, application commands, and project-owned input paths. Do not run `doctor`
@@ -53,14 +65,14 @@ until the next section's files exist.
53
65
 
54
66
  ## 2. Add the project-owned inputs
55
67
 
56
- Create the paths named by `rehearsal.config.ts`:
68
+ Review or create the project-owned inputs named by `rehearsal.config.mjs`:
57
69
 
58
- - a dedicated local Supabase `config.toml`;
70
+ - the dedicated local Supabase `config.toml` (`setup` creates a conservative one);
59
71
  - a sanitization policy describing every exported field;
60
72
  - an active baseline below `.rehearsal/`;
61
73
  - an application proof command that exits nonzero when the restored app is wrong.
62
74
 
63
- For the generated default paths:
75
+ If you used config-only `init`, also create the dedicated Supabase config manually:
64
76
 
65
77
  ```bash
66
78
  mkdir -p infrastructure/rehearsal/supabase infrastructure/rehearsal rehearsal
@@ -68,7 +80,7 @@ cp supabase/config.toml infrastructure/rehearsal/supabase/config.toml
68
80
  ```
69
81
 
70
82
  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
83
+ port, and Studio port used by `rehearsal.config.mjs`. Disable services your proof does
72
84
  not need. This must remain an unlinked local config; never run `supabase link` from it.
73
85
 
74
86
  Also replace the generated `application.startCommand`, `application.proofCommand`, and
@@ -79,13 +91,29 @@ Start with synthetic rows shaped like your schema. Do not start onboarding with
79
91
  production data. The following SQL, policy, row, and ledger form one matched example;
80
92
  do not mix them with differently shaped snippets.
81
93
 
94
+ If you already have the safe NDJSON rows and migration ledger, Rehearsal can enumerate
95
+ their table and column shape into a fail-closed policy draft without printing values:
96
+
97
+ ```bash
98
+ npx rehearsal baseline prepare \
99
+ --records=rehearsal/synthetic-data.ndjson \
100
+ --ledger=rehearsal/migration-ledger.json
101
+ npx rehearsal baseline prepare \
102
+ --records=rehearsal/synthetic-data.ndjson \
103
+ --ledger=rehearsal/migration-ledger.json \
104
+ --write
105
+ ```
106
+
107
+ Review every `REVIEW REQUIRED` field, replace it with correct metadata, and remove
108
+ `"draft": true` only after that review. Rehearsal refuses to activate a draft.
109
+
82
110
  Historical migration `supabase/migrations/20260101000000_create_widgets.sql`:
83
111
 
84
112
  ```sql
85
113
  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()
114
+ id bigint generated by default as identity primary key,
115
+ name text not null,
116
+ created_at timestamptz not null default now()
89
117
  );
90
118
 
91
119
  insert into storage.buckets (id, name, public)
@@ -238,7 +266,8 @@ stops only this project's runtime.
238
266
 
239
267
  ## Generated files
240
268
 
241
- - `rehearsal.config.ts` is written only by `init --write`.
269
+ - `rehearsal.config.mjs` is written only by `init --write`. Its explicit ESM extension
270
+ works whether the consuming project's `package.json` uses CommonJS or ESM.
242
271
  - `.rehearsal/generations/<id>/` contains one immutable baseline generation.
243
272
  - `.rehearsal/current` selects the active generation atomically.
244
273
  - `.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
 
@@ -13,6 +13,12 @@ Every exported field should receive one action:
13
13
 
14
14
  Fail if a new column is unclassified. Do not default unknown fields to `KEEP`.
15
15
 
16
+ For runtime restore, each included column must also classify whether it is generated,
17
+ whether it is an identity column, and its foreign-key target or explicit absence. Run
18
+ `rehearsal baseline prepare` to create a shape-only draft from synthetic NDJSON. The
19
+ draft uses `REVIEW REQUIRED` placeholders and cannot be activated until they are
20
+ replaced and the `draft` marker is removed.
21
+
16
22
  The package exports `validateSanitizationCoverage` and
17
23
  `applySanitizationAction` as generic primitives:
18
24
 
@@ -67,3 +73,7 @@ Before activation, verify:
67
73
 
68
74
  Completeness is not correctness. Human review of the policy and export boundary remains
69
75
  mandatory before any real source is introduced.
76
+
77
+ The exact reviewed policy bytes are checksum-bound to the active baseline. Planning,
78
+ candidate inspection, and runtime restore refuse to continue if that file later changes;
79
+ build a new reviewed baseline instead of editing the active policy in place.
@@ -1,5 +1,19 @@
1
1
  # Troubleshooting
2
2
 
3
+ ## Setup says Node.js 24 is required
4
+
5
+ Rehearsal intentionally supports one maintained Node.js major in its first beta. Switch
6
+ the current shell before installing or running it. With nvm:
7
+
8
+ ```bash
9
+ nvm install 24
10
+ nvm use 24
11
+ node --version
12
+ ```
13
+
14
+ Then reinstall Rehearsal in the consuming project. The guided CLI checks this before it
15
+ writes setup files.
16
+
3
17
  ## Doctor says Docker is unavailable
4
18
 
5
19
  Start Docker Desktop or Colima, confirm `docker info`, then rerun `rehearsal doctor`.
@@ -7,8 +21,10 @@ Restarting the computer is rarely necessary.
7
21
 
8
22
  ## A port is already in use
9
23
 
10
- Choose three unique non-privileged ports in config and mirror them in the dedicated
11
- Supabase config. Do not stop an unrelated database to make the default ports fit.
24
+ Rerun `rehearsal setup` to select a different available block. Setup checks both active
25
+ listeners and whether every selected port can be bound, then checks again before writing.
26
+ For an existing configuration, choose unique non-privileged ports and mirror them in the
27
+ dedicated Supabase config. Do not stop an unrelated database to make defaults fit.
12
28
 
13
29
  ## Baseline checksum mismatch
14
30
 
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.3",
4
4
  "private": false,
5
5
  "description": "Safely rehearse Supabase migrations against sanitized, production-shaped PostgreSQL data.",
6
6
  "repository": {
@@ -19,6 +19,7 @@ import {
19
19
  createMigrationReplayReceipt,
20
20
  readMigrationSourceBundle,
21
21
  } from "./migration_history.mjs";
22
+ import { validateRuntimeSanitizationPolicy } from "./sanitization_policy.mjs";
22
23
 
23
24
  const resolveProjectInput = (projectRoot, value, label) => {
24
25
  if (typeof value !== "string" || value.trim() === "") {
@@ -103,10 +104,9 @@ export const createSyntheticBaselineFromFiles = async ({
103
104
  })),
104
105
  )
105
106
  : [];
106
- const policy = JSON.parse(policyBytes.toString("utf8"));
107
- if (!Array.isArray(policy.tables)) {
108
- throw new Error("The configured sanitization policy does not list tables.");
109
- }
107
+ const policy = validateRuntimeSanitizationPolicy(
108
+ JSON.parse(policyBytes.toString("utf8")),
109
+ );
110
110
  const expectedTables = policy.tables
111
111
  .filter((table) => table.sourceRows !== "EXCLUDE")
112
112
  .map((table) => table.name);
@@ -117,6 +117,11 @@ export const createSyntheticBaselineFromFiles = async ({
117
117
  JSON.parse(ledgerBytes.toString("utf8")),
118
118
  "Synthetic migration ledger",
119
119
  );
120
+ if (policy.migrationCutoff !== sourceMigrationHistory.at(-1).version) {
121
+ throw new Error(
122
+ `The sanitization policy cutoff ${policy.migrationCutoff} does not match migration ledger cutoff ${sourceMigrationHistory.at(-1).version}.`,
123
+ );
124
+ }
120
125
  const migrationFiles = await readMigrationSourceBundle({
121
126
  directory: new URL(
122
127
  "./",
@@ -148,8 +153,8 @@ export const createSyntheticBaselineFromFiles = async ({
148
153
  return {
149
154
  generationId,
150
155
  migrationCutoff: baseline.migrationCutoff,
151
- migrationCount: baseline.migrationCount,
156
+ migrationCount: Object.keys(baseline.migrations).length,
152
157
  rowCount: baseline.rowCount,
153
- tableCount: baseline.tableCount,
158
+ tableCount: Object.keys(baseline.tableCounts).length,
154
159
  };
155
160
  };