@stopnetic/js 0.0.1-pilot → 0.0.3-pilot

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.
@@ -1,29 +1,40 @@
1
- import { createPublicKey } from 'node:crypto';
2
-
1
+ import { createPublicKey } from 'node:crypto';
2
+
3
3
  function publicKey(value) {
4
- if (typeof value !== 'string' || value.length > 2048
5
- || !/^-----BEGIN PUBLIC KEY-----\r?\n[A-Za-z0-9+/=\r\n]+-----END PUBLIC KEY-----\s*$/.test(value)) {
4
+ if (typeof value !== 'string' || value.length > 2048) {
6
5
  throw new Error('Signing verification keys must be public PEMs');
7
6
  }
8
- const key = createPublicKey(value);
9
- if (key.asymmetricKeyType !== 'ed25519') throw new Error('Signing verification keys must be Ed25519');
10
- return key;
11
- }
12
-
13
- export function trustedSigningKeys(primary, additional) {
14
- if (!Array.isArray(additional) || additional.length > 2) throw new Error('Use at most two additional signing public keys');
15
- const keys = [primary, ...additional].map(publicKey);
16
- return [...new Map(keys.map(key => [key.export({ type: 'spki', format: 'der' }).toString('hex'), key])).values()];
17
- }
18
-
19
- /** Parse a server environment JSON array without exposing malformed values. */
20
- export function parseAdditionalDecisionPublicKeys(value) {
21
- if (value === undefined || value === '') return [];
22
- try {
23
- if (typeof value !== 'string' || value.length > 8192) throw new Error();
24
- const keys = JSON.parse(value);
25
- if (!Array.isArray(keys) || keys.length > 2) throw new Error();
26
- keys.forEach(publicKey);
27
- return keys;
28
- } catch { throw new Error('Invalid additional signing public keys'); }
29
- }
7
+ // Hosting value fields may receive the quoted/escaped dotenv representation.
8
+ // Normalize only formatting; retain bounded, public-only Ed25519 trust checks.
9
+ let pem = value.trim();
10
+ try { if (pem.startsWith('"')) pem = JSON.parse(pem); }
11
+ catch { throw new Error('Signing verification keys must be public PEMs'); }
12
+ if (typeof pem !== 'string') throw new Error('Signing verification keys must be public PEMs');
13
+ pem = pem.replaceAll('\\r\\n', '\n').replaceAll('\\n', '\n');
14
+ if (!/^-----BEGIN PUBLIC KEY-----\r?\n[A-Za-z0-9+/=\r\n]+-----END PUBLIC KEY-----\s*$/.test(pem)) {
15
+ throw new Error('Signing verification keys must be public PEMs');
16
+ }
17
+ let key;
18
+ try { key = createPublicKey(pem); }
19
+ catch { throw new Error('Signing verification keys must be public PEMs'); }
20
+ if (key.asymmetricKeyType !== 'ed25519') throw new Error('Signing verification keys must be Ed25519');
21
+ return key;
22
+ }
23
+
24
+ export function trustedSigningKeys(primary, additional) {
25
+ if (!Array.isArray(additional) || additional.length > 2) throw new Error('Use at most two additional signing public keys');
26
+ const keys = [primary, ...additional].map(publicKey);
27
+ return [...new Map(keys.map(key => [key.export({ type: 'spki', format: 'der' }).toString('hex'), key])).values()];
28
+ }
29
+
30
+ /** Parse a server environment JSON array without exposing malformed values. */
31
+ export function parseAdditionalDecisionPublicKeys(value) {
32
+ if (value === undefined || value === '') return [];
33
+ try {
34
+ if (typeof value !== 'string' || value.length > 8192) throw new Error();
35
+ const keys = JSON.parse(value);
36
+ if (!Array.isArray(keys) || keys.length > 2) throw new Error();
37
+ keys.forEach(publicKey);
38
+ return keys;
39
+ } catch { throw new Error('Invalid additional signing public keys'); }
40
+ }
package/package.json CHANGED
@@ -1,47 +1,54 @@
1
- {
2
- "name": "@stopnetic/js",
3
- "version": "0.0.1-pilot",
4
- "description": "Server-side Stopnetic guard for JavaScript websites, Node.js and Express-compatible servers.",
5
- "type": "module",
6
- "license": "MIT",
7
- "author": "Stopnetic",
8
- "repository": {
9
- "type": "git",
10
- "url": "git+https://github.com/KlimentSidorov/stopin.git",
11
- "directory": "integrations/javascript"
12
- },
13
- "keywords": [
14
- "stopnetic",
15
- "javascript",
16
- "nodejs",
17
- "express",
18
- "access-control"
19
- ],
20
- "files": [
21
- "dist"
22
- ],
23
- "exports": {
24
- ".": {
25
- "types": "./dist/index.d.ts",
26
- "default": "./dist/index.js"
27
- }
28
- },
29
- "engines": {
30
- "node": ">=22"
31
- },
32
- "publishConfig": {
33
- "access": "public",
34
- "tag": "pilot",
35
- "registry": "https://registry.npmjs.org/"
36
- },
37
- "scripts": {
38
- "build": "node scripts/build.mjs",
39
- "prepack": "npm run build",
40
- "test": "npm run build && node --test tests/*.test.mjs",
41
- "test:package": "npm run build && node tests/package-check.mjs"
42
- },
43
- "devDependencies": {
44
- "express": "^4.22.3",
45
- "express5": "npm:express@^5.2.1"
46
- }
47
- }
1
+ {
2
+ "name": "@stopnetic/js",
3
+ "version": "0.0.3-pilot",
4
+ "description": "Server-side Stopnetic guard for JavaScript websites, Node.js and Express-compatible servers.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Stopnetic",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/KlimentSidorov/stopin.git",
11
+ "directory": "integrations/javascript"
12
+ },
13
+ "keywords": [
14
+ "stopnetic",
15
+ "javascript",
16
+ "nodejs",
17
+ "express",
18
+ "access-control"
19
+ ],
20
+ "files": [
21
+ "dist",
22
+ "bin"
23
+ ],
24
+ "bin": { "stopnetic-js": "./bin/stopnetic-js.js" },
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "default": "./dist/index.js"
29
+ },
30
+ "./server": { "types": "./dist/server.d.ts", "default": "./dist/server.js" },
31
+ "./browser": { "types": "./dist/browser.d.ts", "default": "./dist/browser.js" },
32
+ "./react": { "types": "./dist/react.d.ts", "default": "./dist/react.js" }
33
+ },
34
+ "peerDependencies": { "react": "*" },
35
+ "peerDependenciesMeta": { "react": { "optional": true } },
36
+ "engines": {
37
+ "node": ">=22"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public",
41
+ "tag": "pilot",
42
+ "registry": "https://registry.npmjs.org/"
43
+ },
44
+ "scripts": {
45
+ "build": "node scripts/build.mjs",
46
+ "prepack": "npm run build",
47
+ "test": "npm run build && node --test tests/*.test.mjs",
48
+ "test:package": "npm run build && node tests/package-check.mjs"
49
+ },
50
+ "devDependencies": {
51
+ "express": "^4.22.3",
52
+ "express5": "npm:express@^5.2.1"
53
+ }
54
+ }