@salamandradevs/core 0.1.3 → 0.2.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.
- package/README.md +4 -2
- package/dist/index.js +4 -2
- package/dist/infra/database/database-provider.js +3 -1
- package/dist/infra/database/mongo/mongo-db-connection.js +14 -2
- package/dist/infra/database/mysql/mysql-db-connection.js +16 -2
- package/dist/keys/config/index.js +3 -0
- package/dist/keys/config/schema.js +51 -0
- package/dist/keys/config/types.js +2 -0
- package/dist/keys/contracts.js +2 -0
- package/dist/keys/factory.js +61 -0
- package/dist/keys/index.js +10 -0
- package/dist/keys/jose/index.js +3 -0
- package/dist/keys/jose/jose-keyfile.js +97 -0
- package/dist/keys/jose/jose-keys-provider.js +256 -0
- package/dist/keys/jose/schema.js +68 -0
- package/dist/keys/jose/types.js +2 -0
- package/dist/keys/jwks/index.js +2 -0
- package/dist/keys/jwks/jwks-verification-key-provider.js +43 -0
- package/dist/keys/openbao/index.js +3 -0
- package/dist/keys/openbao/openbao-keys-provider.js +461 -0
- package/dist/keys/openbao/schema.js +67 -0
- package/dist/keys/openbao/types.js +2 -0
- package/dist/keys/schema.js +65 -0
- package/dist/keys/types.js +2 -0
- package/dist/keys/validation.js +100 -0
- package/dist/runtime/context.js +42 -0
- package/dist/runtime/index.js +2 -0
- package/dist/storage/records-handler.js +2 -2
- package/dist/tokens/access-token-verifier.js +75 -0
- package/dist/tokens/contracts.js +2 -0
- package/dist/tokens/index.js +5 -0
- package/dist/tokens/schema.js +36 -0
- package/dist/tokens/types.js +2 -0
- package/package.json +2 -1
- package/types/index.d.ts +3 -1
- package/types/index.d.ts.map +1 -1
- package/types/infra/database/contracts.d.ts +9 -1
- package/types/infra/database/contracts.d.ts.map +1 -1
- package/types/infra/database/database-provider.d.ts +2 -0
- package/types/infra/database/database-provider.d.ts.map +1 -1
- package/types/infra/database/mongo/mongo-db-connection.d.ts +2 -0
- package/types/infra/database/mongo/mongo-db-connection.d.ts.map +1 -1
- package/types/infra/database/mysql/mysql-db-connection.d.ts +2 -0
- package/types/infra/database/mysql/mysql-db-connection.d.ts.map +1 -1
- package/types/keys/config/index.d.ts +3 -0
- package/types/keys/config/index.d.ts.map +1 -0
- package/types/keys/config/schema.d.ts +66 -0
- package/types/keys/config/schema.d.ts.map +1 -0
- package/types/keys/config/types.d.ts +8 -0
- package/types/keys/config/types.d.ts.map +1 -0
- package/types/keys/contracts.d.ts +52 -0
- package/types/keys/contracts.d.ts.map +1 -0
- package/types/keys/factory.d.ts +22 -0
- package/types/keys/factory.d.ts.map +1 -0
- package/types/keys/index.d.ts +10 -0
- package/types/keys/index.d.ts.map +1 -0
- package/types/keys/jose/index.d.ts +3 -0
- package/types/keys/jose/index.d.ts.map +1 -0
- package/types/keys/jose/jose-keyfile.d.ts +35 -0
- package/types/keys/jose/jose-keyfile.d.ts.map +1 -0
- package/types/keys/jose/jose-keys-provider.d.ts +112 -0
- package/types/keys/jose/jose-keys-provider.d.ts.map +1 -0
- package/types/keys/jose/schema.d.ts +91 -0
- package/types/keys/jose/schema.d.ts.map +1 -0
- package/types/keys/jose/types.d.ts +35 -0
- package/types/keys/jose/types.d.ts.map +1 -0
- package/types/keys/jwks/index.d.ts +2 -0
- package/types/keys/jwks/index.d.ts.map +1 -0
- package/types/keys/jwks/jwks-verification-key-provider.d.ts +27 -0
- package/types/keys/jwks/jwks-verification-key-provider.d.ts.map +1 -0
- package/types/keys/openbao/index.d.ts +3 -0
- package/types/keys/openbao/index.d.ts.map +1 -0
- package/types/keys/openbao/openbao-keys-provider.d.ts +175 -0
- package/types/keys/openbao/openbao-keys-provider.d.ts.map +1 -0
- package/types/keys/openbao/schema.d.ts +68 -0
- package/types/keys/openbao/schema.d.ts.map +1 -0
- package/types/keys/openbao/types.d.ts +52 -0
- package/types/keys/openbao/types.d.ts.map +1 -0
- package/types/keys/schema.d.ts +73 -0
- package/types/keys/schema.d.ts.map +1 -0
- package/types/keys/types.d.ts +53 -0
- package/types/keys/types.d.ts.map +1 -0
- package/types/keys/validation.d.ts +19 -0
- package/types/keys/validation.d.ts.map +1 -0
- package/types/runtime/context.d.ts +67 -0
- package/types/runtime/context.d.ts.map +1 -0
- package/types/runtime/index.d.ts +2 -0
- package/types/runtime/index.d.ts.map +1 -0
- package/types/tokens/access-token-verifier.d.ts +36 -0
- package/types/tokens/access-token-verifier.d.ts.map +1 -0
- package/types/tokens/contracts.d.ts +21 -0
- package/types/tokens/contracts.d.ts.map +1 -0
- package/types/tokens/index.d.ts +5 -0
- package/types/tokens/index.d.ts.map +1 -0
- package/types/tokens/schema.d.ts +34 -0
- package/types/tokens/schema.d.ts.map +1 -0
- package/types/tokens/types.d.ts +20 -0
- package/types/tokens/types.d.ts.map +1 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* OpenBao key namespace, request policy, and connection schema.
|
|
4
|
+
*
|
|
5
|
+
* - TransitMount: Transit secrets-engine mount.
|
|
6
|
+
* - KvMount: KV v2 secrets-engine mount.
|
|
7
|
+
* - StatePath: KV path containing lifecycle state.
|
|
8
|
+
* - KeyNamePrefix: Prefix for provider-managed Transit keys.
|
|
9
|
+
* - RequestTimeoutMs: Deadline applied to every OpenBao HTTP request.
|
|
10
|
+
* - RefreshCooldownSecs: Minimum time between two re-reads of the lifecycle document
|
|
11
|
+
* triggered by an unknown `kid`.
|
|
12
|
+
* - BaoAddr: OpenBao origin without embedded credentials; read from `BAO_ADDR`.
|
|
13
|
+
* - BaoToken: Runtime OpenBao token; a secret, read from `BAO_TOKEN`.
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* `baoAddr` and `baoToken` are marked `.meta({ env })`, so `loadEnvVariables` resolves them
|
|
17
|
+
* from `BAO_ADDR` and `BAO_TOKEN` and hands the values to the provider; the configuration
|
|
18
|
+
* file holds only placeholders, so the token never appears in the config object.
|
|
19
|
+
*/
|
|
20
|
+
export const openBaoSigningKeysConfigSchema = z
|
|
21
|
+
.object({
|
|
22
|
+
transitMount: z.string().min(1),
|
|
23
|
+
kvMount: z.string().min(1),
|
|
24
|
+
statePath: z.string().min(1),
|
|
25
|
+
keyNamePrefix: z.string().min(1),
|
|
26
|
+
requestTimeoutMs: z.number().int().positive().default(10_000),
|
|
27
|
+
refreshCooldownSecs: z.number().int().positive(),
|
|
28
|
+
baoAddr: z.url({ error: 'is required and must be a URL' }).meta({ env: 'BAO_ADDR' }),
|
|
29
|
+
baoToken: z
|
|
30
|
+
.string({ error: 'is required' })
|
|
31
|
+
.min(1, 'must not be empty')
|
|
32
|
+
.meta({ env: 'BAO_TOKEN' })
|
|
33
|
+
})
|
|
34
|
+
.strict();
|
|
35
|
+
/**
|
|
36
|
+
* KV v2 lifecycle-state read response schema.
|
|
37
|
+
*
|
|
38
|
+
* - Data: KV envelope carrying the stored document and its version metadata.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* OpenBao wraps every logical response in an envelope carrying `request_id`, `lease_id`,
|
|
42
|
+
* `lease_duration`, `renewable`, `warnings`, `wrap_info`, `auth` and `mount_type`, and the
|
|
43
|
+
* version metadata adds `created_time`, `custom_metadata`, `deletion_time` and `destroyed`.
|
|
44
|
+
* None of these response schemas may be `strict`, because those unmodelled fields are
|
|
45
|
+
* always present. Verified against OpenBao 2.7.0.
|
|
46
|
+
*/
|
|
47
|
+
export const openBaoKvReadResponseSchema = z.object({
|
|
48
|
+
data: z.object({
|
|
49
|
+
data: z.record(z.string(), z.unknown()),
|
|
50
|
+
metadata: z.object({ version: z.number().int().positive() })
|
|
51
|
+
})
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* Transit signing response schema.
|
|
55
|
+
*
|
|
56
|
+
* - Data: JWS-formatted signature returned by Transit.
|
|
57
|
+
*/
|
|
58
|
+
export const openBaoTransitSignResponseSchema = z.object({
|
|
59
|
+
data: z.object({ signature: z.string().min(1) })
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* OpenBao error response schema.
|
|
63
|
+
*
|
|
64
|
+
* - Errors: Sanitized error messages returned by OpenBao.
|
|
65
|
+
*/
|
|
66
|
+
export const openBaoErrorResponseSchema = z.object({ errors: z.array(z.string()) });
|
|
67
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2tleXMvb3BlbmJhby9zY2hlbWEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUV4Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFDSCxNQUFNLENBQUMsTUFBTSw4QkFBOEIsR0FBRyxDQUFDO0tBQzVDLE1BQU0sQ0FBQztJQUNOLFlBQVksRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMvQixPQUFPLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDMUIsU0FBUyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzVCLGFBQWEsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNoQyxnQkFBZ0IsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM3RCxtQkFBbUIsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFO0lBQ2hELE9BQU8sRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxFQUFFLCtCQUErQixFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLENBQUM7SUFDcEYsUUFBUSxFQUFFLENBQUM7U0FDUixNQUFNLENBQUMsRUFBRSxLQUFLLEVBQUUsYUFBYSxFQUFFLENBQUM7U0FDaEMsR0FBRyxDQUFDLENBQUMsRUFBRSxtQkFBbUIsQ0FBQztTQUMzQixJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsV0FBVyxFQUFFLENBQUM7Q0FDOUIsQ0FBQztLQUNELE1BQU0sRUFBRSxDQUFDO0FBRVo7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxNQUFNLENBQUMsTUFBTSwyQkFBMkIsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQ2xELElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDO1FBQ2IsSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUN2QyxRQUFRLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQztLQUM3RCxDQUFDO0NBQ0gsQ0FBQyxDQUFDO0FBRUg7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGdDQUFnQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDdkQsSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0NBQ2pELENBQUMsQ0FBQztBQUVIOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDIn0=
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Public JSON Web Key material schema.
|
|
4
|
+
*
|
|
5
|
+
* - Kty: Key type.
|
|
6
|
+
* - Kid: Public key identifier.
|
|
7
|
+
* - Use: Optional intended key use.
|
|
8
|
+
* - Alg: Optional JOSE algorithm.
|
|
9
|
+
* - Crv: Optional elliptic curve name.
|
|
10
|
+
* - X: Optional elliptic-curve or RSA coordinate.
|
|
11
|
+
* - Y: Optional elliptic-curve coordinate.
|
|
12
|
+
* - N: Optional RSA modulus.
|
|
13
|
+
* - E: Optional RSA exponent.
|
|
14
|
+
*
|
|
15
|
+
* @remarks
|
|
16
|
+
* Provider-neutral: this is the public key as served to every key consumer, so it carries
|
|
17
|
+
* no provider-specific fields. Shared across every signing-key provider so each validates
|
|
18
|
+
* the lifecycle document against one definition.
|
|
19
|
+
* @group Keys
|
|
20
|
+
* @category Key Providers
|
|
21
|
+
*/
|
|
22
|
+
export const publicJwkSchema = z
|
|
23
|
+
.object({
|
|
24
|
+
kty: z.string(),
|
|
25
|
+
kid: z.string().min(1),
|
|
26
|
+
use: z.string().optional(),
|
|
27
|
+
alg: z.string().optional(),
|
|
28
|
+
crv: z.string().optional(),
|
|
29
|
+
x: z.string().optional(),
|
|
30
|
+
y: z.string().optional(),
|
|
31
|
+
n: z.string().optional(),
|
|
32
|
+
e: z.string().optional()
|
|
33
|
+
})
|
|
34
|
+
.strict();
|
|
35
|
+
/**
|
|
36
|
+
* Durable signing-key lifecycle document schema.
|
|
37
|
+
*
|
|
38
|
+
* - CurrentKid: Identifier of the sole active key.
|
|
39
|
+
* - Keys: Complete provider-managed key lifecycle.
|
|
40
|
+
*
|
|
41
|
+
* @remarks
|
|
42
|
+
* The neutral contract every provider's durable store must satisfy. Behavioural invariants
|
|
43
|
+
* beyond this shape (exactly one active key, status-consistent timestamps) live in
|
|
44
|
+
* {@link validateSigningKeyState}.
|
|
45
|
+
* @group Keys
|
|
46
|
+
* @category Key Providers
|
|
47
|
+
*/
|
|
48
|
+
export const signingKeyStateSchema = z
|
|
49
|
+
.object({
|
|
50
|
+
currentKid: z.string().min(1).nullable(),
|
|
51
|
+
keys: z.array(z
|
|
52
|
+
.object({
|
|
53
|
+
kid: z.string().min(1),
|
|
54
|
+
providerKeyId: z.string().min(1),
|
|
55
|
+
status: z.enum(['pending', 'active', 'retired']),
|
|
56
|
+
publicJwk: publicJwkSchema,
|
|
57
|
+
activateAfter: z.string().pipe(z.iso.datetime()),
|
|
58
|
+
activatedAt: z.string().pipe(z.iso.datetime()).nullable(),
|
|
59
|
+
retiredAt: z.string().pipe(z.iso.datetime()).nullable(),
|
|
60
|
+
verifyUntil: z.string().pipe(z.iso.datetime()).nullable()
|
|
61
|
+
})
|
|
62
|
+
.strict())
|
|
63
|
+
})
|
|
64
|
+
.strict();
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2tleXMvc2NoZW1hLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFFeEI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFDSCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsQ0FBQztLQUM3QixNQUFNLENBQUM7SUFDTixHQUFHLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRTtJQUNmLEdBQUcsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN0QixHQUFHLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUMxQixHQUFHLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUMxQixHQUFHLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUMxQixDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUN4QixDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUN4QixDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUN4QixDQUFDLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtDQUN6QixDQUFDO0tBQ0QsTUFBTSxFQUFFLENBQUM7QUFFWjs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxDQUFDO0tBQ25DLE1BQU0sQ0FBQztJQUNOLFVBQVUsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRTtJQUN4QyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FDWCxDQUFDO1NBQ0UsTUFBTSxDQUFDO1FBQ04sR0FBRyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3RCLGFBQWEsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNoQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxRQUFRLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDaEQsU0FBUyxFQUFFLGVBQWU7UUFDMUIsYUFBYSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNoRCxXQUFXLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFO1FBQ3pELFNBQVMsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUU7UUFDdkQsV0FBVyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRTtLQUMxRCxDQUFDO1NBQ0QsTUFBTSxFQUFFLENBQ1o7Q0FDRixDQUFDO0tBQ0QsTUFBTSxFQUFFLENBQUMifQ==
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { CustomError } from '@salamandradevs/tools/shared';
|
|
2
|
+
import { signingKeyStateSchema } from './schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Parses the signing-key lifecycle document and enforces every invariant providers rely on.
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* Shared by every signing-key provider so the lifecycle invariants have one definition:
|
|
8
|
+
* unique identifiers, an ES256 P-256 public JWK per entry whose `kid` matches its entry,
|
|
9
|
+
* status-consistent timestamps, exactly one active key, at most one pending key, and a
|
|
10
|
+
* `currentKid` that names the active key. Nothing downstream re-checks any of this, so a
|
|
11
|
+
* failure here is fatal on purpose.
|
|
12
|
+
* @group Keys
|
|
13
|
+
* @category Key Providers
|
|
14
|
+
* @param value - Raw lifecycle document read from a provider's durable store.
|
|
15
|
+
* @param algorithm - JOSE algorithm every published key must declare.
|
|
16
|
+
* @returns Validated signing-key state.
|
|
17
|
+
* @throws {CustomError} KEYS_PROVIDER_ERROR when any signing-key invariant fails.
|
|
18
|
+
*/
|
|
19
|
+
export function validateSigningKeyState(value, algorithm) {
|
|
20
|
+
const candidate = signingKeyStateSchema.parse(value);
|
|
21
|
+
const keys = candidate.keys;
|
|
22
|
+
const kids = new Set();
|
|
23
|
+
const providerKeyIds = new Set();
|
|
24
|
+
for (const entry of keys) {
|
|
25
|
+
// Duplicates would make `kid` lookup ambiguous and could point two entries at one signing
|
|
26
|
+
// key, so retiring one would destroy the other's material.
|
|
27
|
+
if (kids.has(entry.kid) || providerKeyIds.has(entry.providerKeyId)) {
|
|
28
|
+
throw new CustomError({
|
|
29
|
+
name: 'KEYS_PROVIDER_ERROR',
|
|
30
|
+
message: 'Signing-key lifecycle state contains duplicate key identifiers'
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
kids.add(entry.kid);
|
|
34
|
+
providerKeyIds.add(entry.providerKeyId);
|
|
35
|
+
// The JWK is served verbatim to every token consumer, so it must be exactly an ES256
|
|
36
|
+
// P-256 verification key whose `kid` matches the entry that carries it.
|
|
37
|
+
if (entry.publicJwk.kty !== 'EC' ||
|
|
38
|
+
entry.publicJwk.crv !== 'P-256' ||
|
|
39
|
+
entry.publicJwk.alg !== algorithm ||
|
|
40
|
+
entry.publicJwk.use !== 'sig' ||
|
|
41
|
+
entry.publicJwk.kid !== entry.kid ||
|
|
42
|
+
!entry.publicJwk.x ||
|
|
43
|
+
!entry.publicJwk.y) {
|
|
44
|
+
throw new CustomError({
|
|
45
|
+
name: 'KEYS_PROVIDER_ERROR',
|
|
46
|
+
message: 'Signing-key lifecycle state contains an invalid public JWK'
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
validateEntryTimestamps(entry);
|
|
50
|
+
}
|
|
51
|
+
const active = keys.filter((entry) => entry.status === 'active');
|
|
52
|
+
const pending = keys.filter((entry) => entry.status === 'pending');
|
|
53
|
+
// Exactly one active key, because issuance picks it by status alone; at most one pending,
|
|
54
|
+
// because a second would be promoted into a key the first already replaced.
|
|
55
|
+
if (active.length !== 1 || pending.length > 1) {
|
|
56
|
+
throw new CustomError({
|
|
57
|
+
name: 'KEYS_PROVIDER_ERROR',
|
|
58
|
+
message: 'Signing-key lifecycle state must contain one active and at most one pending key'
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// `currentKid` is redundant with the active entry, which makes it a useful cross-check that
|
|
62
|
+
// a hand-written or externally provisioned document did not leave the two disagreeing.
|
|
63
|
+
if (candidate.currentKid !== active[0].kid) {
|
|
64
|
+
throw new CustomError({
|
|
65
|
+
name: 'KEYS_PROVIDER_ERROR',
|
|
66
|
+
message: 'Signing-key lifecycle state has an invalid current key'
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return { currentKid: candidate.currentKid, keys };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Enforces the timestamps each signing-key status permits, and their chronological order.
|
|
73
|
+
*
|
|
74
|
+
* @param entry - Signing-key entry to check.
|
|
75
|
+
* @throws {CustomError} KEYS_PROVIDER_ERROR when the entry carries timestamps its status
|
|
76
|
+
* forbids.
|
|
77
|
+
*/
|
|
78
|
+
function validateEntryTimestamps(entry) {
|
|
79
|
+
// Each status implies exactly which timestamps may be set. Checking this here is what lets
|
|
80
|
+
// the rest of the system treat a present `verifyUntil` as proof the entry is retired.
|
|
81
|
+
const pendingIsClean = entry.activatedAt === null && entry.retiredAt === null && entry.verifyUntil === null;
|
|
82
|
+
const activeIsClean = entry.activatedAt !== null && entry.retiredAt === null && entry.verifyUntil === null;
|
|
83
|
+
const retiredIsOrdered = entry.activatedAt !== null &&
|
|
84
|
+
entry.retiredAt !== null &&
|
|
85
|
+
entry.verifyUntil !== null &&
|
|
86
|
+
Date.parse(entry.activatedAt) <= Date.parse(entry.retiredAt) &&
|
|
87
|
+
Date.parse(entry.retiredAt) <= Date.parse(entry.verifyUntil);
|
|
88
|
+
const valid = entry.status === 'pending'
|
|
89
|
+
? pendingIsClean
|
|
90
|
+
: entry.status === 'active'
|
|
91
|
+
? activeIsClean
|
|
92
|
+
: retiredIsOrdered;
|
|
93
|
+
if (!valid) {
|
|
94
|
+
throw new CustomError({
|
|
95
|
+
name: 'KEYS_PROVIDER_ERROR',
|
|
96
|
+
message: `Signing-key lifecycle entry '${entry.kid}' has timestamps its status forbids`
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmFsaWRhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9rZXlzL3ZhbGlkYXRpb24udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBRTNELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUdwRDs7Ozs7Ozs7Ozs7Ozs7O0dBZUc7QUFDSCxNQUFNLFVBQVUsdUJBQXVCLENBQ3JDLEtBQWMsRUFDZCxTQUFrQjtJQUVsQixNQUFNLFNBQVMsR0FBb0IscUJBQXFCLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3RFLE1BQU0sSUFBSSxHQUErQixTQUFTLENBQUMsSUFBSSxDQUFDO0lBQ3hELE1BQU0sSUFBSSxHQUFnQixJQUFJLEdBQUcsRUFBVSxDQUFDO0lBQzVDLE1BQU0sY0FBYyxHQUFnQixJQUFJLEdBQUcsRUFBVSxDQUFDO0lBRXRELEtBQUssTUFBTSxLQUFLLElBQUksSUFBSSxFQUFFLENBQUM7UUFDekIsMEZBQTBGO1FBQzFGLDJEQUEyRDtRQUMzRCxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLGNBQWMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUM7WUFDbkUsTUFBTSxJQUFJLFdBQVcsQ0FBQztnQkFDcEIsSUFBSSxFQUFFLHFCQUFxQjtnQkFDM0IsT0FBTyxFQUFFLGdFQUFnRTthQUMxRSxDQUFDLENBQUM7UUFDTCxDQUFDO1FBRUQsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDcEIsY0FBYyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7UUFFeEMscUZBQXFGO1FBQ3JGLHdFQUF3RTtRQUN4RSxJQUNFLEtBQUssQ0FBQyxTQUFTLENBQUMsR0FBRyxLQUFLLElB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
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { CustomError } from '@salamandradevs/tools/shared';
|
|
2
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
3
|
+
// Async local storage backing the ambient execution context for the current async scope.
|
|
4
|
+
const executionContextStorage = new AsyncLocalStorage();
|
|
5
|
+
/**
|
|
6
|
+
* Runs one callback with the supplied execution context bound to the current async scope.
|
|
7
|
+
*
|
|
8
|
+
* @remarks
|
|
9
|
+
* The context is visible to every asynchronous operation started within `callback` and is
|
|
10
|
+
* torn down when it returns, so nested calls to {@link getExecutionCtx} resolve the same
|
|
11
|
+
* identity without explicit propagation. Transport middleware wraps request handling in
|
|
12
|
+
* this call.
|
|
13
|
+
* @group Utils
|
|
14
|
+
* @category Execution Context
|
|
15
|
+
* @param context - Execution context for the current request or job.
|
|
16
|
+
* @param callback - Work executed while the context is available.
|
|
17
|
+
* @returns The callback return value.
|
|
18
|
+
*/
|
|
19
|
+
export function runWithExecutionCtx(context, callback) {
|
|
20
|
+
return executionContextStorage.run(context, callback);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Reads the current execution context.
|
|
24
|
+
*
|
|
25
|
+
* @group Utils
|
|
26
|
+
* @category Execution Context
|
|
27
|
+
* @returns The active {@link ExecutionContext} for the current async scope.
|
|
28
|
+
* @throws {CustomError} RESOURCE_NOT_FOUND when called outside a {@link runWithExecutionCtx}
|
|
29
|
+
* scope, so no context is bound.
|
|
30
|
+
*/
|
|
31
|
+
export function getExecutionCtx() {
|
|
32
|
+
const context = executionContextStorage.getStore();
|
|
33
|
+
if (!context) {
|
|
34
|
+
throw new CustomError({
|
|
35
|
+
name: 'RESOURCE_NOT_FOUND',
|
|
36
|
+
message: 'Execution context is not available',
|
|
37
|
+
cause: 'Async local storage could not get the execution context'
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return context;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lL2NvbnRleHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzNELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBOENyRCx5RkFBeUY7QUFDekYsTUFBTSx1QkFBdUIsR0FDM0IsSUFBSSxpQkFBaUIsRUFBb0IsQ0FBQztBQUU1Qzs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFJLE9BQXlCLEVBQUUsUUFBaUI7SUFDakYsT0FBTyx1QkFBdUIsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBQ3hELENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSxlQUFlO0lBQzdCLE1BQU0sT0FBTyxHQUFpQyx1QkFBdUIsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUVqRixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDYixNQUFNLElBQUksV0FBVyxDQUFDO1lBQ3BCLElBQUksRUFBRSxvQkFBb0I7WUFDMUIsT0FBTyxFQUFFLG9DQUFvQztZQUM3QyxLQUFLLEVBQUUseURBQXlEO1NBQ2pFLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDIn0=
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { getExecutionCtx } from '../
|
|
2
|
+
import { getExecutionCtx } from '../runtime/context.js';
|
|
3
3
|
/**
|
|
4
4
|
* Base record handler that applies tenant scope and delegates persistence to an
|
|
5
5
|
* {@link ICrud} adapter.
|
|
@@ -137,4 +137,4 @@ export class RecordsHandler {
|
|
|
137
137
|
return this.crud.find({ ...criteria, tenantId }, findOptions);
|
|
138
138
|
}
|
|
139
139
|
}
|
|
140
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
140
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3Jkcy1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0b3JhZ2UvcmVjb3Jkcy1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFekMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBTXhEOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLE9BQWdCLGNBQWM7SUFRYjtJQUNGO0lBUm5COzs7OztPQUtHO0lBQ0gsWUFDcUIsSUFBYyxFQUNoQixXQUE2QjtRQUQzQixTQUFJLEdBQUosSUFBSSxDQUFVO1FBQ2hCLGdCQUFXLEdBQVgsV0FBVyxDQUFrQjtJQUM3QyxDQUFDO0lBRUo7Ozs7Ozs7Ozs7T0FVRztJQUNILE1BQU0sQ0FBQyxNQUE0QjtRQUNqQyxNQUFNLEVBQUUsYUFBYSxFQUFFLEdBQUcsZUFBZSxFQUFFLENBQUM7UUFDNUMsTUFBTSxHQUFHLEdBQVMsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUU3QixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQ3RCLEdBQUcsTUFBTTtZQUNULFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVztZQUM3QixRQUFRLEVBQUUsYUFBYSxDQUFDLFFBQVE7WUFDaEMsUUFBUSxFQUFFLFVBQVUsRUFBRTtZQUN0QixTQUFTLEVBQUUsR0FBRztZQUNkLFNBQVMsRUFBRSxhQUFhLENBQUMsT0FBTztZQUNoQyxTQUFTLEVBQUUsR0FBRztZQUNkLFNBQVMsRUFBRSxhQUFhLENBQUMsT0FBTztTQUM1QixDQUFDLENBQUM7SUFDVixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsSUFBSSxDQUFDLFFBQWdCO1FBQ25CLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxlQUFlLEVBQUUsQ0FBQyxhQUFhLENBQUM7UUFFckQsTUFBTSxRQUFRLEdBQWU7WUFDM0IsUUFBUTtZQUNSLFFBQVE7U0FDSyxDQUFDO1FBRWhCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVEOzs7Ozs7Ozs7OztPQVdHO0lBQ0gsTUFBTSxDQUFDLFFBQWdCLEVBQUUsT0FBeUI7UUFDaEQsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsR0FBRyxlQUFlLEVBQUUsQ0FBQyxhQUFhLENBQUM7UUFFOUQsTUFBTSxRQUFRLEdBQWU7WUFDM0IsUUFBUTtZQUNSLFFBQVE7U0FDSyxDQUFDO1FBRWhCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO1lBQ2hDLEdBQUcsT0FBTztZQUNWLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRTtZQUNyQixTQUFTLEVBQUUsT0FBTztTQUNuQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNILE1BQU0sQ0FBQyxRQUFnQjtRQUNyQixNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsZUFBZSxFQUFFLENBQUMsYUFBYSxDQUFDO1FBRXJELE1BQU0sUUFBUSxHQUFlO1lBQzNCLFFBQVE7WUFDUixRQUFRO1NBQ0ssQ0FBQztRQUVoQixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7O09BWUc7SUFDSCxJQUFJLENBQUMsV0FBdUIsRUFBRSxFQUFFLE9BQTBCO1FBQ3hELE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxlQUFlLEVBQUUsQ0FBQyxhQUFhLENBQUM7UUFFckQsTUFBTSxTQUFTLEdBQXlCO1lBQ3RDLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFO1lBQ3pDLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFO1NBQ3pDLENBQUM7UUFFRixNQUFNLFdBQVcsR0FBbUI7WUFDbEMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUEyQjtZQUMzQyxLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUs7WUFDcEIsT0FBTyxFQUFFLFNBQVM7U0FDbkIsQ0FBQztRQUVGLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLFFBQVEsRUFBRSxRQUFRLEVBQUUsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUNoRSxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { decodeProtectedHeader, jwtVerify } from 'jose';
|
|
2
|
+
import { CustomError } from '@salamandradevs/tools/shared';
|
|
3
|
+
import { accessTokenClaimsSchema } from './schema.js';
|
|
4
|
+
/**
|
|
5
|
+
* Verifies platform access tokens and reconstructs their session grant.
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* Checks the protected header, resolves the public key by `kid` through the injected
|
|
9
|
+
* {@link IVerificationKeyProvider}, verifies signature, issuer, audience, and expiry with
|
|
10
|
+
* `jose`, then parses the claims with {@link accessTokenClaimsSchema}.
|
|
11
|
+
* @group Tokens
|
|
12
|
+
* @category Access Tokens
|
|
13
|
+
*/
|
|
14
|
+
export class AccessTokenVerifier {
|
|
15
|
+
config;
|
|
16
|
+
keys;
|
|
17
|
+
/**
|
|
18
|
+
* @param config - Issuer, audience, and clock tolerance every token must satisfy.
|
|
19
|
+
* @param keys - Source of public verification keys by `kid`.
|
|
20
|
+
*/
|
|
21
|
+
constructor(config, keys) {
|
|
22
|
+
this.config = config;
|
|
23
|
+
this.keys = keys;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Verifies one bearer access token.
|
|
27
|
+
*
|
|
28
|
+
* @param credential - Bearer credential selected by the transport layer.
|
|
29
|
+
* @returns Trusted session grant read from the token claims.
|
|
30
|
+
* @throws {CustomError} AUTHENTICATION_FAILED when the token is malformed, signed by an
|
|
31
|
+
* unknown key, expired, or carries incomplete claims.
|
|
32
|
+
* @throws {CustomError} EXTERNAL_API_ERROR or CONFIG_ERROR when the key provider fails;
|
|
33
|
+
* propagated unchanged.
|
|
34
|
+
*/
|
|
35
|
+
async verify(credential) {
|
|
36
|
+
try {
|
|
37
|
+
const header = decodeProtectedHeader(credential.token);
|
|
38
|
+
if (header.kid === undefined || header.alg !== 'ES256' || header.typ !== 'JWT') {
|
|
39
|
+
throw new Error('JWT protected header is invalid');
|
|
40
|
+
}
|
|
41
|
+
const key = await this.keys.getPublicKey(header.kid);
|
|
42
|
+
if (!key) {
|
|
43
|
+
throw new Error('JWT signing key is unknown');
|
|
44
|
+
}
|
|
45
|
+
const { payload } = await jwtVerify(credential.token, key, {
|
|
46
|
+
algorithms: ['ES256'],
|
|
47
|
+
issuer: this.config.issuer,
|
|
48
|
+
audience: this.config.audience,
|
|
49
|
+
clockTolerance: this.config.clockToleranceSecs
|
|
50
|
+
});
|
|
51
|
+
const claims = accessTokenClaimsSchema.parse(payload);
|
|
52
|
+
return {
|
|
53
|
+
sessionId: claims.sid,
|
|
54
|
+
subject: claims.sub,
|
|
55
|
+
actorId: claims.actorId,
|
|
56
|
+
tenantId: claims.tenantId,
|
|
57
|
+
roles: claims.roles
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
// An infrastructure fault keeps its classification, so a key-source outage is
|
|
62
|
+
// never reported as an invalid credential.
|
|
63
|
+
if (error instanceof CustomError &&
|
|
64
|
+
(error.name === 'EXTERNAL_API_ERROR' || error.name === 'CONFIG_ERROR')) {
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
throw new CustomError({
|
|
68
|
+
name: 'AUTHENTICATION_FAILED',
|
|
69
|
+
message: 'Credentials verification failed',
|
|
70
|
+
cause: error
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjZXNzLXRva2VuLXZlcmlmaWVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rva2Vucy9hY2Nlc3MtdG9rZW4tdmVyaWZpZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHFCQUFxQixFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN4RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFHM0QsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBUXREOzs7Ozs7Ozs7R0FTRztBQUNILE1BQU0sT0FBTyxtQkFBbUI7SUFNWDtJQUNBO0lBTm5COzs7T0FHRztJQUNILFlBQ21CLE1BQStCLEVBQy9CLElBQThCO1FBRDlCLFdBQU0sR0FBTixNQUFNLENBQXlCO1FBQy9CLFNBQUksR0FBSixJQUFJLENBQTBCO0lBQzlDLENBQUM7SUFFSjs7Ozs7Ozs7O09BU0c7SUFDSCxLQUFLLENBQUMsTUFBTSxDQUFDLFVBQXVCO1FBQ2xDLElBQUksQ0FBQztZQUNILE1BQU0sTUFBTSxHQUE4QixxQkFBcUIsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7WUFFbEYsSUFBSSxNQUFNLENBQUMsR0FBRyxLQUFLLFNBQVMsSUFBSSxNQUFNLENBQUMsR0FBRyxLQUFLLE9BQU8sSUFBSSxNQUFNLENBQUMsR0FBRyxLQUFLLEtBQUssRUFBRSxDQUFDO2dCQUMvRSxNQUFNLElBQUksS0FBSyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7WUFDckQsQ0FBQztZQUVELE1BQU0sR0FBRyxHQUFxQixNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUV2RSxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7Z0JBQ1QsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsQ0FBQyxDQUFDO1lBQ2hELENBQUM7WUFFRCxNQUFNLEVBQUUsT0FBTyxFQUFFLEdBQUcsTUFBTSxTQUFTLENBQUMsVUFBVSxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUU7Z0JBQ3pELFVBQVUsRUFBRSxDQUFDLE9BQU8sQ0FBQztnQkFDckIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTtnQkFDMUIsUUFBUSxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUTtnQkFDOUIsY0FBYyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsa0JBQWtCO2FBQy9DLENBQUMsQ0FBQztZQUNILE1BQU0sTUFBTSxHQUFzQix1QkFBdUIsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7WUFFekUsT0FBTztnQkFDTCxTQUFTLEVBQUUsTUFBTSxDQUFDLEdBQUc7Z0JBQ3JCLE9BQU8sRUFBRSxNQUFNLENBQUMsR0FBRztnQkFDbkIsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO2dCQUN2QixRQUFRLEVBQUUsTUFBTSxDQUFDLFFBQVE7Z0JBQ3pCLEtBQUssRUFBRSxNQUFNLENBQUMsS0FBSzthQUNwQixDQUFDO1FBQ0osQ0FBQztRQUFDLE9BQU8sS0FBYyxFQUFFLENBQUM7WUFDeEIsOEVBQThFO1lBQzlFLDJDQUEyQztZQUMzQyxJQUNFLEtBQUssWUFBWSxXQUFXO2dCQUM1QixDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssb0JBQW9CLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxjQUFjLENBQUMsRUFDdEUsQ0FBQztnQkFDRCxNQUFNLEtBQUssQ0FBQztZQUNkLENBQUM7WUFFRCxNQUFNLElBQUksV0FBVyxDQUFDO2dCQUNwQixJQUFJLEVBQUUsdUJBQXVCO2dCQUM3QixPQUFPLEVBQUUsaUNBQWlDO2dCQUMxQyxLQUFLLEVBQUUsS0FBSzthQUNiLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0NBQ0YifQ==
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export * from './access-token-verifier.js';
|
|
2
|
+
export * from './contracts.js';
|
|
3
|
+
export * from './schema.js';
|
|
4
|
+
export * from './types.js';
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdG9rZW5zL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLGFBQWEsQ0FBQztBQUM1QixjQUFjLFlBQVksQ0FBQyJ9
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Access-token verification policy every verifier shares with the issuer.
|
|
4
|
+
*
|
|
5
|
+
* - Issuer: Required `iss`, the issuing service's base URL.
|
|
6
|
+
* - Audience: Required `aud`.
|
|
7
|
+
* - ClockToleranceSecs: Allowed clock skew when checking `exp` and `iat`.
|
|
8
|
+
*/
|
|
9
|
+
export const accessTokenVerifyConfigSchema = z
|
|
10
|
+
.object({
|
|
11
|
+
issuer: z.url(),
|
|
12
|
+
audience: z.string().min(1),
|
|
13
|
+
clockToleranceSecs: z.number().int().nonnegative()
|
|
14
|
+
})
|
|
15
|
+
.strict();
|
|
16
|
+
/**
|
|
17
|
+
* Platform claims carried by every access token.
|
|
18
|
+
*
|
|
19
|
+
* - Sid: Server-side session identifier.
|
|
20
|
+
* - Sub: Authenticated subject.
|
|
21
|
+
* - ActorId: Local actor represented by the session.
|
|
22
|
+
* - TenantId: Tenant the session belongs to.
|
|
23
|
+
* - Roles: Roles granted to the session.
|
|
24
|
+
*
|
|
25
|
+
* @remarks
|
|
26
|
+
* Not strict: `jwtVerify` already checks the registered claims (`iss`, `aud`, `iat`,
|
|
27
|
+
* `exp`), and parsing strips them.
|
|
28
|
+
*/
|
|
29
|
+
export const accessTokenClaimsSchema = z.object({
|
|
30
|
+
sid: z.string(),
|
|
31
|
+
sub: z.string(),
|
|
32
|
+
actorId: z.string(),
|
|
33
|
+
tenantId: z.string(),
|
|
34
|
+
roles: z.array(z.string().min(1))
|
|
35
|
+
});
|
|
36
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rva2Vucy9zY2hlbWEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUV4Qjs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSw2QkFBNkIsR0FBRyxDQUFDO0tBQzNDLE1BQU0sQ0FBQztJQUNOLE1BQU0sRUFBRSxDQUFDLENBQUMsR0FBRyxFQUFFO0lBQ2YsUUFBUSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzNCLGtCQUFrQixFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxXQUFXLEVBQUU7Q0FDbkQsQ0FBQztLQUNELE1BQU0sRUFBRSxDQUFDO0FBRVo7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUM5QyxHQUFHLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRTtJQUNmLEdBQUcsRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFO0lBQ2YsT0FBTyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUU7SUFDbkIsUUFBUSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUU7SUFDcEIsS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztDQUNsQyxDQUFDLENBQUMifQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salamandradevs/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Shared record layer and database contracts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@12.16.1",
|
|
@@ -47,6 +47,7 @@
|
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@salamandradevs/tools": "^0.1.0",
|
|
50
|
+
"jose": "^6.2.12",
|
|
50
51
|
"mongodb": "^7.6.0",
|
|
51
52
|
"mysql2": "^3.23.4",
|
|
52
53
|
"zod": "^4.5.4"
|
package/types/index.d.ts
CHANGED
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC"}
|
|
@@ -18,6 +18,8 @@ export interface IDatabaseProvider {
|
|
|
18
18
|
* Opens the underlying connection and caches its backend-tagged handle.
|
|
19
19
|
*
|
|
20
20
|
* @returns The connected database handle.
|
|
21
|
+
* @throws {CustomError} DB_BACKEND_ERROR when the server is unreachable or rejects the
|
|
22
|
+
* connection; the driver error is kept as the cause.
|
|
21
23
|
*/
|
|
22
24
|
connect(): Promise<DatabaseHandle>;
|
|
23
25
|
/**
|
|
@@ -45,7 +47,13 @@ export interface IDatabaseProvider {
|
|
|
45
47
|
* @template THandle - Raw driver handle produced by `connect`.
|
|
46
48
|
*/
|
|
47
49
|
export interface IDbConnection<THandle> {
|
|
48
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* Opens the database connection and returns the backend handle.
|
|
52
|
+
*
|
|
53
|
+
* @returns The connected raw driver handle.
|
|
54
|
+
* @throws {CustomError} DB_BACKEND_ERROR when the server is unreachable or rejects the
|
|
55
|
+
* connection; the driver error is kept as the cause.
|
|
56
|
+
*/
|
|
49
57
|
connect(): Promise<THandle>;
|
|
50
58
|
/** Closes the database connection. */
|
|
51
59
|
close(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../../src/infra/database/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAEnC,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAElC
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../../src/infra/database/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAEnC,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE1D;;;;;;;;;GASG;AACH,MAAM,WAAW,iBAAiB;IAChC,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAElC;;;;;;OAMG;IACH,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IAEnC;;;;OAIG;IACH,SAAS,IAAI,cAAc,CAAC;IAE5B;;;;OAIG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,aAAa,CAAC,OAAO;IACpC;;;;;;OAMG;IACH,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAE5B,sCAAsC;IACtC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,QAAQ,CAAC,OAAO,EAAE,MAAM,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE;IAChE,yCAAyC;IACzC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAErC,mDAAmD;IACnD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5D,kEAAkE;IAClE,SAAS,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAE1E,iCAAiC;IACjC,WAAW,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClE;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,KAAK,CAAC,CAAC;IACtB,2BAA2B;IAC3B,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAE9B,qDAAqD;IACrD,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAE9C,uDAAuD;IACvD,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAErE,uDAAuD;IACvD,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAEhD,6EAA6E;IAC7E,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7E;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,eAAe,CAAC,OAAO,IAAI,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;AAEpE;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB,CAAC,IAAI;IACvC;;;;;OAKG;IACH,SAAS,CAAC,GAAG,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACrC"}
|
|
@@ -33,6 +33,8 @@ export declare class DatabaseProvider implements IDatabaseProvider {
|
|
|
33
33
|
* without a matching `case` fails the `never` exhaustiveness check. Calling it again
|
|
34
34
|
* reconnects and replaces the cached handle.
|
|
35
35
|
* @returns The connected database handle.
|
|
36
|
+
* @throws {CustomError} DB_BACKEND_ERROR when the server is unreachable or rejects the
|
|
37
|
+
* connection; propagated from the backend connection.
|
|
36
38
|
*/
|
|
37
39
|
connect(): Promise<DatabaseHandle>;
|
|
38
40
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database-provider.d.ts","sourceRoot":"","sources":["../../../src/infra/database/database-provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAElE;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,YAAW,iBAAiB;aAatC,OAAO,EAAE,eAAe;IAZ1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAwC;IACnE,OAAO,CAAC,MAAM,CAA+B;IAE7C;;;;;;;OAOG;gBAEe,OAAO,EAAE,eAAe,EACxC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM;IA4BtB
|
|
1
|
+
{"version":3,"file":"database-provider.d.ts","sourceRoot":"","sources":["../../../src/infra/database/database-provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAElE;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,YAAW,iBAAiB;aAatC,OAAO,EAAE,eAAe;IAZ1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAwC;IACnE,OAAO,CAAC,MAAM,CAA+B;IAE7C;;;;;;;OAOG;gBAEe,OAAO,EAAE,eAAe,EACxC,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM;IA4BtB;;;;;;;;;;;OAWG;IACG,OAAO,IAAI,OAAO,CAAC,cAAc,CAAC;IA2BxC;;;;;;OAMG;IACH,SAAS,IAAI,cAAc;IAW3B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -27,6 +27,8 @@ export declare class MongoDbConnection implements IDbConnection<Db> {
|
|
|
27
27
|
* Opens the Mongo connection and returns the database handle.
|
|
28
28
|
*
|
|
29
29
|
* @returns Connected Mongo database handle.
|
|
30
|
+
* @throws {CustomError} DB_BACKEND_ERROR when the server is unreachable or rejects the
|
|
31
|
+
* connection; the driver error is kept as the cause.
|
|
30
32
|
*/
|
|
31
33
|
connect(): Promise<Db>;
|
|
32
34
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongo-db-connection.d.ts","sourceRoot":"","sources":["../../../../src/infra/database/mongo/mongo-db-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,EAAE,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"mongo-db-connection.d.ts","sourceRoot":"","sources":["../../../../src/infra/database/mongo/mongo-db-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,EAAE,EAAE,MAAM,SAAS,CAAC;AAG/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;GASG;AACH,qBAAa,iBAAkB,YAAW,aAAa,CAAC,EAAE,CAAC;IAavD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAbzB,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,EAAG,SAAS,CAAU;IAEtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC;;;;;OAKG;gBAEgB,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM;IAKjC;;;;;;OAMG;IACG,OAAO,IAAI,OAAO,CAAC,EAAE,CAAC;IAc5B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7B"}
|
|
@@ -27,6 +27,8 @@ export declare class MySqlDbConnection implements IDbConnection<Pool> {
|
|
|
27
27
|
* Opens the MySQL connection and returns the backend handle.
|
|
28
28
|
*
|
|
29
29
|
* @returns Connected MySQL backend handle.
|
|
30
|
+
* @throws {CustomError} DB_BACKEND_ERROR when the server is unreachable or rejects the
|
|
31
|
+
* connection; the driver error is kept as the cause.
|
|
30
32
|
*/
|
|
31
33
|
connect(): Promise<Pool>;
|
|
32
34
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mysql-db-connection.d.ts","sourceRoot":"","sources":["../../../../src/infra/database/mysql/mysql-db-connection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"mysql-db-connection.d.ts","sourceRoot":"","sources":["../../../../src/infra/database/mysql/mysql-db-connection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAErD;;;;;;;;;GASG;AACH,qBAAa,iBAAkB,YAAW,aAAa,CAAC,IAAI,CAAC;IAazD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAb/B,0EAA0E;IAC1E,QAAQ,CAAC,OAAO,EAAG,OAAO,CAAU;IAEpC,OAAO,CAAC,IAAI,CAAqB;IAEjC;;;;;OAKG;gBAEgB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM;IAGvC;;;;;;OAMG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB9B;;;;OAIG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/keys/config/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC"}
|