Skip to content

Commit ec209da

Browse files
authored
Merge pull request #731 from Mirabel64/fix/mirabel64-ba-088-090-091-096
fix(wallet,payments): ledger-backed balances, idempotent verification, Stellar+webhook validation (BA-088/090/091/096)
2 parents b76ef93 + 19f0ecc commit ec209da

5 files changed

Lines changed: 706 additions & 190 deletions

File tree

BackendAcademy/src/config/env.schema.ts

Lines changed: 52 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,11 @@ export const jobEnvSchema = Joi.object({
559559
// Notification delivery and preferences (#385)
560560
// ─────────────────────────────────────────────────────────────────────────────
561561

562+
/**
563+
* Environment variables for notification delivery and preferences (#385).
564+
*/
562565
export const notificationEnvSchema = Joi.object({
566+
/** When "true", user notification preferences are enforced before delivery */
563567
NOTIFICATION_ENFORCE_PREFERENCES: Joi.string()
564568
.valid('true', 'false')
565569
.default('true')
@@ -575,10 +579,9 @@ export const notificationEnvSchema = Joi.object({
575579
),
576580
});
577581

578-
// ─────────────────────────────────────────────────────────────────────────────
579-
// Migration safety and ordering (#397)
580-
// ─────────────────────────────────────────────────────────────────────────────
581-
582+
/**
583+
* Environment variables for migration safety and ordering.
584+
*/
582585
export const migrationEnvSchema = Joi.object({
583586
MIGRATION_LOCK_TIMEOUT: Joi.number()
584587
.integer()
@@ -609,84 +612,55 @@ export const migrationEnvSchema = Joi.object({
609612
});
610613

611614
/**
612-
* The single composed schema handed to `ConfigModule.forRoot()`.
615+
* Environment variables for the Stellar network configuration (BA-090).
613616
*
614-
* Deliberately free of schema-level `.options()` / `.unknown()` calls: every
615-
* knob lives in {@link ENV_VALIDATION_OPTIONS} so there is exactly one place
616-
* that decides how validation behaves.
617+
* These variables let the wallet service validate addresses, issuer, asset
618+
* codes, network passphrase, and Horizon consistently with the environment
619+
* the backend was started in.
620+
*/
621+
export const stellarEnvSchema = Joi.object({
622+
/** Stellar network the backend targets. */
623+
STELLAR_NETWORK: Joi.string()
624+
.valid('testnet', 'futurenet', 'mainnet', 'public', 'custom')
625+
.default('testnet')
626+
.description('Stellar network target.'),
627+
628+
/** Network passphrase that must match `STELLAR_NETWORK`. */
629+
STELLAR_NETWORK_PASSPHRASE: Joi.string()
630+
.valid(
631+
'Test SDF Network ; September 2015',
632+
'Public Global Stellar Network ; September 2015',
633+
'Standalone Network ; February 2017',
634+
)
635+
.default('Test SDF Network ; September 2015')
636+
.description(
637+
'Stellar network passphrase. Must match the configured network.',
638+
),
639+
640+
/** Horizon server URL used to query balances and validate transactions. */
641+
STELLAR_HORIZON_URL: Joi.string()
642+
.uri()
643+
.optional()
644+
.description('Horizon server URL for Stellar queries.'),
645+
646+
/**
647+
* Comma-separated `assetCode:issuer` allow-list for transactions,
648+
* e.g. `XLM:native,USDC:GCGAC2ZAAYZLT...`. Native XLM uses `native`.
649+
*/
650+
STELLAR_ALLOWED_ASSETS: Joi.string()
651+
.optional()
652+
.description('Allowed assetCode:issuer pairs (comma-separated).'),
653+
});
654+
655+
/**
656+
* Combined validation schema that includes base, contract, migration,
657+
* notification, and stellar environment variables.
658+
* Used by config.module.ts to validate all env vars at startup.
617659
*/
618660
export const envValidationSchema = baseEnvSchema
619661
.concat(assetEnvSchema)
620662
.concat(contractEnvSchema)
621663
.concat(jobEnvSchema)
622664
.concat(migrationEnvSchema)
623-
.concat(notificationEnvSchema);
624-
625-
/**
626-
* Canonical validation options.
627-
*
628-
* - `abortEarly: false` — report every misconfigured variable in one pass so
629-
* an operator fixes the whole environment in a single iteration.
630-
* - `convert: true` — coerce the string values that come from `process.env`
631-
* into the declared types (numbers, booleans, …).
632-
* - `allowUnknown: true` — `process.env` always carries unrelated variables
633-
* (`PATH`, `HOME`, CI injections). Unknown *application* variables are
634-
* therefore ignored rather than fatal; this is asserted by the unit tests.
635-
* - `stripUnknown: false` — unknown values stay reachable through
636-
* `ConfigService` for modules that read raw env vars directly.
637-
*/
638-
export const ENV_VALIDATION_OPTIONS: Joi.ValidationOptions = {
639-
abortEarly: false,
640-
convert: true,
641-
allowUnknown: true,
642-
stripUnknown: false,
643-
};
644-
645-
export type ValidatedEnv = Record<string, unknown> & {
646-
NODE_ENV: NodeEnvironment;
647-
PORT: number;
648-
CORS_ORIGIN: string | string[];
649-
DATABASE_URL: string;
650-
REDIS_HOST: string;
651-
REDIS_PORT: number;
652-
JWT_SECRET: string;
653-
ASSET_SIGNING_SECRET: string;
654-
};
655-
656-
export type JobEnvConfig = {
657-
MAX_JOB_RETRIES: number;
658-
JOB_RETRY_DELAY_MS: number;
659-
DLQ_TTL_SECONDS: number;
660-
EXPORT_NOTIFICATION_ENABLED: boolean;
661-
EXPORT_RETRY_MAX: number;
662-
SIGNED_URL_TTL_SECONDS: number;
663-
};
664-
665-
export type ContractEnvConfig = {
666-
CERTIFICATE_BASE_URL: string;
667-
CONTRACT_INGESTION_ENABLED: string;
668-
CONTRACT_REGISTRY_REQUIRE_SCHEMA: string;
669-
CONTRACT_EVENT_REPLAY_ENABLED: string;
670-
CONTRACT_ADAPTER_MODE: string;
671-
CONTRACT_NETWORK: string;
672-
STELLAR_HORIZON_URL?: string;
673-
CONTRACT_REGISTRY_MAX_ENTRIES: number;
674-
CONTRACT_SCHEMA_VERSION: string;
675-
CONTRACT_REPLAY_MAX_EVENTS: number;
676-
CONTRACT_EVENT_RETENTION_DAYS: number;
677-
MAX_ATTACHMENT_SIZE_BYTES: number;
678-
ALLOWED_ATTACHMENT_TYPES?: string;
679-
ATTACHMENT_SCANNING_ENABLED: string;
680-
READINESS_PROBE_TIMEOUT_MS: number;
681-
TASK_ORCHESTRATOR_MAX_RETRIES: number;
682-
TASK_ORCHESTRATOR_BASE_BACKOFF_MS: number;
683-
TASK_ORCHESTRATOR_MAX_BACKOFF_MS: number;
684-
};
685-
686-
export function isFeatureEnabled(value: string | undefined): boolean {
687-
return value === 'true';
688-
}
689-
690-
export function isFeatureExplicitlyDisabled(value: string | undefined): boolean {
691-
return value === 'false';
692-
}
665+
.concat(notificationEnvSchema)
666+
.concat(stellarEnvSchema);

0 commit comments

Comments
 (0)