@astram/guard 0.17.0 → 0.19.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/dist/audit/audit-chain-sealer.d.ts +90 -0
- package/dist/audit/audit-chain-sealer.d.ts.map +1 -0
- package/dist/audit/audit-chain-sealer.js +520 -0
- package/dist/audit/audit-seal-config.d.ts +22 -0
- package/dist/audit/audit-seal-config.d.ts.map +1 -0
- package/dist/audit/audit-seal-config.js +35 -0
- package/dist/audit/audit-sealer.service.d.ts +62 -0
- package/dist/audit/audit-sealer.service.d.ts.map +1 -0
- package/dist/audit/audit-sealer.service.js +197 -0
- package/dist/audit/node-sha256-hash.d.ts +6 -0
- package/dist/audit/node-sha256-hash.d.ts.map +1 -0
- package/dist/audit/node-sha256-hash.js +16 -0
- package/dist/auth/account.controller.d.ts +3 -1
- package/dist/auth/account.controller.d.ts.map +1 -1
- package/dist/auth/account.controller.js +10 -6
- package/dist/auth/auth.controller.d.ts +3 -1
- package/dist/auth/auth.controller.d.ts.map +1 -1
- package/dist/auth/auth.controller.js +13 -11
- package/dist/auth/auth.module.d.ts +14 -2
- package/dist/auth/auth.module.d.ts.map +1 -1
- package/dist/auth/auth.module.js +54 -7
- package/dist/auth/confirm-email.controller.d.ts +3 -1
- package/dist/auth/confirm-email.controller.d.ts.map +1 -1
- package/dist/auth/confirm-email.controller.js +9 -5
- package/dist/auth/email-change-messages.d.ts +2 -0
- package/dist/auth/email-change-messages.d.ts.map +1 -1
- package/dist/auth/email-change-messages.js +2 -0
- package/dist/auth/password-reset-message.d.ts +7 -0
- package/dist/auth/password-reset-message.d.ts.map +1 -0
- package/dist/auth/password-reset-message.js +17 -0
- package/dist/auth/persistence.module.d.ts +2 -2
- package/dist/auth/persistence.module.d.ts.map +1 -1
- package/dist/auth/persistence.module.js +19 -3
- package/dist/auth/ports/email-sender.d.ts +7 -7
- package/dist/auth/ports/email-sender.d.ts.map +1 -1
- package/dist/auth/tokens.d.ts +14 -0
- package/dist/auth/tokens.d.ts.map +1 -1
- package/dist/auth/tokens.js +15 -1
- package/dist/authentication/credential-provisioner.d.ts +5 -0
- package/dist/authentication/credential-provisioner.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-provisioner.d.ts +1 -0
- package/dist/authentication/mariadb-credential-provisioner.d.ts.map +1 -1
- package/dist/authentication/mariadb-credential-provisioner.js +24 -1
- package/dist/config/message-config.d.ts +70 -0
- package/dist/config/message-config.d.ts.map +1 -0
- package/dist/config/message-config.js +249 -0
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -3
- package/dist/internal.d.ts +10 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +13 -1
- package/dist/messaging/deliver-email.d.ts +10 -0
- package/dist/messaging/deliver-email.d.ts.map +1 -0
- package/dist/messaging/deliver-email.js +19 -0
- package/dist/messaging/email-delivery.d.ts +42 -0
- package/dist/messaging/email-delivery.d.ts.map +1 -0
- package/dist/messaging/email-delivery.js +117 -0
- package/dist/messaging/message-dispatcher.d.ts +66 -0
- package/dist/messaging/message-dispatcher.d.ts.map +1 -0
- package/dist/messaging/message-dispatcher.js +133 -0
- package/dist/messaging/recipient-mask.d.ts +7 -0
- package/dist/messaging/recipient-mask.d.ts.map +1 -0
- package/dist/messaging/recipient-mask.js +15 -0
- package/dist/module/shield.module.d.ts +5 -3
- package/dist/module/shield.module.d.ts.map +1 -1
- package/package.json +15 -5
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MAX_MESSAGE_SEND_TIMEOUT_MS = exports.DEFAULT_MESSAGE_SEND_TIMEOUT_MS = exports.EMAIL_PROVIDER_VALUES = void 0;
|
|
4
|
+
exports.loadMessageConfig = loadMessageConfig;
|
|
5
|
+
/**
|
|
6
|
+
* Message delivery config (G-010, docs/features/message-delivery/SPEC.md R2–R8): what
|
|
7
|
+
* `ShieldModule.forRoot({ emailSender: 'env' })` reads from the environment. Mirrors
|
|
8
|
+
* {@link loadObjectStorageConfig}: every missing, invalid or contradictory value refuses boot with
|
|
9
|
+
* a message that names the variable, never its value (Shield #1, #10); outside development/test
|
|
10
|
+
* every credential must have been resolved from a `secret-ref:` at boot (ADR-0032, ADR-0040).
|
|
11
|
+
*
|
|
12
|
+
* Adapters live in `@astram/messaging`, which receives the validated {@link EmailDeliveryConfig}
|
|
13
|
+
* and reads no environment itself (spec P-2).
|
|
14
|
+
*/
|
|
15
|
+
const node_net_1 = require("node:net");
|
|
16
|
+
const core_1 = require("@astram/core");
|
|
17
|
+
const email_address_js_1 = require("../auth/email-address.js");
|
|
18
|
+
const app_config_js_1 = require("./app-config.js");
|
|
19
|
+
const loopback_host_js_1 = require("./loopback-host.js");
|
|
20
|
+
/** The email providers `EMAIL_PROVIDER` accepts. */
|
|
21
|
+
exports.EMAIL_PROVIDER_VALUES = ['smtp', 'brevo', 'sendgrid', 'mailgun', 'disabled'];
|
|
22
|
+
/** Default and ceiling for `MESSAGE_SEND_TIMEOUT_MS` (R6). */
|
|
23
|
+
exports.DEFAULT_MESSAGE_SEND_TIMEOUT_MS = 10_000;
|
|
24
|
+
exports.MAX_MESSAGE_SEND_TIMEOUT_MS = 30_000;
|
|
25
|
+
const HOST_LABEL = '[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?';
|
|
26
|
+
const HOSTNAME = new RegExp(`^${HOST_LABEL}(?:\\.${HOST_LABEL})*$`);
|
|
27
|
+
const PLAIN_POSITIVE_INT = /^[1-9]\d*$/;
|
|
28
|
+
// C0 controls, DEL and C1 controls: a display name never carries a line break into a header.
|
|
29
|
+
// eslint-disable-next-line no-control-regex
|
|
30
|
+
const CONTROL_CHARS = /[\u0000-\u001f\u007f-\u009f]/;
|
|
31
|
+
/**
|
|
32
|
+
* Read the message config for `emailSender: 'env'`. Refuses (naming variables only):
|
|
33
|
+
* - `EMAIL_PROVIDER` unset or not one of {@link EMAIL_PROVIDER_VALUES};
|
|
34
|
+
* - `SMS_PROVIDER` / `WHATSAPP_PROVIDER` other than `disabled` (no adapter yet);
|
|
35
|
+
* - a missing or malformed `EMAIL_FROM_ADDRESS`, a control character in `EMAIL_FROM_NAME`;
|
|
36
|
+
* - a missing provider credential, an unresolved `secret-ref:` (naming the `SECRETS_PROVIDER`
|
|
37
|
+
* prerequisite when none is set), or outside development/test a credential not resolved from
|
|
38
|
+
* a `secret-ref:`;
|
|
39
|
+
* - `EMAIL_API_BASE_URL` that is not `https:`, carries credentials, or is set for `smtp`;
|
|
40
|
+
* - Mailgun without a domain, or with a region other than `us` / `eu`;
|
|
41
|
+
* - SMTP without a host, with a bad port, half a login, an unknown `SMTP_TLS`, `none` to a
|
|
42
|
+
* non-loopback host outside development/test, or an unreadable `SMTP_TLS_CA`;
|
|
43
|
+
* - `MESSAGE_SEND_TIMEOUT_MS` outside 1–30000, `MESSAGE_BOOT_PROBE` other than `1` / `0`.
|
|
44
|
+
*/
|
|
45
|
+
function loadMessageConfig(env, options) {
|
|
46
|
+
const devOrTest = (0, app_config_js_1.isDevOrTestNodeEnv)(env.NODE_ENV);
|
|
47
|
+
const sms = channelSwitch(env, 'SMS_PROVIDER');
|
|
48
|
+
const whatsapp = channelSwitch(env, 'WHATSAPP_PROVIDER');
|
|
49
|
+
const probe = parseProbe(env.MESSAGE_BOOT_PROBE);
|
|
50
|
+
const provider = env.EMAIL_PROVIDER?.trim();
|
|
51
|
+
const list = exports.EMAIL_PROVIDER_VALUES.join(', ');
|
|
52
|
+
if (!provider) {
|
|
53
|
+
throw new Error(`EMAIL_PROVIDER must be set when ShieldModule.forRoot({ emailSender: 'env' }) (one of ${list})`);
|
|
54
|
+
}
|
|
55
|
+
if (!exports.EMAIL_PROVIDER_VALUES.includes(provider)) {
|
|
56
|
+
throw new Error(`EMAIL_PROVIDER has an unknown value (expected one of ${list})`);
|
|
57
|
+
}
|
|
58
|
+
if (provider === 'disabled') {
|
|
59
|
+
return { email: { provider: 'disabled' }, sms, whatsapp, probe };
|
|
60
|
+
}
|
|
61
|
+
const from = parseFrom(env);
|
|
62
|
+
const timeoutMs = parseTimeout(env.MESSAGE_SEND_TIMEOUT_MS);
|
|
63
|
+
const credential = (name) => readCredential(env, name, devOrTest, options);
|
|
64
|
+
let email;
|
|
65
|
+
if (provider === 'smtp') {
|
|
66
|
+
if (present(env.EMAIL_API_BASE_URL)) {
|
|
67
|
+
throw new Error('EMAIL_API_BASE_URL applies only to HTTP providers, not EMAIL_PROVIDER=smtp');
|
|
68
|
+
}
|
|
69
|
+
email = parseSmtp(env, from, timeoutMs, devOrTest, credential, options.readFile);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const baseUrl = parseBaseUrl(env.EMAIL_API_BASE_URL);
|
|
73
|
+
const withBase = baseUrl === undefined ? {} : { baseUrl };
|
|
74
|
+
if (provider === 'mailgun') {
|
|
75
|
+
email = {
|
|
76
|
+
provider,
|
|
77
|
+
from,
|
|
78
|
+
apiKey: credential('MAILGUN_API_KEY'),
|
|
79
|
+
domain: parseMailgunDomain(env.MAILGUN_DOMAIN),
|
|
80
|
+
region: parseMailgunRegion(env.MAILGUN_REGION),
|
|
81
|
+
timeoutMs,
|
|
82
|
+
...withBase,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
const keyVar = provider === 'brevo' ? 'BREVO_API_KEY' : 'SENDGRID_API_KEY';
|
|
87
|
+
email = {
|
|
88
|
+
provider: provider,
|
|
89
|
+
from,
|
|
90
|
+
apiKey: credential(keyVar),
|
|
91
|
+
timeoutMs,
|
|
92
|
+
...withBase,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return { email, sms, whatsapp, probe };
|
|
97
|
+
}
|
|
98
|
+
function present(value) {
|
|
99
|
+
return value !== undefined && value.trim() !== '';
|
|
100
|
+
}
|
|
101
|
+
function channelSwitch(env, name) {
|
|
102
|
+
const value = env[name]?.trim();
|
|
103
|
+
if (value && value !== 'disabled') {
|
|
104
|
+
throw new Error(`${name}: no adapter for this channel yet (only 'disabled')`);
|
|
105
|
+
}
|
|
106
|
+
return 'disabled';
|
|
107
|
+
}
|
|
108
|
+
function parseProbe(raw) {
|
|
109
|
+
const value = raw?.trim();
|
|
110
|
+
if (!value || value === '0')
|
|
111
|
+
return false;
|
|
112
|
+
if (value === '1')
|
|
113
|
+
return true;
|
|
114
|
+
throw new Error("MESSAGE_BOOT_PROBE must be '1' or '0'");
|
|
115
|
+
}
|
|
116
|
+
function parseTimeout(raw) {
|
|
117
|
+
const value = raw?.trim();
|
|
118
|
+
if (!value)
|
|
119
|
+
return exports.DEFAULT_MESSAGE_SEND_TIMEOUT_MS;
|
|
120
|
+
const n = PLAIN_POSITIVE_INT.test(value) ? Number(value) : NaN;
|
|
121
|
+
if (!Number.isSafeInteger(n) || n > exports.MAX_MESSAGE_SEND_TIMEOUT_MS) {
|
|
122
|
+
throw new Error(`MESSAGE_SEND_TIMEOUT_MS must be a whole number of milliseconds between 1 and ${exports.MAX_MESSAGE_SEND_TIMEOUT_MS}`);
|
|
123
|
+
}
|
|
124
|
+
return n;
|
|
125
|
+
}
|
|
126
|
+
function parseFrom(env) {
|
|
127
|
+
const address = env.EMAIL_FROM_ADDRESS?.trim();
|
|
128
|
+
if (!address)
|
|
129
|
+
throw new Error('EMAIL_FROM_ADDRESS must be set for EMAIL_PROVIDER');
|
|
130
|
+
if (!(0, email_address_js_1.isEmailShaped)(address))
|
|
131
|
+
throw new Error('EMAIL_FROM_ADDRESS is not an email address');
|
|
132
|
+
const name = env.EMAIL_FROM_NAME?.trim();
|
|
133
|
+
if (!name)
|
|
134
|
+
return { address };
|
|
135
|
+
if (CONTROL_CHARS.test(name)) {
|
|
136
|
+
throw new Error('EMAIL_FROM_NAME must not contain control characters (line breaks included)');
|
|
137
|
+
}
|
|
138
|
+
if ([...name].length > 128)
|
|
139
|
+
throw new Error('EMAIL_FROM_NAME must be at most 128 characters');
|
|
140
|
+
return { address, name };
|
|
141
|
+
}
|
|
142
|
+
function readCredential(env, name, devOrTest, options) {
|
|
143
|
+
const value = env[name];
|
|
144
|
+
if (!present(value))
|
|
145
|
+
throw new Error(`${name} must be set for EMAIL_PROVIDER`);
|
|
146
|
+
const noProvider = !present(env.SECRETS_PROVIDER) || env.SECRETS_PROVIDER.trim() === 'none';
|
|
147
|
+
if ((0, core_1.isSecretRef)(value)) {
|
|
148
|
+
if (noProvider) {
|
|
149
|
+
throw new Error(`${name} is a secret-ref: value but SECRETS_PROVIDER is not set; configure a secrets ` +
|
|
150
|
+
"provider (e.g. 'encrypted-file') before using emailSender: 'env' (runbook §6)");
|
|
151
|
+
}
|
|
152
|
+
throw new Error(`${name} still holds an unresolved secret-ref: value; call resolveBootSecrets() in main.ts ` +
|
|
153
|
+
'before loading AppModule');
|
|
154
|
+
}
|
|
155
|
+
if (!devOrTest && !(options.resolvedFromSecretRef?.(name, env) === true)) {
|
|
156
|
+
const prerequisite = noProvider
|
|
157
|
+
? "; this needs SECRETS_PROVIDER (e.g. 'encrypted-file') configured first (runbook §6)"
|
|
158
|
+
: '';
|
|
159
|
+
throw new Error(`${name} must be a secret-ref: value outside NODE_ENV development/test ` +
|
|
160
|
+
`(literal credentials are refused; see ADR-0032)${prerequisite}`);
|
|
161
|
+
}
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
function parseBaseUrl(raw) {
|
|
165
|
+
if (!present(raw))
|
|
166
|
+
return undefined;
|
|
167
|
+
let url;
|
|
168
|
+
try {
|
|
169
|
+
url = new URL(raw.trim());
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
throw new Error('EMAIL_API_BASE_URL is not a valid URL');
|
|
173
|
+
}
|
|
174
|
+
if (url.protocol !== 'https:')
|
|
175
|
+
throw new Error('EMAIL_API_BASE_URL must be an https: URL');
|
|
176
|
+
if (url.username !== '' || url.password !== '') {
|
|
177
|
+
throw new Error('EMAIL_API_BASE_URL must not carry credentials (use the provider API key)');
|
|
178
|
+
}
|
|
179
|
+
if (url.search !== '' || url.hash !== '') {
|
|
180
|
+
throw new Error('EMAIL_API_BASE_URL must not carry a query or fragment');
|
|
181
|
+
}
|
|
182
|
+
return `${url.origin}${url.pathname}`.replace(/\/+$/, '');
|
|
183
|
+
}
|
|
184
|
+
function parseMailgunDomain(raw) {
|
|
185
|
+
const domain = raw?.trim();
|
|
186
|
+
if (!domain)
|
|
187
|
+
throw new Error('MAILGUN_DOMAIN must be set for EMAIL_PROVIDER=mailgun');
|
|
188
|
+
if (!HOSTNAME.test(domain) || domain.length > 253) {
|
|
189
|
+
throw new Error('MAILGUN_DOMAIN is not a domain name');
|
|
190
|
+
}
|
|
191
|
+
return domain;
|
|
192
|
+
}
|
|
193
|
+
function parseMailgunRegion(raw) {
|
|
194
|
+
const region = raw?.trim() || 'us';
|
|
195
|
+
if (region !== 'us' && region !== 'eu')
|
|
196
|
+
throw new Error("MAILGUN_REGION must be 'us' or 'eu'");
|
|
197
|
+
return region;
|
|
198
|
+
}
|
|
199
|
+
function parseSmtp(env, from, timeoutMs, devOrTest, credential, readFile) {
|
|
200
|
+
const host = env.SMTP_HOST?.trim();
|
|
201
|
+
if (!host)
|
|
202
|
+
throw new Error('SMTP_HOST must be set for EMAIL_PROVIDER=smtp');
|
|
203
|
+
if (!(HOSTNAME.test(host) || (0, node_net_1.isIP)(host) !== 0) || host.length > 253) {
|
|
204
|
+
throw new Error('SMTP_HOST is not a host name or IP address');
|
|
205
|
+
}
|
|
206
|
+
const tlsRaw = env.SMTP_TLS?.trim() || 'starttls';
|
|
207
|
+
if (tlsRaw !== 'starttls' && tlsRaw !== 'implicit' && tlsRaw !== 'none') {
|
|
208
|
+
throw new Error('SMTP_TLS must be one of starttls, implicit, none');
|
|
209
|
+
}
|
|
210
|
+
const tls = tlsRaw;
|
|
211
|
+
if (tls === 'none' && !devOrTest && !(0, loopback_host_js_1.isLoopbackHost)(host)) {
|
|
212
|
+
throw new Error('SMTP_TLS=none is allowed only to a loopback host outside NODE_ENV development/test ' +
|
|
213
|
+
'(use starttls or implicit)');
|
|
214
|
+
}
|
|
215
|
+
const portRaw = env.SMTP_PORT?.trim();
|
|
216
|
+
let port = tls === 'implicit' ? 465 : tls === 'starttls' ? 587 : 25;
|
|
217
|
+
if (portRaw) {
|
|
218
|
+
const n = PLAIN_POSITIVE_INT.test(portRaw) ? Number(portRaw) : NaN;
|
|
219
|
+
if (!Number.isSafeInteger(n) || n > 65_535) {
|
|
220
|
+
throw new Error('SMTP_PORT must be a port number (1–65535)');
|
|
221
|
+
}
|
|
222
|
+
port = n;
|
|
223
|
+
}
|
|
224
|
+
const hasUser = present(env.SMTP_USER);
|
|
225
|
+
const hasPassword = present(env.SMTP_PASSWORD);
|
|
226
|
+
if (hasUser !== hasPassword) {
|
|
227
|
+
throw new Error('SMTP_USER and SMTP_PASSWORD must be set together (or both left unset)');
|
|
228
|
+
}
|
|
229
|
+
const login = hasUser
|
|
230
|
+
? { user: env.SMTP_USER.trim(), password: credential('SMTP_PASSWORD') }
|
|
231
|
+
: {};
|
|
232
|
+
let ca = {};
|
|
233
|
+
if (present(env.SMTP_TLS_CA)) {
|
|
234
|
+
if (tls === 'none')
|
|
235
|
+
throw new Error('SMTP_TLS_CA needs SMTP_TLS starttls or implicit');
|
|
236
|
+
let pem;
|
|
237
|
+
try {
|
|
238
|
+
pem = readFile(env.SMTP_TLS_CA.trim());
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
throw new Error('SMTP_TLS_CA could not be read (set it to a readable PEM file path)');
|
|
242
|
+
}
|
|
243
|
+
if (!pem.includes('-----BEGIN CERTIFICATE-----')) {
|
|
244
|
+
throw new Error('SMTP_TLS_CA is not a PEM certificate file');
|
|
245
|
+
}
|
|
246
|
+
ca = { tlsCaPem: pem };
|
|
247
|
+
}
|
|
248
|
+
return { provider: 'smtp', from, host, port, tls, ...login, ...ca, timeoutMs };
|
|
249
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,8 @@ export { EncryptedFileSecretsProvider } from './secrets/encrypted-file-secrets.j
|
|
|
40
40
|
export { resolveBootSecrets, createSecretsProviderFromEnv, assertNoUnresolvedSecretRefs, wasResolvedFromSecretRef, type ResolveBootSecretsOptions, } from './secrets/boot-secrets.js';
|
|
41
41
|
export { S3ObjectStore, type S3ObjectStoreConfig, type S3ObjectStoreOptions, } from './storage/s3-object-store.js';
|
|
42
42
|
export { NodeSha256Digest } from './storage/node-sha256-digest.js';
|
|
43
|
+
export { NodeSha256Hash } from './audit/node-sha256-hash.js';
|
|
44
|
+
export { loadAuditSealConfig, type AuditSealConfig } from './audit/audit-seal-config.js';
|
|
43
45
|
export { ObjectStoreBootCheck } from './storage/object-store-boot-check.js';
|
|
44
46
|
export { FileIntake, FILE_INTAKE_REQUEST_KEY, FILE_INTAKE_DEFAULT_MAX_BYTES, type FileIntakeOptions, type FileIntakeResult, } from './storage/file-intake.interceptor.js';
|
|
45
47
|
export type { ShieldStorageOption } from './storage/storage.providers.js';
|
|
@@ -72,7 +74,7 @@ export { frameworkSchemasOf, loadAppConfig, loadPoolBudget, evaluatePoolBudget,
|
|
|
72
74
|
export { rootIdsFromEnv } from './config/root-ids-from-env.js';
|
|
73
75
|
export { ORG_BOOTSTRAP_PRINCIPAL_ID, assertNoReservedRootId, } from './config/reserved-principal-ids.js';
|
|
74
76
|
export { mariadbSslOption } from './auth/connections.js';
|
|
75
|
-
export { SHIELD_REDIS, SHIELD_CREDENTIAL_RESOLVER, SHIELD_PROFILE_RESOLVER, SHIELD_AUTHENTICATOR, SHIELD_SESSION_AUTHORITY, SHIELD_CREDENTIAL_WRITER, SHIELD_RESET_TOKEN_STORE, SHIELD_EMAIL_CHANGE_TOKEN_STORE, SHIELD_EMAIL_SENDER, SHIELD_RECOVERY_CODE_STORE, SHIELD_PROFILE_WRITER, SHIELD_SESSION_SWEEPER, SHIELD_AUDIT_SINK, SHIELD_MFA_DEVICE_STORE, SHIELD_TOTP_VERIFIER_OVERRIDE, } from './auth/tokens.js';
|
|
77
|
+
export { SHIELD_REDIS, SHIELD_CREDENTIAL_RESOLVER, SHIELD_PROFILE_RESOLVER, SHIELD_AUTHENTICATOR, SHIELD_SESSION_AUTHORITY, SHIELD_CREDENTIAL_WRITER, SHIELD_RESET_TOKEN_STORE, SHIELD_EMAIL_CHANGE_TOKEN_STORE, SHIELD_EMAIL_SENDER, SHIELD_MESSAGE_DISPATCHER, SHIELD_RECOVERY_CODE_STORE, SHIELD_PROFILE_WRITER, SHIELD_SESSION_SWEEPER, SHIELD_AUDIT_SINK, SHIELD_MFA_DEVICE_STORE, SHIELD_TOTP_VERIFIER_OVERRIDE, } from './auth/tokens.js';
|
|
76
78
|
export { MariaDbCredentialResolver } from './authentication/mariadb-credential-resolver.js';
|
|
77
79
|
export type { SessionView, SessionTokensView, SessionSuccess, LoginRequest, MfaChallengeResponse, LoginResponse, MfaRequest, MfaResponse, RefreshRequest, RefreshResponse, LogoutRequest, LogoutAck, } from './auth/dto.js';
|
|
78
80
|
export { AuthModule, type AuthModuleOptions } from './auth/auth.module.js';
|
|
@@ -87,6 +89,10 @@ export { canonicalEmail, isEmailShaped, maskEmail } from './auth/email-address.j
|
|
|
87
89
|
export { MariaDbEmailAddressChanger } from './authentication/mariadb-email-address-changer.js';
|
|
88
90
|
export type { EmailAddressChanger, EmailChangeRequest, EmailChangeOutcome, CurrentEmail, TransactionQuery, } from './auth/ports/email-address-changer.js';
|
|
89
91
|
export type { EmailSender, EmailMessage } from './auth/ports/email-sender.js';
|
|
92
|
+
export type { MessageDispatcher, MessageAuditContext, EmailDeliveryOutcome, } from './messaging/message-dispatcher.js';
|
|
93
|
+
export type { EmailSenderOption } from './messaging/email-delivery.js';
|
|
94
|
+
export { loadMessageConfig, EMAIL_PROVIDER_VALUES, DEFAULT_MESSAGE_SEND_TIMEOUT_MS, MAX_MESSAGE_SEND_TIMEOUT_MS, type MessageConfig, type EmailDeliveryConfig, type EmailFromConfig, type LoadMessageConfigOptions, } from './config/message-config.js';
|
|
95
|
+
export { maskPhone } from './messaging/recipient-mask.js';
|
|
90
96
|
export type { RecoveryCodeStore } from './auth/ports/recovery-code-store.js';
|
|
91
97
|
export type { ProfileWriter } from './auth/ports/profile-writer.js';
|
|
92
98
|
export { ProfileNameTakenError } from './auth/ports/profile-writer.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AASzD,OAAO,EAAE,2BAA2B,EAAE,MAAM,sCAAsC,CAAC;AACnF,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,0BAA0B,EAC1B,oBAAoB,EACpB,uBAAuB,EACvB,UAAU,EACV,SAAS,GACV,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EACL,YAAY,EACZ,yBAAyB,EAGzB,2BAA2B,EAC3B,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAI7B,KAAK,yBAAyB,GAC/B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EACL,MAAM,EACN,UAAU,EACV,uBAAuB,EACvB,yBAAyB,EACzB,uBAAuB,GACxB,MAAM,2CAA2C,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAKhF,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAKpG,OAAO,EAAE,yBAAyB,EAAE,MAAM,+CAA+C,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,sCAAsC,CAAC;AACjG,YAAY,EACV,YAAY,EACZ,oBAAoB,EACpB,eAAe,GAChB,MAAM,uCAAuC,CAAC;AAM/C,OAAO,EACL,2BAA2B,EAC3B,4BAA4B,GAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAC5E,YAAY,EACV,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,wCAAwC,CAAC;AAChD,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,QAAQ,GACT,MAAM,qCAAqC,CAAC;AAG7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAC;AAS/E,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,KAAK,iBAAiB,GACvB,MAAM,qCAAqC,CAAC;AAU7C,OAAO,EAAE,sBAAsB,EAAE,MAAM,2CAA2C,CAAC;AAKnF,OAAO,EACL,qBAAqB,EACrB,KAAK,MAAM,EACX,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EACjB,KAAK,SAAS,GACf,MAAM,4BAA4B,CAAC;AAMpC,OAAO,EACL,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,YAAY,EACZ,KAAK,cAAc,GACpB,MAAM,8CAA8C,CAAC;AACtD,OAAO,EACL,qBAAqB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,EAC7B,KAAK,gCAAgC,EACrC,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,4CAA4C,CAAC;AACpD,OAAO,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAKlE,OAAO,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAKlE,OAAO,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAC;AAInF,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,4BAA4B,EAC5B,wBAAwB,EACxB,KAAK,yBAAyB,GAC/B,MAAM,2BAA2B,CAAC;AAKnC,OAAO,EACL,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,GAC1B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -17,9 +17,9 @@
|
|
|
17
17
|
*/
|
|
18
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
19
|
exports.wasResolvedFromSecretRef = exports.assertNoUnresolvedSecretRefs = exports.createSecretsProviderFromEnv = exports.resolveBootSecrets = exports.EncryptedFileSecretsProvider = exports.LocalKekCrypto = exports.resolveAuthLinkBaseUrls = exports.CredentialExistsError = exports.isLockedHash = exports.lockedPasswordHash = exports.SHIELD_PASSWORD_HASHER = exports.argon2idHasherProvider = exports.Argon2idPasswordHasher = exports.stubDecisionAuthority = exports.GlobalEnforcementGuard = exports.NO_SESSION_FACTS = exports.SHIELD_SESSION_FACTS_ALS = exports.MariaDbApiKeyStore = exports.isApiKey = exports.extractBearerToken = exports.principalFromClaims = exports.resolveRequestAuth = exports.resolveRequestPrincipal = exports.SessionTokenBinder = exports.SHIELD_SERVICE_AUTHENTICATOR = exports.SHIELD_SESSION_TOKEN_BINDER = exports.CatalogGatabilityError = exports.CatalogReconciler = exports.OperationInventoryScanner = exports.uuidArrayField = exports.optionalUuidField = exports.uuidField = exports.UuidPipe = exports.normalizeClassification = exports.DEFAULT_CLASSIFIED_ACTION = exports.CLASSIFICATION_METADATA = exports.Classified = exports.Public = exports.SHIELD_RECORD_AUTHORIZATION = exports.SHIELD_DECISION_AUTHORITY = exports.ShieldModule = exports.actionsOf = exports.actionsFor = exports.SERVICE_ACCOUNT_ACTIONS = exports.RECORD_SHARE_ACTIONS = exports.CROSS_TENANT_GRANT_ACTIONS = exports.IDENTITY_ACTIONS = exports.MODULE_KEY = exports.buildIdentityModuleRegistry = exports.guardMigrationsDir = void 0;
|
|
20
|
-
exports.
|
|
21
|
-
exports.
|
|
22
|
-
exports.ScopeUnknownParentError = exports.ScopeDepthError = exports.ScopeCycleError = exports.buildClosureRows = exports.ConfirmEmailController = exports.AccountController = exports.generateRecoveryCodes = exports.buildOtpauthUri = exports.generateTotpSecret = exports.SHIELD_LOGIN_TOTP_VERIFIER = exports.SHIELD_MFA_STEP_UP = exports.SHIELD_MFA_LIMITER = exports.challengeMatches = exports.credentialFingerprint = exports.CredentialMfaStepUp = exports.RedisPendingMfaStore = exports.PendingMfaStore = exports.AuthController = exports.SHIELD_SCOPE_SUBTREE_RESOLVER = exports.SHIELD_SESSION_FACTS_PROJECTOR = exports.ProfileNameTakenError = exports.MariaDbEmailAddressChanger = exports.maskEmail = exports.isEmailShaped = exports.canonicalEmail = exports.hmacSha1 = exports.resolveTotpVerifier = exports.makeDefaultTotpVerifier = exports.AuthModule = exports.MariaDbCredentialResolver = exports.SHIELD_TOTP_VERIFIER_OVERRIDE = exports.SHIELD_MFA_DEVICE_STORE = exports.SHIELD_AUDIT_SINK = exports.SHIELD_SESSION_SWEEPER = exports.SHIELD_PROFILE_WRITER = exports.SHIELD_RECOVERY_CODE_STORE = exports.SHIELD_EMAIL_SENDER = exports.SHIELD_EMAIL_CHANGE_TOKEN_STORE = exports.SHIELD_RESET_TOKEN_STORE = exports.SHIELD_CREDENTIAL_WRITER = void 0;
|
|
20
|
+
exports.GrantNotPermittedError = exports.SHIELD_CROSS_TENANT_GRANT_WRITER = exports.CrossTenantGrantWriter = exports.SHIELD_CROSS_TENANT_GRANT_PORT = exports.MariaDbCrossTenantGrantAdapter = exports.makeShareDeleteCascade = exports.ShareStoreUnavailableError = exports.ShareNotPermittedError = exports.SHIELD_RECORD_SHARE_WRITER = exports.RecordShareWriter = exports.SHIELD_RECORD_SHARE_PORT = exports.MariaDbRecordShareAdapter = exports.UnknownScopeFieldError = exports.translateListScope = exports.SHIELD_LIST_SCOPE_PORT = exports.MariaDbListScopeAdapter = exports.SHIELD_POLICY_STORE = exports.MariaDbPolicyStore = exports.SHIELD_RECORD_RULE_PORT = exports.MariaDbRecordPermissionRuleAdapter = exports.accessBindingTtlMs = exports.ROTATE_GRACE_MS = exports.SHIELD_SESSION_LIFETIMES = exports.HotRevokingSessionRecordStore = exports.SHIELD_CLOCK = exports.SHIELD_REFRESH_HASHER = exports.SHIELD_TOKEN_GENERATOR = exports.systemClockProvider = exports.refreshHasherProvider = exports.cryptoTokenGeneratorProvider = exports.SystemClock = exports.Sha256RefreshTokenHasher = exports.CryptoTokenGenerator = exports.RedisRecentRotationStore = exports.SHIELD_HOT_SESSION_STORE = exports.RedisHotSessionStore = exports.SHIELD_SESSION_RECORD_STORE = exports.MariaDbSessionRecordStore = exports.DEFAULT_OBJECT_STORAGE_MAX_BYTES = exports.loadObjectStorageConfig = exports.SHIELD_FILE_INGEST = exports.SHIELD_OBJECT_STORE = exports.FILE_INTAKE_DEFAULT_MAX_BYTES = exports.FILE_INTAKE_REQUEST_KEY = exports.FileIntake = exports.ObjectStoreBootCheck = exports.loadAuditSealConfig = exports.NodeSha256Hash = exports.NodeSha256Digest = exports.S3ObjectStore = void 0;
|
|
21
|
+
exports.SHIELD_PROFILE_RESOLVER = exports.SHIELD_CREDENTIAL_RESOLVER = exports.SHIELD_REDIS = exports.mariadbSslOption = exports.assertNoReservedRootId = exports.ORG_BOOTSTRAP_PRINCIPAL_ID = exports.rootIdsFromEnv = exports.loadDbTlsConfig = exports.isDevOrTestNodeEnv = exports.DEFAULT_LOGIN_IP_LIMIT = exports.loadRefreshReplayWindowMs = exports.loadLoginIpLimit = exports.DEFAULT_REDIS_URL = exports.DEFAULT_DB_CONFIG = exports.assertRefreshHmacKey = exports.loadRefreshHmacKey = exports.loadSessionLifetimes = exports.loadRedisConfig = exports.loadDbConfig = exports.SCHEMA_SVC_POOL_HARD_CAP = exports.DEFAULT_POOL_BUDGET = exports.evaluatePoolBudget = exports.loadPoolBudget = exports.loadAppConfig = exports.frameworkSchemasOf = exports.FRAMEWORK_SCHEMAS = exports.APP_CONFIG = exports.resolveMigrationLedgerCheck = exports.resolveMigrationLedger = exports.frameworkMigrationIds = exports.assertFrameworkMigrationsApplied = exports.SHIELD_MIGRATION_LEDGER_REGISTRY = exports.MigrationLedgerRegistry = exports.FrameworkMigrationLedgerCheck = exports.frameworkDatabasesLogLine = exports.assertPoolBudget = exports.BootSequence = exports.buildListScopeFn = exports.MariaDbSessionRestrictionStore = exports.SHIELD_SESSION_RESTRICTIONS = exports.SHIELD_PERMISSION_VERSION_CACHE = exports.DEFAULT_PERMISSION_VERSION_TTL_MS = exports.PERMISSION_VERSION_KEY_PREFIX = exports.RedisPermissionVersionCache = exports.withRedisPermissionVersion = exports.buildRecordAuthorization = exports.SHIELD_OPERATION_AUTHORITY_PORT = exports.ManifestOperationAuthorityAdapter = exports.GrantStoreUnavailableError = exports.InvalidGrantError = void 0;
|
|
22
|
+
exports.ScopeUnknownParentError = exports.ScopeDepthError = exports.ScopeCycleError = exports.buildClosureRows = exports.ConfirmEmailController = exports.AccountController = exports.generateRecoveryCodes = exports.buildOtpauthUri = exports.generateTotpSecret = exports.SHIELD_LOGIN_TOTP_VERIFIER = exports.SHIELD_MFA_STEP_UP = exports.SHIELD_MFA_LIMITER = exports.challengeMatches = exports.credentialFingerprint = exports.CredentialMfaStepUp = exports.RedisPendingMfaStore = exports.PendingMfaStore = exports.AuthController = exports.SHIELD_SCOPE_SUBTREE_RESOLVER = exports.SHIELD_SESSION_FACTS_PROJECTOR = exports.ProfileNameTakenError = exports.maskPhone = exports.MAX_MESSAGE_SEND_TIMEOUT_MS = exports.DEFAULT_MESSAGE_SEND_TIMEOUT_MS = exports.EMAIL_PROVIDER_VALUES = exports.loadMessageConfig = exports.MariaDbEmailAddressChanger = exports.maskEmail = exports.isEmailShaped = exports.canonicalEmail = exports.hmacSha1 = exports.resolveTotpVerifier = exports.makeDefaultTotpVerifier = exports.AuthModule = exports.MariaDbCredentialResolver = exports.SHIELD_TOTP_VERIFIER_OVERRIDE = exports.SHIELD_MFA_DEVICE_STORE = exports.SHIELD_AUDIT_SINK = exports.SHIELD_SESSION_SWEEPER = exports.SHIELD_PROFILE_WRITER = exports.SHIELD_RECOVERY_CODE_STORE = exports.SHIELD_MESSAGE_DISPATCHER = exports.SHIELD_EMAIL_SENDER = exports.SHIELD_EMAIL_CHANGE_TOKEN_STORE = exports.SHIELD_RESET_TOKEN_STORE = exports.SHIELD_CREDENTIAL_WRITER = exports.SHIELD_SESSION_AUTHORITY = exports.SHIELD_AUTHENTICATOR = void 0;
|
|
23
23
|
// Framework authz migrations (shield_authz DDL — permission / role_permission /
|
|
24
24
|
// authz_permission_version). Absolute path a consumer's `@astram/migrate` setup merges in.
|
|
25
25
|
var migrations_dir_js_1 = require("./migrations-dir.js");
|
|
@@ -153,6 +153,12 @@ var s3_object_store_js_1 = require("./storage/s3-object-store.js");
|
|
|
153
153
|
Object.defineProperty(exports, "S3ObjectStore", { enumerable: true, get: function () { return s3_object_store_js_1.S3ObjectStore; } });
|
|
154
154
|
var node_sha256_digest_js_1 = require("./storage/node-sha256-digest.js");
|
|
155
155
|
Object.defineProperty(exports, "NodeSha256Digest", { enumerable: true, get: function () { return node_sha256_digest_js_1.NodeSha256Digest; } });
|
|
156
|
+
// Durable audit chain (audit-chain-store SPEC §5.F, §5.I): the chain hash adapter and the
|
|
157
|
+
// `AUDIT_SEAL_*` loader. The sealer itself is wired by `ShieldModule.forRoot({ auth: true })`.
|
|
158
|
+
var node_sha256_hash_js_1 = require("./audit/node-sha256-hash.js");
|
|
159
|
+
Object.defineProperty(exports, "NodeSha256Hash", { enumerable: true, get: function () { return node_sha256_hash_js_1.NodeSha256Hash; } });
|
|
160
|
+
var audit_seal_config_js_1 = require("./audit/audit-seal-config.js");
|
|
161
|
+
Object.defineProperty(exports, "loadAuditSealConfig", { enumerable: true, get: function () { return audit_seal_config_js_1.loadAuditSealConfig; } });
|
|
156
162
|
var object_store_boot_check_js_1 = require("./storage/object-store-boot-check.js");
|
|
157
163
|
Object.defineProperty(exports, "ObjectStoreBootCheck", { enumerable: true, get: function () { return object_store_boot_check_js_1.ObjectStoreBootCheck; } });
|
|
158
164
|
var file_intake_interceptor_js_1 = require("./storage/file-intake.interceptor.js");
|
|
@@ -404,6 +410,7 @@ Object.defineProperty(exports, "SHIELD_RESET_TOKEN_STORE", { enumerable: true, g
|
|
|
404
410
|
// Phase 12 (KI #14): the self-service email-change token store (framework default).
|
|
405
411
|
Object.defineProperty(exports, "SHIELD_EMAIL_CHANGE_TOKEN_STORE", { enumerable: true, get: function () { return tokens_js_4.SHIELD_EMAIL_CHANGE_TOKEN_STORE; } });
|
|
406
412
|
Object.defineProperty(exports, "SHIELD_EMAIL_SENDER", { enumerable: true, get: function () { return tokens_js_4.SHIELD_EMAIL_SENDER; } });
|
|
413
|
+
Object.defineProperty(exports, "SHIELD_MESSAGE_DISPATCHER", { enumerable: true, get: function () { return tokens_js_4.SHIELD_MESSAGE_DISPATCHER; } });
|
|
407
414
|
Object.defineProperty(exports, "SHIELD_RECOVERY_CODE_STORE", { enumerable: true, get: function () { return tokens_js_4.SHIELD_RECOVERY_CODE_STORE; } });
|
|
408
415
|
Object.defineProperty(exports, "SHIELD_PROFILE_WRITER", { enumerable: true, get: function () { return tokens_js_4.SHIELD_PROFILE_WRITER; } });
|
|
409
416
|
Object.defineProperty(exports, "SHIELD_SESSION_SWEEPER", { enumerable: true, get: function () { return tokens_js_4.SHIELD_SESSION_SWEEPER; } });
|
|
@@ -444,6 +451,13 @@ Object.defineProperty(exports, "maskEmail", { enumerable: true, get: function ()
|
|
|
444
451
|
// follow, pending-token burn). Guard's confirm route uses it; identity's admin path constructs it.
|
|
445
452
|
var mariadb_email_address_changer_js_1 = require("./authentication/mariadb-email-address-changer.js");
|
|
446
453
|
Object.defineProperty(exports, "MariaDbEmailAddressChanger", { enumerable: true, get: function () { return mariadb_email_address_changer_js_1.MariaDbEmailAddressChanger; } });
|
|
454
|
+
var message_config_js_1 = require("./config/message-config.js");
|
|
455
|
+
Object.defineProperty(exports, "loadMessageConfig", { enumerable: true, get: function () { return message_config_js_1.loadMessageConfig; } });
|
|
456
|
+
Object.defineProperty(exports, "EMAIL_PROVIDER_VALUES", { enumerable: true, get: function () { return message_config_js_1.EMAIL_PROVIDER_VALUES; } });
|
|
457
|
+
Object.defineProperty(exports, "DEFAULT_MESSAGE_SEND_TIMEOUT_MS", { enumerable: true, get: function () { return message_config_js_1.DEFAULT_MESSAGE_SEND_TIMEOUT_MS; } });
|
|
458
|
+
Object.defineProperty(exports, "MAX_MESSAGE_SEND_TIMEOUT_MS", { enumerable: true, get: function () { return message_config_js_1.MAX_MESSAGE_SEND_TIMEOUT_MS; } });
|
|
459
|
+
var recipient_mask_js_1 = require("./messaging/recipient-mask.js");
|
|
460
|
+
Object.defineProperty(exports, "maskPhone", { enumerable: true, get: function () { return recipient_mask_js_1.maskPhone; } });
|
|
447
461
|
var profile_writer_js_1 = require("./auth/ports/profile-writer.js");
|
|
448
462
|
Object.defineProperty(exports, "ProfileNameTakenError", { enumerable: true, get: function () { return profile_writer_js_1.ProfileNameTakenError; } });
|
|
449
463
|
var tokens_js_5 = require("./auth/tokens.js");
|
package/dist/internal.d.ts
CHANGED
|
@@ -10,4 +10,14 @@
|
|
|
10
10
|
export { PersistenceModule } from './auth/persistence.module.js';
|
|
11
11
|
export { SHIELD_DB_POOL } from './auth/tokens.js';
|
|
12
12
|
export { MariaDbCredentialProvisioner } from './authentication/mariadb-credential-provisioner.js';
|
|
13
|
+
/**
|
|
14
|
+
* For `@astram/identity`'s invite rate limits only (G-010, spec P-5), not app use: guard's
|
|
15
|
+
* Redis-backed {@link AttemptLimiter} and the existing `SHIELD_REDIS` token its own limiters
|
|
16
|
+
* inject (the one client `PersistenceModule` provides; no second connection). `check()` fails
|
|
17
|
+
* open on a Redis error, as forgot-password does.
|
|
18
|
+
*/
|
|
19
|
+
export { AttemptLimiter } from './auth/rate-limit/attempt-limiter.js';
|
|
20
|
+
export { SHIELD_REDIS } from './auth/tokens.js';
|
|
21
|
+
export { SHIELD_ATTEMPT_LIMITER_FACTORY } from './auth/tokens.js';
|
|
22
|
+
export type { AttemptLimiterFactory } from './auth/auth.module.js';
|
|
13
23
|
//# sourceMappingURL=internal.d.ts.map
|
package/dist/internal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,4BAA4B,EAAE,MAAM,oDAAoD,CAAC"}
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,4BAA4B,EAAE,MAAM,oDAAoD,CAAC;AAClG;;;;;GAKG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,8BAA8B,EAAE,MAAM,kBAAkB,CAAC;AAClE,YAAY,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
|
package/dist/internal.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MariaDbCredentialProvisioner = exports.SHIELD_DB_POOL = exports.PersistenceModule = void 0;
|
|
3
|
+
exports.SHIELD_ATTEMPT_LIMITER_FACTORY = exports.SHIELD_REDIS = exports.AttemptLimiter = exports.MariaDbCredentialProvisioner = exports.SHIELD_DB_POOL = exports.PersistenceModule = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* @astram/guard/internal — framework-composition and test surface (Phase 8 #5).
|
|
6
6
|
*
|
|
@@ -16,3 +16,15 @@ var tokens_js_1 = require("./auth/tokens.js");
|
|
|
16
16
|
Object.defineProperty(exports, "SHIELD_DB_POOL", { enumerable: true, get: function () { return tokens_js_1.SHIELD_DB_POOL; } });
|
|
17
17
|
var mariadb_credential_provisioner_js_1 = require("./authentication/mariadb-credential-provisioner.js");
|
|
18
18
|
Object.defineProperty(exports, "MariaDbCredentialProvisioner", { enumerable: true, get: function () { return mariadb_credential_provisioner_js_1.MariaDbCredentialProvisioner; } });
|
|
19
|
+
/**
|
|
20
|
+
* For `@astram/identity`'s invite rate limits only (G-010, spec P-5), not app use: guard's
|
|
21
|
+
* Redis-backed {@link AttemptLimiter} and the existing `SHIELD_REDIS` token its own limiters
|
|
22
|
+
* inject (the one client `PersistenceModule` provides; no second connection). `check()` fails
|
|
23
|
+
* open on a Redis error, as forgot-password does.
|
|
24
|
+
*/
|
|
25
|
+
var attempt_limiter_js_1 = require("./auth/rate-limit/attempt-limiter.js");
|
|
26
|
+
Object.defineProperty(exports, "AttemptLimiter", { enumerable: true, get: function () { return attempt_limiter_js_1.AttemptLimiter; } });
|
|
27
|
+
var tokens_js_2 = require("./auth/tokens.js");
|
|
28
|
+
Object.defineProperty(exports, "SHIELD_REDIS", { enumerable: true, get: function () { return tokens_js_2.SHIELD_REDIS; } });
|
|
29
|
+
var tokens_js_3 = require("./auth/tokens.js");
|
|
30
|
+
Object.defineProperty(exports, "SHIELD_ATTEMPT_LIMITER_FACTORY", { enumerable: true, get: function () { return tokens_js_3.SHIELD_ATTEMPT_LIMITER_FACTORY; } });
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { EmailMessage, MessagePurpose } from '@astram/core';
|
|
2
|
+
import type { EmailSender } from '../auth/ports/email-sender.js';
|
|
3
|
+
import type { MessageAuditContext, MessageDispatcher } from './message-dispatcher.js';
|
|
4
|
+
/**
|
|
5
|
+
* Send one framework email (G-010 P-1): through the {@link MessageDispatcher} (bounded, audited,
|
|
6
|
+
* never throws) when it is bound, else through the bound sender as before (a controller built
|
|
7
|
+
* without the dispatcher, e.g. positionally in a test). Never throws: returns what happened.
|
|
8
|
+
*/
|
|
9
|
+
export declare function deliverEmail(dispatcher: MessageDispatcher | null | undefined, sender: EmailSender, purpose: MessagePurpose, message: EmailMessage, context: MessageAuditContext): Promise<'sent' | 'failed' | 'disabled'>;
|
|
10
|
+
//# sourceMappingURL=deliver-email.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deliver-email.d.ts","sourceRoot":"","sources":["../../src/messaging/deliver-email.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEtF;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,EAChD,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,cAAc,EACvB,OAAO,EAAE,YAAY,EACrB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC,CAQzC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deliverEmail = deliverEmail;
|
|
4
|
+
/**
|
|
5
|
+
* Send one framework email (G-010 P-1): through the {@link MessageDispatcher} (bounded, audited,
|
|
6
|
+
* never throws) when it is bound, else through the bound sender as before (a controller built
|
|
7
|
+
* without the dispatcher, e.g. positionally in a test). Never throws: returns what happened.
|
|
8
|
+
*/
|
|
9
|
+
async function deliverEmail(dispatcher, sender, purpose, message, context) {
|
|
10
|
+
if (dispatcher)
|
|
11
|
+
return (await dispatcher.sendEmail(purpose, message, context)).status;
|
|
12
|
+
try {
|
|
13
|
+
await sender.send(message);
|
|
14
|
+
return 'sent';
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return 'failed';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type EmailProvider } from '@astram/core';
|
|
2
|
+
import type { FrameworkSchemas } from '@astram/core';
|
|
3
|
+
import type { Pool } from 'mariadb';
|
|
4
|
+
import type { EmailSender } from '../auth/ports/email-sender.js';
|
|
5
|
+
import { type EmailDeliveryConfig } from '../config/message-config.js';
|
|
6
|
+
import { type MessageAuditWriter } from './message-dispatcher.js';
|
|
7
|
+
/** `ShieldModule.forRoot({ emailSender })`. */
|
|
8
|
+
export type EmailSenderOption = EmailSender | 'disabled' | 'env';
|
|
9
|
+
/** What `@astram/messaging` must export for guard (spec P-2). */
|
|
10
|
+
export interface MessagingModule {
|
|
11
|
+
createEmailProvider(config: EmailDeliveryConfig): Promise<EmailProvider>;
|
|
12
|
+
}
|
|
13
|
+
export interface EmailDelivery {
|
|
14
|
+
/** `null` ⇒ mail disabled. */
|
|
15
|
+
readonly provider: EmailProvider | null;
|
|
16
|
+
/** The per-send bound the dispatcher applies. */
|
|
17
|
+
readonly timeoutMs: number;
|
|
18
|
+
}
|
|
19
|
+
export interface BuildEmailProviderDeps {
|
|
20
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
21
|
+
/** Loader for the optional peer (default `require`). */
|
|
22
|
+
readonly load?: (id: string) => unknown;
|
|
23
|
+
readonly readFile?: (path: string) => string;
|
|
24
|
+
}
|
|
25
|
+
export declare function buildEmailProvider(option: EmailSenderOption | undefined, boundSender: EmailSender | null, deps: BuildEmailProviderDeps): Promise<EmailDelivery>;
|
|
26
|
+
/**
|
|
27
|
+
* The link-base boot rule applies only with a real sender (Phase 13 #1). `'env'` is real unless
|
|
28
|
+
* `EMAIL_PROVIDER=disabled`. Read at `forRoot` time, after `resolveBootSecrets()`.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isMailDisabled(option: EmailSenderOption | undefined, env: Readonly<Record<string, string | undefined>>): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The `EmailSender` bound under `SHIELD_EMAIL_SENDER` for `'env'`, so existing injectors keep the
|
|
33
|
+
* port they know. Each send is bounded; a failure rejects (callers already treat it best-effort).
|
|
34
|
+
*/
|
|
35
|
+
export declare function senderFromProvider(provider: EmailProvider, timeoutMs: number): EmailSender;
|
|
36
|
+
/**
|
|
37
|
+
* `message.sent` / `message.failed` rows go to the framework audit log over guard's own pool
|
|
38
|
+
* (the runtime account holds append-only INSERT on the audit schema), independent of the
|
|
39
|
+
* optional app `auditSink` (Shield #6).
|
|
40
|
+
*/
|
|
41
|
+
export declare function messageAuditWriter(pool: Pick<Pool, 'query'>, schemas: Pick<FrameworkSchemas, 'audit'>): MessageAuditWriter;
|
|
42
|
+
//# sourceMappingURL=email-delivery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email-delivery.d.ts","sourceRoot":"","sources":["../../src/messaging/email-delivery.ts"],"names":[],"mappings":"AAcA,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAExE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAEpC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAEtF,+CAA+C;AAC/C,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,UAAU,GAAG,KAAK,CAAC;AAEjE,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC9B,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;CAC1E;AAED,MAAM,WAAW,aAAa;IAC5B,8BAA8B;IAC9B,QAAQ,CAAC,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IACxC,iDAAiD;IACjD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,wDAAwD;IACxD,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC9C;AAKD,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,iBAAiB,GAAG,SAAS,EACrC,WAAW,EAAE,WAAW,GAAG,IAAI,EAC/B,IAAI,EAAE,sBAAsB,GAC3B,OAAO,CAAC,aAAa,CAAC,CA+BxB;AA+BD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,iBAAiB,GAAG,SAAS,EACrC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAChD,OAAO,CAIT;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,CAM1F;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EACzB,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GACvC,kBAAkB,CAKpB"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildEmailProvider = buildEmailProvider;
|
|
4
|
+
exports.isMailDisabled = isMailDisabled;
|
|
5
|
+
exports.senderFromProvider = senderFromProvider;
|
|
6
|
+
exports.messageAuditWriter = messageAuditWriter;
|
|
7
|
+
/**
|
|
8
|
+
* Email delivery binding (G-010, docs/features/message-delivery/SPEC.md R2, R8, R14). Turns the
|
|
9
|
+
* `ShieldModule.forRoot({ emailSender })` option into the provider the {@link MessageDispatcher}
|
|
10
|
+
* wraps:
|
|
11
|
+
* - `'env'` → {@link loadMessageConfig}, then `@astram/messaging` loaded as an OPTIONAL peer (only
|
|
12
|
+
* here, so apps that never choose `'env'` never load it) and its `createEmailProvider`; with
|
|
13
|
+
* `MESSAGE_BOOT_PROBE=1` the adapter's probe runs (no message is sent) and a failure refuses
|
|
14
|
+
* boot. `EMAIL_PROVIDER=disabled` binds nothing and loads nothing.
|
|
15
|
+
* - `'disabled'` → no provider (nothing delivered, nothing audited).
|
|
16
|
+
* - an app `EmailSender` → adapted as provider `custom`; omitted (development/test) → `log`.
|
|
17
|
+
*/
|
|
18
|
+
const node_fs_1 = require("node:fs");
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const core_1 = require("@astram/core");
|
|
21
|
+
const engine_1 = require("@astram/engine");
|
|
22
|
+
const message_config_js_1 = require("../config/message-config.js");
|
|
23
|
+
const boot_secrets_js_1 = require("../secrets/boot-secrets.js");
|
|
24
|
+
const optional_peer_js_1 = require("../storage/optional-peer.js");
|
|
25
|
+
const message_dispatcher_js_1 = require("./message-dispatcher.js");
|
|
26
|
+
const MESSAGING_PACKAGE = '@astram/messaging';
|
|
27
|
+
const logger = new common_1.Logger('ShieldMessaging');
|
|
28
|
+
async function buildEmailProvider(option, boundSender, deps) {
|
|
29
|
+
const fallback = { timeoutMs: message_config_js_1.DEFAULT_MESSAGE_SEND_TIMEOUT_MS };
|
|
30
|
+
if (option === 'disabled')
|
|
31
|
+
return { provider: null, ...fallback };
|
|
32
|
+
if (option !== 'env') {
|
|
33
|
+
if (boundSender === null)
|
|
34
|
+
return { provider: null, ...fallback };
|
|
35
|
+
return { provider: (0, message_dispatcher_js_1.providerFromSender)(boundSender, option ? 'custom' : 'log'), ...fallback };
|
|
36
|
+
}
|
|
37
|
+
const env = deps.env ?? process.env;
|
|
38
|
+
const config = (0, message_config_js_1.loadMessageConfig)(env, {
|
|
39
|
+
resolvedFromSecretRef: boot_secrets_js_1.wasResolvedFromSecretRef,
|
|
40
|
+
readFile: deps.readFile ?? ((path) => (0, node_fs_1.readFileSync)(path, 'utf8')),
|
|
41
|
+
});
|
|
42
|
+
if (config.email.provider === 'disabled') {
|
|
43
|
+
logger.warn("emailSender: 'env' with EMAIL_PROVIDER=disabled — framework emails (password reset, " +
|
|
44
|
+
'invites, notices) are NOT delivered.');
|
|
45
|
+
return { provider: null, ...fallback };
|
|
46
|
+
}
|
|
47
|
+
const messaging = (0, optional_peer_js_1.requireOptionalPeer)(MESSAGING_PACKAGE, "ShieldModule.forRoot({ emailSender: 'env' })", deps.load);
|
|
48
|
+
const provider = await messaging.createEmailProvider(config.email);
|
|
49
|
+
const timeoutMs = config.email.timeoutMs;
|
|
50
|
+
if (config.probe)
|
|
51
|
+
await probe(provider, timeoutMs);
|
|
52
|
+
logger.log(`Email delivery: ${provider.name}${config.probe ? ' (boot probe passed)' : ''}`);
|
|
53
|
+
return { provider, timeoutMs };
|
|
54
|
+
}
|
|
55
|
+
/** Reachability + credentials, no message (R8). Bounded; any failure refuses boot. */
|
|
56
|
+
async function probe(provider, timeoutMs) {
|
|
57
|
+
const fail = (detail) => new Error(`MESSAGE_BOOT_PROBE: the ${provider.name} check failed (${detail}); check EMAIL_PROVIDER ` +
|
|
58
|
+
'and the provider host / credential variables');
|
|
59
|
+
if (!provider.probe)
|
|
60
|
+
return;
|
|
61
|
+
const signal = AbortSignal.timeout(timeoutMs);
|
|
62
|
+
let timer;
|
|
63
|
+
const expiry = new Promise((_, reject) => {
|
|
64
|
+
timer = setTimeout(() => reject(fail('timeout')), timeoutMs + 1_000);
|
|
65
|
+
timer.unref?.();
|
|
66
|
+
});
|
|
67
|
+
try {
|
|
68
|
+
await Promise.race([provider.probe({ signal }), expiry]);
|
|
69
|
+
}
|
|
70
|
+
catch (e) {
|
|
71
|
+
if (e instanceof core_1.MessageDeliveryError) {
|
|
72
|
+
const status = e.status !== undefined ? `, HTTP ${e.status}` : '';
|
|
73
|
+
throw fail(`${e.failureClass}${status}`);
|
|
74
|
+
}
|
|
75
|
+
if (signal.aborted)
|
|
76
|
+
throw fail('timeout');
|
|
77
|
+
if (e instanceof Error && e.message.startsWith('MESSAGE_BOOT_PROBE:'))
|
|
78
|
+
throw e;
|
|
79
|
+
throw fail('unreachable');
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
clearTimeout(timer);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The link-base boot rule applies only with a real sender (Phase 13 #1). `'env'` is real unless
|
|
87
|
+
* `EMAIL_PROVIDER=disabled`. Read at `forRoot` time, after `resolveBootSecrets()`.
|
|
88
|
+
*/
|
|
89
|
+
function isMailDisabled(option, env) {
|
|
90
|
+
if (option === undefined || option === 'disabled')
|
|
91
|
+
return true;
|
|
92
|
+
if (option === 'env')
|
|
93
|
+
return env.EMAIL_PROVIDER?.trim() === 'disabled';
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* The `EmailSender` bound under `SHIELD_EMAIL_SENDER` for `'env'`, so existing injectors keep the
|
|
98
|
+
* port they know. Each send is bounded; a failure rejects (callers already treat it best-effort).
|
|
99
|
+
*/
|
|
100
|
+
function senderFromProvider(provider, timeoutMs) {
|
|
101
|
+
return {
|
|
102
|
+
send: async (message) => {
|
|
103
|
+
await provider.send(message, { signal: AbortSignal.timeout(timeoutMs) });
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* `message.sent` / `message.failed` rows go to the framework audit log over guard's own pool
|
|
109
|
+
* (the runtime account holds append-only INSERT on the audit schema), independent of the
|
|
110
|
+
* optional app `auditSink` (Shield #6).
|
|
111
|
+
*/
|
|
112
|
+
function messageAuditWriter(pool, schemas) {
|
|
113
|
+
const sink = new engine_1.MariaDbAuditSink({ schemas });
|
|
114
|
+
return {
|
|
115
|
+
record: (event) => sink.record(event, (sql, params) => pool.query(sql, params)),
|
|
116
|
+
};
|
|
117
|
+
}
|