Commit Graph
182 Commits
Author SHA1 Message Date
Satoshi Qazi Muhammed 16da428e4c chore(deps): bump vitest 4.1.12, zod 4.6.7
Clears the open Dependabot alerts for @vitest/mocker (via vitest 4.1.12)
and zod (transitive, eslint-plugin-react-hooks). Both are dev-only.
The lockfile's root version also catches up with package.json (1.0.248).
2026-10-29 19:11:31 +04:00
SatoshiQaziMuhammed 1f0b687e6e Merge pull request #50 from pezkuwichain/fix/rewards-without-recording
rewards: claim what the chain pays, without recording a score first
2026-10-25 20:29:14 +04:00
Satoshi Qazi Muhammed df9c96b238 rewards: claim what the chain pays, without recording a score first
The People chain has no pezRewards.recordTrustScore and no userEpochScores since the payroll
started holding the roll still through each claim window: a claim pays the trust score at
claim time times the epoch's rate, plus the seat share for a Parlementer seat taken by the
time of the roll. The app still asked for the recorded score, so the claimable list was
always empty, and its Record Trust Score button signed a call that does not exist.

The button, its handler and its texts are removed, and the claimable amount is worked out
as the chain's entitlement does.
2026-10-25 19:32:06 +04:00
SatoshiQaziMuhammed 391d446a53 telegram-bot: make new wallets on the device, not in the bot (#49)
The KRD bot's "Create Wallet" button generated a 12-word seed inside the
edge function and sent it to the user as a chat message. Every new
wallet's seed therefore passed through this server, and stayed in
Telegram's cloud history on every device the account is signed in on:
whoever gets into the server, a log, or the Telegram account gets the
wallet.

The button now opens the mini app at ?page=wallet, which lands on the
wallet section; that section already creates the seed on the device
(src/lib/wallet-service.ts) and never sends it anywhere. The
create_wallet callback stays for buttons on old welcome messages, and
answers with the same mini app link instead of a seed.

With nothing left to derive, the bot no longer imports the keyring,
util-crypto or bip39.
2026-10-25 02:40:47 +04:00
SatoshiQaziMuhammed 83a88d0298 telegram-bot: keep message bodies out of the log, load the keyring alone (#48)
Every Telegram call logged its full request body and the echoed reply. Those
bodies hold what users write, the assistant's answers and, from the KRD bot's
create-wallet button, the generated seed phrase, so the seed reached the
container log in clear. Calls now log the method and chat id, replies only
whether they failed and why, and incoming updates only their id and kind.

The bot imported @pezkuwi/api to build a Keyring. That package brings in every
type definition and rxjs; each worker spent ~40 s and ~300 MB loading it, and a
worker that expired and was replaced kept adding to the container's memory
until the 1 GB limit killed it after about eight hours. @pezkuwi/keyring is the
same Keyring without the API.
2026-10-23 00:02:14 +04:00
SatoshiQaziMuhammed 07cd642051 ops: run the Telegram bots and the assistant on vps3 (#46)
* ops: run the Telegram bots and the assistant on vps3

telegram-bot and ask ran on the free cloud project, which paused itself
after a quiet week; every bot went silent and the deploy job failed against
the paused project. They now run in their own edge-runtime container on vps3
(bots/), from /opt/pezkuwi-bots.

Separate from the shared functions runtime because that one verifies a JWT
on every request, which Telegram cannot send, and holds the platform's wallet
keys, which a public bot feeding user text to a language model should not
sit next to. The new runtime holds only the keys the two functions read.

- telegram-bot refuses updates without Telegram's secret-token header
  (TELEGRAM_WEBHOOK_SECRET); the main slot reads TELEGRAM_BOT_TOKEN_MAIN,
  since TELEGRAM_BOT_TOKEN on vps3 is the miniapp's sign-in check.
- nginx keeps the public URL shape:
  supabase.pezkuwichain.io/functions/v1/{telegram-bot,ask}.
- deploy.yml ships them with a new bots-deploy verb on the existing deploy
  key; the host script accepts exactly main, telegram-bot and ask, restarts
  the container and fails unless the bot comes back refusing unsigned updates.
- Registry: _cloud_hosted becomes _hosted_elsewhere; the gate refuses those
  names in the shared volume and reports any copy there as stale.

* ask: send the legacy service key as a bearer token on vps3

The vps3 gateway has no opaque sb_secret keys and honours the service_role JWT
only as a bearer token; sent on apikey alone it reads as anon, the limiter's
count fails, and every question is refused as rate-limited.
2026-10-22 13:51:35 +04:00
SatoshiQaziMuhammed 8cecbc6622 fix(bot): restore working AI models and answer typed "Start" (#45)
The Gemini-first chain and the Groq model swap from 2026-09-05 never reached
main, so the next deploy from main put back models that no longer exist:
both llama models 404, gpt-oss-120b sits at its daily token cap, and
claude-sonnet-4-20250514 is retired. Every DKS bot question ended in
"could not process your question".

- Gemini first, Groq second, Claude last, in telegram-bot and ask.
- Model lists re-measured against the live accounts today; a hung Gemini
  model is cut off after 20 s so it cannot eat the function's wall-clock.
- Strip <think> blocks from replies.
- The app bots now answer "Start" typed by hand and any other plain text
  with the welcome and its app buttons, instead of staying silent.
2026-10-22 02:07:18 +04:00
dependabot[bot] 26f228c59a chore(deps-dev): bump vite from 6.4.3 to 6.4.4 (#44)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.4.3 to 6.4.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.4.4/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.4.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.4.4
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-20 23:08:13 +04:00
dependabot[bot] f8e59b7185 chore(deps): bump follow-redirects from 1.16.0 to 1.16.1 (#43)
Bumps [follow-redirects](https://github.com/follow-redirects/follow-redirects) from 1.16.0 to 1.16.1.
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.16.0...v1.16.1)

---
updated-dependencies:
- dependency-name: follow-redirects
  dependency-version: 1.16.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-10-20 23:07:48 +04:00
SatoshiQaziMuhammed 70b5f5a210 fix(deps): resolve braces to the patched @pezkuwi/braces fork (#42)
`braces` <= 3.0.3 (GHSA-vfj7-8cjw-p6xm) has no upstream fix. `overrides.braces` points at `npm:@pezkuwi/braces@^3.0.4`, our patched fork, the same resolution pezkuwi-api already uses. Lockfile regenerated with `npm install --package-lock-only`; every `braces` entry now resolves to `@pezkuwi/braces` 3.0.4.

Open after this: `elliptic` <= 6.6.1 (GHSA-848j-6mx2-7j84) has no patched release yet.
2026-10-20 22:51:16 +04:00
SatoshiQaziMuhammed 4f00d3f696 feat(check-deposits): check TRC20 addresses of recently active users only (#41)
TronGrid's free plan allows 10,000 requests a day. Checking every user's
TRC20 address on every five-minute run needs ~29,000 a day at 101 users,
so the key ran out at 03:00 UTC and every later run was refused.

get-deposit-info now records when a user opened the deposit screen.
check-deposits checks users seen in the last 24 hours on every run and
everyone in one run every six hours (00, 06, 12, 18 UTC): about 3,300
requests a day at 10 active users. A deposit made without opening the
screen within the past day waits for the next full scan.

The user-list query now reports its error instead of ending the TRC20
check as if there were no users.
2026-10-19 12:17:13 +04:00
SatoshiQaziMuhammed 90955269df chore(check-deposits): run the deposit check every five minutes (#40)
A run walks every user's TRC20 address at ~4 TronGrid requests a second,
so a one-minute schedule stops fitting at roughly 150 users. Five minutes
leaves room to grow; deposits are detected up to five minutes later.
2026-10-19 10:16:21 +04:00
SatoshiQaziMuhammed a781e456e3 fix(check-deposits): request at most 25 Subscan rows (#39)
Subscan's free plan answers 403 row_limit_exceeded to a page of 50, so
every Polkadot check failed once a key was configured. 25 is the largest
page it accepts (measured: 25 succeeds, 30 is rejected).
2026-10-18 19:52:06 +04:00
SatoshiQaziMuhammed e0d56a5fb5 fix(check-deposits): count only TON transfers sent to the deposit address (#38)
The TON check walked every jetton transfer in the deposit address's event
feed, including the ones it sends. An outgoing transfer whose comment
matched a user's deposit code would have been credited to that user; the
2026-02-13 sweep of 41.9 USDT was reported as an unknown-memo deposit on
every run.

Resolve the configured address to its raw form and skip any transfer
whose recipient is not the deposit address.
2026-10-18 19:48:14 +04:00
SatoshiQaziMuhammed 2b255c56fc fix(check-deposits): stop sending an empty TON bearer token (#37)
tonapi rejects `Authorization: Bearer ` with 401 but serves keyless
requests, so every TON check failed whenever TONAPI_KEY was unset. Send
the header only when a key is configured.

TON and Polkadot API errors now carry the first 200 bytes of the
response body and are logged, so the cause of a failure is visible
instead of a bare status code.
2026-10-18 19:37:32 +04:00
SatoshiQaziMuhammed 2b2d7f10f9 Give the deposit check's cron call a 60 s timeout so its result is kept (#36)
pg_net's default 5 s timeout is shorter than the check, so every call since at
least this morning was stored as a timeout and the function's result was
lost. The function kept running; only the record was missing.
2026-10-18 19:23:56 +04:00
SatoshiQaziMuhammed c0c8ba074e check-deposits: one TronGrid request at a time, at most 4 a second, from a rotating start (#35)
The 429 body logged by the previous change reads: 'The key exceeds the
frequency limit(15), and the query server is suspended for 27 s'. The run sent
batches of 8 at once, which tripped it although it averaged about 7 a second,
and the suspension outlasted the 1 s and 2 s retries, which never recovered a
request.

Requests now go one at a time, at most 4 a second. The retries are removed.
Each run starts at a different user, so a run that does hit the limit stops
at a different place each time instead of always skipping the same users.
2026-10-18 16:05:14 +04:00
SatoshiQaziMuhammed 9f42edc431 check-deposits: log TronGrid's 429 reason and stop the run's TRC20 checks at it (#34)
After the pacing fix, 429 still came back in about a third of the runs: from
around the 17th user on, every request was refused, retries included
(measured 2026-10-18 over 404 runs). The body of that answer says which limit
was hit and for how long, and it was never logged. The first 429 of a run now
logs it, and the users after it are skipped with one line saying how many,
instead of each being sent into the same limit.
2026-10-18 14:49:53 +04:00
SatoshiQaziMuhammed a91d455bfb fix(check-deposits): pace TronGrid calls and retry 429 so later users are checked (#33)
check-deposits polls every user's TRC20 address each minute in unpaced
batches of 8. Since the previous change logged TronGrid failures, two
consecutive runs showed HTTP 429 from about the 24th request on: deposit
indexes 24-53, 30 of 53 users, were skipped on every run, so their TRC20
deposits were never seen. The old code returned silently on a non-2xx reply.

- batches start at least 1.1 s apart
- a 429 is retried twice, after 1 s and 2 s
- per-user failures, including thrown errors, are logged and returned in
  result.errors instead of being dropped

Deposits are found from the last 20 transfers per address and deduplicated
by tx_hash, so once users are checked again a skipped deposit is picked up
on the next run.
2026-10-18 06:28:27 +04:00
SatoshiQaziMuhammed a08754f705 fix(deposits): stop sending an empty TronGrid key and log TronGrid failures (#32)
Both TRC20 deposit functions sent `TRON-PRO-API-KEY: ''` when the key was
unset, and check-deposits returned silently on any non-2xx TronGrid
response, so a 401 or 429 skipped a user's deposits with nothing in the
logs.

- send the key header only when TRONGRID_API_KEY is set; warn once if not
- check-deposits logs the status and deposit index on a failed call
- process-deposits records the TronGrid status in results.trc20.errors
- type the batch item in check-deposits (deno check TS7006, pre-existing)
2026-10-17 20:46:08 +04:00
SatoshiQaziMuhammed 92b4a70cca Merge pull request #31 from pezkuwichain/ops/recreate-functions-only
Recreate only the edge runtime on deploy
2026-10-16 16:07:51 +04:00
Satoshi Qazi Muhammed b13577ba74 Recreate only the edge runtime on deploy
The deploy gate ran docker compose up --force-recreate functions, which also starts what functions depends on: kong, and through kong studio. studio has been down since the stack restarted on 2026-10-12, so compose stopped with "dependency failed to start: container supabase-studio exited (128)" after removing the old runtime, and left the new one in Created: every edge function answered 503 until it was started by hand. --no-deps recreates the runtime alone; checked with compose --dry-run on the host (with deps: the studio error; with --no-deps: recreated and started). The host's gate is updated to this file, so the deploy's hash check matches.
2026-10-16 14:58:09 +04:00
SatoshiQaziMuhammed 57b0ec75e6 Merge pull request #30 from pezkuwichain/deps/postcss-selector-parser-7
Override postcss-selector-parser to 7.1.6 under tailwind 3
2026-10-16 14:50:33 +04:00
Satoshi Qazi Muhammed b0976efe32 Override postcss-selector-parser to 7.1.6 under tailwind 3
tailwind 3 asks for postcss-selector-parser ^6, which held the alert's fixed release (7.1.6) out of reach. Built both ways: the CSS tailwind emits is byte-for-byte the same (index-DNViMQS2.css, 45,648 bytes), so the override changes nothing but the vulnerable parser. tsc clean, vitest passes.
2026-10-16 14:34:17 +04:00
SatoshiQaziMuhammed 73809c68be Merge pull request #29 from pezkuwichain/deps/audit-fix
Apply npm audit fix within semver ranges
2026-10-16 09:07:45 +04:00
Satoshi Qazi Muhammed 9cbea3c69a Apply npm audit fix within semver ranges
source-map-js 1.2.1 -> 1.2.2 (high, build tooling). Left: postcss-selector-parser (fixed only in 7.x; tailwind 3 pins ^6, input is our own CSS), braces and elliptic (no fixed release). tsc clean, vitest 92 passed / 15 skipped, vite build OK.
2026-10-16 08:59:39 +04:00
SatoshiQaziMuhammed 217fd57f1b Merge pull request #26 from pezkuwichain/ci/dependabot-actions
Let Dependabot keep the pinned workflow actions current
2026-10-12 09:27:25 +04:00
SatoshiQaziMuhammed ea80bbbbd2 Merge pull request #27 from pezkuwichain/chore/pezkuwi-crypto-7.5.21
Move to wasm-crypto 7.5.21, util-crypto 14.0.26, api 16.5.39
2026-10-12 09:27:22 +04:00
Satoshi Qazi Muhammed 91b9c9c951 Move to wasm-crypto 7.5.21, util-crypto 14.0.26, api 16.5.39
The locked wasm-crypto 7.5.17 implements only sr25519 and hashing:
ed25519, secp256k1, sr25519 derivation and VRF throw "not yet
implemented". The wallet signs with plain sr25519 today, so nothing
breaks now, but a derivation path or another key type would fail at run
time. 7.5.21 carries the full crate set without known advisories.
2026-10-12 08:28:57 +04:00
Satoshi Qazi Muhammed cdc311b3b0 ci: let Dependabot keep the pinned workflow actions current
The actions are pinned to commit SHAs, and nothing proposes updates to
them: the Node 20 runtime several of them still declare is already being
forced to Node 24, with a warning on every run. Dependabot now checks them
monthly and groups all action updates into one pull request.
2026-10-09 07:03:08 +04:00
Satoshi Qazi Muhammed 4dfd587b2e ci: allow the secret scanner's own licence in dependency review
Pinning trufflehog to a commit made dependency review list it as a changed
dependency, and its AGPL-3.0 licence is on the deny list. It is the scanner
this workflow runs, executed in CI and never shipped or served, so it is
allowed by name; the deny list still applies to everything else.
2026-10-09 06:09:22 +04:00
Satoshi Qazi Muhammed f6d53f51b1 ci: deploy over pinned, single-purpose keys; root installs the gate
The deploy reached VPS3 as root with one key, handed to appleboy actions
referenced by tag, and on every run it reinstalled the edge-function
ownership gate and its registry as root. That gate guards every project's
functions in the shared volume, so any change merged here could rewrite the
rule that protects pwap's functions.

Now CI connects as miniapp-deploy with two keys, each pinned on the host
(authorized_keys restrict,command=) to a script in ops/host:

- MINIAPP_SITE_DEPLOY_KEY -> miniapp-site-receive: the site tar on stdin,
  into /var/www/telegram.pezkiwi.app, nothing else.
- MINIAPP_FUNCTIONS_DEPLOY_KEY -> miniapp-functions-ssh: `gate-sha`, or
  `deploy` with functions.tgz on stdin, run through sudo for exactly those
  arguments.

Root installs the gate and registry from ops/; the deploy checks the host's
copies against them and refuses to deploy functions while they differ.

The asset cleanup that ran after each deploy (/opt/cleanup-miniapp.sh, only
on the host) protected lazy chunks by mtime and so removed live ones when a
build was shipped more than two hours after it was made; it took seven pages
down for about two minutes on 2026-10-09 while this was being tested, and
they were restored from the same tar. The receive script now keeps every
file of the new build and removes other assets only after four hours. Its
tests cover that (red with the keep rule removed) and the refusals; CI runs
them with shellcheck, and apply-repo-settings.sh requires the job.

VPS3's host key is pinned. The commented-out VPS1 deploy is gone; that host
no longer exists. Every action is pinned to a commit SHA.
2026-10-09 06:09:22 +04:00
SatoshiQaziMuhammed 909dacd1af fix(security): patch vulnerable dependencies and code scanning findings (#21)
* chore(deps): move vulnerable dependencies to patched versions

Direct dev dependencies: vite ^5.4.1 -> ^6.4.3 (5.x has no patched
release for the fs.deny bypass and launch-editor advisories; also lifts
esbuild from 0.21.5 to 0.25.12), vitest and @vitest/coverage-v8 ->
^4.1.11, postcss -> ^8.5.23.

Transitive packages refreshed within their existing ranges:
brace-expansion, js-yaml, baseline-browser-mapping, qs, @humanfs/node,
browserslist, postcss-selector-parser, nanoid, form-data, @babel/core,
picomatch.

Overrides with a floor at the patched version where a parent pins an
old release: axios ^1.20.0 (tronweb pins 1.15.0) and ws ^8.21.0
(ethers pins 8.17.1).

* fix(security): address open code scanning findings

- auto-merge: pass workflow_run.head_branch through env instead of
  interpolating it into the shell script (code injection).
- ci, deploy, code-quality: restrict GITHUB_TOKEN to contents: read.
- telegram-bot: return a generic error body on failure; the error stays
  in the function log instead of being echoed to the caller.
- p2p-e2e-test.py: stop printing a prefix of the service-role key.
2026-10-02 21:18:32 +04:00
SatoshiQaziMuhammed 1372978298 fix(ask): use the project's secret key; fail closed when the rate limit cannot count (#20)
The DKSapp project's legacy anon/service_role keys were disabled on
2026-10-02, after the service_role key leaked through a public commit.
ask read SUPABASE_SERVICE_ROLE_KEY, so its rate limiter stopped working.

- Read the secret key from SUPABASE_SECRET_KEYS ('default'), the variable
  Supabase provides alongside the legacy one, and send it on the apikey
  header only: as a Bearer token the gateway rejects it as a malformed JWT.
- The limiter read a missing content-range as a count of zero, so a
  rejected key let every request through to the paid model. A failed
  count, a failed log write or a missing key now refuses the request.
2026-10-02 21:00:04 +04:00
SatoshiQaziMuhammed 78c7c71493 ci: drop the CodeQL job from security.yml (#18)
The organisation's code security configuration enables CodeQL default
setup, and GitHub refuses to apply it while a workflow runs CodeQL itself:
the configuration failed on this repository with "Code scanning conflict".

Default setup covers what this job did. The job ran the default query
suite with no config file, path filters or packs, and the languages it
analysed are among those default setup detects here. Default setup takes
over the scan; this workflow keeps its other jobs.

security-events: write served only the SARIF upload, so it goes with it.
contents: read is all the remaining jobs need.
2026-10-02 04:47:14 +04:00
SatoshiQaziMuhammed 9c6af146e6 ops: let a function be retired, not just deployed (#17)
* ops: let a function be retired, not just deployed

The guarded deploy could create and update, never remove. rsync runs without
--delete on purpose, so one project cannot wipe another's functions — but the
consequence was that nothing ever left. A function deleted from its repository
kept serving traffic, and nobody would know.

Found the concrete case on 2026-08-01: email-verification had been removed from
pwap on 2026-07-30 and was still live and reachable with only the anon key,
running under the service-role key with Access-Control-Allow-Origin *. Its
verify path sets profiles.email_verified for whatever user_id a token maps to.
It was not exploitable — the send path calls getUserByEmail, which the SDK does
not have, so no tokens could be minted and the table was empty. Broken is not
the same as safe; it was protected by a bug, not by design.

- --audit compares the volume against the registry both directions and exits 1
  on drift. Runs after every deploy too, so a leftover is stated rather than
  invisible.
- --retire moves functions into /opt/supabase-self-hosted/retired-functions/
  with a timestamp. Quarantined, not deleted: retiring the wrong thing has to be
  one command to undo, and that copy is the only remaining record of what was
  serving traffic.
- _cloud_hosted names now count as declared. They live on the cloud project and
  are owned by nobody here, so without this the audit would have offered to
  retire ask and telegram-bot, which look live.

Applied: email-verification retired and dropped from the registry; the audit is
clean; two-factor-auth and the miniapp's check-deposits both still answer.

* ops: catch the function a project still serves but no longer ships

The retire mechanism closed the second half of the problem. This closes the
first: nothing could detect that email-verification needed retiring.

It was never an orphan. The registry listed it as owned and current, the volume
agreed, and both were right about each other — the repository was the one that
had dropped it. Volume-vs-registry compares two of the three and cannot see a
disagreement in the third. It only became visible as drift because I removed it
from the registry by hand, which means the mechanism did not find it; I did.

A deploy is the one moment we hold the project's actual source next to the
registry and the volume, so it is the only place all three can be compared.
Anything the project owns, that is on disk, and that is absent from what it just
shipped, is now named with the command to retire it.

Warns rather than refuses: deleting a function and shipping an unrelated change
in the same commit is ordinary, and blocking that deploy until someone retires
would punish the correct move. It is printed in the deploy output and recorded
as an ABANDONED line in the deploy log.

Verified against a source tree missing eight of pwap-web's functions: all eight
named, deploy still allowed.
2026-08-01 02:30:25 -07:00
SatoshiQaziMuhammed 99efd52ed9 Merge pull request #16 from pezkuwichain/ops/version-infrastructure
ops: version the ownership gate and branch protection
2026-07-31 10:10:22 -07:00
Satoshi Qazi Muhammed b2b4751f7a ops: version the ownership gate and this repo's branch protection
Two pieces of infrastructure existed only on servers, as single copies with no
history and no review:

  /usr/local/bin/supabase-deploy-functions   the gate both projects deploy through
  /opt/supabase-self-hosted/functions-registry.json   who owns which function name

The gate exists to stop silent drift between what a repo declares and what a
server actually runs. Leaving it unversioned meant the mechanism was drifting the
same way it was built to prevent — and losing that host would have lost it
entirely, along with any record of why it works the way it does.

Both are now in ops/ and synced to the host by CI on every deploy, installed
before the functions they validate so a change to the gate ships together with
them. Verified identical to the server copies by checksum before committing, so
this captures the running state rather than replacing it.

Branch protection gets the same treatment: apply-repo-settings.sh is idempotent
and has a --check mode that reports drift without changing anything. It was
applied by hand through the API today, so nothing here reflected it.

Documented alongside: why the registry lives in this repo even though pwap-web
depends on it (a pwap-web change needs a PR here — deliberate friction, since
the registry is the record of who owns what and should not be edited on a server
where nobody sees the change), and why listing each CI job individually in the
protection rules is a weakness here that pwap-web avoids with an aggregate job.
2026-07-31 10:02:14 -07:00
SatoshiQaziMuhammed 6c65627cbb Merge pull request #15 from pezkuwichain/fix/check-deposits-cpu-v2
perf(deposits): derive the HD master key once, not once per user
2026-07-30 02:44:59 -07:00
SatoshiQaziMuhammed 89075cefc3 Merge pull request #14 from pezkuwichain/fix/main-slot-new-bot
fix(bot): main slot is @BizinikiwiBot, not a retired bot
2026-07-30 02:44:51 -07:00
Satoshi Qazi Muhammed 96cda97635 perf(deposits): derive the HD master key once, not once per user
check-deposits hits the isolate's CPU ceiling on almost every run — 17 limit
events across 20 invocations in the last 20 minutes — and when it does, the
supervisor cancels the worker and the scan stops partway. Deposits after the
cut-off simply are not seen until some later run happens to reach them.

The cause is in deriveTronAddress: it calls mnemonicToSeedSync per user, which
is PBKDF2 with 2048 iterations. The seed depends only on the mnemonic, so with
51 accounts that cost was paid 51 times a minute to produce the identical seed.
Only the derivation path varies per user.

Derive the master key once and reuse it. Measured over the 51 accounts we
actually scan: 418ms -> 58ms, a 7.2x drop in the part that was blowing the
budget.

Verified the addresses are unchanged: old and new paths produce identical
private keys for every index tested, including repeated indexes in one run,
which is what would expose derive() mutating the parent key. It does not.
2026-07-30 02:36:32 -07:00
Satoshi Qazi Muhammed 6f20008387 fix(bot): point the main slot at @BizinikiwiBot
The main slot was described as a retired testnet bot. It is not retired — a
fresh bot was created for it on 2026-07-30 under separate ownership, username
@BizinikiwiBot, display name Pezkuwichain_Bot. It is not a recovery of the
compromised @pezkuwichain_bot; that account is gone and its token stays invalid.

Its webhook carries no ?bot parameter, so getBotId falls back to main and this
slot is now a live path rather than a fallback. The cloud secret
TELEGRAM_BOT_TOKEN holds the new token.

Also puts the PEX.network link on the main welcome, so all three bots offer it.
2026-07-30 02:35:41 -07:00
SatoshiQaziMuhammed e97d73a0dd Merge pull request #13 from pezkuwichain/fix/bot-main-url-and-pex
fix(bot): dead fallback URL + PEX link on the bot users actually reach
2026-07-30 02:29:25 -07:00
Satoshi Qazi Muhammed b4af085133 fix(bot): stop the main slot handing out a dead link, add PEX to the live menu
MINI_APP_URLS.main still pointed at telegram.pezkuwichain.io, the testnet domain
whose DNS record was removed on 2026-07-12. Live webhooks arrive as ?bot=krd and
?bot=dks so that default is never reached today, but a webhook call without the
parameter would have answered /start with a link that cannot resolve.

Also puts the PEX.network link on the krd menu — @pezkuwichainBot, the bot that
actually opens the mini app. It only existed on the dks welcome, so no user
reaching the mini app through the main bot has ever been shown it.

Leaves the three-slot routing alone: both slots are live and healthy on the
cloud project, and collapsing them would have removed the AI assistant.
2026-07-30 02:25:55 -07:00
SatoshiQaziMuhammed d29d5a9ae4 Merge pull request #12 from pezkuwichain/fix/deploy-targets
ci: deploy each function to the project that actually serves it
2026-07-30 02:05:38 -07:00
Satoshi Qazi Muhammed 9e3844fd89 ci: deploy each function to the project that actually serves it
The functions in this repo do not all live in the same place, and the deploy
step I added yesterday sent all of them to the self-hosted host on vps3.

telegram-bot and ask are served from the cloud project vbhftvdayqfmcgmzdxfv.
Both Telegram bots reach it by webhook — ?bot=krd is @pezkuwichainBot and
?bot=dks is @DKSKurdistanBot — and news.pex.mom's assistant calls ask there.
Copies of both still sit in the vps3 volume from before that split, holding a
bot token revoked on 2026-07-19, and take no traffic. Deploying to vps3 was
therefore updating a dead copy while the live one kept running old code.

So the self-hosted job now excludes those two, and a second job deploys them to
the cloud project. That closes a real gap: they had been deployed by hand for
months, and git drifted far enough behind that on 2026-07-21 the running
function body had to be extracted from the deployed bundle to recover it.

The host registry records the split too, so the gate cannot be pointed at the
wrong target by accident.
2026-07-30 02:02:28 -07:00
SatoshiQaziMuhammed aa5ea29106 Merge pull request #10 from pezkuwichain/fix/groq-model-priority-mining-disclaimer
fix(auth): namespace edge functions, restore miniapp sign-in
2026-07-30 00:42:37 -07:00
Satoshi Qazi Muhammed 6c9883b858 fix(bot): keep the PEX.network button in the DKS welcome
The button is live but has never existed in this repo — `git log -S "Buy/Sell
Crypto"` returns nothing, so it was added by hand on the server and missed when
9bb9d2c synced git with the deployed source. Deploying telegram-bot from CI
would therefore have silently dropped it.

Restoring it here keeps what is actually running. Removing it should be a
deliberate decision, not a side effect of the first automated deploy.
2026-07-29 23:35:31 -07:00
Satoshi Qazi Muhammed 41bfd70322 feat(db): add ai_chat_log so the ask endpoint is actually rate limited
`ask` has never been deployed, and the CI step in this branch will publish it.
Its limiter counts rows in ai_chat_log to cap requests at 8/min and 120/day per
IP, but no migration ever created that table, and the limiter fails open when
the count cannot be read.

Shipping `ask` without this would put an unauthenticated endpoint with
Access-Control-Allow-Origin: * in front of paid model APIs with no limit at all.

Applied to the live database as well.
2026-07-29 22:36:06 -07:00
Satoshi Qazi Muhammed 35723996e1 chore: keep version at 1.0.243
The merge resolution took main's 1.0.242 for the version stamp, which moves it
backwards from this branch. Restore 1.0.243.
2026-07-29 21:55:01 -07:00