@rehearsal-db/core 0.1.0-beta.13 → 0.1.0-beta.15
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 +93 -0
- package/README.md +4 -1
- package/dist/package.json +100 -0
- package/dist/scripts/install/create_root_config.d.mts +3 -0
- package/dist/scripts/install/create_root_config.mjs +13 -0
- package/dist/scripts/runtime/manage_database.d.mts +6 -0
- package/{scripts → dist/scripts}/runtime/manage_database.mjs +6 -8
- package/dist/src/application/session.d.mts +96 -0
- package/dist/src/application/session.mjs +380 -0
- package/dist/src/baseline/artifact.d.mts +119 -0
- package/dist/src/baseline/artifact.mjs +522 -0
- package/dist/src/baseline/builder.d.mts +19 -0
- package/dist/src/baseline/builder.mjs +142 -0
- package/dist/src/baseline/input_discovery.d.mts +13 -0
- package/dist/src/baseline/input_discovery.mjs +149 -0
- package/dist/src/baseline/policy_review.d.mts +56 -0
- package/dist/src/baseline/policy_review.mjs +73 -0
- package/dist/src/baseline/preparation.d.mts +63 -0
- package/dist/src/baseline/preparation.mjs +295 -0
- package/dist/src/baseline/privacy_engine.d.mts +162 -0
- package/dist/src/baseline/privacy_engine.mjs +1162 -0
- package/dist/src/baseline/privacy_structured_json.d.mts +66 -0
- package/dist/src/baseline/privacy_structured_json.mjs +464 -0
- package/dist/src/baseline/sanitization_policy.d.mts +69 -0
- package/dist/src/baseline/sanitization_policy.mjs +227 -0
- package/dist/src/baseline/schema_snapshot.d.mts +19 -0
- package/dist/src/baseline/schema_snapshot.mjs +79 -0
- package/dist/src/cli/arguments.d.mts +43 -0
- package/dist/src/cli/arguments.mjs +135 -0
- package/dist/src/cli/guided.d.mts +51 -0
- package/dist/src/cli/guided.mjs +713 -0
- package/dist/src/cli/init_command.d.mts +21 -0
- package/dist/src/cli/init_command.mjs +90 -0
- package/dist/src/cli/project_commands.d.mts +157 -0
- package/dist/src/cli/project_commands.mjs +183 -0
- package/dist/src/cli/rehearsal.d.mts +7 -0
- package/dist/src/cli/rehearsal.mjs +706 -0
- package/dist/src/cli/renderers.d.mts +299 -0
- package/dist/src/cli/renderers.mjs +554 -0
- package/dist/src/cli/runtime_commands.d.mts +265 -0
- package/dist/src/cli/runtime_commands.mjs +599 -0
- package/dist/src/cli/source_commands.d.mts +432 -0
- package/dist/src/cli/source_commands.mjs +299 -0
- package/dist/src/cli/terminal.d.mts +59 -0
- package/dist/src/cli/terminal.mjs +230 -0
- package/dist/src/identity/claim.d.mts +144 -0
- package/dist/src/identity/claim.mjs +947 -0
- package/dist/src/identity/provider_configuration.d.mts +37 -0
- package/dist/src/identity/provider_configuration.mjs +132 -0
- package/dist/src/identity/storage.d.mts +21 -0
- package/dist/src/identity/storage.mjs +122 -0
- package/dist/src/index.d.mts +4 -0
- package/dist/src/index.mjs +3 -0
- package/dist/src/project/configuration.d.mts +181 -0
- package/dist/src/project/configuration.mjs +958 -0
- package/dist/src/project/install_scaffold.d.mts +42 -0
- package/dist/src/project/install_scaffold.mjs +263 -0
- package/dist/src/project/setup.d.mts +87 -0
- package/dist/src/project/setup.mjs +414 -0
- package/dist/src/project/support_report.d.mts +88 -0
- package/dist/src/project/support_report.mjs +83 -0
- package/dist/src/runtime/cleanup.d.mts +85 -0
- package/dist/src/runtime/cleanup.mjs +311 -0
- package/dist/src/runtime/migration_history.d.mts +51 -0
- package/dist/src/runtime/migration_history.mjs +170 -0
- package/dist/src/runtime/plan.d.mts +134 -0
- package/dist/src/runtime/plan.mjs +636 -0
- package/dist/src/runtime/policy.d.mts +66 -0
- package/dist/src/runtime/policy.mjs +369 -0
- package/dist/src/runtime/restore.d.mts +22 -0
- package/dist/src/runtime/restore.mjs +276 -0
- package/dist/src/runtime/service_environment.d.mts +11 -0
- package/dist/src/runtime/service_environment.mjs +58 -0
- package/dist/src/runtime/topology.d.mts +51 -0
- package/dist/src/runtime/topology.mjs +128 -0
- package/dist/src/shared/diagnostics.d.mts +97 -0
- package/dist/src/shared/diagnostics.mjs +170 -0
- package/dist/src/shared/human_output.d.mts +2 -0
- package/{src → dist/src}/shared/human_output.mjs +1 -3
- package/dist/src/shared/node_runtime.d.mts +14 -0
- package/dist/src/shared/node_runtime.mjs +25 -0
- package/dist/src/shared/operation_guard.d.mts +22 -0
- package/dist/src/shared/operation_guard.mjs +150 -0
- package/dist/src/shared/process_environment.d.mts +15 -0
- package/dist/src/shared/process_environment.mjs +50 -0
- package/dist/src/source/access.d.mts +165 -0
- package/dist/src/source/access.mjs +602 -0
- package/dist/src/source/asset_transfer.d.mts +27 -0
- package/dist/src/source/asset_transfer.mjs +202 -0
- package/dist/src/source/baseline.d.mts +66 -0
- package/dist/src/source/baseline.mjs +372 -0
- package/dist/src/source/external_reader.d.mts +42 -0
- package/dist/src/source/external_reader.mjs +278 -0
- package/dist/src/source/postgresql_access.d.mts +86 -0
- package/dist/src/source/postgresql_access.mjs +454 -0
- package/dist/src/source/privacy_paths.d.mts +10 -0
- package/dist/src/source/privacy_paths.mjs +27 -0
- package/dist/src/targets/driver.d.mts +2 -0
- package/dist/src/targets/driver.mjs +13 -0
- package/dist/src/targets/postgresql.d.mts +5 -0
- package/dist/src/targets/postgresql.mjs +641 -0
- package/dist/src/targets/supabase.d.mts +8 -0
- package/dist/src/targets/supabase.mjs +659 -0
- package/dist/src/targets/supabase_environment.d.mts +49 -0
- package/dist/src/targets/supabase_environment.mjs +162 -0
- package/dist/src/targets/target.d.mts +33 -0
- package/dist/src/targets/target.mjs +39 -0
- package/docs/README.md +1 -0
- package/docs/architecture.md +17 -9
- package/docs/configuration.md +49 -8
- package/docs/getting-started.md +28 -0
- package/docs/index.md +1 -0
- package/docs/production-source.md +43 -7
- package/docs/releasing.md +5 -3
- package/docs/roadmap.md +3 -2
- package/docs/sanitization.md +415 -14
- package/docs/standalone-workflow.md +12 -6
- package/docs/troubleshooting.md +5 -1
- package/docs/tutorial.md +5 -0
- package/docs/typescript.md +87 -0
- package/package.json +35 -29
- package/scripts/install/create_root_config.mjs +0 -36
- package/src/README.md +0 -17
- package/src/application/session.mjs +0 -435
- package/src/baseline/artifact.mjs +0 -684
- package/src/baseline/builder.mjs +0 -164
- package/src/baseline/input_discovery.mjs +0 -155
- package/src/baseline/policy_review.mjs +0 -92
- package/src/baseline/preparation.mjs +0 -323
- package/src/baseline/privacy_engine.mjs +0 -952
- package/src/baseline/sanitization_policy.mjs +0 -299
- package/src/baseline/schema_snapshot.mjs +0 -113
- package/src/cli/arguments.mjs +0 -126
- package/src/cli/guided.mjs +0 -814
- package/src/cli/init_command.mjs +0 -94
- package/src/cli/rehearsal.mjs +0 -970
- package/src/cli/renderers.mjs +0 -626
- package/src/cli/runtime_commands.mjs +0 -707
- package/src/cli/source_commands.mjs +0 -347
- package/src/cli/terminal.mjs +0 -275
- package/src/identity/claim.mjs +0 -1163
- package/src/identity/provider_configuration.mjs +0 -177
- package/src/identity/storage.mjs +0 -165
- package/src/project/configuration.mjs +0 -1337
- package/src/project/install_scaffold.mjs +0 -291
- package/src/project/setup.mjs +0 -466
- package/src/project/support_report.mjs +0 -105
- package/src/runtime/cleanup.mjs +0 -381
- package/src/runtime/migration_history.mjs +0 -220
- package/src/runtime/plan.mjs +0 -722
- package/src/runtime/policy.mjs +0 -438
- package/src/runtime/restore.mjs +0 -337
- package/src/runtime/service_environment.mjs +0 -82
- package/src/runtime/topology.mjs +0 -177
- package/src/shared/diagnostics.mjs +0 -207
- package/src/shared/node_runtime.mjs +0 -31
- package/src/shared/operation_guard.mjs +0 -162
- package/src/shared/process_environment.mjs +0 -68
- package/src/source/access.mjs +0 -753
- package/src/source/asset_transfer.mjs +0 -207
- package/src/source/baseline.mjs +0 -482
- package/src/source/external_reader.mjs +0 -255
- package/src/source/postgresql_access.mjs +0 -581
- package/src/source/privacy_paths.mjs +0 -38
- package/src/targets/postgresql.mjs +0 -808
- package/src/targets/supabase.mjs +0 -840
- package/src/targets/supabase_environment.mjs +0 -229
- package/src/targets/target.mjs +0 -66
- /package/{src/project → types}/configuration.d.mts +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Purpose: Start and inspect local-only Supabase workdirs without inheriting hosted
|
|
3
|
+
* credentials. Do not run directly; this module is reusable script infrastructure.
|
|
4
|
+
*/
|
|
5
|
+
import { type ProcessEnvironment } from "../shared/process_environment.mjs";
|
|
6
|
+
export interface LocalSupabaseEnvironment {
|
|
7
|
+
readonly apiUrl: string;
|
|
8
|
+
readonly databaseUrl: string;
|
|
9
|
+
readonly publishableKey: string;
|
|
10
|
+
readonly serviceRoleKey: string;
|
|
11
|
+
readonly studioUrl: string | undefined;
|
|
12
|
+
readonly databaseHost: string;
|
|
13
|
+
readonly databasePort: string;
|
|
14
|
+
readonly databaseName: string;
|
|
15
|
+
readonly databaseUser: string;
|
|
16
|
+
readonly databasePassword: string;
|
|
17
|
+
}
|
|
18
|
+
interface LocalCommandOptions {
|
|
19
|
+
readonly capture?: boolean;
|
|
20
|
+
readonly cwd?: string | undefined;
|
|
21
|
+
readonly input?: string | Uint8Array;
|
|
22
|
+
readonly environment?: ProcessEnvironment;
|
|
23
|
+
readonly maxBuffer?: number;
|
|
24
|
+
}
|
|
25
|
+
interface SupabaseCommandOptions {
|
|
26
|
+
readonly cwd?: string | undefined;
|
|
27
|
+
readonly workdir?: string | undefined;
|
|
28
|
+
readonly environment?: ProcessEnvironment;
|
|
29
|
+
}
|
|
30
|
+
export declare const parseSupabaseStatusEnvironment: (output: string) => Record<string, string>;
|
|
31
|
+
export declare const parseLocalSupabaseEnvironment: (output: string) => LocalSupabaseEnvironment;
|
|
32
|
+
export declare const runLocalCommand: (command: string, args: readonly string[], { capture, cwd, input, environment, maxBuffer, }?: LocalCommandOptions) => string;
|
|
33
|
+
export declare const localCommandSucceeds: (command: string, args: readonly string[], { cwd, environment, }?: Pick<LocalCommandOptions, "cwd" | "environment">) => boolean;
|
|
34
|
+
export declare const ensureLocalContainerRuntime: ({ cwd, autoStartColima, }?: {
|
|
35
|
+
cwd?: string | undefined;
|
|
36
|
+
autoStartColima?: boolean;
|
|
37
|
+
}) => void;
|
|
38
|
+
export declare const readLocalSupabaseEnvironment: ({ cwd, workdir, environment, }?: SupabaseCommandOptions) => LocalSupabaseEnvironment;
|
|
39
|
+
export declare const startLocalSupabase: ({ cwd, workdir, exclude, environment, applyMigrations, autoStartColima, }?: SupabaseCommandOptions & {
|
|
40
|
+
exclude?: readonly string[];
|
|
41
|
+
applyMigrations?: boolean;
|
|
42
|
+
autoStartColima?: boolean;
|
|
43
|
+
}) => LocalSupabaseEnvironment;
|
|
44
|
+
export declare const stopLocalSupabase: ({ cwd, workdir, environment, }?: SupabaseCommandOptions) => void;
|
|
45
|
+
export declare const removeLocalSupabaseProjectResources: ({ cwd, projectId, }?: {
|
|
46
|
+
cwd?: string;
|
|
47
|
+
projectId?: string;
|
|
48
|
+
}) => void;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Purpose: Start and inspect local-only Supabase workdirs without inheriting hosted
|
|
3
|
+
* credentials. Do not run directly; this module is reusable script infrastructure.
|
|
4
|
+
*/
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
import { createCleanProcessEnvironment, } from "../shared/process_environment.mjs";
|
|
7
|
+
export const parseSupabaseStatusEnvironment = (output) => {
|
|
8
|
+
const values = {};
|
|
9
|
+
for (const line of output.split("\n")) {
|
|
10
|
+
const match = line.match(/^([A-Z][A-Z0-9_]*)=(.*)$/u);
|
|
11
|
+
if (!match)
|
|
12
|
+
continue;
|
|
13
|
+
const key = match[1];
|
|
14
|
+
const rawValue = match[2];
|
|
15
|
+
if (key === undefined || rawValue === undefined)
|
|
16
|
+
continue;
|
|
17
|
+
let value = rawValue.trim();
|
|
18
|
+
if (value.startsWith('"') && value.endsWith('"')) {
|
|
19
|
+
const parsed = JSON.parse(value);
|
|
20
|
+
if (typeof parsed !== "string")
|
|
21
|
+
continue;
|
|
22
|
+
value = parsed;
|
|
23
|
+
}
|
|
24
|
+
values[key] = value;
|
|
25
|
+
}
|
|
26
|
+
return values;
|
|
27
|
+
};
|
|
28
|
+
export const parseLocalSupabaseEnvironment = (output) => {
|
|
29
|
+
const values = parseSupabaseStatusEnvironment(output);
|
|
30
|
+
const required = (label, value) => {
|
|
31
|
+
if (!value)
|
|
32
|
+
throw new Error(`Local Supabase status omitted its ${label}.`);
|
|
33
|
+
return value;
|
|
34
|
+
};
|
|
35
|
+
const apiUrl = required("API URL", values.API_URL);
|
|
36
|
+
const databaseUrl = required("database URL", values.DB_URL);
|
|
37
|
+
const publishableKey = required("publishable key", values.PUBLISHABLE_KEY ?? values.ANON_KEY);
|
|
38
|
+
const serviceRoleKey = required("service-role key", values.SERVICE_ROLE_KEY ?? values.SECRET_KEY);
|
|
39
|
+
const api = new URL(apiUrl);
|
|
40
|
+
const database = new URL(databaseUrl);
|
|
41
|
+
const loopbackHosts = ["127.0.0.1", "::1", "localhost"];
|
|
42
|
+
if (!loopbackHosts.includes(api.hostname) ||
|
|
43
|
+
!loopbackHosts.includes(database.hostname) ||
|
|
44
|
+
!["postgres:", "postgresql:"].includes(database.protocol)) {
|
|
45
|
+
throw new Error("Refusing to use a non-local Supabase status target.");
|
|
46
|
+
}
|
|
47
|
+
const databaseName = decodeURIComponent(database.pathname.replace(/^\//u, ""));
|
|
48
|
+
if (!database.port ||
|
|
49
|
+
!databaseName ||
|
|
50
|
+
!database.username ||
|
|
51
|
+
!database.password) {
|
|
52
|
+
throw new Error("Local Supabase status returned an incomplete database URL.");
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
apiUrl,
|
|
56
|
+
databaseUrl,
|
|
57
|
+
publishableKey,
|
|
58
|
+
serviceRoleKey,
|
|
59
|
+
studioUrl: values.STUDIO_URL,
|
|
60
|
+
databaseHost: database.hostname,
|
|
61
|
+
databasePort: database.port,
|
|
62
|
+
databaseName,
|
|
63
|
+
databaseUser: decodeURIComponent(database.username),
|
|
64
|
+
databasePassword: decodeURIComponent(database.password),
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
export const runLocalCommand = (command, args, { capture = false, cwd = process.cwd(), input, environment = {}, maxBuffer = 16 * 1024 * 1024, } = {}) => {
|
|
68
|
+
const shouldPipe = capture || input !== undefined;
|
|
69
|
+
const result = spawnSync(command, args, {
|
|
70
|
+
cwd,
|
|
71
|
+
encoding: "utf8",
|
|
72
|
+
env: createCleanProcessEnvironment({ overrides: environment }),
|
|
73
|
+
input,
|
|
74
|
+
maxBuffer,
|
|
75
|
+
stdio: shouldPipe ? ["pipe", "pipe", "pipe"] : "inherit",
|
|
76
|
+
});
|
|
77
|
+
if (result.error)
|
|
78
|
+
throw result.error;
|
|
79
|
+
if (result.status !== 0) {
|
|
80
|
+
const detail = [result.stdout, result.stderr]
|
|
81
|
+
.filter(Boolean)
|
|
82
|
+
.join("\n")
|
|
83
|
+
.trim();
|
|
84
|
+
throw new Error(`${command} ${args.join(" ")} failed${detail ? `:\n${detail}` : "."}`);
|
|
85
|
+
}
|
|
86
|
+
return result.stdout ?? "";
|
|
87
|
+
};
|
|
88
|
+
export const localCommandSucceeds = (command, args, { cwd = process.cwd(), environment = {}, } = {}) => spawnSync(command, args, {
|
|
89
|
+
cwd,
|
|
90
|
+
env: createCleanProcessEnvironment({ overrides: environment }),
|
|
91
|
+
stdio: "ignore",
|
|
92
|
+
}).status === 0;
|
|
93
|
+
export const ensureLocalContainerRuntime = ({ cwd = process.cwd(), autoStartColima = true, } = {}) => {
|
|
94
|
+
if (localCommandSucceeds("docker", ["info"], { cwd }))
|
|
95
|
+
return;
|
|
96
|
+
if (autoStartColima && localCommandSucceeds("colima", ["version"], { cwd })) {
|
|
97
|
+
runLocalCommand("colima", ["start"], { cwd });
|
|
98
|
+
}
|
|
99
|
+
if (!localCommandSucceeds("docker", ["info"], { cwd })) {
|
|
100
|
+
throw new Error("A local Docker-compatible runtime is required. Install Docker or Colima, then rerun the command.");
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const withWorkdir = (args, workdir) => (workdir ? [...args, "--workdir", workdir] : [...args]);
|
|
104
|
+
export const readLocalSupabaseEnvironment = ({ cwd, workdir, environment = {}, } = {}) => {
|
|
105
|
+
const output = runLocalCommand("supabase", withWorkdir(["status", "-o", "env"], workdir), { capture: true, cwd, environment });
|
|
106
|
+
return parseLocalSupabaseEnvironment(output);
|
|
107
|
+
};
|
|
108
|
+
export const startLocalSupabase = ({ cwd, workdir, exclude = [], environment = {}, applyMigrations = true, autoStartColima = true, } = {}) => {
|
|
109
|
+
ensureLocalContainerRuntime({ cwd, autoStartColima });
|
|
110
|
+
const startArguments = withWorkdir(["start", ...(exclude.length ? ["--exclude", exclude.join(",")] : [])], workdir);
|
|
111
|
+
runLocalCommand("supabase", startArguments, {
|
|
112
|
+
capture: true,
|
|
113
|
+
cwd,
|
|
114
|
+
environment,
|
|
115
|
+
});
|
|
116
|
+
if (applyMigrations) {
|
|
117
|
+
runLocalCommand("supabase", withWorkdir(["migration", "up", "--local"], workdir), { capture: true, cwd, environment });
|
|
118
|
+
}
|
|
119
|
+
return readLocalSupabaseEnvironment({ cwd, workdir, environment });
|
|
120
|
+
};
|
|
121
|
+
export const stopLocalSupabase = ({ cwd, workdir, environment = {}, } = {}) => {
|
|
122
|
+
if (!localCommandSucceeds("docker", ["info"], { cwd }))
|
|
123
|
+
return;
|
|
124
|
+
runLocalCommand("supabase", withWorkdir(["stop"], workdir), {
|
|
125
|
+
cwd,
|
|
126
|
+
environment,
|
|
127
|
+
});
|
|
128
|
+
};
|
|
129
|
+
export const removeLocalSupabaseProjectResources = ({ cwd = process.cwd(), projectId, } = {}) => {
|
|
130
|
+
if (!/^[a-z0-9][a-z0-9-]{1,62}$/u.test(projectId ?? "")) {
|
|
131
|
+
throw new Error("Refusing to remove local Supabase resources without an exact safe project id.");
|
|
132
|
+
}
|
|
133
|
+
const label = `com.supabase.cli.project=${projectId}`;
|
|
134
|
+
const list = (resource, format) => runLocalCommand("docker", [resource, "ls", "--filter", `label=${label}`, "--format", format], { capture: true, cwd })
|
|
135
|
+
.split("\n")
|
|
136
|
+
.map((value) => value.trim())
|
|
137
|
+
.filter(Boolean);
|
|
138
|
+
const containers = runLocalCommand("docker", ["ps", "--all", "--filter", `label=${label}`, "--format", "{{.ID}}"], { capture: true, cwd })
|
|
139
|
+
.split("\n")
|
|
140
|
+
.map((value) => value.trim())
|
|
141
|
+
.filter(Boolean);
|
|
142
|
+
if (containers.length) {
|
|
143
|
+
runLocalCommand("docker", ["rm", "--force", ...containers], {
|
|
144
|
+
capture: true,
|
|
145
|
+
cwd,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
const volumes = list("volume", "{{.Name}}");
|
|
149
|
+
if (volumes.length) {
|
|
150
|
+
runLocalCommand("docker", ["volume", "rm", "--force", ...volumes], {
|
|
151
|
+
capture: true,
|
|
152
|
+
cwd,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
const networks = list("network", "{{.ID}}");
|
|
156
|
+
if (networks.length) {
|
|
157
|
+
runLocalCommand("docker", ["network", "rm", ...networks], {
|
|
158
|
+
capture: true,
|
|
159
|
+
cwd,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Purpose: Define the small, closed set of database runtimes Rehearsal can select.
|
|
3
|
+
* Runtime implementations stay behind this boundary so the shared CLI does not
|
|
4
|
+
* need target-specific branches.
|
|
5
|
+
*/
|
|
6
|
+
declare const TARGETS: Readonly<{
|
|
7
|
+
supabase: Readonly<{
|
|
8
|
+
id: "supabase";
|
|
9
|
+
label: "Supabase";
|
|
10
|
+
}>;
|
|
11
|
+
postgresql: Readonly<{
|
|
12
|
+
id: "postgresql";
|
|
13
|
+
label: "PostgreSQL";
|
|
14
|
+
}>;
|
|
15
|
+
}>;
|
|
16
|
+
export type RehearsalRuntimeTargetId = keyof typeof TARGETS;
|
|
17
|
+
export type RehearsalRuntimeTarget = (typeof TARGETS)[RehearsalRuntimeTargetId];
|
|
18
|
+
export interface RuntimeInvocation {
|
|
19
|
+
readonly action: string;
|
|
20
|
+
readonly configPath: string | undefined;
|
|
21
|
+
readonly confirmation: string | undefined;
|
|
22
|
+
}
|
|
23
|
+
export interface RuntimeManagerArguments {
|
|
24
|
+
managerPath: string;
|
|
25
|
+
action: string;
|
|
26
|
+
configPath?: string;
|
|
27
|
+
confirmation?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare const REHEARSAL_RUNTIME_TARGETS: readonly ("postgresql" | "supabase")[];
|
|
30
|
+
export declare const parseRuntimeInvocation: (arguments_?: readonly string[]) => RuntimeInvocation;
|
|
31
|
+
export declare const buildRuntimeManagerArguments: ({ managerPath, action, configPath, confirmation, }: RuntimeManagerArguments) => string[];
|
|
32
|
+
export declare const resolveRuntimeTarget: (value?: unknown) => RehearsalRuntimeTarget;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Purpose: Define the small, closed set of database runtimes Rehearsal can select.
|
|
3
|
+
* Runtime implementations stay behind this boundary so the shared CLI does not
|
|
4
|
+
* need target-specific branches.
|
|
5
|
+
*/
|
|
6
|
+
const TARGETS = Object.freeze({
|
|
7
|
+
supabase: Object.freeze({
|
|
8
|
+
id: "supabase",
|
|
9
|
+
label: "Supabase",
|
|
10
|
+
}),
|
|
11
|
+
postgresql: Object.freeze({
|
|
12
|
+
id: "postgresql",
|
|
13
|
+
label: "PostgreSQL",
|
|
14
|
+
}),
|
|
15
|
+
});
|
|
16
|
+
export const REHEARSAL_RUNTIME_TARGETS = Object.freeze(Object.keys(TARGETS));
|
|
17
|
+
export const parseRuntimeInvocation = (arguments_ = process.argv.slice(2)) => {
|
|
18
|
+
const action = arguments_.find((argument) => !argument.startsWith("--"));
|
|
19
|
+
const valueAfter = (prefix) => arguments_
|
|
20
|
+
.find((argument) => argument.startsWith(prefix))
|
|
21
|
+
?.slice(prefix.length);
|
|
22
|
+
return Object.freeze({
|
|
23
|
+
action: action ?? "status",
|
|
24
|
+
configPath: valueAfter("--config="),
|
|
25
|
+
confirmation: valueAfter("--confirm-candidates="),
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
export const buildRuntimeManagerArguments = ({ managerPath, action, configPath, confirmation, }) => [
|
|
29
|
+
managerPath,
|
|
30
|
+
action,
|
|
31
|
+
...(configPath ? [`--config=${configPath}`] : []),
|
|
32
|
+
...(confirmation ? [`--confirm-candidates=${confirmation}`] : []),
|
|
33
|
+
];
|
|
34
|
+
export const resolveRuntimeTarget = (value = "supabase") => {
|
|
35
|
+
if (typeof value !== "string" || !Object.hasOwn(TARGETS, value)) {
|
|
36
|
+
throw new Error(`Unsupported Rehearsal runtime target: ${String(value)}. Supported targets: ${REHEARSAL_RUNTIME_TARGETS.join(", ")}.`);
|
|
37
|
+
}
|
|
38
|
+
return TARGETS[value];
|
|
39
|
+
};
|
package/docs/README.md
CHANGED
|
@@ -24,6 +24,7 @@ want to accomplish and follow that path.
|
|
|
24
24
|
|
|
25
25
|
- [CLI commands](commands.md)
|
|
26
26
|
- [Configuration](configuration.md)
|
|
27
|
+
- [TypeScript](typescript.md)
|
|
27
28
|
- [Runtime and identity policies](runtime-policies.md)
|
|
28
29
|
- [Database adapters](adapters.md)
|
|
29
30
|
- [Glossary](glossary.md)
|
package/docs/architecture.md
CHANGED
|
@@ -5,7 +5,7 @@ documentation so each file has one obvious home.
|
|
|
5
5
|
|
|
6
6
|
```text
|
|
7
7
|
rehearsal-db/
|
|
8
|
-
├── src/
|
|
8
|
+
├── src/ TypeScript product source
|
|
9
9
|
│ ├── application/ application lifecycle and HTTP proofs
|
|
10
10
|
│ ├── baseline/ sanitized baseline creation and validation
|
|
11
11
|
│ ├── cli/ the `rehearsal` executable
|
|
@@ -16,8 +16,12 @@ rehearsal-db/
|
|
|
16
16
|
│ ├── source/ approved source access and refresh
|
|
17
17
|
│ └── targets/ PostgreSQL and Supabase adapters
|
|
18
18
|
├── scripts/
|
|
19
|
-
│ ├──
|
|
19
|
+
│ ├── build/ clean TypeScript compilation helpers
|
|
20
|
+
│ ├── install/ TypeScript install-hook source
|
|
21
|
+
│ ├── runtime/ TypeScript runtime-launcher source
|
|
20
22
|
│ └── verification/ repository-only package and fixture proofs
|
|
23
|
+
├── dist/ generated ESM and declaration output; never edit directly
|
|
24
|
+
├── types/ reviewed public root declaration contract
|
|
21
25
|
├── tests/
|
|
22
26
|
│ ├── unit/ mirrors the `src/` domains
|
|
23
27
|
│ ├── integration/ multi-module and terminal behavior
|
|
@@ -29,6 +33,7 @@ rehearsal-db/
|
|
|
29
33
|
## Boundaries
|
|
30
34
|
|
|
31
35
|
- `src/` must never import from tests or repository-only verification scripts.
|
|
36
|
+
- `dist/` is rebuilt from TypeScript before tests and packaging; never hand-edit it.
|
|
32
37
|
- Database-specific lifecycle behavior belongs in `src/targets/`.
|
|
33
38
|
- `scripts/verification/` is never included in the npm package.
|
|
34
39
|
- Public consumers use only the paths declared in `package.json#exports`.
|
|
@@ -40,13 +45,13 @@ rehearsal-db/
|
|
|
40
45
|
The executable is split by responsibility so no command file becomes a second
|
|
41
46
|
application layer:
|
|
42
47
|
|
|
43
|
-
- `rehearsal.
|
|
44
|
-
- `arguments.
|
|
45
|
-
- `guided.
|
|
46
|
-
- `runtime_commands.
|
|
47
|
-
- `source_commands.
|
|
48
|
-
- `renderers.
|
|
49
|
-
- `terminal.
|
|
48
|
+
- `rehearsal.mts` starts the process and dispatches commands.
|
|
49
|
+
- `arguments.mts` owns the command-line contract and mutation classification.
|
|
50
|
+
- `guided.mts` owns the interactive home screen and first-run questions.
|
|
51
|
+
- `runtime_commands.mts` coordinates local runtimes and project proofs.
|
|
52
|
+
- `source_commands.mts` coordinates approved source access and refresh.
|
|
53
|
+
- `renderers.mts` formats human-readable results without changing state.
|
|
54
|
+
- `terminal.mts` owns prompts, colors, and terminal exit behavior.
|
|
50
55
|
|
|
51
56
|
## Adding something new
|
|
52
57
|
|
|
@@ -56,3 +61,6 @@ application layer:
|
|
|
56
61
|
4. Add an integration or contract test only when behavior crosses domains or becomes a
|
|
57
62
|
public promise.
|
|
58
63
|
5. Update the documentation map when adding a new guide.
|
|
64
|
+
|
|
65
|
+
Run `npm run build` after changing TypeScript source. Tests import the generated package
|
|
66
|
+
code so the same JavaScript boundary consumers install is exercised locally.
|
package/docs/configuration.md
CHANGED
|
@@ -25,6 +25,11 @@ Use this page when changing the generated file. The schema is strict: misspelled
|
|
|
25
25
|
unknown fields, and unsupported versions are errors. The `.mjs` extension works in both
|
|
26
26
|
CommonJS and ESM projects.
|
|
27
27
|
|
|
28
|
+
The generated file also receives editor and compiler checking through the package's
|
|
29
|
+
public TypeScript declarations. See [TypeScript](typescript.md) for the supported type
|
|
30
|
+
surface and checked examples. Keep the runnable configuration as `.mjs`; a project does
|
|
31
|
+
not need to rename it to `.ts`.
|
|
32
|
+
|
|
28
33
|
```ts
|
|
29
34
|
// @ts-check
|
|
30
35
|
import { defineRehearsalConfig } from "@rehearsal-db/core";
|
|
@@ -130,15 +135,20 @@ All paths resolve inside the consuming project. The artifact directory must be n
|
|
|
130
135
|
`.rehearsal`; this is an intentional deletion guard. `runtimeWorkdir` must be its
|
|
131
136
|
`runtime` child, and the generated application environment file must remain inside it.
|
|
132
137
|
|
|
133
|
-
Rehearsal never overwrites this config.
|
|
134
|
-
safe, run setup again, and compare the two files before deleting either one.
|
|
135
|
-
|
|
138
|
+
Rehearsal never overwrites this config. Do not move it merely to inspect a newer template.
|
|
136
139
|
After upgrading, run `npx rehearsal init` to print the current release's generated
|
|
137
140
|
template beside the path of your existing config. This comparison is read-only; adding a
|
|
138
141
|
new optional key remains your decision. `npx rehearsal init --write` still refuses to
|
|
139
142
|
replace an existing config. Rehearsal lists important optional settings that are
|
|
140
143
|
available but not enabled before printing the template, so they are easier to find.
|
|
141
144
|
|
|
145
|
+
If setup was interrupted after creating only some files, rerun
|
|
146
|
+
`npx rehearsal setup --write`. It recreates missing generated files while preserving every
|
|
147
|
+
existing config and local runtime file. When a config itself is invalid, keep it as a
|
|
148
|
+
backup, generate a fresh file, and manually carry over only reviewed settings. See
|
|
149
|
+
[Getting started](getting-started.md#if-setup-or-an-upgrade-is-interrupted) for the short
|
|
150
|
+
recovery table.
|
|
151
|
+
|
|
142
152
|
### Workspaces and custom paths
|
|
143
153
|
|
|
144
154
|
For an npm workspace, automatic creation proceeds only when exactly one application
|
|
@@ -151,8 +161,38 @@ checkout never receive project files.
|
|
|
151
161
|
|
|
152
162
|
Supported existing config paths—including
|
|
153
163
|
`infrastructure/rehearsal/rehearsal.config.mjs`—are preserved, and a second root config
|
|
154
|
-
is not created.
|
|
155
|
-
|
|
164
|
+
is not created. The install hook reports the exact active path when npm displays lifecycle
|
|
165
|
+
output, and setup always prints it. `npx rehearsal init --json` is the package-manager-
|
|
166
|
+
independent way to check the `destination`. Rehearsal checks the supported root filenames
|
|
167
|
+
first and then the supported nested filenames; finding any one of them prevents automatic
|
|
168
|
+
creation of another. Use
|
|
169
|
+
`--config=<project-relative-path>` for other explicit paths when running commands.
|
|
170
|
+
|
|
171
|
+
### Move an existing config to the project root
|
|
172
|
+
|
|
173
|
+
Relocation is deliberately manual because the config may contain reviewed settings and
|
|
174
|
+
JavaScript imports. Rehearsal will never move it or create a competing root file.
|
|
175
|
+
|
|
176
|
+
From the directory containing `package.json`:
|
|
177
|
+
|
|
178
|
+
1. Stop active Rehearsal commands and confirm the current path with
|
|
179
|
+
`npx rehearsal init --json`.
|
|
180
|
+
2. Make a backup outside every supported discovery path, such as
|
|
181
|
+
`.rehearsal/config-backups/rehearsal.config.mjs`.
|
|
182
|
+
3. Move—do not copy—the active file to `./rehearsal.config.mjs`. Use `git mv` when it is
|
|
183
|
+
tracked so review history remains clear.
|
|
184
|
+
4. Update relative JavaScript `import` specifiers inside the moved file. Imports resolve
|
|
185
|
+
from the config file's own folder, so a nested `../../something.mjs` import usually
|
|
186
|
+
changes after moving to the root.
|
|
187
|
+
5. Leave config values such as `migrationDirectory`, `sanitizationPolicy`,
|
|
188
|
+
`runtimePolicy`, `identityPolicy`, and `dependentTargets[].configPath` unchanged unless
|
|
189
|
+
the referenced project file also moved. Rehearsal resolves those values from the
|
|
190
|
+
project root, not from the config file's folder.
|
|
191
|
+
6. Run `npx rehearsal init --json`, confirm its `destination` is
|
|
192
|
+
`rehearsal.config.mjs`, then run `npx rehearsal doctor` and review the Git diff.
|
|
193
|
+
|
|
194
|
+
If validation fails, restore the backup to its original path. Do not run setup while the
|
|
195
|
+
move is half-finished; setup may correctly conclude that no supported config exists.
|
|
156
196
|
|
|
157
197
|
`preparation.privacyKey` must stay inside `.rehearsal`; it is ignored and owner-readable
|
|
158
198
|
only. Source, runtime, and identity policy files are declarations that may be reviewed in
|
|
@@ -431,9 +471,10 @@ may use these explicit subpaths:
|
|
|
431
471
|
- `@rehearsal-db/core/service-environment`
|
|
432
472
|
- `@rehearsal-db/core/source-access`
|
|
433
473
|
|
|
434
|
-
These advanced entry points
|
|
435
|
-
configuration and sanitization
|
|
436
|
-
|
|
474
|
+
These advanced entry points ship as ordinary ESM JavaScript with generated TypeScript
|
|
475
|
+
declarations. The root configuration and sanitization contract remains the explicitly
|
|
476
|
+
reviewed public type surface. The exact current boundary is documented in
|
|
477
|
+
[TypeScript](typescript.md).
|
|
437
478
|
|
|
438
479
|
Undocumented files under `scripts/` are package internals and are not compatibility
|
|
439
480
|
contracts.
|
package/docs/getting-started.md
CHANGED
|
@@ -48,6 +48,11 @@ especially:
|
|
|
48
48
|
- the application start and proof commands;
|
|
49
49
|
- the local ports.
|
|
50
50
|
|
|
51
|
+
If a supported configuration already exists elsewhere—such as
|
|
52
|
+
`infrastructure/rehearsal/rehearsal.config.mjs`—the installer reports that exact active
|
|
53
|
+
path and does not generate a competing root file. Keep using it, or follow the explicit
|
|
54
|
+
[root relocation guide](configuration.md#move-an-existing-config-to-the-project-root).
|
|
55
|
+
|
|
51
56
|
If lifecycle scripts were disabled, a global/cache install was used, or a workspace has
|
|
52
57
|
more than one possible application, no project files are created automatically. Run
|
|
53
58
|
`npx rehearsal` inside the intended application, choose **Set the stage**, select
|
|
@@ -180,6 +185,29 @@ config during an upgrade. After upgrading, run `npx rehearsal init` to see impor
|
|
|
180
185
|
optional settings you have not enabled and compare your file with the installed
|
|
181
186
|
release's current template.
|
|
182
187
|
|
|
188
|
+
### If setup or an upgrade is interrupted
|
|
189
|
+
|
|
190
|
+
Do not delete `.rehearsal/` or your existing config. Start with:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
npx rehearsal doctor
|
|
194
|
+
npx rehearsal init
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Use the reported problem to choose the smallest recovery:
|
|
198
|
+
|
|
199
|
+
| Problem | Safe recovery |
|
|
200
|
+
| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
201
|
+
| A generated runtime file is missing | Run `npx rehearsal setup --write`. Existing files stay unchanged; only missing files are created. |
|
|
202
|
+
| A port is already in use | Stop the conflicting local process or choose new dedicated ports, then rerun setup. |
|
|
203
|
+
| The config is malformed | Move it to a backup name, run `npx rehearsal setup --write`, then copy reviewed choices into the new file. |
|
|
204
|
+
| OAuth credentials are missing | Create the ignored file named by `supabase.authentication.environmentFile`, add only the declared keys, and run `chmod 600` on it. Ambient shell credentials are not used. |
|
|
205
|
+
| An npm upgrade fails | Keep the existing config, baseline, and lockfile. Restore dependencies with your package manager, then run `npx rehearsal init` before retrying. |
|
|
206
|
+
| Docker storage is low | Run `npx rehearsal cleanup` for an exact preview. Rehearsal never performs a global Docker prune or silently removes volumes. |
|
|
207
|
+
|
|
208
|
+
`setup --write` and package installation never replace a config. If an existing file is
|
|
209
|
+
invalid, Rehearsal fails closed and leaves it available for comparison.
|
|
210
|
+
|
|
183
211
|
## Files Rehearsal creates
|
|
184
212
|
|
|
185
213
|
- `rehearsal.config.mjs` — reviewed project configuration
|
package/docs/index.md
CHANGED
|
@@ -11,6 +11,7 @@ you want, then follow the links when a term or safety check is new.
|
|
|
11
11
|
| Try Rehearsal without touching my app | [Hands-on tutorial](tutorial.md) |
|
|
12
12
|
| Understand what makes a copy safe | [Baselines](baselines.md) and [Sanitization](sanitization.md) |
|
|
13
13
|
| Look up a command or setting | [CLI commands](commands.md) and [Configuration](configuration.md) |
|
|
14
|
+
| Add editor and compiler type checks | [TypeScript](typescript.md) |
|
|
14
15
|
| Fix something that did not work | [Troubleshooting](troubleshooting.md) |
|
|
15
16
|
|
|
16
17
|
## The short version
|
|
@@ -23,6 +23,15 @@ The privacy key stays ignored under `.rehearsal`. The policy is safe to review i
|
|
|
23
23
|
control because it contains hashes and environment-variable names, not credentials,
|
|
24
24
|
URLs, or raw owner identifiers.
|
|
25
25
|
|
|
26
|
+
`credentialFile` must be inside the selected target's
|
|
27
|
+
`baseline.artifactDirectory`, under its `secrets` folder. With the default artifact
|
|
28
|
+
directory, use `.rehearsal/secrets/source-reader.env`. For a target whose artifact
|
|
29
|
+
directory is `targets/primary/.rehearsal`, use
|
|
30
|
+
`targets/primary/.rehearsal/secrets/source-reader.env` and place `privacyKey` there as
|
|
31
|
+
well. Rehearsal stores that target's access receipt beside its baseline at
|
|
32
|
+
`targets/primary/.rehearsal/source-access-receipt.json`; separate targets never share
|
|
33
|
+
the receipt or credential.
|
|
34
|
+
|
|
26
35
|
## 2. Declare the source boundary
|
|
27
36
|
|
|
28
37
|
`source-access-policy.json` uses this shape:
|
|
@@ -112,6 +121,7 @@ an administrator credential or change the source:
|
|
|
112
121
|
"reader": {
|
|
113
122
|
"mode": "external",
|
|
114
123
|
"role": "provided_rehearsal_reader",
|
|
124
|
+
"allowedMemberships": ["provided_rehearsal_readers"],
|
|
115
125
|
"connectionEnvironmentVariable": "REHEARSAL_SOURCE_READER_URL",
|
|
116
126
|
"credentialFile": ".rehearsal/secrets/source-reader.env",
|
|
117
127
|
"maximumValidForMinutes": 30
|
|
@@ -153,9 +163,25 @@ view hash, columns, scopes, or reader declaration requires a new verification.
|
|
|
153
163
|
|
|
154
164
|
External mode also requires all non-system readable columns to match only the declared
|
|
155
165
|
views and migration-ledger columns. It refuses database, schema, relation, or column
|
|
156
|
-
writes;
|
|
157
|
-
|
|
158
|
-
|
|
166
|
+
writes; privileged role attributes; executable non-system security-definer functions;
|
|
167
|
+
a reader-owned view; or a database-enforced expiration beyond
|
|
168
|
+
`maximumValidForMinutes`.
|
|
169
|
+
|
|
170
|
+
This audit is intentionally conservative: an object-level table, column, sequence, or
|
|
171
|
+
function grant remains disallowed even when its schema currently lacks `USAGE`. Do not
|
|
172
|
+
use schema visibility to hide stale grants. Revoke the object grant or move the approved
|
|
173
|
+
surface behind the reviewed export views; this also avoids relying on behavior of an
|
|
174
|
+
already-open or prepared database session.
|
|
175
|
+
|
|
176
|
+
An external login may inherit its narrow permissions from provider-owned group roles.
|
|
177
|
+
List every direct group in `allowedMemberships`; omit the field or use `[]` when the
|
|
178
|
+
login has direct grants only. Rehearsal requires the observed membership set to match
|
|
179
|
+
that list exactly. Every allowed group must be non-login and non-privileged, grant
|
|
180
|
+
inheritance to the login, disable both `SET ROLE` and membership delegation, inherit no
|
|
181
|
+
other role, and own none of the export views. PostgreSQL versions that cannot prove the
|
|
182
|
+
per-membership role-switch setting are refused. Rehearsal still evaluates the login's
|
|
183
|
+
complete effective read, write, sequence, and executable-function surface after those
|
|
184
|
+
checks. Adding, removing, or changing a group changes the reviewed plan digest.
|
|
159
185
|
|
|
160
186
|
`targetSchema` is optional and defaults to `public`. Set it when the restored relation
|
|
161
187
|
belongs elsewhere, and use the same schema in privacy policy version 2. This is relation
|
|
@@ -167,6 +193,9 @@ non-identity prefix may use `prefix`. A private owner prefix uses
|
|
|
167
193
|
the privacy policy below. Its raw value stays out of tracked files and the review plan
|
|
168
194
|
records only its SHA-256. Objects outside the exact bucket/prefix are not listed or
|
|
169
195
|
downloaded. Size, object-count, path, ETag, and exact-byte checks apply.
|
|
196
|
+
Supabase folder entries are traversed recursively beneath that exact prefix. Folder
|
|
197
|
+
entries count toward `maximumObjects`, so the same reviewed limit bounds both the
|
|
198
|
+
directory walk and transferred files. Empty files remain files and are copied normally.
|
|
170
199
|
|
|
171
200
|
## 3. Use executable privacy policy version 2
|
|
172
201
|
|
|
@@ -227,10 +256,12 @@ Every selected column has one action and, where required, a bounded recipe:
|
|
|
227
256
|
}
|
|
228
257
|
```
|
|
229
258
|
|
|
230
|
-
Supported recipes are intentionally small: keyed UUID/email/text/integer
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
259
|
+
Supported recipes are intentionally small: keyed UUID/email/text/integer/hex/GTIN/URL
|
|
260
|
+
pseudonyms, hexadecimal digests of explicitly named sanitized columns, explicit
|
|
261
|
+
constants, bounded or grouped date shifts, identity-aware path mappings, bounded
|
|
262
|
+
reviewed-identity substitution inside retained text, and fully classified JSON
|
|
263
|
+
structures. Unknown tables, columns, digest inputs, JSON keys, formats, and recipes stop
|
|
264
|
+
the refresh. There is no JavaScript or SQL escape hatch. See
|
|
234
265
|
[Sanitization policy](sanitization.md) for complete path and date examples.
|
|
235
266
|
|
|
236
267
|
## 4. Preview, apply, refresh, and retire
|
|
@@ -290,6 +321,11 @@ limits access, and the provider may revoke it sooner. Rehearsal does not claim t
|
|
|
290
321
|
cleanup revoked a provider-owned credential. Unrelated roles, grants, objects, baselines,
|
|
291
322
|
runtimes, and Docker resources are preserved.
|
|
292
323
|
|
|
324
|
+
Apply, refresh, and retire always resolve those local files from the active config's
|
|
325
|
+
`baseline.artifactDirectory`. If you switch configs or target roots, Rehearsal refuses
|
|
326
|
+
to retire a receipt from the other target. It also refuses an existing receipt or
|
|
327
|
+
credential rather than overwriting or adopting it.
|
|
328
|
+
|
|
293
329
|
## Limits
|
|
294
330
|
|
|
295
331
|
Rehearsal does not decide consent, licensing, retention rights, privileged-role meaning,
|
package/docs/releasing.md
CHANGED
|
@@ -32,9 +32,11 @@ publication must change and prove the workflow before narrowing that permission.
|
|
|
32
32
|
1. Start from protected `main` on a dedicated ticketed release branch.
|
|
33
33
|
2. Verify the exact version, changelog, compatibility notes, and packed file list.
|
|
34
34
|
3. Run unit and contract tests, formatting, package-content and secret audits,
|
|
35
|
-
dependency audit, clean tarball installation, and the installed
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
dependency audit, packed onboarding, clean tarball installation, and the installed
|
|
36
|
+
Docker fixtures.
|
|
37
|
+
4. When an unfamiliar developer is available, have them follow clean-project onboarding.
|
|
38
|
+
Correct and retest the first confusing, missing, or wrong instruction. Record when
|
|
39
|
+
this human observation was unavailable; automated checks must not impersonate it.
|
|
38
40
|
5. Change `private` to `false` only in the reviewed release change.
|
|
39
41
|
6. Record the exact tarball filename, SHA-1, SHA-256, allowlisted files, unpacked size,
|
|
40
42
|
executable, declared runtime dependency inventory, and dependency audit result.
|
package/docs/roadmap.md
CHANGED
|
@@ -29,8 +29,9 @@ Track the full breakdown in
|
|
|
29
29
|
invalid migrations, identities, images, persistence, reset, and cleanup.
|
|
30
30
|
- Run the released package in the real reporting consumer and record positives and
|
|
31
31
|
negatives.
|
|
32
|
-
- Directly observe any claimed Google account-picker/callback
|
|
33
|
-
onboarding behavior; automation cannot
|
|
32
|
+
- Directly observe any claimed Google account-picker/callback. Record
|
|
33
|
+
unfamiliar-developer onboarding behavior when a tester is available; automation cannot
|
|
34
|
+
invent either kind of human evidence.
|
|
34
35
|
- Remove consumer integration code only after its replacement passes and that deletion
|
|
35
36
|
is separately approved.
|
|
36
37
|
|