@cequrebackends/plugin-security 0.12.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/dist/mfa.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * RFC 6238 TOTP (Time-Based One-Time Password) implementation.
3
+ * Uses HMAC-SHA1 via Web Crypto — no external dependencies.
4
+ * Compatible with Google Authenticator, Authy, 1Password, etc.
5
+ */
6
+ /** Generate a random 20-byte base32-encoded TOTP secret. */
7
+ export declare function generateTOTPSecret(): string;
8
+ /** Generate a TOTP code for the current time. */
9
+ export declare function generateTOTP(secret: string, timeStep?: number, digits?: number): Promise<string>;
10
+ /** Verify a TOTP code against the current time, with a configurable window. */
11
+ export declare function verifyTOTP(secret: string, code: string, window?: number): Promise<boolean>;
12
+ /** Generate an `otpauth://` provisioning URI for QR code enrollment. */
13
+ export declare function generateOTPAuthURI(secret: string, account: string, issuer?: string): string;
14
+ /** Generate single-use backup codes (hex format: XXXXX-XXXXX-XXXXXX). */
15
+ export declare function generateBackupCodes(count?: number): string[];
16
+ /** Hash a backup code with SHA-256 for storage (like refresh tokens). */
17
+ export declare function hashBackupCode(code: string): Promise<string>;
18
+ //# sourceMappingURL=mfa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mfa.d.ts","sourceRoot":"","sources":["../src/mfa.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,4DAA4D;AAC5D,wBAAgB,kBAAkB,IAAI,MAAM,CAa3C;AA8BD,iDAAiD;AACjD,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,SAAK,EAAE,MAAM,SAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAG7F;AAED,+EAA+E;AAC/E,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3F;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAE,MAAiB,GAAG,MAAM,CAIrG;AAED,yEAAyE;AACzE,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,MAAW,GAAG,MAAM,EAAE,CAQhE;AAED,yEAAyE;AACzE,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAElE"}
@@ -0,0 +1,20 @@
1
+ import type { CequreAST } from "@cequrebackends/cequre-ts";
2
+ import type { CequreKV } from "@cequrebackends/cequre-ts";
3
+ /**
4
+ * Extract the real client IP, respecting trusted proxies.
5
+ *
6
+ * When `trustedProxies` is provided, X-Forwarded-For / X-Real-IP are
7
+ * only honoured if the direct connection IP is in the trusted list.
8
+ * When empty, the headers are ignored and the direct IP is used.
9
+ */
10
+ export declare function resolveClientIP(request: Request, trustedProxies?: string[]): string;
11
+ export declare class RateLimiter {
12
+ private kv;
13
+ private schema;
14
+ private hasRateLimit;
15
+ private trustedProxies;
16
+ constructor(schema: CequreAST, kv: CequreKV, trustedProxies?: string[]);
17
+ check(request: Request): Promise<Response | null> | Response | null;
18
+ private _doCheckAsync;
19
+ }
20
+ //# sourceMappingURL=rate-limiter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limiter.d.ts","sourceRoot":"","sources":["../src/rate-limiter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAI1D;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC9B,OAAO,EAAE,OAAO,EAChB,cAAc,CAAC,EAAE,MAAM,EAAE,GACvB,MAAM,CA4BR;AAED,qBAAa,WAAW;IACvB,OAAO,CAAC,EAAE,CAAW;IACrB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,YAAY,CAAU;IAC9B,OAAO,CAAC,cAAc,CAAW;gBAErB,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE;IAOtE,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,QAAQ,GAAG,IAAI;YAyCrD,aAAa;CAW3B"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Secrets provider abstraction.
3
+ *
4
+ * Allows production deployments to resolve secrets (JWT keys, encryption
5
+ * keys, audit secrets) from a KMS, HashiCorp Vault, or other external
6
+ * store instead of environment variables.
7
+ *
8
+ * The default implementation (`EnvVarSecrets`) reads from `process.env`.
9
+ * Future implementations: `VaultSecrets`, `KMSSecrets` — same interface.
10
+ */
11
+ export interface SecretsProvider {
12
+ /** Resolve a secret value by name. Returns null if not found. */
13
+ getSecret(name: string): Promise<string | null>;
14
+ /** List all available secret names (for diagnostics). */
15
+ listSecrets(): Promise<string[]>;
16
+ }
17
+ /**
18
+ * Default secrets provider — reads from environment variables.
19
+ * No external dependencies, works everywhere.
20
+ */
21
+ export declare class EnvVarSecrets implements SecretsProvider {
22
+ getSecret(name: string): Promise<string | null>;
23
+ listSecrets(): Promise<string[]>;
24
+ }
25
+ //# sourceMappingURL=secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,WAAW,eAAe;IAC9B,iEAAiE;IACjE,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAEhD,yDAAyD;IACzD,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;CAClC;AAED;;;GAGG;AACH,qBAAa,aAAc,YAAW,eAAe;IAC7C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAI/C,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAGvC"}
@@ -0,0 +1,58 @@
1
+ import type { CequreAdapter } from "@cequrebackends/cequre-ts";
2
+ /**
3
+ * A persisted entry for a refresh token.
4
+ * The hash is the SHA-256 of the raw refresh JWT string.
5
+ */
6
+ export interface RefreshTokenEntry {
7
+ userId: string;
8
+ collection: string;
9
+ role?: string;
10
+ expiresAt: number;
11
+ }
12
+ /**
13
+ * Abstraction over where refresh tokens are stored.
14
+ *
15
+ * - `InMemoryTokenStore` — process-local Map (dev / single-instance).
16
+ * - `AdapterTokenStore` — persisted via the CequreAdapter in a
17
+ * `cequre_refresh_tokens` system table (multi-instance / production).
18
+ *
19
+ * Every method takes the token *hash* (SHA-256 hex), never the raw token.
20
+ */
21
+ export interface TokenStore {
22
+ store(hash: string, entry: RefreshTokenEntry): Promise<void>;
23
+ lookup(hash: string): Promise<RefreshTokenEntry | null>;
24
+ revoke(hash: string): Promise<void>;
25
+ revokeAllForUser(userId: string): Promise<void>;
26
+ purgeExpired(): Promise<void>;
27
+ }
28
+ export declare class InMemoryTokenStore implements TokenStore {
29
+ private store_;
30
+ store(hash: string, entry: RefreshTokenEntry): Promise<void>;
31
+ lookup(hash: string): Promise<RefreshTokenEntry | null>;
32
+ revoke(hash: string): Promise<void>;
33
+ revokeAllForUser(userId: string): Promise<void>;
34
+ purgeExpired(): Promise<void>;
35
+ }
36
+ /**
37
+ * System collection/table name used by AdapterTokenStore.
38
+ */
39
+ export declare const REFRESH_TOKEN_COLLECTION = "cequre_refresh_tokens";
40
+ /**
41
+ * Persists refresh tokens through the CequreAdapter so they survive
42
+ * process restarts and are visible across multiple server instances.
43
+ *
44
+ * Each token is stored as a document whose `id` is the token hash.
45
+ * This works across SQL adapters (Postgres, SQLite), MongoDB, Redis,
46
+ * and SurrealDB — all of which expose the same `create / findById /
47
+ * find / delete` contract.
48
+ */
49
+ export declare class AdapterTokenStore implements TokenStore {
50
+ private adapter;
51
+ constructor(adapter: CequreAdapter);
52
+ store(hash: string, entry: RefreshTokenEntry): Promise<void>;
53
+ lookup(hash: string): Promise<RefreshTokenEntry | null>;
54
+ revoke(hash: string): Promise<void>;
55
+ revokeAllForUser(userId: string): Promise<void>;
56
+ purgeExpired(): Promise<void>;
57
+ }
58
+ //# sourceMappingURL=token-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../src/token-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAK/D;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B;AAMD,qBAAa,kBAAmB,YAAW,UAAU;IACnD,OAAO,CAAC,MAAM,CAAwC;IAEhD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAIvD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInC,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/C,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAMpC;AAMD;;GAEG;AACH,eAAO,MAAM,wBAAwB,0BAA0B,CAAC;AAEhE;;;;;;;;GAQG;AACH,qBAAa,iBAAkB,YAAW,UAAU;IACtC,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAEpC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC5D,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAgBvD,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQnC,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe/C,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;CAepC"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Webhook signing utility.
3
+ *
4
+ * Provides HMAC-SHA256 signing for outbound webhook payloads so consumers
5
+ * can verify authenticity. Follows the Stripe-style header format:
6
+ *
7
+ * X-Cequre-Signature: t=<timestamp>,v1=<hex-hmac>
8
+ *
9
+ * Consumers verify by:
10
+ * 1. Splitting the header on ","
11
+ * 2. Extracting the timestamp (t=) and signature (v1=)
12
+ * 3. Computing HMAC-SHA256 over "<timestamp>.<payload>"
13
+ * 4. Comparing with constant-time equality
14
+ */
15
+ /**
16
+ * Signs a webhook payload and returns the signature header value.
17
+ *
18
+ * @param secret - The shared secret (must be known by both sender and receiver)
19
+ * @param payload - The raw payload string (JSON body, etc.)
20
+ * @param timestamp - Optional timestamp (defaults to now, in seconds)
21
+ * @returns Header value string: "t=<ts>,v1=<hex>"
22
+ */
23
+ export declare function signWebhook(secret: string, payload: string, timestamp?: number): Promise<string>;
24
+ /**
25
+ * The header name to use for the signature.
26
+ */
27
+ export declare const WEBHOOK_SIGNATURE_HEADER = "X-Cequre-Signature";
28
+ /**
29
+ * Verifies a webhook signature against a payload.
30
+ *
31
+ * @param secret - The shared secret
32
+ * @param headerValue - The value of the X-Cequre-Signature header
33
+ * @param payload - The raw payload string
34
+ * @param toleranceSeconds - Maximum age of the signature (default: 300 = 5 min)
35
+ * @returns true if the signature is valid and within the tolerance window
36
+ */
37
+ export declare function verifyWebhookSignature(secret: string, headerValue: string, payload: string, toleranceSeconds?: number): Promise<boolean>;
38
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH;;;;;;;GAOG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CAajB;AAED;;GAEG;AACH,eAAO,MAAM,wBAAwB,uBAAgB,CAAC;AAEtD;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,gBAAgB,GAAE,MAAY,GAC7B,OAAO,CAAC,OAAO,CAAC,CAmClB"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@cequrebackends/plugin-security",
3
+ "version": "0.12.2",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "files": [
9
+ "dist"
10
+ ],
11
+ "scripts": {
12
+ "build": "rm -rf dist && bun build ./src/index.ts --outdir ./dist --target bun --packages external && tsc --emitDeclarationOnly"
13
+ },
14
+ "devDependencies": {
15
+ "tsup": "^8.5.1",
16
+ "typescript": "^5.0.0",
17
+ "@cequrebackends/cequre-ts": "0.12.2"
18
+ },
19
+ "sideEffects": false,
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js",
24
+ "default": "./dist/index.js"
25
+ },
26
+ "./auth": {
27
+ "types": "./dist/auth.d.ts",
28
+ "import": "./dist/auth.js",
29
+ "default": "./dist/auth.js"
30
+ },
31
+ "./rate-limiter": {
32
+ "types": "./dist/rate-limiter.d.ts",
33
+ "import": "./dist/rate-limiter.js",
34
+ "default": "./dist/rate-limiter.js"
35
+ },
36
+ "./token-store": {
37
+ "types": "./dist/token-store.d.ts",
38
+ "import": "./dist/token-store.js",
39
+ "default": "./dist/token-store.js"
40
+ },
41
+ "./audit": {
42
+ "types": "./dist/audit.d.ts",
43
+ "import": "./dist/audit.js",
44
+ "default": "./dist/audit.js"
45
+ },
46
+ "./encryption": {
47
+ "types": "./dist/encryption.d.ts",
48
+ "import": "./dist/encryption.js",
49
+ "default": "./dist/encryption.js"
50
+ },
51
+ "./mfa": {
52
+ "types": "./dist/mfa.d.ts",
53
+ "import": "./dist/mfa.js",
54
+ "default": "./dist/mfa.js"
55
+ }
56
+ },
57
+ "publishConfig": {
58
+ "access": "public",
59
+ "registry": "https://registry.npmjs.org/"
60
+ },
61
+ "repository": {
62
+ "type": "git",
63
+ "url": "https://github.com/cequrebackends/cequre.git"
64
+ },
65
+ "peerDependencies": {
66
+ "@cequrebackends/cequre-ts": "0.12.2"
67
+ }
68
+ }