soulprint-express 0.1.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.
@@ -0,0 +1,60 @@
1
+ import { SoulprintToken } from "soulprint-core";
2
+ import { verifySPT, SoulprintOptions } from "./verify.js";
3
+ export { verifySPT, SoulprintOptions };
4
+ /**
5
+ * soulprint() — Express/Connect middleware for Soulprint identity verification.
6
+ *
7
+ * USAGE:
8
+ *
9
+ * ```typescript
10
+ * import express from "express";
11
+ * import { soulprint } from "soulprint-express";
12
+ *
13
+ * const app = express();
14
+ *
15
+ * // Protect entire API — require KYC verified humans
16
+ * app.use(soulprint({ minScore: 60 }));
17
+ *
18
+ * // Protect specific route — require full biometric KYC
19
+ * app.post("/sensitive", soulprint({ require: ["DocumentVerified", "FaceMatch"] }), handler);
20
+ *
21
+ * // Inside a handler — get the verified identity
22
+ * app.get("/me", soulprint({ minScore: 20 }), (req, res) => {
23
+ * const identity = req.soulprint; // SoulprintToken
24
+ * res.json({ nullifier: identity.nullifier, score: identity.score });
25
+ * });
26
+ * ```
27
+ *
28
+ * Token is read from:
29
+ * - HTTP header: X-Soulprint: <SPT>
30
+ * - Query param: ?spt=<SPT>
31
+ * - Bearer token: Authorization: Bearer <SPT>
32
+ */
33
+ export declare function soulprint(opts?: SoulprintOptions): (req: any, res: any, next: Function) => void;
34
+ /**
35
+ * soulprintFastify() — Fastify plugin for Soulprint verification.
36
+ *
37
+ * USAGE:
38
+ *
39
+ * ```typescript
40
+ * import Fastify from "fastify";
41
+ * import { soulprintFastify } from "soulprint-express";
42
+ *
43
+ * const fastify = Fastify();
44
+ * await fastify.register(soulprintFastify, { minScore: 60 });
45
+ *
46
+ * fastify.get("/me", async (request) => {
47
+ * const identity = request.soulprint;
48
+ * return { nullifier: identity?.nullifier };
49
+ * });
50
+ * ```
51
+ */
52
+ export declare function soulprintFastify(fastify: any, opts?: SoulprintOptions): Promise<void>;
53
+ declare global {
54
+ namespace Express {
55
+ interface Request {
56
+ soulprint?: SoulprintToken;
57
+ }
58
+ }
59
+ }
60
+ export { decodeToken, SoulprintToken, TrustLevel, CredentialType } from "soulprint-core";
package/dist/index.js ADDED
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decodeToken = exports.verifySPT = void 0;
4
+ exports.soulprint = soulprint;
5
+ exports.soulprintFastify = soulprintFastify;
6
+ const verify_js_1 = require("./verify.js");
7
+ Object.defineProperty(exports, "verifySPT", { enumerable: true, get: function () { return verify_js_1.verifySPT; } });
8
+ // ── Express Middleware ────────────────────────────────────────────────────────
9
+ /**
10
+ * soulprint() — Express/Connect middleware for Soulprint identity verification.
11
+ *
12
+ * USAGE:
13
+ *
14
+ * ```typescript
15
+ * import express from "express";
16
+ * import { soulprint } from "soulprint-express";
17
+ *
18
+ * const app = express();
19
+ *
20
+ * // Protect entire API — require KYC verified humans
21
+ * app.use(soulprint({ minScore: 60 }));
22
+ *
23
+ * // Protect specific route — require full biometric KYC
24
+ * app.post("/sensitive", soulprint({ require: ["DocumentVerified", "FaceMatch"] }), handler);
25
+ *
26
+ * // Inside a handler — get the verified identity
27
+ * app.get("/me", soulprint({ minScore: 20 }), (req, res) => {
28
+ * const identity = req.soulprint; // SoulprintToken
29
+ * res.json({ nullifier: identity.nullifier, score: identity.score });
30
+ * });
31
+ * ```
32
+ *
33
+ * Token is read from:
34
+ * - HTTP header: X-Soulprint: <SPT>
35
+ * - Query param: ?spt=<SPT>
36
+ * - Bearer token: Authorization: Bearer <SPT>
37
+ */
38
+ function soulprint(opts = {}) {
39
+ return function soulprintMiddleware(req, res, next) {
40
+ const spt = extractSPT(req);
41
+ const result = (0, verify_js_1.verifySPT)(spt, opts);
42
+ if (!result.allowed) {
43
+ opts.onRejected?.(result.reason);
44
+ res.status(403).json({
45
+ error: "soulprint_required",
46
+ message: opts.rejectMessage ?? result.reason,
47
+ docs: "https://github.com/manuelariasfz/soulprint",
48
+ required: {
49
+ minScore: opts.minScore ?? 40,
50
+ require: opts.require,
51
+ },
52
+ });
53
+ return;
54
+ }
55
+ opts.onVerified?.(result.token);
56
+ // Attach to req for downstream handlers
57
+ req.soulprint = result.token;
58
+ next();
59
+ };
60
+ }
61
+ function extractSPT(req) {
62
+ // 1. Header dedicado
63
+ const header = req.headers?.["x-soulprint"] ?? req.headers?.["X-Soulprint"];
64
+ if (header)
65
+ return header;
66
+ // 2. Authorization: Bearer <SPT>
67
+ const auth = req.headers?.authorization ?? "";
68
+ if (auth.startsWith("Bearer ")) {
69
+ const token = auth.slice(7);
70
+ // Solo si parece un SPT (base64url largo) — no interferir con JWTs normales
71
+ if (token.length > 200)
72
+ return token;
73
+ }
74
+ // 3. Query param: ?spt=...
75
+ if (req.query?.spt)
76
+ return req.query.spt;
77
+ return undefined;
78
+ }
79
+ // ── Fastify Plugin ────────────────────────────────────────────────────────────
80
+ /**
81
+ * soulprintFastify() — Fastify plugin for Soulprint verification.
82
+ *
83
+ * USAGE:
84
+ *
85
+ * ```typescript
86
+ * import Fastify from "fastify";
87
+ * import { soulprintFastify } from "soulprint-express";
88
+ *
89
+ * const fastify = Fastify();
90
+ * await fastify.register(soulprintFastify, { minScore: 60 });
91
+ *
92
+ * fastify.get("/me", async (request) => {
93
+ * const identity = request.soulprint;
94
+ * return { nullifier: identity?.nullifier };
95
+ * });
96
+ * ```
97
+ */
98
+ async function soulprintFastify(fastify, opts = {}) {
99
+ fastify.addHook("preHandler", async (request, reply) => {
100
+ const spt = extractSPT(request);
101
+ const result = (0, verify_js_1.verifySPT)(spt, opts);
102
+ if (!result.allowed) {
103
+ opts.onRejected?.(result.reason);
104
+ reply.status(403).send({
105
+ error: "soulprint_required",
106
+ message: opts.rejectMessage ?? result.reason,
107
+ docs: "https://github.com/manuelariasfz/soulprint",
108
+ });
109
+ return;
110
+ }
111
+ opts.onVerified?.(result.token);
112
+ request.soulprint = result.token;
113
+ });
114
+ }
115
+ var soulprint_core_1 = require("soulprint-core");
116
+ Object.defineProperty(exports, "decodeToken", { enumerable: true, get: function () { return soulprint_core_1.decodeToken; } });
@@ -0,0 +1,14 @@
1
+ import { SoulprintToken, TrustLevel, CredentialType } from "soulprint-core";
2
+ export interface SoulprintOptions {
3
+ minScore?: number;
4
+ minLevel?: TrustLevel;
5
+ require?: CredentialType | CredentialType[];
6
+ rejectMessage?: string;
7
+ onVerified?: (token: SoulprintToken) => void;
8
+ onRejected?: (reason: string) => void;
9
+ }
10
+ export declare function verifySPT(spt: string | undefined | null, opts?: SoulprintOptions): {
11
+ allowed: boolean;
12
+ token?: SoulprintToken;
13
+ reason?: string;
14
+ };
package/dist/verify.js ADDED
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifySPT = verifySPT;
4
+ const soulprint_core_1 = require("soulprint-core");
5
+ const LEVEL_SCORES = {
6
+ Unverified: 0, EmailVerified: 10, PhoneVerified: 25, KYCLite: 45, KYCFull: 80,
7
+ };
8
+ function verifySPT(spt, opts = {}) {
9
+ if (!spt) {
10
+ const result = { allowed: false, reason: "No Soulprint token provided" };
11
+ opts.onRejected?.(result.reason);
12
+ return result;
13
+ }
14
+ const token = (0, soulprint_core_1.decodeToken)(spt);
15
+ if (!token) {
16
+ const result = { allowed: false, reason: "Invalid or expired Soulprint token" };
17
+ opts.onRejected?.(result.reason);
18
+ return result;
19
+ }
20
+ const minScore = opts.minScore ?? 40;
21
+ if (token.score < minScore) {
22
+ const result = { allowed: false, reason: `Trust score too low: ${token.score} < ${minScore}` };
23
+ opts.onRejected?.(result.reason);
24
+ return result;
25
+ }
26
+ if (opts.minLevel) {
27
+ const req = LEVEL_SCORES[opts.minLevel] ?? 0;
28
+ const got = LEVEL_SCORES[token.level] ?? 0;
29
+ if (got < req) {
30
+ const result = { allowed: false, reason: `Trust level too low: ${token.level} < ${opts.minLevel}` };
31
+ opts.onRejected?.(result.reason);
32
+ return result;
33
+ }
34
+ }
35
+ if (opts.require) {
36
+ const required = Array.isArray(opts.require) ? opts.require : [opts.require];
37
+ const missing = required.filter(c => !token.credentials.includes(c));
38
+ if (missing.length > 0) {
39
+ const result = { allowed: false, reason: `Missing credentials: ${missing.join(", ")}` };
40
+ opts.onRejected?.(result.reason);
41
+ return result;
42
+ }
43
+ }
44
+ opts.onVerified?.(token);
45
+ return { allowed: true, token };
46
+ }
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "soulprint-express",
3
+ "version": "0.1.0",
4
+ "description": "Soulprint Express/Fastify middleware — app.use(soulprint({ minScore: 40 }))",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/manuelariasfz/soulprint",
17
+ "directory": "packages/express"
18
+ },
19
+ "homepage": "https://github.com/manuelariasfz/soulprint#readme",
20
+ "keywords": [
21
+ "soulprint",
22
+ "express",
23
+ "fastify",
24
+ "middleware",
25
+ "kyc",
26
+ "identity",
27
+ "ai-agents"
28
+ ],
29
+ "license": "MIT",
30
+ "dependencies": {
31
+ "soulprint-core": "0.1.0"
32
+ },
33
+ "peerDependencies": {
34
+ "express": ">=4.0.0"
35
+ },
36
+ "peerDependenciesMeta": {
37
+ "express": {
38
+ "optional": true
39
+ }
40
+ },
41
+ "devDependencies": {
42
+ "typescript": "^5.4.0",
43
+ "@types/node": "^20.0.0",
44
+ "@types/express": "^4.17.0"
45
+ },
46
+ "engines": {
47
+ "node": ">=18.0.0"
48
+ },
49
+ "scripts": {
50
+ "build": "tsc"
51
+ }
52
+ }