@warpgogol/werkstatt-shared 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warpgogol/werkstatt-shared",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -1343,6 +1343,15 @@
|
|
|
1343
1343
|
"default": "./src/share/scripts/index.ts"
|
|
1344
1344
|
}
|
|
1345
1345
|
},
|
|
1346
|
+
"scripts": {
|
|
1347
|
+
"lint": "pnpm exec eslint \"src/**/*.ts\"",
|
|
1348
|
+
"typecheck": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
1349
|
+
"build": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
1350
|
+
"build:check": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
1351
|
+
"prepublishOnly": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
1352
|
+
"test": "vitest run",
|
|
1353
|
+
"test:watch": "vitest"
|
|
1354
|
+
},
|
|
1346
1355
|
"publishConfig": {
|
|
1347
1356
|
"access": "public"
|
|
1348
1357
|
},
|
|
@@ -1382,12 +1391,5 @@
|
|
|
1382
1391
|
"typescript-eslint": "8.65.0",
|
|
1383
1392
|
"vitest": "^4.1.10"
|
|
1384
1393
|
},
|
|
1385
|
-
"
|
|
1386
|
-
|
|
1387
|
-
"typecheck": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
1388
|
-
"build": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
1389
|
-
"build:check": "pnpm exec tsc -p tsconfig.json --noEmit",
|
|
1390
|
-
"test": "vitest run",
|
|
1391
|
-
"test:watch": "vitest"
|
|
1392
|
-
}
|
|
1393
|
-
}
|
|
1394
|
+
"packageManager": "pnpm@11.10.0"
|
|
1395
|
+
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<keywords>middleware, access-protection, basic-auth, pin, dev, alt, RFC-0899</keywords>
|
|
5
5
|
<responsibilities>
|
|
6
6
|
<item>Check Host header against dev.* and alt.* patterns — pass through for main domain.</item>
|
|
7
|
-
<item>Require Basic Auth (username:
|
|
7
|
+
<item>Require Basic Auth (username: warp, password: ACCESS_PIN env var) for dev/alt hosts.</item>
|
|
8
8
|
<item>Set X-Robots-Tag: noindex, nofollow, noai, noimageai on ALL dev/alt responses (including 401).</item>
|
|
9
9
|
<item>Use constant-time string comparison for auth check to prevent timing attacks.</item>
|
|
10
10
|
<item>Pass through when ACCESS_PIN is unset (allows new sites before protection is configured).</item>
|
|
@@ -73,7 +73,7 @@ export function checkAccessProtection(
|
|
|
73
73
|
|
|
74
74
|
// Check Basic Auth
|
|
75
75
|
const auth = request.headers.get("authorization") ?? "";
|
|
76
|
-
const expected = `Basic ${btoa(`
|
|
76
|
+
const expected = `Basic ${btoa(`warp:${pin}`)}`;
|
|
77
77
|
|
|
78
78
|
if (auth && constantTimeEqual(auth, expected)) {
|
|
79
79
|
return null; // Authenticated — pass through
|
|
@@ -155,7 +155,7 @@ export const accessProtectionMiddleware = defineMiddleware(async (context: any,
|
|
|
155
155
|
|
|
156
156
|
// Check Basic Auth BEFORE calling next()
|
|
157
157
|
const auth = context.request.headers.get("authorization") ?? "";
|
|
158
|
-
const expected = `Basic ${btoa(`
|
|
158
|
+
const expected = `Basic ${btoa(`warp:${pin}`)}`;
|
|
159
159
|
|
|
160
160
|
if (auth && constantTimeEqual(auth, expected)) {
|
|
161
161
|
const response = await next();
|
|
@@ -80,7 +80,7 @@ describe("RFC-0899: access protection middleware", () => {
|
|
|
80
80
|
|
|
81
81
|
it("passes through dev.* with correct Basic Auth", async () => {
|
|
82
82
|
mockEnv.ACCESS_PIN = "1234";
|
|
83
|
-
const expected = `Basic ${btoa("
|
|
83
|
+
const expected = `Basic ${btoa("warp:1234")}`;
|
|
84
84
|
const handler = await loadMiddleware();
|
|
85
85
|
const res = await runMiddleware(handler, "dev.example.com", expected);
|
|
86
86
|
expect(res._nextCalled).toBe(true);
|
|
@@ -90,7 +90,7 @@ describe("RFC-0899: access protection middleware", () => {
|
|
|
90
90
|
|
|
91
91
|
it("returns 401 for dev.* with wrong PIN", async () => {
|
|
92
92
|
mockEnv.ACCESS_PIN = "1234";
|
|
93
|
-
const wrong = `Basic ${btoa("
|
|
93
|
+
const wrong = `Basic ${btoa("warp:9999")}`;
|
|
94
94
|
const handler = await loadMiddleware();
|
|
95
95
|
const res = await runMiddleware(handler, "dev.example.com", wrong);
|
|
96
96
|
expect(res._nextCalled).toBe(false);
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { test, expect } from "vitest";
|
|
2
|
-
import { createDevPropsValidator } from "../dev-props-validator.ts";
|
|
3
|
-
|
|
4
|
-
/*
|
|
5
|
-
<MODULE_CONTRACT>
|
|
6
|
-
<purpose>
|
|
7
|
-
RFC-0262: end-to-end test of createDevPropsValidator against the real
|
|
8
|
-
packages/werkstatt-site/src/domain/ui/sections/hero manifest (this test runs from within the
|
|
9
|
-
actual monorepo checkout, so workspace-root discovery resolves for real).
|
|
10
|
-
</purpose>
|
|
11
|
-
</MODULE_CONTRACT>
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
test("createDevPropsValidator: passes valid Europa (hero-section) props", async () => {
|
|
15
|
-
const validate = createDevPropsValidator();
|
|
16
|
-
await validate("Europa", { header: { heading: "Hello" } }, "hero-block"); // cosmic-literals-ignore: fixture cosmicName exercising the real hero-section manifest
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
test("createDevPropsValidator: throws PAGE-PROPS-01 on an undeclared prop key", async () => {
|
|
20
|
-
const validate = createDevPropsValidator();
|
|
21
|
-
try {
|
|
22
|
-
await validate(
|
|
23
|
-
"Europa", // cosmic-literals-ignore: fixture cosmicName exercising the real hero-section manifest
|
|
24
|
-
{ header: { heading: "Hello" }, totallyUnknownField: true },
|
|
25
|
-
"hero-block",
|
|
26
|
-
); // cosmic-literals-ignore: fixture cosmicName exercising the real hero-section manifest
|
|
27
|
-
expect.fail("should have thrown");
|
|
28
|
-
} catch (error) {
|
|
29
|
-
expect(error).toBeInstanceOf(Error);
|
|
30
|
-
expect((error as Error).message).toMatch(/PAGE-PROPS-01/);
|
|
31
|
-
expect((error as Error).message).toMatch(/hero-block/);
|
|
32
|
-
}
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test("createDevPropsValidator: an unknown planetName resolves no schema and does not throw", async () => {
|
|
36
|
-
const validate = createDevPropsValidator();
|
|
37
|
-
await validate("NotARealPlanet", { anything: true }, null);
|
|
38
|
-
});
|