@salamandradevs/core 0.1.4 → 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.
Files changed (87) hide show
  1. package/README.md +4 -2
  2. package/dist/index.js +4 -2
  3. package/dist/keys/config/index.js +3 -0
  4. package/dist/keys/config/schema.js +51 -0
  5. package/dist/keys/config/types.js +2 -0
  6. package/dist/keys/contracts.js +2 -0
  7. package/dist/keys/factory.js +61 -0
  8. package/dist/keys/index.js +10 -0
  9. package/dist/keys/jose/index.js +3 -0
  10. package/dist/keys/jose/jose-keyfile.js +97 -0
  11. package/dist/keys/jose/jose-keys-provider.js +256 -0
  12. package/dist/keys/jose/schema.js +68 -0
  13. package/dist/keys/jose/types.js +2 -0
  14. package/dist/keys/jwks/index.js +2 -0
  15. package/dist/keys/jwks/jwks-verification-key-provider.js +43 -0
  16. package/dist/keys/openbao/index.js +3 -0
  17. package/dist/keys/openbao/openbao-keys-provider.js +461 -0
  18. package/dist/keys/openbao/schema.js +67 -0
  19. package/dist/keys/openbao/types.js +2 -0
  20. package/dist/keys/schema.js +65 -0
  21. package/dist/keys/types.js +2 -0
  22. package/dist/keys/validation.js +100 -0
  23. package/dist/runtime/context.js +42 -0
  24. package/dist/runtime/index.js +2 -0
  25. package/dist/storage/records-handler.js +2 -2
  26. package/dist/tokens/access-token-verifier.js +75 -0
  27. package/dist/tokens/contracts.js +2 -0
  28. package/dist/tokens/index.js +5 -0
  29. package/dist/tokens/schema.js +36 -0
  30. package/dist/tokens/types.js +2 -0
  31. package/package.json +2 -1
  32. package/types/index.d.ts +3 -1
  33. package/types/index.d.ts.map +1 -1
  34. package/types/keys/config/index.d.ts +3 -0
  35. package/types/keys/config/index.d.ts.map +1 -0
  36. package/types/keys/config/schema.d.ts +66 -0
  37. package/types/keys/config/schema.d.ts.map +1 -0
  38. package/types/keys/config/types.d.ts +8 -0
  39. package/types/keys/config/types.d.ts.map +1 -0
  40. package/types/keys/contracts.d.ts +52 -0
  41. package/types/keys/contracts.d.ts.map +1 -0
  42. package/types/keys/factory.d.ts +22 -0
  43. package/types/keys/factory.d.ts.map +1 -0
  44. package/types/keys/index.d.ts +10 -0
  45. package/types/keys/index.d.ts.map +1 -0
  46. package/types/keys/jose/index.d.ts +3 -0
  47. package/types/keys/jose/index.d.ts.map +1 -0
  48. package/types/keys/jose/jose-keyfile.d.ts +35 -0
  49. package/types/keys/jose/jose-keyfile.d.ts.map +1 -0
  50. package/types/keys/jose/jose-keys-provider.d.ts +112 -0
  51. package/types/keys/jose/jose-keys-provider.d.ts.map +1 -0
  52. package/types/keys/jose/schema.d.ts +91 -0
  53. package/types/keys/jose/schema.d.ts.map +1 -0
  54. package/types/keys/jose/types.d.ts +35 -0
  55. package/types/keys/jose/types.d.ts.map +1 -0
  56. package/types/keys/jwks/index.d.ts +2 -0
  57. package/types/keys/jwks/index.d.ts.map +1 -0
  58. package/types/keys/jwks/jwks-verification-key-provider.d.ts +27 -0
  59. package/types/keys/jwks/jwks-verification-key-provider.d.ts.map +1 -0
  60. package/types/keys/openbao/index.d.ts +3 -0
  61. package/types/keys/openbao/index.d.ts.map +1 -0
  62. package/types/keys/openbao/openbao-keys-provider.d.ts +175 -0
  63. package/types/keys/openbao/openbao-keys-provider.d.ts.map +1 -0
  64. package/types/keys/openbao/schema.d.ts +68 -0
  65. package/types/keys/openbao/schema.d.ts.map +1 -0
  66. package/types/keys/openbao/types.d.ts +52 -0
  67. package/types/keys/openbao/types.d.ts.map +1 -0
  68. package/types/keys/schema.d.ts +73 -0
  69. package/types/keys/schema.d.ts.map +1 -0
  70. package/types/keys/types.d.ts +53 -0
  71. package/types/keys/types.d.ts.map +1 -0
  72. package/types/keys/validation.d.ts +19 -0
  73. package/types/keys/validation.d.ts.map +1 -0
  74. package/types/runtime/context.d.ts +67 -0
  75. package/types/runtime/context.d.ts.map +1 -0
  76. package/types/runtime/index.d.ts +2 -0
  77. package/types/runtime/index.d.ts.map +1 -0
  78. package/types/tokens/access-token-verifier.d.ts +36 -0
  79. package/types/tokens/access-token-verifier.d.ts.map +1 -0
  80. package/types/tokens/contracts.d.ts +21 -0
  81. package/types/tokens/contracts.d.ts.map +1 -0
  82. package/types/tokens/index.d.ts +5 -0
  83. package/types/tokens/index.d.ts.map +1 -0
  84. package/types/tokens/schema.d.ts +34 -0
  85. package/types/tokens/schema.d.ts.map +1 -0
  86. package/types/tokens/types.d.ts +20 -0
  87. package/types/tokens/types.d.ts.map +1 -0
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMva2V5cy90eXBlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiIn0=
@@ -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=
@@ -0,0 +1,2 @@
1
+ export * from './context.js';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcnVudGltZS9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLGNBQWMsQ0FBQyJ9
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { getExecutionCtx } from '../utils/context.js';
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVjb3Jkcy1oYW5kbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3N0b3JhZ2UvcmVjb3Jkcy1oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFekMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBTXREOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLE9BQWdCLGNBQWM7SUFRYjtJQUNGO0lBUm5COzs7OztPQUtHO0lBQ0gsWUFDcUIsSUFBYyxFQUNoQixXQUE2QjtRQUQzQixTQUFJLEdBQUosSUFBSSxDQUFVO1FBQ2hCLGdCQUFXLEdBQVgsV0FBVyxDQUFrQjtJQUM3QyxDQUFDO0lBRUo7Ozs7Ozs7Ozs7T0FVRztJQUNILE1BQU0sQ0FBQyxNQUE0QjtRQUNqQyxNQUFNLEVBQUUsYUFBYSxFQUFFLEdBQUcsZUFBZSxFQUFFLENBQUM7UUFDNUMsTUFBTSxHQUFHLEdBQVMsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUU3QixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO1lBQ3RCLEdBQUcsTUFBTTtZQUNULFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVztZQUM3QixRQUFRLEVBQUUsYUFBYSxDQUFDLFFBQVE7WUFDaEMsUUFBUSxFQUFFLFVBQVUsRUFBRTtZQUN0QixTQUFTLEVBQUUsR0FBRztZQUNkLFNBQVMsRUFBRSxhQUFhLENBQUMsT0FBTztZQUNoQyxTQUFTLEVBQUUsR0FBRztZQUNkLFNBQVMsRUFBRSxhQUFhLENBQUMsT0FBTztTQUM1QixDQUFDLENBQUM7SUFDVixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsSUFBSSxDQUFDLFFBQWdCO1FBQ25CLE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxlQUFlLEVBQUUsQ0FBQyxhQUFhLENBQUM7UUFFckQsTUFBTSxRQUFRLEdBQWU7WUFDM0IsUUFBUTtZQUNSLFFBQVE7U0FDSyxDQUFDO1FBRWhCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVEOzs7Ozs7Ozs7OztPQVdHO0lBQ0gsTUFBTSxDQUFDLFFBQWdCLEVBQUUsT0FBeUI7UUFDaEQsTUFBTSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsR0FBRyxlQUFlLEVBQUUsQ0FBQyxhQUFhLENBQUM7UUFFOUQsTUFBTSxRQUFRLEdBQWU7WUFDM0IsUUFBUTtZQUNSLFFBQVE7U0FDSyxDQUFDO1FBRWhCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO1lBQ2hDLEdBQUcsT0FBTztZQUNWLFNBQVMsRUFBRSxJQUFJLElBQUksRUFBRTtZQUNyQixTQUFTLEVBQUUsT0FBTztTQUNuQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNILE1BQU0sQ0FBQyxRQUFnQjtRQUNyQixNQUFNLEVBQUUsUUFBUSxFQUFFLEdBQUcsZUFBZSxFQUFFLENBQUMsYUFBYSxDQUFDO1FBRXJELE1BQU0sUUFBUSxHQUFlO1lBQzNCLFFBQVE7WUFDUixRQUFRO1NBQ0ssQ0FBQztRQUVoQixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3BDLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7O09BWUc7SUFDSCxJQUFJLENBQUMsV0FBdUIsRUFBRSxFQUFFLE9BQTBCO1FBQ3hELE1BQU0sRUFBRSxRQUFRLEVBQUUsR0FBRyxlQUFlLEVBQUUsQ0FBQyxhQUFhLENBQUM7UUFFckQsTUFBTSxTQUFTLEdBQXlCO1lBQ3RDLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFO1lBQ3pDLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFO1NBQ3pDLENBQUM7UUFFRixNQUFNLFdBQVcsR0FBbUI7WUFDbEMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxNQUEyQjtZQUMzQyxLQUFLLEVBQUUsT0FBTyxDQUFDLEtBQUs7WUFDcEIsT0FBTyxFQUFFLFNBQVM7U0FDbkIsQ0FBQztRQUVGLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLFFBQVEsRUFBRSxRQUFRLEVBQUUsRUFBRSxXQUFXLENBQUMsQ0FBQztJQUNoRSxDQUFDO0NBQ0YifQ==
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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udHJhY3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rva2Vucy9jb250cmFjdHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IiJ9
@@ -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==
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHlwZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdG9rZW5zL3R5cGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiIifQ==
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@salamandradevs/core",
3
- "version": "0.1.4",
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
@@ -1,4 +1,6 @@
1
1
  export * from './storage/index.js';
2
2
  export * from './infra/database/index.js';
3
- export * from './utils/index.js';
3
+ export * from './keys/index.js';
4
+ export * from './tokens/index.js';
5
+ export * from './runtime/index.js';
4
6
  //# sourceMappingURL=index.d.ts.map
@@ -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,kBAAkB,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"}
@@ -0,0 +1,3 @@
1
+ export * from './schema.js';
2
+ export * from './types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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"}
@@ -0,0 +1,66 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Supported signing-key provider identifiers; grows as new providers are added.
4
+ *
5
+ * @group Keys
6
+ * @category Key Providers
7
+ */
8
+ export declare const signingKeyProviderSchema: z.ZodEnum<{
9
+ jose: "jose";
10
+ openbao: "openbao";
11
+ }>;
12
+ /**
13
+ * Signing-key provider selector resolved from the environment.
14
+ *
15
+ * - Provider: Active signing-key provider; read from `SIGNING_KEY_PROVIDER`.
16
+ *
17
+ * @remarks
18
+ * `provider` is marked `.meta({ env })`, so `loadEnvVariables` resolves it from
19
+ * `SIGNING_KEY_PROVIDER`; the active provider is chosen at runtime, never baked into the
20
+ * configuration file.
21
+ * @group Keys
22
+ * @category Key Providers
23
+ */
24
+ export declare const signingKeyProviderSelectorSchema: z.ZodObject<{
25
+ provider: z.ZodEnum<{
26
+ jose: "jose";
27
+ openbao: "openbao";
28
+ }>;
29
+ }, z.core.$strict>;
30
+ /**
31
+ * Provider-neutral signing lifecycle schema.
32
+ *
33
+ * - Algorithm: JOSE algorithm supported by this key set.
34
+ * - Jose: Jose provider configuration, present when the deployment may select `jose`.
35
+ * - Openbao: OpenBao provider configuration, present when the deployment may select
36
+ * `openbao`.
37
+ *
38
+ * @remarks
39
+ * Each provider block is optional so a deployment configures only the providers it uses;
40
+ * the active one is chosen at runtime by `SIGNING_KEY_PROVIDER` and must have its block
41
+ * present. Composed into each service's own `serviceConfigSchema` and validated there; core
42
+ * never reads a configuration file.
43
+ * @group Keys
44
+ * @category Key Providers
45
+ */
46
+ export declare const signingKeysConfigSchema: z.ZodObject<{
47
+ algorithm: z.ZodLiteral<"ES256">;
48
+ jose: z.ZodOptional<z.ZodObject<{
49
+ keyNamePrefix: z.ZodString;
50
+ storage: z.ZodObject<{
51
+ filePath: z.ZodString;
52
+ passphrase: z.ZodString;
53
+ }, z.core.$strict>;
54
+ }, z.core.$strict>>;
55
+ openbao: z.ZodOptional<z.ZodObject<{
56
+ transitMount: z.ZodString;
57
+ kvMount: z.ZodString;
58
+ statePath: z.ZodString;
59
+ keyNamePrefix: z.ZodString;
60
+ requestTimeoutMs: z.ZodDefault<z.ZodNumber>;
61
+ refreshCooldownSecs: z.ZodNumber;
62
+ baoAddr: z.ZodURL;
63
+ baoToken: z.ZodString;
64
+ }, z.core.$strict>>;
65
+ }, z.core.$strict>;
66
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/keys/config/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;EAA8B,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gCAAgC;;;;;kBAIlC,CAAC;AAEZ;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;kBAMzB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { z } from 'zod';
2
+ import type { signingKeyProviderSchema } from './schema.js';
3
+ import type { signingKeysConfigSchema } from './schema.js';
4
+ /** Durable signing lifecycle and per-provider configuration. */
5
+ export type SigningKeysConfig = z.infer<typeof signingKeysConfigSchema>;
6
+ /** Signing-key provider selected at runtime by `SIGNING_KEY_PROVIDER`. */
7
+ export type SigningKeyProvider = z.infer<typeof signingKeyProviderSchema>;
8
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/keys/config/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAE3D,gEAAgE;AAChE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,0EAA0E;AAC1E,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
@@ -0,0 +1,52 @@
1
+ import type { CryptoKey } from 'jose';
2
+ import type { PublicJwk, SigningKeyHandle } from './types.js';
3
+ /**
4
+ * Owner of a key set that signs with it and lists its public keys.
5
+ *
6
+ * @remarks
7
+ * {@link JoseKeysProvider} and {@link OpenBaoKeysProvider} are the shipped implementations,
8
+ * each over the key set it owns. A consumer that only issues signatures depends on this
9
+ * role, never on {@link IVerificationKeyProvider} or {@link IKeysProvider}.
10
+ * @group Keys
11
+ * @category Key Providers
12
+ */
13
+ export interface ISigningKeyProvider {
14
+ /** Loads durable state and ensures that an active key exists. */
15
+ initialize(): Promise<void>;
16
+ /** Returns a signer bound to the active key. */
17
+ getCurrentSigner(): Promise<SigningKeyHandle>;
18
+ /** Lists public keys eligible for JWKS publication. */
19
+ listPublicKeys(): Promise<readonly PublicJwk[]>;
20
+ }
21
+ /**
22
+ * Source of public keys that verify signatures, looked up by key identifier.
23
+ *
24
+ * @remarks
25
+ * {@link JoseKeysProvider} and {@link OpenBaoKeysProvider} implement it over the key set they
26
+ * own, next to {@link ISigningKeyProvider}; {@link JwksVerificationKeyProvider} implements it
27
+ * over a remote JWKS.
28
+ * @group Keys
29
+ * @category Key Providers
30
+ */
31
+ export interface IVerificationKeyProvider {
32
+ /**
33
+ * Resolves an eligible public verification key by exact key identifier.
34
+ *
35
+ * @param kid - Key identifier carried with the signature.
36
+ * @returns The public key, or null when no eligible key has that identifier.
37
+ */
38
+ getPublicKey(kid: string): Promise<CryptoKey | null>;
39
+ }
40
+ /**
41
+ * Owner of a key set, which signs with it and verifies against it.
42
+ *
43
+ * @remarks
44
+ * Adds no members: it names the class the composition root builds once, which then hands
45
+ * each consumer only {@link ISigningKeyProvider} or {@link IVerificationKeyProvider}.
46
+ * {@link JoseKeysProvider} and {@link OpenBaoKeysProvider} are the shipped implementations.
47
+ * @group Keys
48
+ * @category Key Providers
49
+ */
50
+ export interface IKeysProvider extends ISigningKeyProvider, IVerificationKeyProvider {
51
+ }
52
+ //# sourceMappingURL=contracts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/keys/contracts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEtC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9D;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IAClC,iEAAiE;IACjE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B,gDAAgD;IAChD,gBAAgB,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE9C,uDAAuD;IACvD,cAAc,IAAI,OAAO,CAAC,SAAS,SAAS,EAAE,CAAC,CAAC;CACjD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;;;OAKG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;CACtD;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAc,SAAQ,mBAAmB,EAAE,wBAAwB;CAAG"}
@@ -0,0 +1,22 @@
1
+ import type { IKeysProvider } from './contracts.js';
2
+ import type { SigningKeysConfig } from './config/types.js';
3
+ /**
4
+ * Selects and constructs the keys provider named by `SIGNING_KEY_PROVIDER`.
5
+ *
6
+ * @remarks
7
+ * Construction only: each provider resolves its own environment as it is constructed but
8
+ * performs no input or output, so all network and file work is deferred to `initialize()`.
9
+ * The `switch` is the single extension point; a new provider is a new enum member, a new
10
+ * `case`, and its own configuration block, with no change to the bootstrap step or the
11
+ * services that consume the provider. Returns the owner of the key set as
12
+ * {@link IKeysProvider}; the composition root hands each consumer only the role it uses.
13
+ * @group Keys
14
+ * @category Key Providers
15
+ * @param config - Signing lifecycle and per-provider configuration.
16
+ * @returns The keys provider named by `SIGNING_KEY_PROVIDER`, ready for `initialize()`.
17
+ * @throws {CustomError} ENV_VAR_ERROR when `SIGNING_KEY_PROVIDER` is missing or not a
18
+ * recognized provider, or (for OpenBao) when the provider's own variables are missing.
19
+ * @throws {CustomError} CONFIG_ERROR when the selected provider has no configuration block.
20
+ */
21
+ export declare function createKeysProvider(config: SigningKeysConfig): IKeysProvider;
22
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/keys/factory.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,iBAAiB,GAAG,aAAa,CAiD3E"}
@@ -0,0 +1,10 @@
1
+ export * from './config/index.js';
2
+ export * from './contracts.js';
3
+ export * from './factory.js';
4
+ export * from './jose/index.js';
5
+ export * from './jwks/index.js';
6
+ export * from './openbao/index.js';
7
+ export * from './schema.js';
8
+ export * from './types.js';
9
+ export * from './validation.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/keys/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './jose-keys-provider.js';
2
+ export * from './schema.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/keys/jose/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC"}