Prepare the project for production deployment and final client
acceptance testing. Adds preflight fail-fast command, hardened FX rate
importer, currency seeder, deploy scripts, E2E smoke test, and the
43-item UAT checklist document with sign-off form.
Key changes:
- Phase 3.9.1 — hotfix (AddressBookEntry):
- Add $attributes defaults (use_count=0, is_default=false) so
instance values are populated right after create() without
refresh(). Resolves the red test
`it_increments_use_count_and_sets_last_used_at`.
- Phase 3.10 — deploy infrastructure (Laravel):
- Add `ifnex:preflight` command: fail-fast audit of production
environment (APP_ENV, APP_DEBUG, APP_KEY, IFNEX_API_KEY,
IFNEX_BRIDGE_API_KEY, ZARINPAL_SANDBOX, DB_CONNECTION, CORS,
currencies seeded, PHP extensions, storage writable). Exits 1
if any check fails; supports --skip-db for pre-migrate runs.
- Add `ifnex:import-fx-rates` command: replacement for
`ifnex:update-rates`. Fetches USD/AED from Exir.io + EUR/CNY
from FreeCurrencyAPI. Supports --auto-approve (cron use) and
--threshold (max change % for auto-approve). Logs critical on
HTTP failure. URL configurable via EXIR_API_URL env.
- Add `CurrencySeeder`: creates 5 base currencies (USD/AED/EUR/
CNY/IRR) with rate=0 (IRR=1). Idempotent — does not overwrite
real rates already set by admin or cron.
- Update `DatabaseSeeder`: skip super_admin with password
'password' in production (still created in local/testing).
- Fix `bootstrap/app.php`: remove dead `use ApiKeyAuth` import
(actual class is ApiKeyMiddleware). Latent fatal if api_key
alias was used.
- Add `config/ifnex.php` exir block + preflight config.
- Harden `.env.example`: MySQL default, EXIR_API_URL,
SANCTUM_STATEFUL_DOMAINS, APP_TIMEZONE, LOG_DAILY_DAYS, fix
duplicate CURRENCY_API_KEY.
- Phase 3.10 — deploy scripts (Linux):
- Add `scripts/deploy.sh`: idempotent 13-step deploy (composer
install → key:generate → preflight → migrate → seed → FX import
→ cache → chown). Fail-fast with set -e.
- Add `scripts/cron-exir-rates.sh`: daily cron wrapper for
`ifnex:import-fx-rates --source=all --auto-approve`.
- Phase 3.10.1 — preflight hotfix:
- Make expected DB connection configurable
(ifnex.preflight.expected_db_connection) instead of hardcoded
'mysql'. Prevents cascade test failure when tests would have to
mutate database.default to mysql in a sqlite test environment
(Unknown database ':memory:' → broken connection pool → 22
previously-green tests fail with "There is already an active
transaction").
- Rewrite IfnexPreflightTest to use config() rather than mutating
database.default.
- Phase 3.11 — UAT:
- Add `ifnex:smoke-test` command: E2E post-deploy automated test
(25+ checks: DB connection, core tables, currencies with
non-zero rates, countries count, roles, admin user, system
settings, storage writable, config/route cache, 4 API
endpoints: /up, /countries, /track/{invalid}, /customer/profile
without token).
- Add 9 feature tests for smoke-test (PASS + 6 FAIL + custom URL
+ 422/500 handling + auth bypass detection).
- Add `UAT-3.11.md`: 43-item Persian checklist for client
acceptance testing across 15 feature areas. Includes sign-off
form for both parties (client + VernaSoft).
- Update `CLIENT_DELIVERY.md` to record phases 3.10 and 3.11.
Tests:
- Total: 51 → 82 tests, 150 → 220+ assertions, all green.
- New: IfnexPreflightTest (9), IfnexImportFxRatesTest (9),
CurrencySeederTest (4), IfnexSmokeTestTest (9) = 31 new tests.
Documentation:
- DEPLOYMENT_HANDOFF.md §2.4: add CurrencySeeder + import-fx-rates.
- DEPLOYMENT_HANDOFF.md §2.8: update cron to use cron-exir-rates.sh.
- UAT-3.11.md: new 43-item client acceptance checklist + sign-off.
- CLIENT_DELIVERY.md: record phases 3.10 and 3.11 completion.
390 lines
7.4 KiB
PHP
390 lines
7.4 KiB
PHP
<?php return array(
|
|
'a11y/index.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'version' => 'f62f48906198ea8abc60'
|
|
),
|
|
'abilities/index.js' => array(
|
|
'dependencies' => array(
|
|
'wp-data',
|
|
'wp-i18n'
|
|
),
|
|
'version' => '104b6117f4f3d5b94cc3'
|
|
),
|
|
'block-editor/utils/fit-text-frontend.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/interactivity',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => 'f465b12ad4eba72e96bb'
|
|
),
|
|
'block-library/accordion/view.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/interactivity',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => '2bfb90e7aee6b5300a7c'
|
|
),
|
|
'block-library/file/view.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/interactivity',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => 'a9114a756e418400594c'
|
|
),
|
|
'block-library/form/view.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'version' => '5542f8ad251fe43ef09e'
|
|
),
|
|
'block-library/image/view.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/interactivity',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => '25f29e3c6cc00370914b'
|
|
),
|
|
'block-library/navigation/view.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/interactivity',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => '1bf28ded04f9f188bdcb'
|
|
),
|
|
'block-library/playlist/view.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/interactivity',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => 'e921883a3f8a7b1ead70'
|
|
),
|
|
'block-library/query/view.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/interactivity',
|
|
'import' => 'static'
|
|
),
|
|
array(
|
|
'id' => '@wordpress/interactivity-router',
|
|
'import' => 'dynamic'
|
|
)
|
|
),
|
|
'version' => '7a4ec5bfb61a7137cf4b'
|
|
),
|
|
'block-library/search/view.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/interactivity',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => '38bd0e230eaffa354d2a'
|
|
),
|
|
'block-library/tabs/view.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/interactivity',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => 'cc1a34b1bee3c2e17bc4'
|
|
),
|
|
'boot/index.js' => array(
|
|
'dependencies' => array(
|
|
'react',
|
|
'react-dom',
|
|
'react-jsx-runtime',
|
|
'wp-components',
|
|
'wp-compose',
|
|
'wp-core-data',
|
|
'wp-data',
|
|
'wp-editor',
|
|
'wp-element',
|
|
'wp-html-entities',
|
|
'wp-i18n',
|
|
'wp-keyboard-shortcuts',
|
|
'wp-keycodes',
|
|
'wp-notices',
|
|
'wp-primitives',
|
|
'wp-private-apis',
|
|
'wp-theme'
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/a11y',
|
|
'import' => 'static'
|
|
),
|
|
array(
|
|
'id' => '@wordpress/lazy-editor',
|
|
'import' => 'dynamic'
|
|
),
|
|
array(
|
|
'id' => '@wordpress/route',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => '97d6c844a12f1615212a'
|
|
),
|
|
'connectors/index.js' => array(
|
|
'dependencies' => array(
|
|
'react-jsx-runtime',
|
|
'wp-components',
|
|
'wp-data',
|
|
'wp-element',
|
|
'wp-i18n',
|
|
'wp-private-apis'
|
|
),
|
|
'version' => '8aa4346de9f4f9cbfaef'
|
|
),
|
|
'content-types/index.js' => array(
|
|
'dependencies' => array(
|
|
'react',
|
|
'react-dom',
|
|
'react-jsx-runtime',
|
|
'wp-components',
|
|
'wp-compose',
|
|
'wp-core-data',
|
|
'wp-data',
|
|
'wp-date',
|
|
'wp-deprecated',
|
|
'wp-element',
|
|
'wp-i18n',
|
|
'wp-is-shallow-equal',
|
|
'wp-keycodes',
|
|
'wp-notices',
|
|
'wp-preferences',
|
|
'wp-primitives',
|
|
'wp-private-apis',
|
|
'wp-rich-text',
|
|
'wp-theme',
|
|
'wp-url',
|
|
'wp-warning'
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/a11y',
|
|
'import' => 'static'
|
|
),
|
|
array(
|
|
'id' => '@wordpress/route',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => '06bbdee380f4cf86dff0'
|
|
),
|
|
'core-abilities/index.js' => array(
|
|
'dependencies' => array(
|
|
'wp-api-fetch',
|
|
'wp-url'
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/abilities',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => '012760fd849397dd0031'
|
|
),
|
|
'dashboard-init/index.js' => array(
|
|
'dependencies' => array(
|
|
'wp-core-data',
|
|
'wp-data',
|
|
'wp-i18n'
|
|
),
|
|
'version' => 'dfe923ac4bd0bd01b9aa'
|
|
),
|
|
'edit-site-init/index.js' => array(
|
|
'dependencies' => array(
|
|
'react-jsx-runtime',
|
|
'wp-data',
|
|
'wp-element',
|
|
'wp-primitives'
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/boot',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => 'e2f82d3d1c3179d25626'
|
|
),
|
|
'interactivity/index.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'version' => '6a43cba92ed701f32cd9'
|
|
),
|
|
'interactivity-router/full-page.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/interactivity-router',
|
|
'import' => 'dynamic'
|
|
)
|
|
),
|
|
'version' => '5c07cd7a12ae073c5241'
|
|
),
|
|
'interactivity-router/index.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/a11y',
|
|
'import' => 'dynamic'
|
|
),
|
|
array(
|
|
'id' => '@wordpress/interactivity',
|
|
'import' => 'static'
|
|
)
|
|
),
|
|
'version' => 'dea5032c2153d213c1ee'
|
|
),
|
|
'latex-to-mathml/index.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'version' => '662cb0e7f68d2a21cd68'
|
|
),
|
|
'latex-to-mathml/loader.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/latex-to-mathml',
|
|
'import' => 'dynamic'
|
|
)
|
|
),
|
|
'version' => '4f37456af539bd3d2351'
|
|
),
|
|
'lazy-editor/index.js' => array(
|
|
'dependencies' => array(
|
|
'react-jsx-runtime',
|
|
'wp-block-editor',
|
|
'wp-blocks',
|
|
'wp-components',
|
|
'wp-core-data',
|
|
'wp-data',
|
|
'wp-editor',
|
|
'wp-element',
|
|
'wp-i18n',
|
|
'wp-private-apis',
|
|
'wp-style-engine'
|
|
),
|
|
'version' => 'f947bd8281443624c0d0'
|
|
),
|
|
'route/index.js' => array(
|
|
'dependencies' => array(
|
|
'react',
|
|
'react-dom',
|
|
'react-jsx-runtime',
|
|
'wp-private-apis'
|
|
),
|
|
'version' => 'ef851c0f4dda0d1dd359'
|
|
),
|
|
'video-conversion/loader.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/video-conversion/worker',
|
|
'import' => 'dynamic'
|
|
)
|
|
),
|
|
'version' => '81a2ac6d5619086278fd'
|
|
),
|
|
'video-conversion/worker.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'version' => '4d3627c45251ceb4f9a2'
|
|
),
|
|
'vips/loader.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/vips/worker',
|
|
'import' => 'dynamic'
|
|
)
|
|
),
|
|
'version' => '07c9acb45d3e5d81829a'
|
|
),
|
|
'vips/worker.js' => array(
|
|
'dependencies' => array(
|
|
|
|
),
|
|
'version' => '7e33cd8c4128731126e8'
|
|
),
|
|
'workflow/index.js' => array(
|
|
'dependencies' => array(
|
|
'react',
|
|
'react-dom',
|
|
'react-jsx-runtime',
|
|
'wp-components',
|
|
'wp-data',
|
|
'wp-element',
|
|
'wp-i18n',
|
|
'wp-keyboard-shortcuts',
|
|
'wp-primitives',
|
|
'wp-private-apis'
|
|
),
|
|
'module_dependencies' => array(
|
|
array(
|
|
'id' => '@wordpress/abilities',
|
|
'import' => 'static'
|
|
),
|
|
array(
|
|
'id' => '@wordpress/core-abilities',
|
|
'import' => 'dynamic'
|
|
)
|
|
),
|
|
'version' => '9e09ede3195f2f51bc49'
|
|
)
|
|
); |