npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 check > node scripts/run-quality-checks.js [phase-20-check] Running lint npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 lint > eslint . --max-warnings=0 [phase-20-check] Running format:check npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 format:check > prettier . --check Checking formatting... All matched files use Prettier code style! [phase-20-check] Running test npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 test > node --test ✔ Admin auth routes are composed behind validation, session, and CSRF gates (155.015642ms) ✔ configured Admin IP policy rejects disallowed networks before authentication (22.379353ms) ✔ Express foundation serves service, liveness, readiness, and safe 404 responses (170.211629ms) ✔ readiness returns 503 without disclosing database errors (26.256384ms) ✔ web bootstrap verifies MySQL, configures HTTP, becomes ready, and shuts down (59.571266ms) ✔ web bootstrap fails closed and releases resources for an unsupported database (5.850871ms) ✔ web bootstrap connects Redis for distributed protection and closes it on shutdown (7.101086ms) ✔ Spaceship web bootstrap selects the database limiter without starting Redis (30.979189ms) ✔ migration dry run validates all files without secrets or a live database (662.990958ms) ✔ seed and rollback dry runs are offline and deterministic (1322.381821ms) ✔ unknown database command options fail closed (618.720182ms) ✔ example verification succeeds and redacts sensitive placeholders (631.448873ms) ✔ using the example as a runtime environment fails closed without leaking secrets (462.658512ms) ✔ runtime verification succeeds from deployment environment values (420.276589ms) ✔ wallet and history endpoints require a verified Telegram session (143.786283ms) ✔ wallet API returns string amounts and cursor pagination metadata (28.461424ms) ✔ wallet history rejects excessive limits and unknown query input (34.209475ms) ✔ task APIs require a server-verified Telegram user session (236.118724ms) ✔ task start requires CSRF, an empty body, and an Idempotency-Key (87.283778ms) ✔ claim validates ownership-shaped IDs and returns server reward data (38.627998ms) ✔ Admin task lifecycle routes enforce their exact permission (34.589353ms) ✔ public referral endpoints require a verified Telegram session (189.942396ms) ✔ Admin referral routes enforce distinct view, review, and settings permissions (72.207957ms) ✔ Admin review requires CSRF, review permission, reason, and resource version (46.134387ms) ✔ public Mystery Box endpoints require a verified Telegram session (223.414857ms) ✔ free claim requires CSRF, an empty body, and an Idempotency-Key (120.935136ms) ✔ Admin reads, claims, management, and lifecycle use distinct permissions (57.028795ms) ✔ public method, quote, and withdrawal history endpoints require verified Telegram identity (219.540567ms) ✔ quote and create use strict schemas, CSRF, and a required idempotency key (120.477169ms) ✔ Admin withdrawal reads and decrypted destination details use distinct permissions (22.583667ms) ✔ Admin review checks the submitted decision permission and payout confirmation is separate (22.111588ms) ✔ content endpoints require verified Telegram identity (167.320095ms) ✔ announcement read evidence requires CSRF and an empty strict body (52.192164ms) ✔ Admin banner reading, editing, and publishing use separate permissions (36.598941ms) ✔ Admin settings and feature flags enforce exact permissions and strict versions (35.775656ms) ✔ Notification inbox requires Telegram identity and read mutation requires CSRF (178.982841ms) ✔ Template reads and broadcast approval require their exact Admin permissions (35.74232ms) ✔ Reminder creation validates timezone-shaped schedule inputs before service execution (25.758063ms) ✔ earning history and leaderboard require a Telegram-authenticated user (180.473174ms) ✔ financial analytics require their exact high-sensitivity permission (43.724131ms) ✔ report range and leaderboard pagination are rejected before service execution (23.060535ms) ✔ Mini App shell renders EJS with a narrowly scoped official Telegram SDK CSP (244.074505ms) ✔ Mini App module assets revalidate and private paths remain inaccessible (120.562947ms) ✔ Maintenance allows only the public shell/assets while protected API stays closed (22.385268ms) ✔ Banned sessions can load the shell for an error screen but cannot access API data (15.014417ms) ✔ admin shell and assets are public but contain no account data and deny framing (214.862661ms) ✔ every operational route fails closed without its exact read permission (68.00918ms) ✔ authorized reads validate pagination, return string amounts, and record audit context (22.366204ms) ✔ catalog exposes only allowed screens and hides payment account details from reviewers (26.938272ms) ✔ maintenance preserves shell access and follows configured admin access policy (53.512755ms) ✔ upload size exception requires permission and CSRF and does not enlarge other routes (137.816071ms) ✔ all Phase 19 operations reject anonymous callers even with a valid anonymous CSRF token (293.068077ms) ✔ all Phase 19 operations enforce their exact permissions before invoking the service (146.762541ms) ✔ every authorized operation routes a strict validated body and trusted actor context (139.061487ms) ✔ CSRF, malformed money, stale-body fields and oversized input are rejected without a write (20.341845ms) ✔ public enrollment keeps CSRF protection and strict one-time-token validation (16.294101ms) ✔ Phase 9 user endpoints require a server-attached session (175.840158ms) ✔ profile mutation requires CSRF and rejects unapproved fields (88.397361ms) ✔ admin user inspection requires both admin authentication and users.view (21.827214ms) ✔ maintenance keeps bootstrap, authenticated admins, and configured webhook reachable (31.718658ms) ✔ Telegram auth and webhook routes are composed behind their security gates (226.756152ms) ✔ Admin authentication and RBAC trust only server-attached identity and permissions (2.355277ms) ✔ Admin IP allowlist supports exact addresses and bounded CIDR ranges (10.893858ms) ✔ database schema enforces the current security and money contract (126.450771ms) ✔ unexpected async errors disclose neither stack traces nor embedded Telegram tokens (117.944726ms) ✔ invalid incoming request IDs are replaced with server-generated identifiers (48.792701ms) ✔ security headers allow Telegram framing only through CSP (117.535823ms) ✔ production responses enable HSTS and HTTPS upgrade policy (27.005304ms) ✔ strict CORS rejects unknown origins and handles approved preflights (45.283137ms) ✔ signed double-submit CSRF flow protects unsafe JSON requests (48.712196ms) ✔ body parsing rejects unsupported, malformed, and oversized payloads safely (41.751553ms) ✔ rate limiting emits standard controls and fails closed when its store fails (34.629033ms) ✔ maintenance gates application traffic but preserve liveness (23.744802ms) ✔ readiness fails safely when the distributed security dependency is unavailable (8.442592ms) ✔ Phase 10 migration makes ledger entries append-only and excludes pending balances (8.772844ms) ✔ ledger repository locks account rows in deterministic database order (2.19801ms) ✔ wallet history keeps cursor values parameterized (0.726052ms) ✔ runtime ledger repository contains no entry update or delete operation (7.275587ms) ✔ Phase 11 migration snapshots attempts and blocks duplicate active attempts and claims (31.95734ms) ✔ public task mapping never exposes destination or internal database identifiers (1.449078ms) ✔ Admin task filters keep hostile input parameterized (0.865861ms) ✔ task completion uses the existing transaction for ledger settlement (13.588317ms) ✔ task routes declare separate permissions for viewing, editing, publishing, and review (3.88613ms) ✔ Phase 12 migration preserves referral evidence and optimistic state transitions (10.587295ms) ✔ Admin referral search keeps hostile input in query parameters (0.879853ms) ✔ Referral reward settings require string minor units and matching versions (4.948395ms) ✔ Task completion invokes referral activation inside its existing transaction (4.352159ms) ✔ Referral API exposes reads only while Admin mutations require exact permissions (1.622535ms) ✔ Referral activation amount comes only from validated server settings (4.122242ms) ✔ Phase 13 migration enforces single-active, free-only, immutable claim evidence (14.58909ms) ✔ claim flow locks user and reward state before atomic ledger settlement (2.332591ms) ✔ client cannot select the box, reward, amount, ticket, or paid access fields (9.65082ms) ✔ Admin claim search keeps hostile values parameterized (1.431989ms) ✔ repository hardcodes zero cost and no purchase on every box insert (0.700538ms) ✔ route permissions separate claim evidence from lifecycle and configuration (4.316919ms) ✔ Phase 14 migration protects immutable quotes, requests, approvals, history, and payouts (25.129726ms) ✔ withdrawal creation locks user, quote, and method before holding funds and consuming the quote (18.987053ms) ✔ client payloads cannot choose fees, net totals, status, approvals, or payout evidence (5.180144ms) ✔ Admin search values remain parameterized and LIKE metacharacters are escaped (1.338168ms) ✔ destination details use authenticated encryption context and a separate hash (3.623336ms) ✔ manual provider is the only enabled payout implementation and rejects automatic mode (1.214519ms) ✔ route permissions separate reads, sensitive details, decisions, payout, methods, and settings (2.835944ms) ✔ Phase 15 migration versions content and protects lifecycle evidence (16.813982ms) ✔ public banner query requires active time window and verified public media (0.894286ms) ✔ public announcement query binds user reads and server-owned visibility windows (1.530245ms) ✔ public tutorial queries expose published rows only with safe cover media (0.333463ms) ✔ content routes separate management, viewing, and publishing permissions (8.995253ms) ✔ configuration routes enforce exact settings, flag, theme, currency, and maintenance permissions (1.583613ms) ✔ raw Admin text is converted to safe HTML and never passed through as body_html (4.650669ms) ✔ public media serving uses verified metadata, containment, size, and hash controls (2.147374ms) ✔ Phase 16 migration protects immutable template and delivery evidence (20.584794ms) ✔ Outbox claim query uses row locks, leases, bounded attempts, and SKIP LOCKED (6.964272ms) ✔ Message routes separate view, edit, approval, cancellation, and reminder permissions (5.733731ms) ✔ Telegram worker has one allowlisted method and never stores raw provider response (2.759189ms) ✔ Broadcast audience excludes deleted and non-writable Telegram accounts (1.148933ms) ✔ Phase 17 migration protects immutable leaderboard and rollup evidence (7.742602ms) ✔ leaderboard materialization snapshots privacy-safe display data (2.544609ms) ✔ earning history is sourced from posted ledger evidence and uses keyset pagination (7.623043ms) ✔ financial totals and operational reports use distinct permissions (4.437193ms) ✔ Telegram re-sync merges profile data instead of erasing privacy preferences (0.903104ms) ✔ Mini App modules use local resolvable imports and do not persist authentication material (73.373248ms) ✔ Mini App shell permits zoom, has safe-area viewport and loads no inline code (3.225317ms) ✔ Mini App CSS retains mobile clearance, keyboard focus and reduced effects (4.37319ms) ✔ media processor decodes pixels, removes appended data and strips metadata (48.659904ms) ✔ media processor rejects disguised SVG, mismatched MIME, truncated data and excess pixels (17.192346ms) ✔ upload accepts only strict filenames, bounded base64 and explicit supported media types (11.544071ms) ✔ upload writes only generated paths and stores a digest matching the served pixels (43.872281ms) ✔ operational searches bind escaped wildcards and reject unknown query models (1.105252ms) ✔ console projections exclude password, session, payload and raw security evidence columns (0.59231ms) ✔ admin user filters keep hostile search and status values out of SQL text (1.533401ms) ✔ admin user repository parameterizes pagination and search values (1.902121ms) ✔ profile writes update only allowlisted preference columns (0.661653ms) ✔ Telegram webhook requires the exact secret header without reflecting it (3.523347ms) ✔ approved project directories exist (17.821122ms) ✔ package metadata is private, ESM, exact-pinned, and script-complete (3.091976ms) ✔ runtime policy accepts supported LTS lines and rejects unsupported lines (0.656273ms) ✔ web entry point fails closed when deployment configuration is missing (1511.974808ms) ✔ repository does not contain a real environment file (10.5188ms) ✔ password success creates only a staged two-factor challenge (4.844552ms) ✔ unknown and incorrect Admin credentials return the same public failure (3.506666ms) ✔ valid TOTP atomically advances replay state and promotes the challenge (1.419809ms) ✔ invalid TOTP revokes its challenge and commits lockout evidence (2.262346ms) ✔ one-time bootstrap creates an active 2FA Super Admin under a database lock (3.503368ms) ✔ bootstrap command refuses missing one-time inputs before opening MySQL (1.403616ms) ✔ native Argon2id hashes verify correctly and reject malformed resource parameters (506.539763ms) ✔ AES-256-GCM encrypts TOTP secrets with admin-bound authenticated context (12.268173ms) ✔ TOTP matches RFC 6238 vectors and blocks accepted-step replay (4.706498ms) ✔ recovery codes are one-time-hashable, bounded, and never store plaintext (1.959692ms) ✔ admin challenge is opaque, hashed at rest, short-lived, and cookie-separated (7.773193ms) ✔ authenticated admin session loads server-side permissions and rolls idle expiry (2.325457ms) ✔ operational error classes expose stable codes and HTTP statuses (1.922509ms) ✔ AppError rejects invalid status codes and unstable error codes (1.327913ms) ✔ unknown errors normalize to a non-exposed internal failure (0.478764ms) ✔ malformed JSON normalizes to a safe client error (0.347545ms) ✔ configuration modules map validated values and preserve bigint-safe database options (30.071657ms) ✔ complete configuration is deeply frozen (2.311457ms) ✔ diagnostic projection does not expose configuration secrets (3.82475ms) ✔ MySQL version policy accepts supported Oracle MySQL and rejects alternatives (2.863412ms) ✔ acquired MySQL connections are initialized with UTC and strict SQL mode (0.502886ms) ✔ query helpers keep values parameterized and identifiers allowlisted (1.251043ms) ✔ pagination helpers clamp limits and calculate stable metadata (0.482808ms) ✔ transaction helper commits success and rolls back failure (0.955424ms) ✔ transaction helper retries only deadlock-class errors (0.405343ms) ✔ example template contains every declared key and validates in template mode (54.77446ms) ✔ valid production values are parsed into typed and frozen environment data (3.988356ms) ✔ runtime parsing rejects placeholders without exposing their values (3.11337ms) ✔ production validation rejects insecure transport, proxy, cache, logging, and cookie choices (1.74846ms) ✔ cross-field validation rejects unsafe TTL and upload directory relationships (1.751755ms) ✔ cross-field validation keeps route limits within the global request budget (1.304142ms) ✔ database configuration requires UTC and TLS for remote production servers (1.155119ms) ✔ path traversal and unknown template keys are rejected (3.651498ms) ✔ duplicate environment keys fail before parsing (0.92939ms) ✔ file loading rejects file typos while ignoring unrelated process variables (23.829708ms) ✔ unrelated process variables are ignored when strict file mode is not requested (1.566156ms) ✔ environment and nested diagnostic redaction hide all sensitive values (1.061898ms) ✔ health-check CLI parses bounded options and rejects unknown input (7.541484ms) ✔ health-check URL defaults locally and rejects embedded credentials (0.852163ms) ✔ health-check client validates the response contract (7.107563ms) ✔ application lifecycle moves through starting, ready, draining, and stopped (4.991124ms) ✔ application lifecycle rejects impossible transitions (1.219884ms) ✔ graceful shutdown stops HTTP before closing the database and is idempotent (29.676216ms) ✔ shutdown deadline force-closes connections and still closes the pool (18.443121ms) ✔ secret redaction handles nested keys, tokens, URL credentials, bigint, and cycles (3.708539ms) ✔ JSON logger applies thresholds, child bindings, and stderr separation (3.717828ms) ✔ hotfix changes only the pending FK action in the exact released MariaDB source (28.861894ms) ✔ repair preserves statement hashes, timestamps and completed migrations, then resumes at broadcasts (19.798149ms) ✔ repair refuses modified prior migration without altering the database history (1.266029ms) ✔ repair refuses incomplete prior migrations without altering the database history (5.287968ms) ✔ repair refuses old completed migration 010 without altering the database history (1.225221ms) ✔ repair refuses missing checkpoint without altering the database history (5.483943ms) ✔ repair refuses changed statement without altering the database history (1.689961ms) ✔ repair refuses unknown checksum without altering the database history (1.112951ms) ✔ repair refuses mixed checksums without altering the database history (5.081614ms) ✔ repair refuses rollback checkpoint without altering the database history (1.2727ms) ✔ repair refuses later progress without altering the database history (1.007777ms) ✔ repair refuses unrecorded broadcasts table without altering the database history (1.388366ms) ✔ repair refuses missing prefix table without altering the database history (1.36991ms) ✔ repair rolls back a checkpoint count mismatch and releases its schema lock (1.637696ms) ✔ repair refuses MySQL, an unrecognized SQL file, and an unavailable lock (0.983362ms) ✔ ledger validation rejects unbalanced, duplicate-account, and unsafe amount inputs (2.61543ms) ✔ balanced reward posts atomically and rebuilds the user projection (22.331497ms) ✔ a repeated ledger idempotency key returns the committed result without new entries (6.024345ms) ✔ reusing a ledger idempotency key for different data is rejected (1.374935ms) ✔ a debit cannot make a user available account negative (2.635773ms) ✔ reversal appends opposite entries and restores reward and lifetime projections (4.571882ms) ✔ wallet cursor is signed, round-trips, and rejects tampering (6.495703ms) ✔ wallet history validation bounds limit and rejects unknown query fields (3.528096ms) ✔ wallet returns authoritative integer strings and projection health (1.243153ms) ✔ history preserves available and held deltas and emits a signed next cursor (1.207606ms) ✔ projection comparison identifies exact mismatched fields (0.481613ms) ✔ reconciliation repair locks user accounts before replacing the snapshot (1.288839ms) ✔ Admin-created task always uses the server settlement currency and starts as draft (11.82707ms) ✔ publishing a future timer task uses optimistic versioning and scheduled state (2.749032ms) ✔ unsupported verification integrations and stale Admin versions fail closed (1.987633ms) ✔ an early task claim rolls back without creating a ledger reward (60.115369ms) ✔ verified task claim posts ledger and completion in one transaction (5.163891ms) ✔ manual verification claim becomes pending without issuing a reward (1.770688ms) ✔ claim idempotency replay returns the committed completion before task mutation (1.671053ms) ✔ task validation accepts only server-governed task fields and integer minor units (12.699617ms) ✔ eligibility rules fail closed when stored configuration is malformed (1.853614ms) ✔ eligibility evaluates username, geography, progress, and account age server-side (3.640313ms) ✔ completion policy enforces active, global, one-time, daily, and cooldown limits (0.819585ms) ✔ task configuration uses deployment URL policy and rejects unavailable callbacks (0.997245ms) ✔ start and claim idempotency hashes are scoped and compared safely (1.953134ms) ✔ completion period keys make one-time, daily, and repeatable awards deterministic (0.518695ms) ✔ scheduled task activates safely and snapshots all reward-critical fields on start (65.452617ms) ✔ an existing active attempt blocks a second start before any insert (6.101217ms) ✔ start idempotency replay returns the immutable destination snapshot (4.056874ms) ✔ referral policy uses safe defaults for invalid database settings (2.365863ms) ✔ referral activation waits for the server-counted task threshold (4.877756ms) ✔ eligible referral activation posts both server-controlled rewards atomically (3.835263ms) ✔ shared-device risk holds a referral and never posts a reward (0.916019ms) ✔ account restriction is evaluated before age and task progress (0.371831ms) ✔ Admin referral setting update versions history and commits optimistic write (3.145817ms) ✔ stale Admin referral setting version rolls back without writing (1.267631ms) ✔ Admin approval records review then re-runs activation in the same transaction (4.0853ms) ✔ Admin-created boxes persist only server-enforced free access fields (4.721247ms) ✔ stale Admin box updates roll back before a database mutation (1.945796ms) ✔ publish validates the reward pool and performs one optimistic transition (1.664063ms) ✔ reward inventory cannot be reduced below its immutable awarded count (0.814191ms) ✔ daily eligibility uses server task count and timezone period boundaries (36.509697ms) ✔ task requirements are evaluated from authoritative integer counts (0.521306ms) ✔ cooldown eligibility is anchored to the last committed claim (0.518959ms) ✔ weighted selection uses an injected cryptographic ticket boundary (0.449642ms) ✔ exhausted rewards are excluded and fixed mode requires exactly one reward (0.895619ms) ✔ publishing enforces free-only configuration and a valid reward pool (1.439273ms) ✔ Admin payloads cannot introduce payment fields or unsafe money numbers (6.098446ms) ✔ eligible free claim reserves inventory, posts ledger, and stores evidence atomically (46.025867ms) ✔ insufficient verified task progress rolls back before reward or ledger mutation (1.820035ms) ✔ a committed idempotency key returns the original claim without a new transaction (4.208784ms) ✔ earning-restricted users cannot reserve inventory or receive a reward (0.811767ms) ✔ reject atomically refunds the full held gross amount, never only the net amount (8.48292ms) ✔ the first high-value approval remains under review and does not move money (0.506354ms) ✔ the required final approval transitions to approved with immutable approval evidence (0.677806ms) ✔ manual paid confirmation settles held gross into exact net payout and fee credits (2.047067ms) ✔ decrypted destination details are released only after stored hash verification (2.207695ms) ✔ payout confirmation rejects stale versions and non-approved states before settlement (0.948836ms) ✔ global and method rules combine using the stricter financial limits (3.709994ms) ✔ percentage fees round upward and all amounts stay decimal strings (2.860627ms) ✔ eligibility is derived from server account, task, referral, wallet, day, and cooldown state (3.19321ms) ✔ restricted and too-new accounts fail closed (0.344829ms) ✔ dynamic destination fields reject unknown values and produce a safe display mask (2.081268ms) ✔ dual approval is required only at or above the configured high-value threshold (0.289911ms) ✔ withdrawal payload schemas reject client-controlled totals and unsafe numeric amounts (5.879617ms) ✔ Admin method and setting schemas enforce consistent fees and optimistic versions (22.771979ms) ✔ invalid stored setting values fall back to conservative defaults (0.632374ms) ✔ quote derives fee and expiry on the server without posting ledger entries (62.74964ms) ✔ request atomically encrypts details, holds the gross amount, consumes quote, and records history (8.773015ms) ✔ a concurrent quote-consumption conflict rolls back the complete request transaction (4.787323ms) ✔ idempotent request replays must match the original canonical input fingerprint (1.452231ms) ✔ managed setting policy preserves the free-only Mystery Box boundary (2.496123ms) ✔ managed setting policy bounds pagination and normalizes allowlisted URLs (0.572022ms) ✔ theme payload accepts the closed token contract and rejects CSS injection (6.449473ms) ✔ feature flag mutation permits rollout only and rejects targeting objects (2.317669ms) ✔ currency input canonicalizes ISO-style codes and caps decimal precision (3.339383ms) ✔ maintenance windows require strictly ordered timestamps (2.700948ms) ✔ setting updates write an immutable next-version record in one transaction (5.520036ms) ✔ setting updates reject null when it violates the stored value type (1.505362ms) ✔ settlement currency precision cannot change after ledger setup (1.151295ms) ✔ publishing a theme retires the former active theme inside the transaction (1.747989ms) ✔ plain content is encoded into inert server-generated HTML (4.788361ms) ✔ banner validation requires verified-media identity and paired actions (8.810631ms) ✔ announcement targeting schema is strict and date ordered (4.500069ms) ✔ tutorial validation rejects client lifecycle and malformed slugs (4.014213ms) ✔ announcement targeting fails closed for missing or mismatched user attributes (0.435281ms) ✔ disabled banner feature avoids every content database read (2.107662ms) ✔ banner creation rejects media that is not verified and public (2.451021ms) ✔ future announcement publishing selects scheduled state on the server clock (4.816158ms) ✔ tutorial creation rejects a URL outside the deployment allowlist (2.680025ms) ✔ media resolution blocks storage paths that escape the public root (1.482162ms) ✔ Telegram templates preserve allowlisted markup and escape every variable (4.394279ms) ✔ Template buttons are HTTPS-only and expose one closed Telegram keyboard shape (1.809509ms) ✔ Internal Telegram payload contract rejects arbitrary methods, chats, and oversized text (13.331918ms) ✔ Outbox claims use leases and exponential retry is bounded and honors Telegram retry-after (2.75852ms) ✔ Outbox worker completes successes and records failures without logging payloads (1.193881ms) ✔ Telegram job rejects malformed success responses instead of recording a false delivery (0.842522ms) ✔ Reminder next-run calculation follows IANA local time and ISO weekdays (149.395033ms) ✔ Broadcast creator cannot approve their own draft (5.828888ms) ✔ Transactional amount placeholders format integer minor units without floating point (0.515431ms) ✔ analytics periods use closed UTC dates and ISO calendar boundaries (7.611871ms) ✔ earning-history cursors are scoped, signed, and reject tampering (3.203748ms) ✔ earning history emits only signed server ledger deltas and an opaque next cursor (1.392281ms) ✔ earning summary keeps integer minor units and reports reversals separately (1.586371ms) ✔ public leaderboard uses snapshots and never requests Telegram identifiers (1.143937ms) ✔ rollup is idempotent per closed date and builds every allowlisted snapshot (3.214661ms) ✔ Admin financial reports keep monetary values behind a separate service method (1.177984ms) ✔ profile contract accepts explicit leaderboard privacy without accepting identity fields (4.087472ms) ✔ miniapp money formatting preserves every BIGINT minor unit including negative fractions (56.767206ms) ✔ miniapp amount entry never uses floating point or accepts exponent notation (0.570451ms) ✔ miniapp navigation normalizes hashes and rejects malformed or traversal routes (2.559557ms) ✔ miniapp rejects credential-bearing and executable URLs (0.480679ms) ✔ withdrawal field validation mirrors allowed format and option contracts (1.748928ms) ✔ miniapp API rejects non-local paths before sending credentials (1.522172ms) ✔ miniapp shares CSRF retrieval and coalesces concurrent identical mutations (12.208328ms) ✔ failed CSRF requests can be retried and do not send a mutation (5.438371ms) ✔ uncertain financial mutations reuse the same key on deliberate retry (3.277152ms) ✔ API failures retain safe request references and distinguish timeout (2.072486ms) ✔ authentication never invents a development identity outside Telegram (0.792245ms) ✔ theme tokens reject CSS injection and reset stale per-theme overrides (3.132699ms) ✔ admin client rejects external and traversal destinations before sending credentials (3.741156ms) ✔ admin mutations coalesce and use the admin CSRF token without persisting credentials (5.851334ms) ✔ failed mutations are never automatically retried and preserve error context (1.085319ms) ✔ session invalidation discards late responses and does not send an awaiting mutation (0.958919ms) ✔ 401 invalidates authentication while 403 keeps an actionable permission error (4.743449ms) ✔ catalog hides ungranted resources and exact withdrawal decision controls (0.640771ms) ✔ minor units remain decimal strings and numeric configuration rejects unsafe integers (1.275288ms) ✔ forms preserve optional omission, explicit null, booleans and nested reward values (335.020052ms) ✔ create task form submits only supported server fields and keeps rewards precise (37.729181ms) ✔ editing plain content round-trips server HTML without double encoding (18.775751ms) ✔ reminder form reconstructs template keys and keeps nested audience rules (18.671649ms) ✔ template editor sends all strict fields and represents nullable button config (19.399464ms) ✔ settings editor fixes free-only protection and preserves server versions (18.940138ms) ✔ resource query only includes route-supported fields and identities are encoded (0.393478ms) ✔ login completes password challenge and TOTP without persisting a password (29.49136ms) ✔ withdrawal confirmation requires review and duplicate clicks share one request (23.421564ms) ✔ conflict keeps the draft visible and prevents immediate resubmission (36.158757ms) ✔ resource UI renders hostile text inert and ignores a disposed response (24.922914ms) ✔ dashboard renders daily chart and table from real response values and isolates financial reports (22.958792ms) ✔ search phrases with spaces and encoded URL punctuation stay on the local admin endpoint (0.801273ms) ✔ admin entry restores an authenticated shell and logout clears its private data (23.386989ms) ✔ administrator form loads named roles, reviews the request and displays a one-time invitation safely (277.09379ms) ✔ wallet correction editor creates a stable hidden idempotency key per draft (26.738998ms) ✔ resolved fraud records offer no further review action (92.616141ms) ✔ enrollment accepts own password then verifies TOTP without retaining invitation or password fields (28.168293ms) ✔ closing enrollment while a response is pending cannot restore its secret (36.720245ms) ✔ enrollment API obtains anonymous admin CSRF and never exempts its mutations (1.93429ms) ✔ mobile authenticator app switching hides the setup key but permits returning with a code (22.9025ms) ✔ retry risk acknowledgement requires a deliberate checked choice (14.260677ms) ✔ administrative changes recheck active session and fresh permission before writing (12.206866ms) ✔ identity management cannot be delegated by assigning only a manage permission (1.632435ms) ✔ invitation stores only a token digest and does not provision active credentials (9.943793ms) ✔ self access changes and stale administrator versions cannot revoke the last operator (2.212526ms) ✔ administrator role/status change and session revocation commit together (7.776001ms) ✔ a cancelled, unenrolled administrator cannot be enabled through access editing (6.69198ms) ✔ built-in roles cannot be edited, while custom grants revoke assigned sessions (1.832783ms) ✔ account ban revokes sessions without leaving a permanent banned status after expiry (1.449304ms) ✔ unban removes only the selected scope and requires its separate permission (1.148809ms) ✔ competing fraud decisions have one winner and persist the review reason (9.788805ms) ✔ wallet correction preparation is idempotent and cannot change money (1.731215ms) ✔ wallet adjustment rejects self approval and posts exactly once under competing reviews (25.672571ms) ✔ insufficient debit rolls back review and ledger; rejection never changes money (2.803405ms) ✔ money and control inputs reject floats, forged actor fields and missing risk acknowledgement (3.550765ms) ✔ manual retry refuses sent, cancelled, unlinked, stale and permanent recipient failures (1.389327ms) ✔ manual retry retains attempt number/payload and only schedules one additional attempt (2.676563ms) ✔ retry rechecks delivery consent and cannot revive an ineligible campaign (0.446121ms) ✔ invitation enrollment consumes both tokens, encrypts TOTP, and returns recovery codes only once (18.069875ms) ✔ failed enrollment attempts commit their counter and stop verification after five codes (6.346765ms) ✔ outbox terminal failure records its linked job in the same executor and never writes for a lost lease (1.239619ms) ✔ administrative repositories bind arbitrary text and refuse arbitrary table names (0.460018ms) ✔ fraud evidence reveal redacts nested credentials and sensitive identity evidence (1.312848ms) ✔ release schema check is read-only and verifies the complete release (36.734852ms) ✔ release refuses missing schema history (24.798954ms) ✔ release refuses changed schema history (15.760529ms) ✔ release refuses missingSeed schema history (36.064041ms) ✔ release refuses partial schema history (23.320193ms) ✔ Redis fails immediately while offline and bounds queued commands (0.631369ms) ✔ production rejects unsafe DATABASE_QUEUE_LIMIT=0 (24.916776ms) ✔ production rejects unsafe REDIS_URL=redis://default:valid-pass@remote.internal:6379 (3.185855ms) ✔ production rejects unsafe REDIS_URL=redis://127.0.0.1:6379 (5.453941ms) ✔ live acceptance cannot select a production database or an unconfirmed target (0.91194ms) ✔ backup roundtrip preserves binary bytes and private output permissions (56.675801ms) ✔ backup rejects wrong-key and removes unauthenticated plaintext (36.485518ms) ✔ backup rejects ciphertext and removes unauthenticated plaintext (25.564592ms) ✔ backup rejects tag and removes unauthenticated plaintext (23.954694ms) ✔ backup rejects header and removes unauthenticated plaintext (19.638844ms) ✔ backup rejects truncated and removes unauthenticated plaintext (19.919736ms) ✔ backup rejects size-limit and removes unauthenticated plaintext (16.305039ms) ✔ backup and restore never overwrite an existing output (10.249454ms) ✔ backup key rejects malformed, ambiguous or short key material (0.836338ms) ✔ completed polling intervals release abort listeners over repeated cycles (34.971178ms) ✔ readiness times out even when the database connection queue never resolves (17.381111ms) ✔ mysql backup CLI publishes only a successful dump (failure=false) (465.898057ms) ✔ mysql backup CLI publishes only a successful dump (failure=true) (349.77989ms) ✔ mariadb backup CLI publishes only a successful dump (failure=false) (292.718203ms) ✔ mariadb backup CLI publishes only a successful dump (failure=true) (246.959322ms) ✔ admin user list schema caps page sizes and rejects deleted pseudo-filter (4.954682ms) ✔ admin user mappings preserve large numeric values as strings (4.354674ms) ✔ admin user list uses normalized pagination and parallel repository reads (0.933768ms) ✔ admin user detail combines profile, restrictions, wallets, and metrics (0.79487ms) ✔ cache returns a valid hit without invoking the loader (2.737992ms) ✔ cache fails open on malformed reads and write failures (0.756581ms) ✔ cache does not persist oversized responses (2.212034ms) ✔ local day and week boundaries are converted to UTC for Dhaka (50.841598ms) ✔ day boundaries respect daylight-saving transitions (1.417808ms) ✔ database and offset datetimes normalize to the same UTC representation (1.309876ms) ✔ theme tokens accept a closed safe schema and reject CSS injection (1.392457ms) ✔ setting guards accept only usable locale lists and IANA timezones (60.464897ms) ✔ bootstrap combines safe public configuration with user-scoped state (3.252942ms) ✔ dashboard returns decimal-safe strings and never exposes task destination URLs (8.197101ms) ✔ feature gates prevent disabled task and free-reward database reads (3.400128ms) ✔ database numeric guards reject unsafe representations (1.136084ms) ✔ free reward eligibility is display-only and honors frequency boundaries (0.812306ms) ✔ profile schema rejects Telegram-owned and financial fields (4.92959ms) ✔ profile reads expose Telegram IDs as strings and only public fields (2.543435ms) ✔ profile update validates flags/settings before opening a transaction (41.409764ms) ✔ disabled profile editing fails before a database transaction begins (1.529069ms) ✔ unsupported language and invalid timezone are rejected server-side (1.398574ms) ✔ memory rate-limit store increments and resets fixed windows (2.257947ms) ✔ Redis rate-limit store uses one atomic script and namespaced keys (0.848704ms) ✔ Redis client factory applies TLS verification and bounded reconnects (0.369228ms) ✔ Redis connection, readiness cache, and close lifecycle are bounded (0.836166ms) ✔ database readiness is cached and concurrent checks share one query (1.908256ms) ✔ database readiness fails closed without throwing dependency details (2.317442ms) ✔ migration runner applies each immutable migration once under a schema lock (6.010318ms) ✔ migration runner resumes after a partial DDL failure without replaying recorded statements (11.217154ms) ✔ migration runner rejects a changed file after it has been applied (2.214692ms) ✔ seeds require all migrations, run once, and rollback invalidates seed history (7.521877ms) ✔ validation middleware stores only schema-approved data and returns safe issues (12.283167ms) ✔ maintenance and ban gates use trusted server-side providers (0.739705ms) ✔ idempotency middleware hashes accepted keys and rejects duplicates (2.174012ms) ✔ audit middleware records completed mutations without delaying responses (6.910297ms) ✔ HMAC signatures are deterministic and reject modified input (4.757586ms) ✔ CSRF tokens are signed, session-bound, and time-limited (1.057278ms) ✔ secure random and idempotency helpers enforce bounded keys (0.610759ms) ✔ managed URL allowlist requires approved schemes, domains, and credential-free URLs (0.667709ms) ✔ HTML and plain-text helpers encode markup and remove unsafe controls (0.496097ms) ✔ Spaceship accepts the supplied MariaDB release and rejects other engine/version families (1.97449ms) ✔ Spaceship production configuration keeps database rate limiting without Redis (24.547638ms) ✔ Spaceship refuses unsafe profile override RATE_LIMIT_STORE=memory (1.389ms) ✔ Spaceship refuses unsafe profile override DATABASE_DIALECT=mysql (0.865339ms) ✔ Spaceship refuses unsafe profile override REDIS_ENABLED=true (1.31915ms) ✔ Spaceship refuses unsafe profile override QUEUE_BATCH_SIZE=20 (1.40261ms) ✔ Spaceship refuses unsafe profile override DATABASE_CONNECTION_LIMIT=1 (1.778992ms) ✔ Spaceship refuses unsafe profile override DATABASE_CONNECTION_LIMIT=10 (1.600128ms) ✔ Spaceship refuses unsafe profile override DATABASE_QUEUE_LIMIT=0 (1.654368ms) ✔ the Spaceship template includes and validates every environment key (31.247591ms) ✔ MariaDB requires the configured engine, its collation alias and enabled CHECK constraints (1.311914ms) ✔ MariaDB permits only the reviewed broadcast FK difference and refuses MySQL history (96.049563ms) ✔ persistent workers are rejected before opening any connection on Spaceship (9.00762ms) ✔ database rate limit uses a transaction and database clock without storing the client key (0.962083ms) ✔ database limiter outage denies the request with 503 (0.910613ms) ✔ cron already_running does not execute work (0.671688ms) ✔ cron interval_not_elapsed does not execute work (0.150801ms) ✔ cron reports failures without private payloads and releases its connection lock (0.412983ms) ✔ cron defers further batches when its work budget expires (0.355276ms) ✔ cron stops work when the owning database lock is lost (0.575029ms) ✔ SQL splitter preserves quoted semicolons and removes comments (1.503594ms) ✔ migration parser requires both sections and rejects session control (1.749817ms) ✔ seed parser accepts one section and checksum is deterministic (2.649467ms) ✔ all migration and seed files load in contiguous order (78.578713ms) ✔ Telegram exchange creates one user, first-touch referral, and opaque session atomically (6.367066ms) ✔ existing Telegram users retain their internal database ID during profile sync (1.167151ms) ✔ simultaneous first login recovers from a unique-user insert race (1.865012ms) ✔ Telegram API client sends JSON webhook settings and exposes no token on failure (4.06537ms) ✔ bot command routing is private-chat only and preserves a bounded referral payload (1.049619ms) ✔ Mini App keyboards require HTTPS and Telegram HTML is escaped (0.491907ms) ✔ webhook service acknowledges duplicates and retries failed processing safely (0.732393ms) ✔ failed webhook retries cannot replace the payload for an existing update ID (1.372473ms) ✔ Telegram initData validates HMAC, freshness, and bigint-safe identity strings (9.732456ms) ✔ Telegram initData rejects tampering, expiry, future dates, and duplicate protected fields (4.542718ms) ✔ Telegram initData rejects bot users and unsafe numeric identities (1.984367ms) ✔ user sessions store only a hash and emit an HttpOnly secure cookie (5.055128ms) ✔ cookie and IP parsing fail safely on malformed values (11.888489ms) ✔ session authentication maps public identity and rolls idle expiry server-side (0.982759ms) ✔ public IDs are 26-character sortable Crockford identifiers (0.962738ms) ℹ tests 475 ℹ suites 0 ℹ pass 475 ℹ fail 0 ℹ cancelled 0 ℹ skipped 0 ℹ todo 0 ℹ duration_ms 9998.657469 [phase-20-check] Running verify:environment:example npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 verify:environment:example > node bin/verify-environment.js --example Telegram Task Earning — Phase 20 environment verification Mode: example-template Source: .env.example (found) Node.js: v24.19.0 (supported) Keys: 89/89 recognized Placeholders: 13 Environment verification passed. [phase-20-check] Running verify:database-schema npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 verify:database-schema > node scripts/verify-database-schema.js Database schema verified: 23 migrations, 6 seeds, 77 tables, 259 named constraints, 202 up statements, 178 down statements, 19 seed statements. [phase-20-check] Running verify:spaceship npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 verify:spaceship > node scripts/verify-spaceship.js {"passed":true,"scope":"static-only","migrations":24,"seeds":6,"liveMariaDb":"pending"} [phase-20-check] Running build:css npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 build:css > node scripts/build-css.js npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 build:css:miniapp > postcss resources/css/miniapp.css --output public/miniapp/css/app.min.css --env production npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 build:css:admin > postcss resources/css/admin.css --output public/admin/css/admin.min.css --env production CSS bundles built successfully. [phase-20-check] Running verify:project npm warn Unknown env config "http-proxy". This will stop working in the next major version of npm. > telegram-task-earning@0.20.1 verify:project > node scripts/verify-project.js Phase 20 project verification passed: 81 directories, 521 required files, and 40 npm scripts. Phase 20 quality gate passed.