@dreadkn1ght123/vvp-integration-installer 1.0.0
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/README.md +21 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +597 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# VVP consumer integration installer
|
|
2
|
+
|
|
3
|
+
For Node.js 20+ Express + React/Vite projects:
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npx --yes @dreadkn1ght123/vvp-integration-installer@1.0.0 dry-run --capabilities auth,provisioning
|
|
7
|
+
npx --yes @dreadkn1ght123/vvp-integration-installer@1.0.0 setup --capabilities auth,provisioning
|
|
8
|
+
npx --yes @dreadkn1ght123/vvp-integration-installer@1.0.0 doctor
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Setup installs the aligned public `@dreadkn1ght123` packages from the
|
|
12
|
+
consumer's configured npm registry, writes the `iam.vvp/v1` manifest and
|
|
13
|
+
managed Express/React integration, and creates an integrity lockfile with
|
|
14
|
+
lifecycle scripts disabled. It safely migrates legacy `@vvp/*` dependency
|
|
15
|
+
entries to their public names. Reruns are idempotent and preserve the union of
|
|
16
|
+
installed capabilities; modified managed files cause an explicit conflict
|
|
17
|
+
instead of being overwritten.
|
|
18
|
+
|
|
19
|
+
The installer only reports required secret names. It never reads or prints
|
|
20
|
+
secret values and never registers IAM applications, machine identities, or
|
|
21
|
+
Keycloak clients.
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { doctor, InstallerError, parseCliArgs, setup } from "./index.js";
|
|
3
|
+
const usage = "Usage: vvp-integrate <setup|dry-run|doctor> [--root PATH] [--capabilities auth|provisioning|auth,provisioning]";
|
|
4
|
+
try {
|
|
5
|
+
const parsed = parseCliArgs(process.argv.slice(2));
|
|
6
|
+
if (parsed.command === "help") {
|
|
7
|
+
process.stdout.write(`${usage}\n`);
|
|
8
|
+
}
|
|
9
|
+
else if (parsed.command === "doctor") {
|
|
10
|
+
const result = await doctor(parsed.root);
|
|
11
|
+
for (const check of result.checks)
|
|
12
|
+
process.stdout.write(`${check.ok ? "PASS" : "FAIL"} ${check.name}: ${check.message}\n`);
|
|
13
|
+
process.exitCode = result.ok ? 0 : 1;
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
await setup({ root: parsed.root, capabilities: parsed.capabilities, dryRun: parsed.command === "dry-run",
|
|
17
|
+
output: (line) => process.stdout.write(`${line}\n`) });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
const safe = error instanceof InstallerError ? `${error.code}: ${error.message}\n${usage}` : "INSTALLER_FAILED: unexpected error";
|
|
22
|
+
process.stderr.write(`${safe}\n`);
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,KAAK,GAAG,gHAAgH,CAAC;AAE/H,IAAI,CAAC;IACH,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnD,IAAI,MAAM,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;QAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC;IACrC,CAAC;SAAM,IAAI,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACzC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QAC3H,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC;SAAM,CAAC;QACN,MAAM,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,KAAK,SAAS;YACtG,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAAC,OAAO,KAAK,EAAE,CAAC;IACf,MAAM,IAAI,GAAG,KAAK,YAAY,cAAc,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,oCAAoC,CAAC;IAClI,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC;IAClC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type Capability = "auth" | "provisioning";
|
|
2
|
+
export interface InstallerOptions {
|
|
3
|
+
root: string;
|
|
4
|
+
capabilities: readonly Capability[];
|
|
5
|
+
dryRun?: boolean;
|
|
6
|
+
output?: (line: string) => void;
|
|
7
|
+
install?: false | ((command: readonly string[], cwd: string) => Promise<void>);
|
|
8
|
+
}
|
|
9
|
+
export interface InstallerResult {
|
|
10
|
+
changed: readonly string[];
|
|
11
|
+
unchanged: readonly string[];
|
|
12
|
+
requiredSecrets: readonly string[];
|
|
13
|
+
}
|
|
14
|
+
export declare class InstallerError extends Error {
|
|
15
|
+
readonly code: "UNSUPPORTED_STACK" | "MANAGED_FILE_CONFLICT" | "INVALID_CONFIGURATION";
|
|
16
|
+
constructor(code: "UNSUPPORTED_STACK" | "MANAGED_FILE_CONFLICT" | "INVALID_CONFIGURATION", message: string);
|
|
17
|
+
}
|
|
18
|
+
export type CliOptions = {
|
|
19
|
+
command: "help";
|
|
20
|
+
} | {
|
|
21
|
+
command: "doctor";
|
|
22
|
+
root: string;
|
|
23
|
+
} | {
|
|
24
|
+
command: "setup" | "dry-run";
|
|
25
|
+
root: string;
|
|
26
|
+
capabilities: Capability[];
|
|
27
|
+
};
|
|
28
|
+
export declare function parseCliArgs(args: readonly string[], cwd?: string): CliOptions;
|
|
29
|
+
export declare function setup(options: InstallerOptions): Promise<InstallerResult>;
|
|
30
|
+
export interface DoctorResult {
|
|
31
|
+
ok: boolean;
|
|
32
|
+
checks: readonly {
|
|
33
|
+
name: string;
|
|
34
|
+
ok: boolean;
|
|
35
|
+
message: string;
|
|
36
|
+
}[];
|
|
37
|
+
}
|
|
38
|
+
export declare function doctor(rootInput: string, environment?: NodeJS.ProcessEnv): Promise<DoctorResult>;
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,cAAc,CAAC;AACjD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,SAAS,UAAU,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IACpE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,OAAO,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CAChF;AACD,MAAM,WAAW,eAAe;IAAG,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;AACjI,qBAAa,cAAe,SAAQ,KAAK;IAC3B,QAAQ,CAAC,IAAI,EAAE,mBAAmB,GAAG,uBAAuB,GAAG,uBAAuB;gBAA7E,IAAI,EAAE,mBAAmB,GAAG,uBAAuB,GAAG,uBAAuB,EAAE,OAAO,EAAE,MAAM;CAGpH;AACD,MAAM,MAAM,UAAU,GAClB;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GACnB;IAAE,OAAO,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACnC;IAAE,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,UAAU,EAAE,CAAA;CAAE,CAAC;AAC/E,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,GAAG,SAAgB,GAAG,UAAU,CAgCrF;AAqUD,wBAAsB,KAAK,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAiG/E;AAED,MAAM,WAAW,YAAY;IAAG,EAAE,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAAE;AAChH,wBAAsB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,YAAY,CAAC,CA4FnH"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,597 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { lstat, mkdir, readFile, readdir, realpath, rename, unlink, writeFile } from "node:fs/promises";
|
|
4
|
+
import { dirname, resolve } from "node:path";
|
|
5
|
+
export class InstallerError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
constructor(code, message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.name = "InstallerError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function parseCliArgs(args, cwd = process.cwd()) {
|
|
14
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
15
|
+
if (args.some((arg) => !["--help", "-h", "setup", "dry-run", "doctor"].includes(arg)))
|
|
16
|
+
throw new InstallerError("INVALID_CONFIGURATION", "Help does not accept additional options");
|
|
17
|
+
return { command: "help" };
|
|
18
|
+
}
|
|
19
|
+
const command = args[0];
|
|
20
|
+
if (command !== "setup" && command !== "dry-run" && command !== "doctor")
|
|
21
|
+
throw new InstallerError("INVALID_CONFIGURATION", "Expected setup, dry-run, doctor, or --help");
|
|
22
|
+
let root = cwd;
|
|
23
|
+
let capabilityValue;
|
|
24
|
+
const seen = new Set();
|
|
25
|
+
for (let index = 1; index < args.length; index += 2) {
|
|
26
|
+
const name = args[index];
|
|
27
|
+
const value = args[index + 1];
|
|
28
|
+
if ((name !== "--root" && name !== "--capabilities") || !value || value.startsWith("--") || seen.has(name))
|
|
29
|
+
throw new InstallerError("INVALID_CONFIGURATION", `Invalid or duplicate option: ${name ?? "(missing)"}`);
|
|
30
|
+
seen.add(name);
|
|
31
|
+
if (name === "--root")
|
|
32
|
+
root = value;
|
|
33
|
+
else
|
|
34
|
+
capabilityValue = value;
|
|
35
|
+
}
|
|
36
|
+
if (command === "doctor") {
|
|
37
|
+
if (capabilityValue !== undefined)
|
|
38
|
+
throw new InstallerError("INVALID_CONFIGURATION", "doctor does not accept --capabilities");
|
|
39
|
+
return { command, root };
|
|
40
|
+
}
|
|
41
|
+
if (!capabilityValue)
|
|
42
|
+
throw new InstallerError("INVALID_CONFIGURATION", "--capabilities is required for setup and dry-run");
|
|
43
|
+
const values = capabilityValue.split(",");
|
|
44
|
+
if (values.some((value) => value !== "auth" && value !== "provisioning") || new Set(values).size !== values.length)
|
|
45
|
+
throw new InstallerError("INVALID_CONFIGURATION", "Capabilities must be auth, provisioning, or auth,provisioning");
|
|
46
|
+
return { command, root, capabilities: values };
|
|
47
|
+
}
|
|
48
|
+
const versions = {
|
|
49
|
+
"@dreadkn1ght123/auth-types": "0.2.0", "@dreadkn1ght123/auth-core": "0.2.0",
|
|
50
|
+
"@dreadkn1ght123/auth-express": "0.2.0", "@dreadkn1ght123/auth-react": "0.2.0",
|
|
51
|
+
"@dreadkn1ght123/provisioning-client": "1.0.0",
|
|
52
|
+
};
|
|
53
|
+
const authConfiguration = ["VVP_ISSUER", "VVP_CLIENT_ID", "VVP_PUBLIC_ORIGIN"];
|
|
54
|
+
const provisioningConfiguration = ["VVP_PROVISIONING_API_URL", "VVP_PROVISIONING_TOKEN_URL", "VVP_PROVISIONING_CLIENT_ID"];
|
|
55
|
+
const legacyPackages = {
|
|
56
|
+
"@vvp/auth-types": "@dreadkn1ght123/auth-types",
|
|
57
|
+
"@vvp/auth-core": "@dreadkn1ght123/auth-core",
|
|
58
|
+
"@vvp/auth-express": "@dreadkn1ght123/auth-express",
|
|
59
|
+
"@vvp/auth-react": "@dreadkn1ght123/auth-react",
|
|
60
|
+
"@vvp/provisioning-client": "@dreadkn1ght123/provisioning-client",
|
|
61
|
+
};
|
|
62
|
+
const marker = /^\/\/ @vvp-managed sha256:([a-f0-9]{64})\n/;
|
|
63
|
+
const mdMarker = /^<!-- @vvp-managed sha256:([a-f0-9]{64}) -->\n/;
|
|
64
|
+
const digest = (value) => createHash("sha256").update(value).digest("hex");
|
|
65
|
+
const managed = (body, markdown = false) => markdown ? `<!-- @vvp-managed sha256:${digest(body)} -->\n${body}` : `// @vvp-managed sha256:${digest(body)}\n${body}`;
|
|
66
|
+
async function existing(path) {
|
|
67
|
+
try {
|
|
68
|
+
return await readFile(path, "utf8");
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (error.code === "ENOENT")
|
|
72
|
+
return undefined;
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function isManagedValid(value) {
|
|
77
|
+
const match = marker.exec(value) ?? mdMarker.exec(value);
|
|
78
|
+
return !!match && digest(value.slice(match[0].length)) === match[1];
|
|
79
|
+
}
|
|
80
|
+
async function atomicWrite(root, path, value, encoding = "utf8") {
|
|
81
|
+
await mkdir(dirname(path), { recursive: true });
|
|
82
|
+
const actualRoot = await realpath(root);
|
|
83
|
+
const actualParent = await realpath(dirname(path));
|
|
84
|
+
if (actualParent !== actualRoot && !actualParent.startsWith(`${actualRoot}/`))
|
|
85
|
+
throw new InstallerError("INVALID_CONFIGURATION", `Refusing to write outside project: ${path}`);
|
|
86
|
+
try {
|
|
87
|
+
if ((await lstat(path)).isSymbolicLink())
|
|
88
|
+
throw new InstallerError("INVALID_CONFIGURATION", `Refusing to replace symlink: ${path}`);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (error.code !== "ENOENT")
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
const temporary = `${path}.vvp-${randomUUID()}.tmp`;
|
|
95
|
+
try {
|
|
96
|
+
await writeFile(temporary, value, { encoding, mode: 0o600, flag: "wx" });
|
|
97
|
+
await rename(temporary, path);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
await unlink(temporary).catch(() => undefined);
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function defaultInstall(command, cwd) {
|
|
105
|
+
return new Promise((resolvePromise, reject) => {
|
|
106
|
+
const child = spawn(command[0], command.slice(1), { cwd, stdio: "inherit", shell: false });
|
|
107
|
+
child.once("error", reject);
|
|
108
|
+
child.once("exit", (code) => code === 0 ? resolvePromise() : reject(new Error(`Dependency installation exited with ${code}`)));
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
async function installCommand(root) {
|
|
112
|
+
if (await existing(resolve(root, "pnpm-lock.yaml")))
|
|
113
|
+
return ["pnpm", "install", "--ignore-scripts"];
|
|
114
|
+
if (await existing(resolve(root, "yarn.lock")))
|
|
115
|
+
return ["yarn", "install", "--ignore-scripts"];
|
|
116
|
+
if (await existing(resolve(root, "bun.lockb")) || await existing(resolve(root, "bun.lock")))
|
|
117
|
+
return ["bun", "install", "--ignore-scripts"];
|
|
118
|
+
return ["npm", "install", "--ignore-scripts"];
|
|
119
|
+
}
|
|
120
|
+
async function hasIntegrityLockfile(root) {
|
|
121
|
+
const pnpm = await existing(resolve(root, "pnpm-lock.yaml"));
|
|
122
|
+
if (pnpm?.includes("lockfileVersion:") && /\bintegrity:\s+\S+/.test(pnpm))
|
|
123
|
+
return true;
|
|
124
|
+
for (const name of ["package-lock.json", "npm-shrinkwrap.json"]) {
|
|
125
|
+
const source = await existing(resolve(root, name));
|
|
126
|
+
if (!source)
|
|
127
|
+
continue;
|
|
128
|
+
try {
|
|
129
|
+
const lock = JSON.parse(source);
|
|
130
|
+
if (typeof lock.lockfileVersion === "number" && lock.packages &&
|
|
131
|
+
Object.entries(lock.packages).some(([path, value]) => path.startsWith("node_modules/") && typeof value.integrity === "string"))
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
catch { /* try another supported lockfile */ }
|
|
135
|
+
}
|
|
136
|
+
const yarn = await existing(resolve(root, "yarn.lock"));
|
|
137
|
+
if (yarn && (/^# yarn lockfile v/m.test(yarn) || /^__metadata:/m.test(yarn)) &&
|
|
138
|
+
(/^\s+integrity\s+\S+/m.test(yarn) || /^\s+checksum:\s+\S+/m.test(yarn)))
|
|
139
|
+
return true;
|
|
140
|
+
const bun = await existing(resolve(root, "bun.lock")) ?? await existing(resolve(root, "bun.lockb"));
|
|
141
|
+
return !!bun && bun.length > 32 && /integrity|sha(256|512)/i.test(bun);
|
|
142
|
+
}
|
|
143
|
+
async function dependencyLockIsReady(root, dependencies) {
|
|
144
|
+
if (!await hasIntegrityLockfile(root))
|
|
145
|
+
return false;
|
|
146
|
+
const lockSources = (await Promise.all([
|
|
147
|
+
"pnpm-lock.yaml", "package-lock.json", "npm-shrinkwrap.json", "yarn.lock", "bun.lock", "bun.lockb",
|
|
148
|
+
].map((name) => existing(resolve(root, name))))).filter((value) => value !== undefined);
|
|
149
|
+
const combined = lockSources.join("\n");
|
|
150
|
+
return Object.entries(dependencies)
|
|
151
|
+
.filter(([name]) => name.startsWith("@dreadkn1ght123/"))
|
|
152
|
+
.every(([name, specifier]) => combined.includes(name) && combined.includes(specifier));
|
|
153
|
+
}
|
|
154
|
+
async function containsProvisioningImport(path) {
|
|
155
|
+
try {
|
|
156
|
+
for (const entry of await readdir(path, { withFileTypes: true })) {
|
|
157
|
+
const child = resolve(path, entry.name);
|
|
158
|
+
if (entry.isDirectory()) {
|
|
159
|
+
if (await containsProvisioningImport(child))
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
else if (/\.[cm]?[jt]sx?$/.test(entry.name) &&
|
|
163
|
+
(await readFile(child, "utf8")).includes("@dreadkn1ght123/provisioning-client"))
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
if (error.code !== "ENOENT")
|
|
169
|
+
throw error;
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
const authServer = `import { createVvpAuth, type AuthTransactionStore } from "@dreadkn1ght123/auth-express";
|
|
174
|
+
import type { SessionStore } from "@dreadkn1ght123/auth-core";
|
|
175
|
+
import type { Express } from "express";
|
|
176
|
+
|
|
177
|
+
export interface VvpSharedStores {
|
|
178
|
+
sessionStore: SessionStore;
|
|
179
|
+
transactionStore: AuthTransactionStore;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Production must inject persistent shared stores; consume must be atomic. */
|
|
183
|
+
export async function mountVvpAuth(app: Express, stores: VvpSharedStores) {
|
|
184
|
+
const auth = await createVvpAuth({
|
|
185
|
+
config: {
|
|
186
|
+
issuer: required("VVP_ISSUER"),
|
|
187
|
+
clientId: required("VVP_CLIENT_ID"),
|
|
188
|
+
clientSecret: required("VVP_CLIENT_SECRET"),
|
|
189
|
+
publicOrigin: required("VVP_PUBLIC_ORIGIN"),
|
|
190
|
+
scopes: ["openid", "profile", "email", "vvp-identity"],
|
|
191
|
+
environment: process.env.NODE_ENV === "production" ? "production" : "development",
|
|
192
|
+
},
|
|
193
|
+
...stores,
|
|
194
|
+
routes: { basePath: "/auth", start: "start", login: "login", callback: "callback",
|
|
195
|
+
logout: "logout", signedOut: "signed-out", error: "error" },
|
|
196
|
+
});
|
|
197
|
+
app.use(auth.router);
|
|
198
|
+
app.use(auth.authenticate);
|
|
199
|
+
return auth;
|
|
200
|
+
}
|
|
201
|
+
function required(name: string): string {
|
|
202
|
+
const value = process.env[name];
|
|
203
|
+
if (!value) throw new Error(\`Missing required configuration: \${name}\`);
|
|
204
|
+
return value;
|
|
205
|
+
}
|
|
206
|
+
`;
|
|
207
|
+
const authClient = `import { VvpAuthBoundary, VvpAuthProvider } from "@dreadkn1ght123/auth-react";
|
|
208
|
+
import type { PropsWithChildren } from "react";
|
|
209
|
+
|
|
210
|
+
export function VvpAuthenticatedApp({ children }: PropsWithChildren) {
|
|
211
|
+
return <VvpAuthProvider meUrl="/auth/me" logoutUrl="/auth/logout">
|
|
212
|
+
<VvpAuthBoundary>{children}</VvpAuthBoundary>
|
|
213
|
+
</VvpAuthProvider>;
|
|
214
|
+
}
|
|
215
|
+
`;
|
|
216
|
+
const provisioning = `import { randomUUID } from "node:crypto";
|
|
217
|
+
import { Router, type Request } from "express";
|
|
218
|
+
import { createProvisioningClient } from "@dreadkn1ght123/provisioning-client";
|
|
219
|
+
import type { InviteActor, ListActors, MutationContext, ReadContext, UpdateAccess } from "@dreadkn1ght123/provisioning-client";
|
|
220
|
+
|
|
221
|
+
export interface MachineTokenProvider { getAccessToken(): Promise<string> }
|
|
222
|
+
|
|
223
|
+
/** Backend facade only. Never return machine tokens or this client to browser code. */
|
|
224
|
+
export function createVvpProvisioning(tokenProvider: MachineTokenProvider) {
|
|
225
|
+
const baseUrl = process.env.VVP_PROVISIONING_API_URL;
|
|
226
|
+
if (!baseUrl) throw new Error("Missing required configuration: VVP_PROVISIONING_API_URL");
|
|
227
|
+
const client = createProvisioningClient({
|
|
228
|
+
baseUrl,
|
|
229
|
+
getAccessToken: () => tokenProvider.getAccessToken(),
|
|
230
|
+
});
|
|
231
|
+
return {
|
|
232
|
+
invite: (body: InviteActor, context: MutationContext) => client.invite(body, context),
|
|
233
|
+
list: (query: ListActors, context: ReadContext) => client.list(query, context),
|
|
234
|
+
get: (id: string, context: ReadContext) => client.get(id, context),
|
|
235
|
+
access: (id: string, body: UpdateAccess, context: MutationContext) => client.access(id, body, context),
|
|
236
|
+
disable: (id: string, reason: string, context: MutationContext) => client.disable(id, reason, context),
|
|
237
|
+
restore: (id: string, reason: string, context: MutationContext) => client.restore(id, reason, context),
|
|
238
|
+
resend: (id: string, reason: string, context: MutationContext) => client.resend(id, reason, context),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
type Facade = ReturnType<typeof createVvpProvisioning>;
|
|
243
|
+
const opaqueHeader = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
244
|
+
const correlationId = (request: Request) => {
|
|
245
|
+
const supplied = request.get("x-correlation-id");
|
|
246
|
+
return supplied && opaqueHeader.test(supplied) ? supplied : randomUUID();
|
|
247
|
+
};
|
|
248
|
+
const readContext = (request: Request) => ({ correlationId: correlationId(request) });
|
|
249
|
+
const mutationContext = (request: Request, response: import("express").Response): MutationContext | undefined => {
|
|
250
|
+
const context = readContext(request);
|
|
251
|
+
const idempotencyKey = request.get("idempotency-key");
|
|
252
|
+
if (!idempotencyKey || idempotencyKey.length < 16 || !opaqueHeader.test(idempotencyKey)) {
|
|
253
|
+
response.status(400).json({
|
|
254
|
+
error: { code: "IDEMPOTENCY_KEY_REQUIRED", message: "A valid Idempotency-Key header is required" },
|
|
255
|
+
correlationId: context.correlationId,
|
|
256
|
+
});
|
|
257
|
+
return undefined;
|
|
258
|
+
}
|
|
259
|
+
return { ...context, idempotencyKey };
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
/** Protected backend CRUD routes. The caller must mount an authorization middleware before this router. */
|
|
263
|
+
export function createVvpProvisioningRouter(facade: Facade) {
|
|
264
|
+
const router = Router();
|
|
265
|
+
router.get("/actors", async (req, res) => res.json(await facade.list(req.query as unknown as ListActors, readContext(req))));
|
|
266
|
+
router.get("/actors/:id", async (req, res) => res.json(await facade.get(req.params.id!, readContext(req))));
|
|
267
|
+
router.post("/actors", async (req, res) => {
|
|
268
|
+
const context = mutationContext(req, res);
|
|
269
|
+
if (context) res.json(await facade.invite(req.body, context));
|
|
270
|
+
});
|
|
271
|
+
router.put("/actors/:id/access", async (req, res) => {
|
|
272
|
+
const context = mutationContext(req, res);
|
|
273
|
+
if (context) res.json(await facade.access(req.params.id!, req.body, context));
|
|
274
|
+
});
|
|
275
|
+
router.post("/actors/:id/disable", async (req, res) => {
|
|
276
|
+
const context = mutationContext(req, res);
|
|
277
|
+
if (context) res.json(await facade.disable(req.params.id!, req.body.reason, context));
|
|
278
|
+
});
|
|
279
|
+
router.post("/actors/:id/restore", async (req, res) => {
|
|
280
|
+
const context = mutationContext(req, res);
|
|
281
|
+
if (context) res.json(await facade.restore(req.params.id!, req.body.reason, context));
|
|
282
|
+
});
|
|
283
|
+
router.post("/actors/:id/resend-invitation", async (req, res) => {
|
|
284
|
+
const context = mutationContext(req, res);
|
|
285
|
+
if (context) res.json(await facade.resend(req.params.id!, req.body.reason, context));
|
|
286
|
+
});
|
|
287
|
+
return router;
|
|
288
|
+
}
|
|
289
|
+
`;
|
|
290
|
+
const serverEntrypoint = (capabilities) => {
|
|
291
|
+
const auth = capabilities.includes("auth");
|
|
292
|
+
const provision = capabilities.includes("provisioning");
|
|
293
|
+
return `import type { Express, RequestHandler } from "express";
|
|
294
|
+
${auth ? 'import { mountVvpAuth, type VvpSharedStores } from "./vvp-auth.js";' : ""}
|
|
295
|
+
${provision ? 'import { createVvpProvisioning, createVvpProvisioningRouter, type MachineTokenProvider } from "./vvp-provisioning.js";' : ""}
|
|
296
|
+
|
|
297
|
+
export interface VvpIntegrationDependencies {
|
|
298
|
+
${auth ? "authStores: VvpSharedStores;" : ""}
|
|
299
|
+
${provision ? "machineTokens: MachineTokenProvider;\n authorizeProvisioning: RequestHandler;" : ""}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** Call once, before product routes. This is the managed server integration entrypoint. */
|
|
303
|
+
export async function mountVvpIntegration(app: Express, dependencies: VvpIntegrationDependencies) {
|
|
304
|
+
${auth ? "const auth = await mountVvpAuth(app, dependencies.authStores);" : ""}
|
|
305
|
+
${provision ? "const provisioning = createVvpProvisioning(dependencies.machineTokens);" : ""}
|
|
306
|
+
${provision ? 'app.use("/api/vvp", dependencies.authorizeProvisioning, createVvpProvisioningRouter(provisioning));' : ""}
|
|
307
|
+
return { ${auth ? "auth," : ""} ${provision ? "provisioning," : ""} };
|
|
308
|
+
}
|
|
309
|
+
`;
|
|
310
|
+
};
|
|
311
|
+
const clientEntrypoint = (capabilities) => `import type { PropsWithChildren } from "react";
|
|
312
|
+
${capabilities.includes("auth") ? 'import { VvpAuthenticatedApp } from "./vvp-auth.js";' : ""}
|
|
313
|
+
${capabilities.includes("provisioning") ? 'export { VvpActorsExample } from "./vvp-actors-example.js";' : ""}
|
|
314
|
+
|
|
315
|
+
/** Use this managed component at the React root. */
|
|
316
|
+
export function VvpIntegrationRoot({ children }: PropsWithChildren) {
|
|
317
|
+
return ${capabilities.includes("auth") ? "<VvpAuthenticatedApp>{children}</VvpAuthenticatedApp>" : "<>{children}</>"};
|
|
318
|
+
}
|
|
319
|
+
`;
|
|
320
|
+
const provisioningUi = `import { useEffect, useState } from "react";
|
|
321
|
+
|
|
322
|
+
type SafeActor = { vvpActorId: string; email: string; state: string };
|
|
323
|
+
|
|
324
|
+
/** Calls only the consumer backend facade. No machine token or provisioning credential reaches React. */
|
|
325
|
+
export function VvpActorsExample() {
|
|
326
|
+
const [actors, setActors] = useState<readonly SafeActor[]>([]);
|
|
327
|
+
useEffect(() => {
|
|
328
|
+
void fetch("/api/vvp/actors", { credentials: "same-origin" })
|
|
329
|
+
.then((response) => response.ok ? response.json() : Promise.reject(new Error("request failed")))
|
|
330
|
+
.then((result: { status: string; value?: { items: SafeActor[] } }) => {
|
|
331
|
+
if (result.status !== "succeeded" || !result.value) throw new Error("provisioning not completed");
|
|
332
|
+
setActors(result.value.items);
|
|
333
|
+
});
|
|
334
|
+
}, []);
|
|
335
|
+
return <ul>{actors.map((actor) => <li key={actor.vvpActorId}>{actor.email} — {actor.state}</li>)}</ul>;
|
|
336
|
+
}
|
|
337
|
+
`;
|
|
338
|
+
function manifest(capabilities) {
|
|
339
|
+
const auth = capabilities.includes("auth");
|
|
340
|
+
const provision = capabilities.includes("provisioning");
|
|
341
|
+
return {
|
|
342
|
+
apiVersion: "iam.vvp/v1", kind: "ConsumerIntegration", capabilities: [...capabilities].sort(),
|
|
343
|
+
stack: { server: "express", client: "react-vite", runtime: "node20" },
|
|
344
|
+
...(auth ? { auth: {
|
|
345
|
+
basePath: "/auth", callbackPath: "/auth/callback", logoutPath: "/auth/logout",
|
|
346
|
+
signedOutPath: "/auth/signed-out", requiredClientRoles: [],
|
|
347
|
+
requiredConfiguration: authConfiguration,
|
|
348
|
+
} } : {}),
|
|
349
|
+
...(provision ? { provisioning: { apiVersion: "v1", baseUrlEnvironment: "VVP_PROVISIONING_API_URL",
|
|
350
|
+
requiredClientRoles: ["provisioning-api:provisioning_admin"],
|
|
351
|
+
requiredConfiguration: provisioningConfiguration,
|
|
352
|
+
} } : {}),
|
|
353
|
+
secrets: [
|
|
354
|
+
...(auth ? ["VVP_CLIENT_SECRET"] : []),
|
|
355
|
+
...(provision ? ["VVP_PROVISIONING_CLIENT_SECRET"] : []),
|
|
356
|
+
],
|
|
357
|
+
manualRegistration: true,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function instructions(capabilities, secrets) {
|
|
361
|
+
return `# VVP integration (managed)
|
|
362
|
+
|
|
363
|
+
Capabilities: ${capabilities.join(", ")}.
|
|
364
|
+
|
|
365
|
+
## Trust boundaries
|
|
366
|
+
- Authentication tokens and provisioning credentials remain on the Express backend.
|
|
367
|
+
- Never call or expose Keycloak Admin API. Never automate IAM client or machine-identity registration.
|
|
368
|
+
- Never print, read, commit, or place secret values in commands. The owner adds these secret names: ${secrets.join(", ") || "none"}.
|
|
369
|
+
- Production auth requires shared persistent session and transaction stores with atomic consume.
|
|
370
|
+
|
|
371
|
+
## Remaining owner actions
|
|
372
|
+
1. Ask IAM to register exact callback \`<VVP_PUBLIC_ORIGIN>/auth/callback\` and logout URL \`<VVP_PUBLIC_ORIGIN>/auth/signed-out\`.
|
|
373
|
+
2. Ask IAM for the least-privilege roles in \`vvp-integration.json\`.
|
|
374
|
+
3. Add the listed secrets using the deployment secret manager.
|
|
375
|
+
4. Run \`vvp-integrate doctor\`, then the project's test, typecheck, and build commands.
|
|
376
|
+
|
|
377
|
+
Ambiguous provisioning mutations must be retried with the same body and idempotency key.
|
|
378
|
+
Reconciliation-required results go to IAM operators; do not bypass them.
|
|
379
|
+
`;
|
|
380
|
+
}
|
|
381
|
+
export async function setup(options) {
|
|
382
|
+
const root = resolve(options.root);
|
|
383
|
+
const output = options.output ?? (() => undefined);
|
|
384
|
+
const requested = [...new Set(options.capabilities)];
|
|
385
|
+
if (!requested.length || requested.some((c) => c !== "auth" && c !== "provisioning"))
|
|
386
|
+
throw new InstallerError("INVALID_CONFIGURATION", "Select auth, provisioning, or both");
|
|
387
|
+
const packagePath = resolve(root, "package.json");
|
|
388
|
+
const rawPackage = await existing(packagePath);
|
|
389
|
+
if (!rawPackage)
|
|
390
|
+
throw new InstallerError("UNSUPPORTED_STACK", "No package.json found");
|
|
391
|
+
let pkg;
|
|
392
|
+
try {
|
|
393
|
+
pkg = JSON.parse(rawPackage);
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
throw new InstallerError("INVALID_CONFIGURATION", "package.json is not valid JSON");
|
|
397
|
+
}
|
|
398
|
+
const all = { ...pkg.devDependencies, ...pkg.dependencies };
|
|
399
|
+
if (!all["express"] || !all["react"] || !all["vite"])
|
|
400
|
+
throw new InstallerError("UNSUPPORTED_STACK", "Supported stack requires Express + React + Vite");
|
|
401
|
+
const oldManifest = await existing(resolve(root, "vvp-integration.json"));
|
|
402
|
+
const oldDigest = await existing(resolve(root, ".vvp/manifest.sha256"));
|
|
403
|
+
let installed = [];
|
|
404
|
+
if (oldManifest !== undefined || oldDigest !== undefined) {
|
|
405
|
+
if (oldManifest === undefined || oldDigest?.trim() !== digest(oldManifest))
|
|
406
|
+
throw new InstallerError("MANAGED_FILE_CONFLICT", "Refusing to overwrite a modified VVP manifest");
|
|
407
|
+
try {
|
|
408
|
+
const parsed = JSON.parse(oldManifest);
|
|
409
|
+
if (parsed.apiVersion !== "iam.vvp/v1" || parsed.kind !== "ConsumerIntegration" ||
|
|
410
|
+
!Array.isArray(parsed.capabilities) || parsed.capabilities.some((item) => item !== "auth" && item !== "provisioning"))
|
|
411
|
+
throw new Error("invalid");
|
|
412
|
+
installed = parsed.capabilities;
|
|
413
|
+
}
|
|
414
|
+
catch {
|
|
415
|
+
throw new InstallerError("MANAGED_FILE_CONFLICT", "Existing VVP manifest is invalid");
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
const capabilities = [...new Set([...installed, ...requested])].sort();
|
|
419
|
+
const dependencies = { ...pkg.dependencies };
|
|
420
|
+
const devDependencies = { ...pkg.devDependencies };
|
|
421
|
+
for (const [legacyName, publicName] of Object.entries(legacyPackages)) {
|
|
422
|
+
if (dependencies[legacyName] !== undefined || devDependencies[legacyName] !== undefined)
|
|
423
|
+
dependencies[publicName] = versions[publicName];
|
|
424
|
+
delete dependencies[legacyName];
|
|
425
|
+
delete devDependencies[legacyName];
|
|
426
|
+
}
|
|
427
|
+
for (const name of capabilities.includes("auth")
|
|
428
|
+
? ["@dreadkn1ght123/auth-types", "@dreadkn1ght123/auth-core", "@dreadkn1ght123/auth-express", "@dreadkn1ght123/auth-react"] : [])
|
|
429
|
+
dependencies[name] = versions[name];
|
|
430
|
+
if (capabilities.includes("provisioning"))
|
|
431
|
+
dependencies["@dreadkn1ght123/provisioning-client"] = versions["@dreadkn1ght123/provisioning-client"];
|
|
432
|
+
const nextPackage = `${JSON.stringify({ ...pkg, dependencies, ...(pkg.devDependencies ? { devDependencies } : {}) }, null, 2)}\n`;
|
|
433
|
+
const data = manifest(capabilities);
|
|
434
|
+
const secrets = data.secrets;
|
|
435
|
+
const manifestSource = `${JSON.stringify(data, null, 2)}\n`;
|
|
436
|
+
const files = new Map([
|
|
437
|
+
["vvp-integration.json", manifestSource],
|
|
438
|
+
[".vvp/manifest.sha256", `${digest(manifestSource)}\n`],
|
|
439
|
+
[".replit/agent-vvp.md", managed(instructions(capabilities, secrets), true)],
|
|
440
|
+
["src/server/vvp-integration.ts", managed(serverEntrypoint(capabilities))],
|
|
441
|
+
["src/client/vvp-integration.tsx", managed(clientEntrypoint(capabilities))],
|
|
442
|
+
...(capabilities.includes("auth") ? [
|
|
443
|
+
["src/server/vvp-auth.ts", managed(authServer)],
|
|
444
|
+
["src/client/vvp-auth.tsx", managed(authClient)],
|
|
445
|
+
] : []),
|
|
446
|
+
...(capabilities.includes("provisioning") ? [
|
|
447
|
+
["src/server/vvp-provisioning.ts", managed(provisioning)],
|
|
448
|
+
["src/client/vvp-actors-example.tsx", managed(provisioningUi)],
|
|
449
|
+
] : []),
|
|
450
|
+
]);
|
|
451
|
+
const changed = [], unchanged = [];
|
|
452
|
+
const pending = [];
|
|
453
|
+
const packageChanged = rawPackage !== nextPackage;
|
|
454
|
+
if (packageChanged) {
|
|
455
|
+
files.set("package.json", nextPackage);
|
|
456
|
+
}
|
|
457
|
+
for (const [relative, value] of files) {
|
|
458
|
+
const path = resolve(root, relative);
|
|
459
|
+
const old = await existing(path);
|
|
460
|
+
if (old === value) {
|
|
461
|
+
unchanged.push(relative);
|
|
462
|
+
continue;
|
|
463
|
+
}
|
|
464
|
+
if (old !== undefined && relative !== "package.json" && relative !== "vvp-integration.json" &&
|
|
465
|
+
relative !== ".vvp/manifest.sha256" && !isManagedValid(old))
|
|
466
|
+
throw new InstallerError("MANAGED_FILE_CONFLICT", `Refusing to overwrite modified file: ${relative}`);
|
|
467
|
+
changed.push(relative);
|
|
468
|
+
pending.push({ relative, path, value });
|
|
469
|
+
}
|
|
470
|
+
const command = await installCommand(root);
|
|
471
|
+
const installRequired = packageChanged || !await dependencyLockIsReady(root, dependencies);
|
|
472
|
+
if (installRequired) {
|
|
473
|
+
output("Dependencies use the consumer project's approved npm registry configuration.");
|
|
474
|
+
output(`${options.dryRun ? "would run" : "run"} ${command.join(" ")}`);
|
|
475
|
+
}
|
|
476
|
+
for (const { relative, path, value, encoding } of pending) {
|
|
477
|
+
output(`${options.dryRun ? "would update" : "update"} ${relative}`);
|
|
478
|
+
if (!options.dryRun)
|
|
479
|
+
await atomicWrite(root, path, value, encoding);
|
|
480
|
+
}
|
|
481
|
+
if (installRequired) {
|
|
482
|
+
if (!options.dryRun && options.install !== false)
|
|
483
|
+
await (options.install ?? defaultInstall)(command, root);
|
|
484
|
+
if (!options.dryRun && options.install !== false && !await dependencyLockIsReady(root, dependencies))
|
|
485
|
+
throw new InstallerError("INVALID_CONFIGURATION", "Dependency installation did not create a matching integrity lockfile");
|
|
486
|
+
}
|
|
487
|
+
output(`Required secret names: ${secrets.join(", ") || "none"}`);
|
|
488
|
+
output("IAM application and machine identity registration remain manual.");
|
|
489
|
+
return { changed, unchanged, requiredSecrets: secrets };
|
|
490
|
+
}
|
|
491
|
+
export async function doctor(rootInput, environment = process.env) {
|
|
492
|
+
const root = resolve(rootInput);
|
|
493
|
+
const checks = [];
|
|
494
|
+
const rawManifest = await existing(resolve(root, "vvp-integration.json"));
|
|
495
|
+
let data;
|
|
496
|
+
try {
|
|
497
|
+
const candidate = rawManifest ? JSON.parse(rawManifest) : undefined;
|
|
498
|
+
if (candidate && Array.isArray(candidate.capabilities) && candidate.capabilities.length > 0 &&
|
|
499
|
+
candidate.capabilities.every((item) => item === "auth" || item === "provisioning")) {
|
|
500
|
+
const expected = manifest(candidate.capabilities);
|
|
501
|
+
if (JSON.stringify(candidate) === JSON.stringify(expected))
|
|
502
|
+
data = expected;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
catch { /* safe failure below */ }
|
|
506
|
+
checks.push({ name: "manifest", ok: !!data, message: data ? "manifest contract is consistent" : "missing or inconsistent v1 manifest" });
|
|
507
|
+
const storedDigest = await existing(resolve(root, ".vvp/manifest.sha256"));
|
|
508
|
+
checks.push({ name: "manifest-digest", ok: !!rawManifest && storedDigest?.trim() === digest(rawManifest),
|
|
509
|
+
message: "managed manifest digest checked" });
|
|
510
|
+
const rawPackage = await existing(resolve(root, "package.json"));
|
|
511
|
+
let pkg = {};
|
|
512
|
+
let packageOk = false;
|
|
513
|
+
try {
|
|
514
|
+
const parsed = rawPackage ? JSON.parse(rawPackage) : undefined;
|
|
515
|
+
packageOk = !!parsed && typeof parsed === "object" && !Array.isArray(parsed);
|
|
516
|
+
if (packageOk)
|
|
517
|
+
pkg = parsed;
|
|
518
|
+
}
|
|
519
|
+
catch {
|
|
520
|
+
packageOk = false;
|
|
521
|
+
}
|
|
522
|
+
checks.push({ name: "package-json", ok: packageOk, message: packageOk ? "package.json parsed" : "package.json is missing or malformed" });
|
|
523
|
+
checks.push({ name: "integrity-lockfile", ok: await dependencyLockIsReady(root, pkg.dependencies ?? {}),
|
|
524
|
+
message: "package-manager integrity lockfile and VVP dependency entries checked" });
|
|
525
|
+
for (const capability of data?.capabilities ?? []) {
|
|
526
|
+
const names = capability === "auth"
|
|
527
|
+
? ["@dreadkn1ght123/auth-types", "@dreadkn1ght123/auth-core", "@dreadkn1ght123/auth-express", "@dreadkn1ght123/auth-react"]
|
|
528
|
+
: ["@dreadkn1ght123/provisioning-client"];
|
|
529
|
+
for (const name of names) {
|
|
530
|
+
const specifier = pkg.dependencies?.[name];
|
|
531
|
+
const ok = specifier === versions[name];
|
|
532
|
+
checks.push({ name: `dependency:${name}`, ok, message: ok ? "aligned" : `expected ${versions[name]}` });
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
const expectedFiles = new Map();
|
|
536
|
+
if (data) {
|
|
537
|
+
expectedFiles.set(".replit/agent-vvp.md", managed(instructions(data.capabilities, data.secrets), true));
|
|
538
|
+
expectedFiles.set("src/server/vvp-integration.ts", managed(serverEntrypoint(data.capabilities)));
|
|
539
|
+
expectedFiles.set("src/client/vvp-integration.tsx", managed(clientEntrypoint(data.capabilities)));
|
|
540
|
+
if (data.capabilities.includes("auth")) {
|
|
541
|
+
expectedFiles.set("src/server/vvp-auth.ts", managed(authServer));
|
|
542
|
+
expectedFiles.set("src/client/vvp-auth.tsx", managed(authClient));
|
|
543
|
+
}
|
|
544
|
+
if (data.capabilities.includes("provisioning")) {
|
|
545
|
+
expectedFiles.set("src/server/vvp-provisioning.ts", managed(provisioning));
|
|
546
|
+
expectedFiles.set("src/client/vvp-actors-example.tsx", managed(provisioningUi));
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
for (const [name, expected] of expectedFiles) {
|
|
550
|
+
checks.push({ name: `managed-file:${name}`, ok: await existing(resolve(root, name)) === expected,
|
|
551
|
+
message: "managed file content and digest checked" });
|
|
552
|
+
}
|
|
553
|
+
if (data?.capabilities.includes("auth")) {
|
|
554
|
+
const origin = environment["VVP_PUBLIC_ORIGIN"];
|
|
555
|
+
let originOk = false;
|
|
556
|
+
try {
|
|
557
|
+
originOk = !!origin && new URL(origin).origin === origin && (new URL(origin).protocol === "https:" || new URL(origin).hostname === "localhost");
|
|
558
|
+
}
|
|
559
|
+
catch { }
|
|
560
|
+
checks.push({ name: "public-origin", ok: originOk, message: originOk ? "callback and logout origins valid" : "VVP_PUBLIC_ORIGIN must be an HTTPS origin" });
|
|
561
|
+
let issuerOk = false;
|
|
562
|
+
try {
|
|
563
|
+
issuerOk = new URL(environment["VVP_ISSUER"] ?? "").protocol === "https:";
|
|
564
|
+
}
|
|
565
|
+
catch { }
|
|
566
|
+
checks.push({ name: "issuer-url", ok: issuerOk, message: "VVP_ISSUER URL checked without displaying its value" });
|
|
567
|
+
checks.push({ name: "auth-config", ok: [...authConfiguration, "VVP_CLIENT_SECRET"].every((n) => !!environment[n]),
|
|
568
|
+
message: "required auth configuration names checked; values are never displayed" });
|
|
569
|
+
const source = await existing(resolve(root, "src/server/vvp-auth.ts"));
|
|
570
|
+
const boundary = await existing(resolve(root, "src/client/vvp-auth.tsx"));
|
|
571
|
+
checks.push({ name: "auth-mount-and-stores", ok: !!source?.includes("mountVvpAuth(app") &&
|
|
572
|
+
source.includes("AuthTransactionStore") && source.includes("SessionStore"),
|
|
573
|
+
message: "Express mount and shared store extension points checked" });
|
|
574
|
+
checks.push({ name: "react-boundary", ok: !!boundary?.includes("VvpAuthProvider") && boundary.includes("VvpAuthBoundary"),
|
|
575
|
+
message: "React provider and boundary checked" });
|
|
576
|
+
}
|
|
577
|
+
if (data?.capabilities.includes("provisioning")) {
|
|
578
|
+
const facade = await existing(resolve(root, "src/server/vvp-provisioning.ts"));
|
|
579
|
+
const browserImport = await containsProvisioningImport(resolve(root, "src/client"));
|
|
580
|
+
checks.push({ name: "backend-boundary", ok: !!facade && !browserImport,
|
|
581
|
+
message: "provisioning client must exist only under src/server" });
|
|
582
|
+
let urlsOk = false;
|
|
583
|
+
try {
|
|
584
|
+
urlsOk = ["VVP_PROVISIONING_API_URL", "VVP_PROVISIONING_TOKEN_URL"]
|
|
585
|
+
.every((name) => new URL(environment[name] ?? "").protocol === "https:");
|
|
586
|
+
}
|
|
587
|
+
catch { }
|
|
588
|
+
checks.push({ name: "provisioning-urls", ok: urlsOk, message: "provisioning URLs checked without displaying values" });
|
|
589
|
+
checks.push({ name: "provisioning-config", ok: [...provisioningConfiguration, "VVP_PROVISIONING_CLIENT_SECRET"].every((n) => !!environment[n]),
|
|
590
|
+
message: "required provisioning configuration names checked; values are never displayed" });
|
|
591
|
+
checks.push({ name: "provisioning-facade", ok: !!facade &&
|
|
592
|
+
["invite:", "list:", "get:", "access:", "disable:", "restore:", "resend:"].every((operation) => facade.includes(operation)),
|
|
593
|
+
message: "all backend provisioning operations checked" });
|
|
594
|
+
}
|
|
595
|
+
return { ok: checks.every((check) => check.ok), checks };
|
|
596
|
+
}
|
|
597
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dreadkn1ght123/vvp-integration-installer",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Idempotent VVP integration installer for Express and React/Vite",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"vvp-integrate": "./dist/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=20"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public",
|
|
26
|
+
"provenance": true
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/express": "^5.0.3",
|
|
30
|
+
"@types/node": "^22.15.0",
|
|
31
|
+
"@types/supertest": "^6.0.3",
|
|
32
|
+
"express": "^5.1.0",
|
|
33
|
+
"supertest": "^7.1.4",
|
|
34
|
+
"@dreadkn1ght123/provisioning-client": "^1.0.0"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc -b",
|
|
38
|
+
"typecheck": "tsc -b --pretty false",
|
|
39
|
+
"test": "vitest run --root ../.. packages/integration-installer/src/installer.test.ts"
|
|
40
|
+
}
|
|
41
|
+
}
|