* fix(ci): unblock deploy pipeline (audit gate + orphan submodule)
The Quality Gate & Deploy pipeline was failing at security-audit
(npm audit --audit-level=high), which blocks telegram-gate and the
whole deploy chain — that is why production was serving a stale bundle.
- npm audit fix (no --force, lockfile only): clears the critical vitest
advisory (GHSA-5xrq-8626-4rwp) and the high elliptic one; only low-
severity items remain, so 'npm audit --audit-level=high' now exits 0.
- Remove the orphaned 'exchange' gitlink: it is an empty submodule
pointer with no .gitmodules mapping, which made git print
'fatal: no submodule mapping found' during checkout.
Verified: lint, test (32 passed), and vite build all pass; audit gate
is green. No package.json changes.
* feat(web): PEZ-20 badge on PEZ and USDT balance cards
Add a small reusable Pez20Badge pill next to the PEZ and USDT tokens in
the wallet balance view, linking to the Token Standards docs. These are
fungible assets on Asset Hub, i.e. the PEZ-20 standard — this gives users
the familiar ERC-20-style mental model at a glance.
Additive only: no labels removed, native HEZ is intentionally not badged
(it is the native/gas token, not a PEZ-20 asset).
The Quality Gate & Deploy pipeline was failing at security-audit
(npm audit --audit-level=high), which blocks telegram-gate and the
whole deploy chain — that is why production was serving a stale bundle.
- npm audit fix (no --force, lockfile only): clears the critical vitest
advisory (GHSA-5xrq-8626-4rwp) and the high elliptic one; only low-
severity items remain, so 'npm audit --audit-level=high' now exits 0.
- Remove the orphaned 'exchange' gitlink: it is an empty submodule
pointer with no .gitmodules mapping, which made git print
'fatal: no submodule mapping found' during checkout.
Verified: lint, test (32 passed), and vite build all pass; audit gate
is green. No package.json changes.
Staking migrated to Asset Hub (AHM), but the landing page still read
nominators from the relay (api.query.staking.counterForNominators),
which is now empty there — so the count showed '—'. Collators were read
from collatorSelection.candidates (empty; collators are invulnerables)
and only on Asset Hub, missing the People chain set.
- Nominators: query Asset Hub staking.counterForNominators (verified 30).
- Collators: count collatorSelection.invulnerables on both Asset Hub and
People chain (2 + 2), tracked per-chain and summed.
- NetworkStats.tsx already used the correct sources; this aligns the
landing page with it.
B2B button (/bereketli SSO interstitial): if there is no Supabase session
or the token exchange fails, redirect to https://bereketli.pezkiwi.app
instead of stranding the user on app.pezkuwichain.io/bereketli. (The
backend CORS allowlist was also missing app.pezkuwichain.io; fixed
server-side so the SSO exchange itself now succeeds.)
docker/login-action writes ~/.docker/config.json but cosign on self-
hosted runner does not always read it. Add 'cosign login ghcr.io'
before sign (build-image) and verify (deploy-app, deploy-pex) so the
registry blob upload/download authenticates correctly.
The previous run signed via Sigstore (Fulcio cert + Rekor tlog entry
created) but failed at the final 'push signature blob to GHCR' step
with UNAUTHORIZED. Explicit cosign login solves this.
The earlier npm override 'create-ecdh: ^5.0.1' resolved to no version on
the registry. CI install failed with ETARGET. Removing the override —
elliptic override alone covers the high-severity transitive vulns.
Remaining 6 lows in vite-plugin-node-polyfills chain accepted.
* Faz 3.1 — All CI jobs moved to self-hosted pwap-runner (DEV VPS).
No more dependency on GitHub-hosted runners — supply-chain attack
surface from GHA runner image compromise eliminated.
* Faz 3.3 — Automatic rollback on health-check fail. Each deploy stamps
/.deploy-sha into the artifact. On health-check failure, the deploy
job reads the previous SHA from the live site, pulls that image, and
redeploys. Telegram notification differentiates: rolled-back-OK,
rollback-also-failed, no-prev-available, manual-rollback-needed.
* E.3 — cosign keyless image signing. build-image signs the GHCR
manifest via Sigstore Fulcio (OIDC, no long-lived keys). deploy-app
and deploy-pex verify the signature before extracting /dist —
unsigned or tampered images cannot deploy. Identity-pinned to this
workflow file.
* E.5 — Subresource Integrity (SRI). vite-plugin-subresource-integrity
injects sha384 integrity= into <script>/<link> tags at build time.
CDN/proxy compromise cannot inject tampered JS — browser blocks on
hash mismatch.
* E.2 — Dependabot triage. 14 alerts: 7 high + 4 moderate cleared via
npm audit fix + npm overrides (elliptic, create-ecdh). 6 low
(transitive in vite-plugin-node-polyfills chain) accepted; the
upstream fix proposes a semver-major DOWNGRADE which makes no sense.
* E.1 — Branch protection on main: CI Gate ✅ required, 1 review
required, force-push and deletion blocked.
Vite aliases @pezkuwi/utils → ../shared/utils, so the Docker build context
must include both web/ and shared/. Previous context: ./web missed shared/
which caused 'Could not load /shared/utils/formatting' at module resolution.
Changes:
- Dockerfile WORKDIR=/build/web; COPY web/* and shared/* explicitly
- Workflow context: ./ + file: ./web/Dockerfile
- Move .dockerignore from web/ to pwap root (matches new context)
Faz 1 — State-actor threat-model defenses:
* Telegram approval gate via PEXSEC_BOT — CEO must approve every deploy in Telegram (30-min timeout). Runs on new self-hosted pwap-runner on DEV VPS, shares /tmp/pexsec-gates/ with pexsec-bot.service.
* DEV VPS app-deploy user privilege drop — deploys no longer run as root. CI key restricted with no-port-forwarding,no-agent-forwarding,no-X11-forwarding,no-user-rc. Privilege drop verified (cannot read /etc/shadow, /root/, sudo blocked).
* Image-based deploy — Dockerfile (node 20 build → busybox:musl dist) pushed to GHCR with SHA tag. Deploys pull image, extract /dist, scp to VPS. Immutable artifacts, full provenance.
* Health check + Telegram failure alert post-deploy.
* Rollback path: workflow_dispatch with rollback_to=<sha> — skips build, redeploys old image. CEO gate still required.
Faz 2 — Higher-tier defenses:
* TruffleHog secret scan — PR diff (fast) + push full-repo (verified secrets only).
* CodeQL SAST workflow — javascript-typescript, security-extended + security-and-quality queries. PR + push + weekly cron.
* npm audit raised from --audit-level=critical to --audit-level=high (caught more CVEs).
* CI Gate ✅ explicit merge-block job — fails if any required check is not success/skipped.
Enables manual re-deploy via 'gh workflow run quality-gate.yml' without
needing a code push. Useful for: redeploy after secret rotation, post-
incident recovery, deploy verification.
Split monolithic deploy job into bump-version + deploy-app + deploy-pex.
Both deploys run in parallel from same build artifact, independent
secrets per VPS. If one country blocks a domain, the other VPS keeps
serving the same version.
- bump-version: single source of version bump, runs before both deploys
- deploy-app: existing target /var/www/subdomains/app on DEV VPS
- deploy-pex: new target /var/www/pex.mom on VPS3 (217.77.6.126)
Requires secrets: VPS_PEX_HOST, VPS_PEX_USER, VPS_PEX_SSH_KEY, VPS_PEX_SSH_PORT
- Wrap web3Enable() with Promise.race against a 20-second timeout
- On timeout: show descriptive error explaining the popup may be blocked
- Surface actual error messages (incl. timeout) instead of generic 'Failed to connect wallet'
- Both auto-restore and manual connect button now fail fast instead of hanging
- Extension button now shows 'Approve in extension...' spinner while web3Enable waits
- Add generic error fallback for errors not matching 'authorize'/'not found' patterns
- Replace 'Coming soon on Play Store' with real Play Store download link (io.pezkuwichain.wallet)
- WalletConnectModal mobile hint now links directly to Play Store
- Updated in all 6 locales: en, tr, ar, fa, kmr, ckb
- Remove ArrowRightLeft icon from desktop nav Trading dropdown button
- Bottom tab bar: add max-w-md mx-auto (centered) and bump z-index to z-50 to match MobileHomeLayout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add body content sections (HeroSection, NetworkStats, TrustScoreCalculator, ChainSpecs, RewardDistribution) after section grid
- Update section cards with distinct gradient header colors per category (Finance/green, Governance/purple, Social/blue, Education/orange)
- Fix bottom tab bar to be full-width (removed max-w-md mx-auto)
- Adjust role/score cards background to bg-gray-800/70 for contrast against main bg
- Add bodyOnly prop to LandingPageDesktop (non-breaking, unused)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add isApiInitializing state (true during WS connect, false on ready/fail)
- Add isApiReadyRef for closure-safe polling in connectWalletConnect
- connectWalletConnect now waits up to 30s for API instead of throwing immediately
- WalletModal connect buttons disabled + show spinner while blockchain is initializing
TelegramConnect: query tg_users instead of users, resolve visa UUID
from p2p_visa table and store as p2p_user_id for cross-platform P2P.
P2PIdentityContext: when citizen resolves their UUID, backfill
tg_users.p2p_user_id if their wallet is linked to a Telegram account.
* chore: update exchange submodule to pex.network release + add shared images
Exchange submodule advanced to include:
- sweeper.js: TRC-20 JWT Bearer auth, DOT transferAll, PEZ-AH pre-fund
- docker-compose.yml: pex.network defaults for VITE_API_BASE_URL and SMTP_FROM
- .github/workflows/build-deploy.yml: pex.network build arg for web service
Shared images added: keziyakurd, kiwi_perwerde, kurdistan_assembly, pezkuwi, satoshi_qazi_muh
* chore: remove mobile/ from monorepo, suspend CI mobile job
Mobile app moved to /home/mamostehp/pwap-mobile (local, suspended).
Will be re-integrated when mobile development resumes.
- Removed mobile/ directory entirely
- Removed Mobile App job from quality-gate.yml so CI no longer blocks
Mobile app moved to /home/mamostehp/pwap-mobile (local, suspended).
Will be re-integrated when mobile development resumes.
- Removed mobile/ directory entirely
- Removed Mobile App job from quality-gate.yml so CI no longer blocks
Replaces the buggy useEffect that derived citizen number from wallet
address (and re-triggered whenever user cleared the field) with a clean
sync from DashboardContext's NFT-derived citizenNumber. Field is read-only
when NFT data is present, preventing the refill loop entirely.
- Use PezkuwiExchange.png logo instead of emoji for exchange app icon
- External link opens exchange.pezkuwichain.io in new tab (noopener)
- No auth required (exchange is publicly accessible)
- Added imgIcon and href fields to AppItem interface