Estzapros.ru in August 2026: Payments, Security, Email and Content Generation
- Published on
- • 5 mins read•--- views
In August 2026 I spent 17 working days on estzapros.ru, a service that matches customers with contractors. The month produced 196 commits touching 413 files, with 38,744 lines added and 15,897 removed. Every figure here comes from the repository history.
The work split into a few lines: payments, security, email, content generation, new features, the interface and a final check of the live site. Below, each one follows the same order: what was wrong, what changed, and what that led to.
Payments
Problem. Paying for a plan had bugs that lost money and left purchases hanging. The amount was calculated wrongly in places, and when processing failed the site still answered the bank with OK.
Solution. Six fixes. The purchase status and the delivery of what was bought now happen in one transaction, and the bank receives RETRY instead of OK when processing fails. Subscriptions are looked up by status rather than by a column that did not exist, and the T-Bank credentials are read from configuration instead of the environment.
Result. A failed payment no longer disappears: the bank retries it, and a purchase can no longer end up paid but not delivered.
Security
Problem. A guest could impersonate another user, accounts could be enumerated, and the contacts block had an injection in its onclick handler. The right to reply to a request was checked only in the template.
Solution. Eight fixes. The reply permission is now checked in the controller, moderator endpoints require authorisation, the API documentation sits behind a password, and the .env file is closed to outsiders after every deploy.
Result. The critical holes are closed, and access rules are enforced on the server, where a crafted request cannot skip them.
Problem. Emails did not arrive, lost their subjects, locked people out and landed in spam. Offer notifications went out with an empty list of recipients, and for years the log recorded them as sent.
Solution. Twelve fixes. The email confirmation link works again and unconfirmed users can no longer sign in. Users locked out by a failed delivery got their access back, empty subjects were repaired with a migration on the production database, and offer notifications reach their authors again. The plain-text part of each email was cleaned of markup and a hidden open tracker was removed. On the mail server, nine DKIM signatures per message were reduced to one.
Result. The site's emails reach their recipients again, and people who had been stuck without access can sign in.
Content Generation
Problem. The marketplace needed fresh listings and responses, and the first generator held its output format only through the prompt text. When the model answered in prose, the format fell apart.
Solution. Four n8n workflows: new listings on a schedule, responses to fresh and to older requests on two schedules, a shared sub-workflow that generates responses, and an alerts workflow that fires when a run fails. Generated records are marked is_fake, generation now uses a strict OpenAI JSON schema, and the service contacts of generated records are hidden on the server.
Result. Content arrives on schedule in a fixed format, and a failed run shows up as an alert instead of a silent gap.
New Features and Interface
Problem. The home page counters were hardcoded numbers, categories hidden in bulk back in 2020 were still hidden, and the mobile layout scrolled sideways.
Solution. The home page got a feed of fresh requests with tabs, cities and pages that switch without a reload, cached in Redis. Avatars can now be uploaded; they are re-encoded with GD and stored outside the webroot under a random name. Users can subscribe to new requests in a category for free, cities and categories are available through /api/v1, and the category order and interface texts are set from the admin panel. On the interface side there were 17 fixes: no more horizontal scroll, touch targets of at least 44px and text contrast raised to WCAG AA.
Result. The site shows real numbers and hidden content again, and it is usable on a phone.
Checking the Live Site
On 30 August I went through the live scenarios end to end: a request, a response, a private message, a subscription, a password reset and the personal account. The check found six defects and all were fixed. Two of them crashed a form with a 500 error, and in the "My offers" section 366 people were seeing their own requests.
Quality
The test suite has 751 tests in 83 files, all passing, and static analysis reports zero issues. Every fix is covered by a test that failed before the change, and the suite and the analysis run before each deploy. Not one deploy this month went out with failing tests.
The full report is below.
Related
Projects

EstZapros.ru, Request & Offer Marketplace
Before: buyers hunted for suppliers manually through classifieds and cold calls, most requests went unanswered. After: post one request, receive offers from sellers and then pick the best one. Hundreds of deals a month with zero phone calls at the selection stage.
Posts

WordPress & WooCommerce Maintenance: PHP Upgrade, Search Fix, and Security Audit
Complete WooCommerce maintenance including PHP 8.0 upgrade, product search restoration, plugin compatibility fixes, and security audit, executed during off-peak hours to minimize downtime.
OpenZeppelin Pausable: The Kill Switch for Your Smart Contract
When the mechanisms you designed into a contract fail, one is left: the switch. OpenZeppelin gives you Pausable for that, and you should never skip it.
Derive the queue, do not store it: resumable email campaigns
A bulk email run that crashes halfway is either restarted from the beginning, mailing everyone twice, or tracked with a cursor that goes stale. There is a third option: compute who still needs the message instead of recording it.
Open for contract collaboration
I am available for contract-based collaboration. If you have an interesting project idea, schedule a call via Calendly.
Schedule a 30-min call