parity(api,apps): delivery-mode gaps — master OTP, non-blocking SMS, faToEn, v2 cart cap
D20: OTP_MASTER_CODE login bypass read only from the environment, disabled when unset, audited on every use, with a boot banner while armed. SMS no longer aborts the boot in production — it warns and declines silently, so no message can stop an operation. D19: port Utility::faTOen onto admin-entered mobiles (before the uniqueness lookup, which could previously be bypassed with Persian digits), and the create-only welcome SMS, byte-identical to the reference and fire-and-forget. user-app-v2 was missing the cart stock ceiling entirely: capQty/maxQty, the un-orderable guard and the qty clamp are ported, leaving v2's own design intact. The two cart stores are now byte-identical. isVariantOrderable and the orderable-first default selection ported too. jest 45/45; typecheck clean on api, admin-panel, user-app, user-app-v2. [ref: henza_server/app/Http/Controllers/Adm/AdminController.php:333,348,364,378-387] [ref: henza_server/app/Models/Utility.php:26] Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2194b3d4d9
commit
460cf276b6
@@ -2,9 +2,11 @@ import { Logger } from '@nestjs/common';
|
||||
import { assertSmsConfigured, smsConfig, smsConfigured } from './sms.service';
|
||||
|
||||
/**
|
||||
* Covers the boot-time contract the owner specified:
|
||||
* Covers the boot-time contract as REVISED by D20:
|
||||
* * while no key is set, development behaviour is unchanged;
|
||||
* * in production a missing key is a clear, explicit boot failure.
|
||||
* * a missing key NEVER stops the boot, in any environment — it warns, and
|
||||
* sending silently declines. (D14's "fail to boot in production" rule was
|
||||
* removed by the owner for the delivery.)
|
||||
*/
|
||||
describe('SMS configuration', () => {
|
||||
const saved = { ...process.env };
|
||||
@@ -71,32 +73,39 @@ describe('SMS configuration', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('assertSmsConfigured', () => {
|
||||
it('only warns outside production when keys are missing', () => {
|
||||
/**
|
||||
* D20 REVERSED the original boot contract. SMS must never stop the server
|
||||
* from starting, in any environment — an earlier revision of these tests
|
||||
* asserted the opposite (a throw in production) and is intentionally gone.
|
||||
*/
|
||||
describe('assertSmsConfigured (D20 — never throws)', () => {
|
||||
it('warns outside production when keys are missing', () => {
|
||||
process.env.NODE_ENV = 'development';
|
||||
expect(() => assertSmsConfigured(logger)).not.toThrow();
|
||||
expect(logger.warn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('THROWS in production when keys are missing, naming them', () => {
|
||||
it('warns in production when keys are missing, naming them, and still boots', () => {
|
||||
process.env.NODE_ENV = 'production';
|
||||
expect(() => assertSmsConfigured(logger)).toThrow(/SMS_TREZ_USERNAME/);
|
||||
expect(() => assertSmsConfigured(logger)).toThrow(/SMS_TREZ_PASSWORD/);
|
||||
expect(() => assertSmsConfigured(logger)).toThrow(/SMS_TREZ_SENDER_LINE/);
|
||||
expect(() => assertSmsConfigured(logger)).not.toThrow();
|
||||
const warned = (logger.warn as jest.Mock).mock.calls.flat().join(' ');
|
||||
expect(warned).toMatch(/SMS_TREZ_USERNAME/);
|
||||
expect(warned).toMatch(/SMS_TREZ_PASSWORD/);
|
||||
expect(warned).toMatch(/SMS_TREZ_SENDER_LINE/);
|
||||
});
|
||||
|
||||
it('passes in production once everything is set', () => {
|
||||
it('passes silently in production once everything is set', () => {
|
||||
process.env.NODE_ENV = 'production';
|
||||
configureFully();
|
||||
expect(() => assertSmsConfigured(logger)).not.toThrow();
|
||||
expect(logger.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('THROWS in production when SMS is explicitly disabled', () => {
|
||||
// Disabling SMS in production means nobody can log in; that must be a
|
||||
// deliberate, visible failure rather than a silent one.
|
||||
it('allows SMS to be explicitly disabled in production', () => {
|
||||
process.env.NODE_ENV = 'production';
|
||||
process.env.SMS_PROVIDER = 'none';
|
||||
expect(() => assertSmsConfigured(logger)).toThrow(/Refusing to start in production/);
|
||||
expect(() => assertSmsConfigured(logger)).not.toThrow();
|
||||
expect(logger.warn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('allows SMS to be disabled outside production', () => {
|
||||
@@ -105,9 +114,12 @@ describe('SMS configuration', () => {
|
||||
expect(() => assertSmsConfigured(logger)).not.toThrow();
|
||||
});
|
||||
|
||||
it('rejects an unknown provider name outright', () => {
|
||||
it('warns about an unknown provider name instead of refusing to boot', () => {
|
||||
process.env.SMS_PROVIDER = 'kavenegar';
|
||||
expect(() => assertSmsConfigured(logger)).toThrow(/Unknown SMS_PROVIDER/);
|
||||
expect(() => assertSmsConfigured(logger)).not.toThrow();
|
||||
expect((logger.warn as jest.Mock).mock.calls.flat().join(' ')).toMatch(
|
||||
/Unknown SMS_PROVIDER/,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user