@faable/auth-sdk 2.6.1 → 2.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -31,3 +31,8 @@ jobs:
|
|
|
31
31
|
- run: npm run release
|
|
32
32
|
env:
|
|
33
33
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
34
|
+
# Proves the RESULT: downloads what was just published and fails if the
|
|
35
|
+
# sentinels survived. test:pack checks they are present before the
|
|
36
|
+
# release; only this catches something rebuilding dist/ in between —
|
|
37
|
+
# which is exactly how 2.6.0 shipped as `auth-sdk/0.0.0-dev`.
|
|
38
|
+
- run: npm run verify:published
|
package/dist/version.js
CHANGED
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
// login pages could not import the SDK at all. Same pattern as auth-js.
|
|
10
10
|
//
|
|
11
11
|
// The sentinels MUST stay byte-identical to the `from` values in `.releaserc`.
|
|
12
|
-
export const version = "
|
|
12
|
+
export const version = "2.6.2";
|
|
13
13
|
// Short git SHA of the released commit. The version dates a build; this names
|
|
14
14
|
// the exact tree, so a canonical log line or an audit entry leads straight to
|
|
15
15
|
// `git show <sha>`. Deliberately NOT hex: an unreleased build (dev, a local
|
|
16
16
|
// link) cannot be mistaken for a real commit — auth only records values that
|
|
17
17
|
// look like a SHA, and this one never will.
|
|
18
|
-
export const commit = "
|
|
18
|
+
export const commit = "6d035ad";
|
|
19
19
|
// What this SDK writes in `x-faable-client`. Exported for a consumer that
|
|
20
20
|
// builds a strategy on its own (outside `FaableAuthApi`) and still wants the
|
|
21
21
|
// token request attributed — a bare `authClientCredentials` stamps only what
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faable/auth-sdk",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.2",
|
|
4
4
|
"author": "Marc Pomar <marc@faable.com>",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"gentypes": "openapi-typescript ${AUTH_OPENAPI:-spec/openapi.json} -o src/api/types.ts && node scripts/gen-client.mjs",
|
|
31
31
|
"build": "rimraf dist && tsc",
|
|
32
32
|
"prebuild": "npm run gentypes",
|
|
33
|
-
"prepublishOnly": "npm run build",
|
|
34
33
|
"test": "ava",
|
|
35
34
|
"release": "semantic-release",
|
|
36
|
-
"test:pack": "node tests/pack/verify-pack.mjs"
|
|
35
|
+
"test:pack": "node tests/pack/verify-pack.mjs",
|
|
36
|
+
"verify:published": "node tests/pack/verify-published.mjs"
|
|
37
37
|
},
|
|
38
38
|
"resolutions": {
|
|
39
39
|
"npm/chalk": "^4.1.2"
|
|
@@ -30,6 +30,7 @@ console.log("→ Building dist/");
|
|
|
30
30
|
run("npm run build", { cwd: ROOT });
|
|
31
31
|
|
|
32
32
|
// 1. Sentinels, verbatim, straight from .releaserc so the two cannot drift.
|
|
33
|
+
const pkgScripts = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8")).scripts ?? {};
|
|
33
34
|
const releaserc = JSON.parse(readFileSync(join(ROOT, ".releaserc"), "utf8"));
|
|
34
35
|
const replacePlugin = releaserc.plugins.find(
|
|
35
36
|
(p) => Array.isArray(p) && p[0] === "semantic-release-replace-plugin",
|
|
@@ -43,6 +44,23 @@ for (const { from } of replacePlugin[1].replacements) {
|
|
|
43
44
|
}
|
|
44
45
|
console.log("✓ sentinels present in dist/version.js");
|
|
45
46
|
|
|
47
|
+
// The sentinels being here is only half the story: anything that rebuilds
|
|
48
|
+
// dist/ AFTER semantic-release's replacement and BEFORE the upload undoes it.
|
|
49
|
+
// `npm pack` fires `prepack`, never `prepublishOnly`, so this guard cannot
|
|
50
|
+
// observe that hook — it refuses to let one exist instead. (2.6.0 shipped
|
|
51
|
+
// anonymous exactly this way.) The release workflow builds explicitly, so no
|
|
52
|
+
// publish-time rebuild hook is needed.
|
|
53
|
+
const REBUILD_HOOKS = ["prepublishOnly", "prepublish", "prepack", "prepare"];
|
|
54
|
+
const offending = REBUILD_HOOKS.filter((hook) => pkgScripts[hook]);
|
|
55
|
+
if (offending.length) {
|
|
56
|
+
fail(
|
|
57
|
+
`package.json defines ${offending.join(", ")} — npm runs these around publish, ` +
|
|
58
|
+
"and a rebuild there would overwrite the version semantic-release just injected. " +
|
|
59
|
+
"Build in the workflow instead.",
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
console.log("✓ no publish-time rebuild hook");
|
|
63
|
+
|
|
46
64
|
// 2. Browser-safety: no node: specifiers anywhere in the published JS.
|
|
47
65
|
const jsFiles = (dir) =>
|
|
48
66
|
readdirSync(dir, { withFileTypes: true }).flatMap((e) =>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Post-publish guard: download the version that was just published and fail if
|
|
3
|
+
// it still carries the release sentinels.
|
|
4
|
+
//
|
|
5
|
+
// `verify-pack.mjs` checks the OPPOSITE — that the sentinels ARE in dist/, so
|
|
6
|
+
// the replacement has something to hit. Both are needed, and only this one
|
|
7
|
+
// proves the result: 2.6.0 shipped anonymous because `prepublishOnly` ran
|
|
8
|
+
// `rimraf dist && tsc` between the replacement and the upload, and `npm pack`
|
|
9
|
+
// (which the pre-publish guard uses) never fires that hook.
|
|
10
|
+
import { execSync } from "node:child_process";
|
|
11
|
+
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
13
|
+
import { join, resolve } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
15
|
+
|
|
16
|
+
const ROOT = resolve(fileURLToPath(import.meta.url), "../../..");
|
|
17
|
+
const pkg = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8"));
|
|
18
|
+
const version = pkg.version;
|
|
19
|
+
|
|
20
|
+
// semantic-release writes the released version into package.json during
|
|
21
|
+
// `prepare`. Still the dev placeholder ⇒ no release was cut on this run.
|
|
22
|
+
if (version === "0.0.0-dev") {
|
|
23
|
+
console.log("→ No release cut on this run; nothing to verify.");
|
|
24
|
+
process.exit(0);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const sentinels = JSON.parse(readFileSync(join(ROOT, ".releaserc"), "utf8"))
|
|
28
|
+
.plugins.find((p) => Array.isArray(p) && p[0] === "semantic-release-replace-plugin")[1]
|
|
29
|
+
.replacements.map((r) => r.from);
|
|
30
|
+
|
|
31
|
+
const tmp = mkdtempSync(join(tmpdir(), "faable-auth-sdk-published-"));
|
|
32
|
+
try {
|
|
33
|
+
// The registry needs a moment to serve a brand-new version.
|
|
34
|
+
let tarball;
|
|
35
|
+
for (let attempt = 1; attempt <= 10; attempt++) {
|
|
36
|
+
try {
|
|
37
|
+
tarball = execSync(`npm pack ${pkg.name}@${version} --silent`, {
|
|
38
|
+
cwd: tmp,
|
|
39
|
+
encoding: "utf8",
|
|
40
|
+
}).trim();
|
|
41
|
+
break;
|
|
42
|
+
} catch {
|
|
43
|
+
console.log(`→ ${pkg.name}@${version} not served yet (attempt ${attempt}/10)`);
|
|
44
|
+
execSync("sleep 10");
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (!tarball) {
|
|
48
|
+
console.error(`✖ ${pkg.name}@${version} never became available on the registry`);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
execSync(`tar xzf ${tarball}`, { cwd: tmp });
|
|
53
|
+
const published = readFileSync(join(tmp, "package/dist/version.js"), "utf8");
|
|
54
|
+
for (const sentinel of sentinels) {
|
|
55
|
+
if (published.includes(sentinel)) {
|
|
56
|
+
console.error(
|
|
57
|
+
`✖ ${pkg.name}@${version} was published with the sentinel "${sentinel}" intact — ` +
|
|
58
|
+
"every consumer will report as that. Something between the replacement and the " +
|
|
59
|
+
"upload rebuilt dist/ (a `prepublishOnly`/`prepack` hook is the usual culprit).",
|
|
60
|
+
);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!published.includes(version)) {
|
|
65
|
+
console.error(`✖ ${pkg.name}@${version} does not carry its own version in dist/version.js`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
console.log(`✓ ${pkg.name}@${version} reports itself correctly on the wire`);
|
|
69
|
+
} finally {
|
|
70
|
+
rmSync(tmp, { recursive: true, force: true });
|
|
71
|
+
}
|