Commit Graph
100 Commits
Author SHA1 Message Date
Satoshi Qazi Muhammed 1771162793 usdt-bridge: never drop a withdrawal record on a transient RPC failure
process_withdrawal_block's reserve/circuit-breaker check used to `continue`
past a Polkadot connect failure without ever calling db.add_withdrawal() -
a transient RPC error (confirmed live: a public-endpoint rate limit) meant
an already-finalized Pezkuwi withdrawal was silently untracked, with no
pending_multisig_approval entry for the signatories to ever see. It now
always records the withdrawal; an unreachable reserve check is treated as
"unverified" (never auto-paid, flagged distinctly from a confirmed
shortfall) rather than as a reason to drop the record.

Also add bounded exponential backoff (2s..32s, 6 attempts) to
connect_to_chain instead of failing on the first error - every caller
either bubbles the failure through a listener's outer reconnect loop or
out of main() to a systemd restart, so a single blip was tearing down and
fully re-initializing both listeners instead of just waiting it out.

Finally, support POLKADOT_RPC_URL/PEZKUWI_RPC_URL env var overrides for
the configured RPC endpoints, so a dedicated/API-keyed provider URL (e.g.
Dwellir, adopted after the public Polkadot Asset Hub endpoint started
rate-limiting us) can live in a tightly-permissioned EnvironmentFile
instead of the git-tracked bridge_config.json - same pattern already used
for PEZBRIDGE_TELEGRAM_TOKEN and AUTOMATION_KEY_MNEMONIC.
2026-07-16 08:51:23 -07:00
Satoshi Qazi Muhammed 8265794150 Retry auto-pay once with a fresh connection before falling back to manual
The automation key's signing clients (pezkuwi_signing_client/
polkadot_signing_client) are created once at startup and reused for every
auto-pay call. Same failure class as the listener's live subscription
(silent WS death, no error until the next real use, see
LIVE_SUBSCRIPTION_STALL_TIMEOUT's comment): a real withdrawal auto-pay hit
"Connection reset by peer... restart required" twice in a row today,
sending both to manual 3-of-5 review even though the automation key's
Polkadot approval had just been granted and should have covered them.

Both execute_wusdt_auto_payout/execute_usdt_auto_payout call sites now
retry once against a genuinely fresh client on failure before giving up -
cheap for an occasional per-event call (unlike the listener's persistent
subscription, no reason to avoid reconnecting every time). Falls back to
manual review exactly as before if the retry also fails - never a new
failure mode, just a narrower one.
2026-07-15 21:44:48 -07:00
Satoshi Qazi Muhammed f02f831edf Fix silent live-subscription stall: force reconnect if no block for 120s
A real 1 USDT deposit landed on-chain at block #18250967 and was never
detected: subscribe_finalized()'s stream silently stopped yielding new
blocks after startup - no error, no closed stream, the process stayed up
and "Listening for deposits..." was the last line logged for 3+ hours while
the deposit sat undetected the whole time. Checkpoint + backfill (added
earlier) only covers a gap across a process restart; it does nothing for a
stall with no restart at all, which is exactly what happened here.

Both listen_deposits and listen_withdrawals now wrap their subscribe loop in
an outer reconnect loop: each blocks.next() call is bounded by a 120s
timeout (Asset Hub blocks land every ~6-12s, so this is a wide margin), and
a timeout, a closed stream, or a stream-yielded error all trigger a full
reconnect (fresh client + fresh legacy RPC) rather than silently hanging or
crashing the whole process. The existing checkpoint-vs-head backfill then
catches up whatever was missed during the stall, same as it already does
for an ordinary restart.
2026-07-15 09:56:59 -07:00
Satoshi Qazi Muhammed 17de8a171d Add checkpoint + backfill: never rely on live subscription alone
listen_deposits/listen_withdrawals previously used ONLY a live finalized-
block subscription with no persisted cursor - the last_polkadot_block/
last_pezkuwi_block fields existed in BridgeStats but were never read or
written anywhere. A transient subscription gap (no logging, no crash, just
a silently skipped block) could make a real deposit vanish from detection
entirely. Confirmed live: a real user's 1 USDT deposit landed correctly at
the multisig custody address (verified via direct chain balance query) but
was never once logged as detected across 7+ hours of continuous uptime with
zero errors - see res/validators-tiki.md 2026-07-15 for the full incident.

Both listeners now:
1. On startup, compare the persisted checkpoint against current chain head
   and explicitly backfill (fetch block-by-hash via the legacy RPC's
   chain_get_block_hash, then process identically to the live path) any gap
   before starting the live subscription.
2. During live operation, detect if the subscription itself ever jumps ahead
   unexpectedly and backfill that gap too, paging Telegram when it happens.
3. Persist the checkpoint after every block processed, live or backfilled.

process_deposit_block/process_withdrawal_block are the single shared
per-block handlers - backfilled and live blocks run through identical logic,
so there's no way for the two paths to silently diverge in behavior.
2026-07-15 05:38:39 -07:00
Satoshi Qazi Muhammed c0a982b32c Fix min_deposit/min_withdraw mismatch: 10 USDT backend vs 1 USDT wallet UI
wallet-android's Bridge screen has always advertised a 1 USDT minimum
(MIN_USDT constant), but usdt-bridge's actual min_deposit/min_withdraw
defaulted to 10 USDT since the tool's original scaffold commit - nobody had
ever reconciled the two. Confirmed live: a real user swap of ~1 USDT landed
correctly at the multisig custody address but was silently skipped by
listen_deposits (amount < min_deposit), so the user never received wUSDT
despite the wallet telling them 1 USDT was a valid amount.

Backend now matches the value already promised to users, not the other way
around - changing the wallet's displayed minimum after users have already
relied on it would be the wrong direction to reconcile this in.
2026-07-14 21:10:10 -07:00
Satoshi Qazi Muhammed 96840fd17e Add bounded automation-key auto-pay: per-tx cap, daily velocity cap, circuit breaker
Small/mid-size swaps no longer have to wait on 3-of-5 for every single
transaction. usdt-bridge can now execute Assets.transfer_approved directly via
the automation key's existing delegated allowance when a deposit/withdrawal
passes all three independent guards:

- max_single_tx (50,000 USDT): any single transaction above this always queues
  for manual multisig review, no exceptions.
- auto_pay_daily_cap (200,000 USDT): a rolling 24h budget tracked separately
  per leg (wUSDT payouts vs USDT payouts draw on separate on-chain allowances),
  not a per-tx ceiling - lets many legitimate sub-cap swaps clear same-day.
- circuit breaker: if >=50% of the daily cap is consumed within 30 minutes,
  auto-pay halts entirely until a human runs reset-circuit-breaker - a burst
  that fast reads as a compromised key or a bug, not organic demand.

The automation key can only ever move funds via its pre-approved allowance
(never mint/burn/set_team/transfer_ownership - those stay multisig-only), so
its worst case is bounded by whatever allowance + daily cap remain, not
unbounded custody. Withdrawal auto-pay releases real USDT immediately but
defers the corresponding wUSDT burn (Owner/Admin-only, no delegation exists
for it) to a periodic manual multisig batch - tracked via a distinct
auto_paid_burn_pending status so it can't be silently forgotten.

Auto-pay is opt-in at the infra level: AUTOMATION_KEY_MNEMONIC unset means
100% manual behavior, unchanged from before. Bumped pezbridge-bot's
renewal_threshold/topup_amount so the next 3-of-5-approved allowance renewal
scales to the new daily cap.
2026-07-14 15:28:20 -07:00
Satoshi Qazi Muhammed a1555ce952 Fix 3 real bugs in usdt-bridge's listener before trusting it at custody scale
- show_status/show_balances/show_reserves checked the wrong account:
  load_wallet_addresses(&config.seed_path), the old, explicitly-retired
  single-operator key, never the multisig custody addresses. These
  commands were actively misleading, not just unfinished.
- listen_deposits/listen_withdrawals ran as concurrent tasks sharing one
  BridgeDatabase JSON file with no locking and a non-atomic write - two
  events landing close together could produce a lost update, and a
  mid-write crash left a truncated file that hard-crashed the next
  start. Added a process-wide async mutex around every load-mutate-save
  critical section, and made save() write-temp-then-rename so a crash
  mid-write can never corrupt the file in place. load() now refuses to
  silently treat a corrupt file as empty (would erase replay-protection
  history) - only a genuinely missing file gets a fresh database.
- The reserve-shortfall circuit breaker - the single most safety-critical
  signal this tool can produce - only called a local error!() log macro.
  Nobody was notified. Added real Telegram alerting (reusing
  PezbridgeBot's exact chats/send pattern rather than a second channel)
  for reserve shortfalls, max-single-tx-cap deposits/withdrawals needing
  manual review, and every new pending_multisig_approval row.

Also removed ProcessDeposit/MintWusdt/TransferUsdt - dead-but-dangerous
CLI subcommands that still loaded the retired operator key and attempted
direct mint/transfer/burn calls that only happened to fail today because
that key lost asset authority. A latent trap, not a safe no-op by
design; production flow is listen-all -> pending_multisig_approval ->
pwap-web signing, never a single-key path.

cargo check: 0 errors, 0 warnings (both binaries).
2026-07-14 14:08:38 -07:00
Satoshi Qazi Muhammed eb821b2ff5 Rewrite pezbridge-bot as notify-only, drop Noter key custody entirely
Renewing the automation key's spending allowance always needs 3-of-5
multisig approval regardless, so having this bot hold one signer's
(Noter's) private key on a VPS to auto-submit one of those three
signatures was never actually saving a real step - the other two
signers still had to sign manually every time. Once pwap-web shipped
a real multisig operations UI (and now wallet-android's Bridge screen
too), the bot's only remaining job is to detect a low allowance and
notify all 5 signers via Telegram - they each sign with their own
wallet through one of pwap-web, pezbridge-sign.pex.mom, or the wallet
app directly. Noter's mnemonic was removed from the VPS entirely
(shred -u) after this rewrite was deployed and verified.

Also adds gen_automation_key.rs (one-off key generation helper) and
the updated systemd unit with LoadCredential removed.
2026-07-14 07:38:24 -07:00
Satoshi Qazi Muhammed 042e1df314 fix(usdt-bridge): replace fragile Debug-string event matching with real byte decoding
listen_deposits/listen_withdrawals matched the bridge address by
checking whether a Debug-formatted string of the decoded dynamic Value
contained a 10-char slice of the address's SS58 text - flagged earlier
this session as unverified and provably broken (that same Debug string
was also fed into convert_ss58_prefix, which only parses real SS58
text and could never have succeeded on it).

Added account_id_from_dynamic(), which decodes an AccountId32's actual
32 bytes out of the event field (peeling the single-item composite
wrapper subxt's dynamic API adds, same nesting seen in Tiki storage
this session) and account_bytes_to_ss58() to re-encode them properly.
Both listeners now compare raw bytes against the target address
instead of matching strings, and derive the sender's real SS58 address
for logging and convert_ss58_prefix() instead of a Debug string.

Verified against a live event, not just read: sent a real 1 wUSDT
transfer from Treasury_1 to the multisig and confirmed the decoder
correctly extracted and matched the multisig's AccountId32 bytes from
the resulting Assets.Transferred event.
2026-07-13 17:43:16 -07:00
Satoshi Qazi Muhammed 45e4b26068 feat(usdt-bridge): migrate custody from single hot key to 3-of-5 multisig
The single-key custodial model (see prior commit's own doc comment:
"Custodial: A single keypair controls both sides") was replaced with
a 3-of-5 multisig spanning the Serok/SerokiMeclise/Xezinedar/Berdevk/
Noter tiki role-holders (full record in res/validators-tiki.md,
outside this repo). Discovered along the way: wUSDT's ~100M supply
had zero real USDT backing on Polkadot Asset Hub - Treasury_1 (the
actual asset owner, not the seed_path wallet this tool assumed) held
0 USDT/DOT there, with ~99M of the 100M supply sitting undistributed
in Treasury_1's own account. Migrated Pezkuwi Asset Hub custody in one
atomic batch (transfer 1M wUSDT to the multisig, set_team, then
transfer_ownership last) signed by Treasury_1 - tx
0xd5dc550c5cf04f323e5c1d9c13f2056acafc9f56404c657b9743c15ff3a3aacb,
verified on-chain.

listen_deposits/listen_withdrawals no longer sign and submit
mint/burn/transfer - no key this process holds has authority over the
multisig account. They now only detect on-chain events and record
status=pending_multisig_approval with the exact call parameters an
operator needs; actual approval happens through pwap-web's existing
multisig UI (shared/lib/multisig.ts, shared/lib/usdt.ts), not this
relayer. BridgeConfig gained custody_multisig_polkadot/_pezkuwi
fields.

Added pezkuwi-subxt/pezkuwi-subxt-signer alongside the existing
vanilla subxt dependency: vanilla subxt's codegen hardcodes the
`sp_runtime` module path and its default signed-extension handling
produced "bad signature" on submission against this chain's actual
metadata - pezkuwi-subxt (following vendor/pezkuwi-subxt's own
grant_noter_tiki.rs example: PezkuwiConfig, XCM v3, sudo_unchecked_weight)
is what actually signs and submits successfully. Also used to grant
the Xezinedar and Berdevk tiki roles (previously missing signatories
for the multisig) to two validators via a relay-chain sudo XCM Transact,
since the People chain has no local Sudo pallet.
2026-07-13 16:59:20 -07:00
Satoshi Qazi Muhammed cc246664ee fix(usdt-bridge): replay protection, real recipients, working withdraw path, reserve check
The withdrawal direction (burn wUSDT -> release real USDT) had no
listener at all - nothing watched Pezkuwi for redemption deposits, and
the manual ProcessWithdrawals command was an empty stub. The deposit
listener also had two real bugs: it minted to the bridge's own address
instead of the sender's (a leftover "for demo" placeholder), and it
never checked whether a deposit had already been processed before
minting again.

- Add is_deposit_processed/is_withdrawal_processed idempotency checks,
  enforced before every mint/burn/release, not just recorded after.
- Fix listen_deposits() to mint to the sender's actual Pezkuwi address
  (same AccountId32, re-encoded under Pezkuwi's SS58 prefix - both
  chains share one derivation, so no memo/registration is needed) and
  to persist processed deposits to the database, which it never did.
- Add listen_withdrawals(), mirroring the deposit listener: detects
  wUSDT sent to bridge custody, burns it, verifies the Polkadot
  custody wallet actually holds enough real USDT before releasing
  (circuit breaker - an under-collateralized peg must halt loudly,
  not silently short-pay), then releases to the sender's Polkadot
  address.
- Add max_single_tx cap so one bad/anomalous event can't move an
  unbounded amount automatically.
- Add a Reserves command reporting real custody balance vs circulating
  wUSDT supply - the exact invariant that, when broken, is what the
  wallet's "waiting for liquidity" banner was masking.
- load_keypair() now prefers BRIDGE_SEED_MNEMONIC (meant to be
  Vault-injected, matching how the exchange's hot wallets are already
  provisioned) over the plaintext seed_path file, which remains only
  as a local/dev fallback with a loud warning.

Flagged, not fixed here: the event-matching in both listeners
(Debug-formatted Value string containing a slice of the bridge's SS58
text) is unverified against a live node in this environment and should
be replaced with subxt's typed/codegen API before this handles real
value. Custody is still single-keypair (no multisig/MPC threshold
signing) - that is an infrastructure/key-ceremony decision, not a code
change, and is the highest-priority follow-up.
2026-07-13 13:03:16 -07:00
Kurdistan Tech Ministry 3e294180b3 fix(test-runtime): update BizinikiwiTest storage key hashes
After rebrand from SubstrateTest → BizinikiwiTest, the pallet prefix
twox_128 hash changed from 00771836bebdd29870ff246d305c578c to
d98085a84eac4903081fb752c3d8ecde.

generate_expected_storage_hashed_keys was already updated to use
b"BizinikiwiTest" but get_expected_storage_hashed_keys and
build_minimal_genesis_config_works tests still had the old hardcoded
SubstrateTest hashes. This caused expected_keys_vec_are_matching to
fail in CI.
2026-04-30 21:52:51 +03:00
Kurdistan Tech Ministry 4ab1dee12f style: apply cargo fmt to build.rs and location_conversion.rs 2026-04-30 03:55:29 +03:00
Kurdistan Tech Ministry 3119c7edee fix: resolve 4 classes of test failures from partition-1/2 CI runs
1. bip39: revert test password Bizinikiwi to Substrate — VECTORS were
   generated with Substrate; only the test code was renamed during
   rebrand, not the precomputed PBKDF2 reference values.

2. xcm: revert DescribePalletTerminal byte tag Pezpallet to Pallet —
   XCM location-to-account hashing uses protocol-level byte strings
   that must not be rebranded; the change silently broke account
   derivation for pallet-instance XCM locations in all zagros runtimes.

3. CI: exclude pez-chain-spec-guide-runtime from all 5 test-partition
   and test-no-try-runtime jobs — its tests require WASM_BINARY_PATH
   which is None under SKIP_WASM_BUILD=1 (same pattern as the 10
   emulated integration test exclusions already in place).

4. polkavm: downgrade fixtures build-dep polkavm-linker 0.30.0 to
   0.29.0 to match pallet polkavm 0.29.1 (polkavm-common 0.29.0)
   validator; the format mismatch caused CodeRejected on all PVM blob
   uploads in tests. Updated build.rs: target_json_path(args) becomes
   target_json_64_path(), program_from_elf 3-arg becomes 2-arg.
2026-04-30 03:07:40 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 9941af28b1 fix(ci): exclude emulated integration tests from partition jobs, add test-emulated
Emulated XCM integration tests call WASM_BINARY.expect() in their genesis
functions (e.g. asset-hub-zagros/genesis.rs:168). With SKIP_WASM_BUILD=1
(set in .test-base) these all panic immediately with "WASM binary was not
built, please build it!" — causing every test-partition and
test-no-try-runtime job to fail.

Fix: exclude all 10 emulated integration test packages from the 5 partition
jobs. Add a dedicated test-emulated job that runs those 10 packages with
SKIP_WASM_BUILD=0, so WASM blobs are compiled and the genesis functions
succeed. test-emulated shares the same CARGO_TARGET_DIR as the partition
jobs so jemalloc, rocksdb, and Rust deps are warm; WASM blobs land in a
separate debug/build/<hash>/out/ subtree.

Packages excluded from partitions / run in test-emulated:
  asset-hub-pezkuwichain-integration-tests
  asset-hub-zagros-integration-tests
  collectives-zagros-integration-tests
  coretime-pezkuwichain-integration-tests
  coretime-zagros-integration-tests
  governance-zagros-integration-tests
  people-pezkuwichain-integration-tests
  people-zagros-integration-tests
  pezbridge-hub-pezkuwichain-integration-tests
  pezbridge-hub-zagros-integration-tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-29 01:47:23 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 563fd2ca87 fix(ci): check-try-runtime add warm-cache env + increase timeout to 180m
Job was timing out at 120m because it had no CARGO_HOME or shared
CARGO_TARGET_DIR — every run was a cold registry download + full
cold compile even when test-base jobs had already built the same
crates. Add /root/.cargo pre-baked image registry and share the
same /cache/cargo-target/${CACHE_KEY}/test-release directory used
by .test-base. With warm cache this completes in under 30m.

Increase timeout 120m → 180m as belt-and-suspenders for the case
where this job runs before any .test-base job has warmed the cache.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 17:57:21 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 7a71dc80b1 fix(ci): increase test-partition timeout to 420m for cold cache builds
Cold debug build + 1/3 partition test execution observed at 300m+ on VPS2
(14 CPU, 28GB RAM). First pipeline after a Cargo.lock change triggers a cold
CACHE_KEY rebuild (~180-190m), leaving insufficient time for test execution.
420m provides headroom for cold-cache pipelines; warm cache runs complete in
45-90m well within the limit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 11:41:20 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 47a229d1a9 fix(ci): add LLD linker + make check-core-crypto-features resilient
1. Add -Clink-arg=-fuse-ld=lld to .test-base RUSTFLAGS.
   LLD uses significantly less RAM than ld when linking large debug binaries
   (pezkuwi-availability-distribution, pezsc-service). On kurditv with 8G
   container memory limit, ld Bus-errors during the link step. LLD resolves
   this without raising the memory cap.

2. Apply the same fmt resilience pattern to check-core-crypto-features:
   CARGO_HOME=/root/.cargo, before_script:[], retry: when:always max:2.
   The job hits server_timeout_running on vps3 (same root cause as fmt —
   GitLab CI cache download hangs before the script produces any output).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 04:37:59 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 6b962273bb fix(ci): make fmt resilient to server_timeout_running on flaky runners
Two changes:
1. Use CARGO_HOME=/root/.cargo + before_script:[] + cache:[] for fmt.
   cargo fmt --check does not compile and needs no registry download.
   GitLab CI cache downloads happen before any log output — if the download
   hangs on a flaky runner, the job silently times out with server_timeout_running
   and an empty trace, blocking all downstream jobs.

2. Switch retry when: to `always`. GitLab has no retry keyword for
   server_timeout_running (internal code). `always` ensures infrastructure
   failures (container-start, cache-download, runner crash) are retried on
   a different runner. Real format violations fail deterministically on all
   retries and still produce a correct FAIL outcome; max: 2 caps wasted runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-28 00:24:40 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 ab18c725c2 fix(deps): update arrayvec patch to fix core_io_borrowed_buf on wasm32v1-none
The arrayvec fork's io::Write impl used `use std::io` which in no_std mode
(wasm32v1-none with std feature unified by workspace) expands to `use core::io`.
`core::io` is gated behind the unstable `core_io_borrowed_buf` feature in
Rust 1.88 — causing wasm-check (cargo check --target wasm32v1-none) to fail.

Upstream fix: gate io import and io::Write impl behind
not(all(target_arch = "wasm32", target_os = "none")).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 23:30:04 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 f027f7aa83 fix(ci): cut debug binary size and prevent wasm-check from deleting shared test cache
Two root-cause fixes for repeated disk-full (ENOSPC) failures on VPS runners:

1. Add -Cdebuginfo=1 to RUSTFLAGS in .test-base.
   Line-tables-only strips variable/type debug info while keeping file:line
   in panic stack traces. On a full Substrate workspace this cuts the debug/
   artifacts from ~52 G to ~20 G (~60% reduction).

2. Change wasm-check CARGO_TARGET_DIR from its own per-job dir to the shared
   test-release dir. The wasm32v1-none artifacts land in test-release/wasm32v1-none/
   which is orthogonal to test-release/debug/ used by test-partition jobs.
   Removing the intra-key find…rm prevents wasm-check from wiping the 52 G
   test-release dir mid-pipeline when test-no-try-runtime jobs are still queued.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 22:39:41 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 a46e336e81 fix(ci): test-doc must not persist to /cache (was filling 27G per run)
test-doc has SKIP_WASM_BUILD=0 which compiles WASM runtimes and doc tests,
producing 27G+ of artifacts. It was persisting those to /cache/cargo-target/
alongside the test-release dir, filling the 96G kurditv volume to 100%.

Since test-doc is allow_failure and the warm-cache benefit doesn't justify
the disk cost, switch it to the ephemeral container filesystem (same approach
as clippy). The before_script no longer sets CARGO_TARGET_DIR.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 13:04:47 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 635d0151ad fix(ci): add explicit timeouts to all non-test jobs + job_execution_timeout retry
Root cause: server_timeout_running (kurditv disk-full Docker failures) hits
GitLab's 60m default timeout and is not caught by stuck_or_timeout_failure,
runner_system_failure, or unknown_failure — meaning no retry triggers, and fmt
(a pipeline blocker) fails permanently, skipping ALL downstream jobs.

Fix: give every quick-check and security job an explicit tight timeout. A stuck
runner now hits job_execution_timeout (a matchable retry condition) in seconds
or minutes, not 60m. The retry then lands on one of the two healthy runners.

Timeouts added (worst-case real duration shown):
  fmt: 10m (normally ~90s)                     retry: max 2
  check-toml-format: 5m
  check-dependency-rules: 5m
  check-fail-ci: 5m
  check-workspace-integrity: 15m
  check-zepter: 20m
  test-rust-features: 10m
  check-umbrella: 30m
  check-licenses-headers: 10m
  check-core-crypto-features: 15m
  cargo-deny-licenses: 20m
  cargo-deny-sources: 20m
  cargo-audit: 20m                              retry: max 2

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 12:59:05 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 1486a3c2c8 fix(ci): add intra-cache-key cleanup, switch tests to debug mode
Two root causes from pipeline 2480888929:

1. /cache volume bloat — kurditv hit 93G/96G (97% full). The before_script
   pruned old cache KEYS but never cleaned other job dirs within the SAME key.
   Old test-partition-1/, test-partition-2/, wasm-check/, … accumulated across
   pipelines alongside the new test-release/ dir, filling the volume.
   Fix: add a second find that removes every sibling dir in CACHE_KEY/ except
   the current job's dir. .test-base keeps only test-release/; wasm-check keeps
   only wasm-check/. Each pipeline run starts with a clean slate per job type.

2. Release builds exceeded 300m — vps3 was still compiling
   pezbridge-hub-zagros-runtime at minute 300 in --release mode.
   Clippy (debug) took 162m cold; release mode is 2-3x slower.
   Fix: remove --release from all cargo nextest run commands. RUSTFLAGS already
   includes -Cdebug-assertions=y so assertion coverage is identical. Debug
   artifacts are smaller (less disk pressure) and compile faster.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-27 11:03:43 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 0354c96a84 fix(ci): catch server_timeout_running/no_updates_running, fix test cold-build timeout
Three root causes from pipeline 2480399247 (b756499b):

1. kurditv runner failures: `server_timeout_running` and `no_updates_running`
   are internal GitLab failure codes NOT caught by stuck_or_timeout_failure or
   runner_system_failure. Added unknown_failure to all retry conditions so
   retries trigger and land on a healthy runner.

2. Test partition job_execution_timeout (150m): tests run with --release so
   C deps (jemalloc/rocksdb) take hours to compile on cold VPS cache. CARGO_TARGET_DIR
   was per-CI_JOB_NAME so each partition compiled independently. Changed to shared
   test-release dir — C deps compiled once per runner per cache key, all partitions
   reuse. Timeout bumped from 150m to 300m to survive a full cold build.

3. wasm-check: no explicit timeout → hit 60m GitLab default. Added timeout: 2h
   and retry conditions.

Also: test-doc/build-rustdoc/build-implementers-guide got retry conditions;
build-implementers-guide got explicit 15m timeout (mdbook is fast).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 23:04:11 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 b756499b66 ci: add stuck_or_timeout_failure retry to all remaining jobs
Unstable runners occasionally get stuck in the prepare phase with no
log output. Any job can be affected. Adding retry: max: 1, when:
stuck_or_timeout_failure to all remaining jobs that lacked it:

quick-checks: check-dependency-rules, check-fail-ci,
  check-workspace-integrity, check-zepter, test-rust-features,
  check-umbrella, check-licenses-headers

security: cargo-deny-sources, cargo-audit

checks: check-core-crypto-features

Clippy and check-try-runtime excluded — retrying 36m/81m jobs on
actual timeout would be too expensive; those get runner_system_failure
coverage for runner crashes instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 12:51:50 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 612d6fa38f ci: retry fmt on stuck_or_timeout_failure
fmt occasionally gets stuck on unstable runners (empty log, 17+ min
with no output). Since clippy depends on fmt, a stuck fmt blocks the
entire critical path: clippy → check-try-runtime → all tests.

retry: max: 1, when: stuck_or_timeout_failure covers runner freeze
without masking actual cargo fmt formatting failures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 12:44:20 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 c458686071 ci: retry check-toml-format and cargo-deny-licenses on stuck/timeout
Both jobs occasionally get stuck on unstable runners with no output
for 40-50+ minutes (empty log, runner preparing phase freeze). Without
explicit retry, they fail the pipeline with stuck_or_timeout_failure.

retry: max: 1, when: stuck_or_timeout_failure retries only on genuine
runner freezes, not on taplo format errors or license violations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 12:26:07 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 07f7a5b442 ci(clippy): revert persistent CARGO_TARGET_DIR, keep CARGO_HOME fix
librocksdb-sys debug build writes a multi-GB librocksdb.a static archive
to /cache/cargo-target, filling the volume and causing build failure.
Persistent cache is not safe for C++ heavy dependencies.

Keep CARGO_HOME=/root/.cargo (avoids re-downloading the Rust crate
registry on every run). CARGO_TARGET_DIR stays ephemeral (Docker
container fs has ample space).

Timeout stays at 3h to cover cold builds on slower runners.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 11:34:06 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 9e5cf4e833 ci(clippy): persistent cache + pre-baked registry for fast warm builds
Two root causes for clippy taking 100+ minutes on cold runners:
1. CARGO_HOME=$CI_PROJECT_DIR/.cargo (global default) is wiped each job,
   forcing re-download of the entire crate registry on every run.
   Fix: override CARGO_HOME=/root/.cargo (pre-baked in the CI image).
2. CARGO_TARGET_DIR not persisted — compiled artifacts discarded after
   each run, forcing full recompile on the same runner.
   Fix: same /cache/cargo-target/$CACHE_KEY/clippy setup as test jobs.

First run on a fresh runner: still slow (~100m, cold compile).
Subsequent runs on same runner: ~10-15m (warm cache reuse).
Timeout bumped to 3h to safely cover the cold-build case.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 03:37:12 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 b13009b415 ci: retry test jobs once on runner_system_failure
VPS2 Docker daemon crashed mid-run, killing test-partition-1/2 and
leaving wasm-check/test-no-try-runtime-2 with 404 exec errors. None
of these were test failures — all were runner infrastructure failures.

retry: max: 1, when: runner_system_failure retries only on runner
crashes, never on actual test failures. Correct safeguard for
multi-runner setups where any VPS can restart unexpectedly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-26 01:52:23 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 73e5bfea3e fix(ci): retry cargo-deny-advisories on transient network failure
advisory-db is cloned from GitHub (rustsec/advisory-db). The runner
(merkez-server) occasionally fails to reach GitHub — the clone fails
silently, the advisory-dbs/ directory is not created, and cargo-deny
then tries to run git-log on a non-existent path, producing:
  'fatal: cannot change to ...' parsed as an ISO-8601 date → crash

Real fix: GitLab native retry (max: 2, when: script_failure).
This retries the full job on infrastructure failures without bypassing
the security check — if all 3 attempts fail, the job still fails.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 22:10:40 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 7a20770f63 fix(ci): fix test-partition timeouts and wasm-check arrayvec failure
Two root causes fixed:

1. test-partition-* timeout (90m):
   - WASM runtime sub-builds were running during test compilation.
     SKIP_WASM_BUILD=1 skips them — unit/integration tests use mock
     environments and don't need actual WASM blobs.
   - WASM_BUILD_WORKSPACE_HINT=$CI_PROJECT_DIR: when CARGO_TARGET_DIR is
     outside the project directory, wasm-builder's build script searches
     upward for Cargo.lock and fails to find it. Without Cargo.lock it
     resolves deps fresh (no --locked), selecting alloy-eips@1.8.3 and
     ruint@1.18.0 which require Rust 1.91/1.90 (toolchain is 1.88).
   - Timeout increased 90m → 150m for cold-cache headroom.

2. wasm-check arrayvec compile failure (197 errors):
   cargo check --target wasm32v1-none uses whole-workspace feature
   unification, which enables arrayvec's std feature. wasm32v1-none is
   a bare-metal target with no libstd, so arrayvec must be no_std there.
   Fixed in arrayvec fork: force no_std when
   target_arch=wasm32 && target_os=none, regardless of feature flags.
   Cargo.lock updated to new arrayvec commit (0c417574).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 21:57:28 +03:00
Kurdistan Tech MinistryandClaude Sonnet 4.6 fd36770895 fix(ci): consolidate check-try-runtime into single superset command
Three sequential cargo check commands were causing a 90m timeout on GitLab
shared runners (no persistent target/ cache). Command 3 (try-runtime,experimental)
is a strict superset of commands 1 and 2:
- cmd 1: --all --features try-runtime → redundant, cmd 3 covers it
- cmd 2: -p teyrchain-template-node --features try-runtime → redundant,
  teyrchain-template-node is in the workspace (templates/teyrchain/node)
  so --all already includes it

Keep only the most comprehensive check. Increase timeout to 120m to give the
single compile sufficient headroom on shared runners (~60-70m observed).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 16:39:57 +03:00
Kurdistan Tech Ministry e5802599f3 chore: reformat Cargo.toml with taplo 0.9.3 (CI version) 2026-04-25 05:48:52 +03:00
Kurdistan Tech Ministry 90aa6f5350 fix: patch core2 0.4.0 via git mirror to unblock wasm sub-build resolution
core2 0.4.0 was yanked from crates.io. Wasm runtime builds invoke cargo
as a subprocess without --locked, causing fresh dependency resolution to
fail when selecting core2 ^0.4 (no non-yanked version available).

The dependency path: pezsc-network -> cid v0.9.0 -> core2 ^0.4

Adding a git mirror at git.pezkuwichain.io/pezkuwichain/core2 as a
workspace [patch.crates-io] entry. The wasm-builder propagates workspace
patches to the generated wbuild Cargo.toml, so the sub-build resolves
core2 from the git source instead of the yanked crates.io version.
2026-04-25 05:46:20 +03:00
Kurdistan Tech Ministry 45b58174c0 fix(readme): replace all GitHub links with Gitea/GitLab equivalents
GitHub repo was DMCA-taken-down. All links updated:
- Clone URL: github.com → git.pezkuwichain.io
- Badges: GitHub stats → GitLab equivalents via shields.io
- GitHub Pages rustdoc URLs → GitLab Pages (pezkuwichain.gitlab.io)
- getting-started.sh: raw.githubusercontent.com → gitlab.com raw
- Release badges pointing to dead GitHub release-registry → removed
- psvm, pezkuwi-fellows, mentor issues: github.com → git.pezkuwichain.io
- License section: lists all 4 licenses now present in the repo

Also updated license section to reflect all 4 licenses:
Apache-2.0, GPL-3.0-or-later WITH Classpath-exception-2.0, MIT-0, Unlicense
2026-04-25 02:31:30 +03:00
Kurdistan Tech Ministry 6ee99cc5ba fix(license): proper license compliance across the repository
Critical issues fixed:

1. Workspace Cargo.toml license: GPL-3.0-only → GPL-3.0-or-later WITH
   Classpath-exception-2.0 to match the SPDX-License-Identifier headers
   in 648 source files. These are legally distinct licenses — GPL-3.0-only
   prohibits use of future GPL versions; GPL-3.0-or-later WITH
   Classpath-exception-2.0 permits linking without contaminating linked
   code (critical for WASM runtime use case).

2. Add LICENSE-MIT0: 32 source files declare MIT-0 (pezframe examples)
   but no license text existed in the repository.

3. Add LICENSE-UNLICENSE: 9 source files declare Unlicense (penpal test
   runtime) but no license text existed.

4. Add SPDX-License-Identifier headers to 150 crate_placeholder source
   files. These crates explicitly declare Apache-2.0 in Cargo.toml but
   had no license headers in their .rs files.

5. Fix repository URL: GitHub URL was DMCA-taken-down; updated to
   git.pezkuwichain.io canonical URL.

Root cause of GitHub DMCA: inconsistent license declarations make it
ambiguous whether Apache-2.0 upstream code was properly attributed.
All four license texts (Apache-2.0, GPL-3, MIT-0, Unlicense) are now
present and every source file has a corresponding SPDX header.
2026-04-25 02:07:08 +03:00
Kurdistan Tech Ministry 9406efbcd6 Add LICENSE file for GitLab/GitHub license detection
Primary license is GPL-3.0-only per Cargo.toml workspace config.
LICENSE-GPL3 already existed; this adds the standard LICENSE filename
that repository hosting platforms use for automatic detection.
2026-04-25 01:57:58 +03:00
Kurdistan Tech Ministry c4d47da770 fix(ci): use git diff --quiet instead of git status for umbrella check
git status --porcelain also reports untracked files — cargo install zepter
writes .cargo/ inside the project dir on shared GitLab runners, causing
false positives. git diff --quiet only checks tracked file changes.
2026-04-25 01:37:12 +03:00
Kurdistan Tech Ministry 2bd0f4ce47 debug(ci): show changed files and diff in check-umbrella failure 2026-04-25 01:29:07 +03:00
Kurdistan Tech Ministry 3ac8a1bc80 fix(ci): use zepter run default to propagate umbrella features
'propagate-features' is not a valid zepter workflow. The correct workflow
is 'default' which runs propagate-feature --fix for workspace + umbrella.
Since check-zepter validates workspace cleanliness first, the workspace
step is a no-op — only umbrella feature lists get populated by Zepter.
2026-04-25 00:18:27 +03:00
Kurdistan Tech Ministry 2bbe41e97d fix(ci): complete umbrella check with zepter propagate-features
Generator intentionally emits empty feature lists (filled by Zepter).
Without running propagate-features after generate, diff always exists.
Add zepter run propagate-features step so check reflects actual state.
2026-04-24 23:59:59 +03:00
Kurdistan Tech Ministry 5d1cbbac15 Update Cargo.lock for arrayvec git patch 2026-04-24 23:36:18 +03:00
Kurdistan Tech Ministry 05c31c9ee9 Patch arrayvec 0.7.6 for wasm32v1-none compatibility
arrayvec 0.7.6 fails to compile on wasm32v1-none (Rust 1.87+):
- E0223: Self::Target/Self::IntoIter ambiguous due to Receiver trait
- char.rs: Ok/Err/Result not in scope (prelude not injected on target_os=none)

Fork at git.pezkuwichain.io/pezkuwichain/arrayvec fixes both issues.
2026-04-24 23:34:27 +03:00
Kurdistan Tech Ministry a88c024e38 fix(ci): taplo-format Cargo.toml after alloy/ruint version pins 2026-04-24 22:44:56 +03:00
Kurdistan Tech Ministry 1d69ab5416 fix(deps): pin alloy-eips, alloy-tx-macros, ruint to Rust 1.88-compatible versions
The wasm-builder creates an inner workspace (wbuild/) without a Cargo.lock,
causing it to resolve to latest alloy-eips 1.8.3 (requires Rust 1.91) and
ruint 1.18.0 (requires Rust 1.90). Pin to the same exact versions already
in Cargo.lock (alloy-eips/alloy-tx-macros =1.5.2, ruint =1.17.2).
2026-04-24 22:28:16 +03:00
Kurdistan Tech Ministry 4c465efba3 ci: fix cargo-target volume path (/var/cache → /cache)
/var/cache is not bind-mountable by Docker on VPS2 (filesystem restriction).
/cache is already a persistent volume and works correctly.
2026-04-24 17:41:13 +03:00
Kurdistan Tech Ministry b99f16f934 ci: route test jobs to self-hosted runner with persistent CARGO_TARGET_DIR
- Add tags: [pezkuwi-runner] to .test-base, wasm-check, test-doc
- Set CARGO_TARGET_DIR to /var/cache/cargo-target/<hash>/<job-name> on VPS2
- Hash is md5(Cargo.lock + rust-toolchain.toml) — auto-deletes old keys
- Set CARGO_HOME: /root/.cargo (persistent volume, skip GitLab cache upload)
- Disable GitLab registry cache for self-hosted jobs (cache: [])
- Fix basic-authorship doc test: mark as no_run (requires compiled WASM at runtime)
2026-04-24 17:24:34 +03:00
Kurdistan Tech Ministry 578190da50 ci: install wasm32v1-none target globally, migrate wasm-check to wasm32v1-none
wasm32-unknown-unknown with build-std=core,alloc on Rust >=1.88 now ships
a pre-built std in the sysroot, causing E0152 duplicate core lang items when
serde_core is compiled. Switching to wasm32v1-none (target_os=none, no sysroot
std) eliminates the conflict. Also fixes wasm-check getrandom compile_error
which only triggers on wasm*-unknown-unknown, not wasm32v1-none.
2026-04-24 00:59:18 +03:00
Kurdistan Tech Ministry 418c6c92d7 ci: remove stale target/ cache that caused E0152 duplicate lang item
target-main cache key doesn't invalidate on Cargo.lock changes, so
pre-fix serde_core compiled artifacts were restored into test builds,
reintroducing duplicate alloc lang items after the serde fork fix.
2026-04-23 19:34:59 +03:00
Kurdistan Tech Ministry f1f3f46e30 ci: increase clippy timeout to 2h and cache target/ for incremental speedup 2026-04-23 15:42:39 +03:00
Kurdistan Tech Ministry 9ada06798d ci: retrigger after serde cache warmup 2026-04-23 13:39:31 +03:00
Kurdistan Tech Ministry a58ad37b78 fix(deps): update serde fork - correct alloc extern guard for wasm32v1-none + std feature unification 2026-04-23 03:30:11 +03:00
Kurdistan Tech Ministry 7cf3b01bcb fix(deps): update serde fork to fix E0152 duplicate alloc lang item in std test builds 2026-04-23 02:06:01 +03:00
Kurdistan Tech Ministry 861dfbe195 ci: retrigger clippy with warm cache after welati rebuild 2026-04-22 22:48:06 +03:00
Kurdistan Tech Ministry 47699b592b style(welati): rustfmt reorder cfg-gated imports 2026-04-22 20:25:10 +03:00
Kurdistan Tech Ministry c61bccc9ae fix(welati): cfg-gate Currency and SaturatedConversion imports to avoid unused-import in benchmarks
clippy runs with --all-features (includes runtime-benchmarks) so the
#[cfg(not(feature = "runtime-benchmarks"))] block is excluded and the
imports appeared unused. check-try-runtime runs without runtime-benchmarks
so the block is included and the imports are required.
2026-04-22 20:16:25 +03:00
Kurdistan Tech Ministry 606b7d3021 fix(ci): prefix unused alice_reward with _ in pez-rewards tests 2026-04-22 17:59:47 +03:00
Kurdistan Tech Ministry 19d869f588 fix(ci): ignore RUSTSEC-2026-0104 (webpki CRL parsing panic)
Transitive dep via kube/rustls. We do not parse CRLs in our P2P/RPC stack.
Added to both deny.toml and check-audit.py ignore lists.
2026-04-22 16:59:38 +03:00
Kurdistan Tech Ministry a36393b9f2 fix(ci): fix missing trailing newlines in validator-pool files (fmt)
bash command substitution strips trailing newlines; restored them.
2026-04-22 16:40:31 +03:00
Kurdistan Tech Ministry 84ea4f042a fix(ci): remove unused imports in welati pallet, add license headers to validator-pool
welati/src/lib.rs: Currency and SaturatedConversion were unused (clippy -D warnings).
pezkuwi/pezpallets/validator-pool/src/*.rs: 5 files missing Apache-2.0 SPDX headers.
2026-04-22 16:33:53 +03:00
Kurdistan Tech Ministry d98dfafc49 fix(runtime): fix CreatePresaleOrigin type mismatch in asset-hub runtime
EnsureRoot::Success = () but presale pallet requires Success = AccountId.
Switch to EnsureSigned<AccountId> so the transaction signer becomes
the presale owner — consistent with mock.rs and pallet semantics.
2026-04-22 07:52:07 +03:00
Kurdistan Tech Ministry 9d5b101fd7 fix(ci): fix check-zepter PATH and cargo-audit pipefail
check-zepter: CARGO_HOME=$CI_PROJECT_DIR/.cargo but export used $HOME/.cargo/bin;
switched to $CARGO_HOME/bin so installed zepter 1.82.1 takes precedence.

cargo-audit: set -o pipefail caused the pipe to fail with cargo-audit's exit
code (1 when vulns exist) even when python check passed; redirect to file first.
2026-04-22 06:39:22 +03:00
Kurdistan Tech Ministry 482cbbb1f6 fix(ci): fix taplo formatting and skip .cargo dir in workspace check
taplo.toml and deny.toml were using 2-space indent; taplo requires tabs.
check-workspace.py now skips .cargo the same way it skips target/ —
prevents 1000+ registry crates from being flagged as missing from workspace
when GitLab cache restores .cargo into the project directory.
2026-04-22 05:06:44 +03:00
Kurdistan Tech Ministry 99be20ba05 fix(ci): fix check-toml-format, check-licenses-headers, check-zepter
- taplo.toml: add .cargo/** to exclude list (prevents scanning cached registry files)
- deny.toml: reformat with taplo (tab indentation, proper spacing)
- pezpallets: add Apache-2.0 SPDX license header to 51 files missing headers
  (referral, trust, perwerde, pez-treasury, pez-rewards, welati, token-wrapper,
   messaging, staking-score, presale, identity-kyc)
- ci: check-zepter: prepend $HOME/.cargo/bin to PATH after cargo install
  so newly installed 1.82.1 takes precedence over system 1.78.2
- identity-kyc: fix clippy::needless_borrows_for_generic_args at lib.rs:326
2026-04-22 04:52:25 +03:00
Kurdistan Tech Ministry 857b63130d fix(ci): fix YAML syntax error — move audit python script to .gitlab/check-audit.py 2026-04-22 03:56:46 +03:00
Kurdistan Tech Ministry a2a37dca32 fix(ci): fix all cargo-deny and cargo-audit failures
- deny.toml: add all-features=true to [graph] — prevents krates 0.20+ panic
  on workspace crates that have std feature but don't enable it by default
- deny.toml: allow pezkuwichain/serde.git in [sources] (our wasm32v1-none fork)
- deny.toml: remove stale RUSTSEC ignores (2023-0071, 2024-0428, 2025-0055)
- deny.toml: add new wasmtime/rand/webpki advisories to ignore list
- ci: remove --exclude flag from cargo-deny jobs (flag removed in new versions)
- ci: rewrite cargo-audit to use JSON + python summary (prevents 4MB log overflow)
  and add all current advisories to ignore set with documented rationale
- ci: fix check-zepter to use --force (not --locked) so 1.82.1 actually installs
- Cargo.toml: add default=[std] to bizinikiwi-test-runtime-transaction-pool
  (std crate that was missing default feature, confusing krates graph builder)
2026-04-22 03:06:35 +03:00
Kurdistan Tech Ministry cfbde6de5a fix(ci): pass both --exclude paths to single flag (nargs=* overwrites on repeated use) 2026-04-22 01:29:52 +03:00
Kurdistan Tech Ministry 5b898402ad docs: fix all domain URLs — pezkuwichain.app → pezkuwichain.io, app link → app.pezkuwichain.io 2026-04-22 00:10:20 +03:00
Kurdistan Tech Ministry 1ca19e0956 ci: fix all failing jobs — upgrade cargo-deny/audit, fix CARGO_HOME, zepter version, mdbook image 2026-04-22 00:01:47 +03:00
pezkuwichain 0254a8ad3e ci: add Runtime Upgrade MR template 2026-04-21 20:28:22 +00:00
pezkuwichain ebecc350f9 ci: add Default MR template 2026-04-21 20:28:20 +00:00
pezkuwichain c0b0c371f5 ci: add Security issue template 2026-04-21 20:28:04 +00:00
pezkuwichain dc59853fe9 ci: add Feature Request issue template 2026-04-21 20:28:03 +00:00
pezkuwichain 04852535c6 ci: add Bug Report issue template 2026-04-21 20:28:02 +00:00
pezkuwichain 287fbfbcd2 docs: add DEVELOPMENT.md contributor setup guide 2026-04-21 20:27:35 +00:00
pezkuwichain 18d57b8e0c docs: add CODEOWNERS 2026-04-21 20:27:08 +00:00
pezkuwichain aa87740810 docs: add CHANGELOG.md 2026-04-21 20:26:51 +00:00
pezkuwichain b717fa5556 docs: add SECURITY.md — vulnerability disclosure policy 2026-04-21 20:26:11 +00:00
Kurdistan Tech Ministry 7caf11b2d2 ci: professional pipeline — unified image, nextest partitions, docs, schedules 2026-04-21 23:20:17 +03:00
Kurdistan Tech Ministry 4e6079fb47 ci: add GitLab CI pipeline with protobuf-compiler fix 2026-04-21 22:54:24 +03:00
pezkuwichain cc86ff5f2b security: remove AI tooling files — CLAUDE.md, .claude/ 2026-04-21 19:20:23 +02:00
pezkuwichain cb0ac10df2 security: ignore internal rebranding and operational scripts 2026-04-21 16:32:55 +00:00
pezkuwichain 6f61b89beb docs: remove local filesystem paths from runtimes-pallets.md 2026-04-21 16:31:49 +00:00
Kurdistan Tech Ministry 787efa3cce fix(security): update vulnerable dependencies, clean up deny.toml
Cargo.lock updates (cargo update):
- tar 0.4.44 -> 0.4.45 (RUSTSEC-2026-0067, RUSTSEC-2026-0068)
- rustls-webpki 0.103.9 -> 0.103.11 (RUSTSEC-2026-0049)
- tracing-subscriber 0.3.22 -> 0.3.23
- yamux 0.13.8 -> 0.13.10 (RUSTSEC-2024-0428 for 0.13.x branch)

deny.toml: remove fixed advisory ignores, add accurate tracking comments

Remaining known issues (cannot fix without toolchain/vendor upgrade):
- wasmtime 37.x: fix in 42.x requires rustc 1.91 (pinned to 1.88)
- yamux 0.12.1: locked by libp2p-yamux 0.47.0 in zombienet vendor
2026-04-14 00:15:21 +03:00
Kurdistan Tech Ministry a683b836fe chore: repo cleanup and security hardening
- Remove stale root files: chain_spec.json, pezkuwi.gbp, publish.log,
  test-asset-hub.toml (moved to .claude/)
- Move publish_batch.sh and publish_crates.sh to scripts/
- Remove hardcoded /home/mamostehp/res/ paths from scripts and comments
  (WALLETS_FILE env var now required, no silent fallback)
- Update .gitignore: add protection entries for regenerable artifacts
  and .claude/ experience files
2026-04-13 21:30:38 +03:00
Kurdistan Tech Ministry f82546fdb1 chore: add license files and attribution notice for Apache-2.0 compliance
- Add LICENSE-APACHE (Apache License 2.0 full text)
- Add LICENSE-GPL3 (GNU GPL 3.0 full text)
- Add NOTICE file with full attribution to original Polkadot SDK,
  Parity Technologies (UK) Ltd., and Web3 Foundation, documenting
  all significant changes made as required by Apache-2.0 Section 4(b)
- Update README License section to accurately reflect dual licensing
  and link to NOTICE file
2026-04-10 15:59:29 +03:00
Kurdistan Tech Ministry a0607b420c fix(security): add missing advisory ignores for cargo-audit + cargo-deny
Re-add RUSTSEC-2023-0071 (rsa) and RUSTSEC-2025-0055 (tracing-subscriber)
which were incorrectly removed — they are still in transitive deps.

Add new advisories:
- RUSTSEC-2026-0067 (tar symlink traversal) — no 0.4.x patch available
- RUSTSEC-2026-0068 (tar link following) — no 0.4.x patch available
2026-03-28 15:47:09 +03:00
Kurdistan Tech Ministry fd197ae78f fix: presale benchmark missing args + security audit advisory cleanup
- Fix refund_cancelled_presale benchmark: add missing start_index and
  batch_size arguments (0, 100) to match the 3-param extrinsic signature
- Remove 3 stale RUSTSEC advisories from deny.toml and security-audit.yml
  (RUSTSEC-2023-0071, RUSTSEC-2025-0055, RUSTSEC-2026-0002 no longer in deps)
- Add RUSTSEC-2026-0049 (rustls-webpki) to ignore lists (upstream kube/jsonrpsee
  haven't released compatible versions yet)
2026-03-27 09:34:47 +03:00
Kurdistan Tech Ministry 894617563a fix: default version=0.0.0 in generate-umbrella.py 2026-03-22 20:27:18 +03:00
Kurdistan Tech Ministry b27c12d306 fix(ci): add missing version field to umbrella Cargo.toml 2026-03-22 20:26:48 +03:00
Kurdistan Tech Ministry 9f4c9b4d19 style: fix formatting, regenerate umbrella, taplo format 2026-03-22 20:17:58 +03:00
Kurdistan Tech Ministry 288978c088 fix(security): audit fixes across 9 custom pallets
- pez-rewards: checked arithmetic in parliamentary reward distribution
- tiki: saturating_add in get_tiki_score fold, benchmarking cleanup
- ping: saturating_add on PingCount
- staking-score: saturating_mul on 4 duration multipliers
- pez-treasury: proper error on TreasuryStartBlock None, saturating_add on NextReleaseMonth, doc fix 70->75%
- messaging: InboxOverflow event on FIFO eviction
- token-wrapper: reorder wrap/unwrap operations, add pallet balance pre-check
- welati: u64 cast for turnout percentage overflow prevention
- presale: fix refund calculation to use net_in_treasury (98%) instead of impossible 99%, update tests
2026-03-22 18:56:37 +03:00
Kurdistan Tech Ministry ad9204cab1 fix(security): address HIGH audit findings across 5 pallets
identity-kyc (H1):
- Add IdentityHashToAccount reverse mapping to prevent same identity hash
  being used by multiple accounts
- Check uniqueness in apply_for_citizenship, populate on confirm_citizenship,
  clean up on renounce_citizenship

pez-rewards (H2):
- Add EpochTotalClaimed storage to track claimed amounts per epoch
- do_close_epoch now only claws back unclaimed rewards (total_allocated -
  total_claimed), not the entire pot balance

tiki (H3):
- Replace custom "locked" attribute with pezpallet_nfts::disable_transfer()
  which sets the system-level PalletAttributes::TransferDisabled attribute
  that is actually enforced during transfers

tiki (H4):
- Fix EnsureTiki to check UserTikis storage for non-unique roles (Wezir,
  Parlementer) instead of TikiHolder which only stores unique roles

perwerde (H5):
- Add MaxPointsPerCourse config constant (1000 in runtime)
- Validate points in complete_course against the max
- Use saturating_add in get_perwerde_score to prevent u32 overflow

welati (H6):
- Add NativeCurrency: ReservableCurrency to Config
- Actually reserve candidacy deposit from candidate's balance

welati (H7):
- Add MaxEndorsers config constant (1000 in runtime)
- Validate endorsers count at the start of register_candidate before
  any storage reads
2026-03-21 21:58:24 +03:00
Kurdistan Tech Ministry 741a65416a fix(security): address remaining CRITICAL audit findings
presale:
- C2: Convert refund_cancelled_presale to batch pattern (start_index, batch_size)
  to prevent unbounded iteration with many contributors
- C3: Add status validation to cancel_presale — prevent cancelling Finalized/Failed
  presales (prevents double-dipping: tokens distributed + refund issued)
- C4: Enforce CreatePresaleOrigin (was defined in Config but never checked)
  Changed to Success = AccountId for proper owner extraction
- Clarified presale_account_id expect() safety comment (Blake2_256 = 32 bytes,
  always sufficient for AccountId decode)
- Removed unused imports (Defensive, AccountIdConversion)

perwerde:
- C5: Prevent NextCourseId overflow — added ensure!(< u32::MAX) check and
  replaced unchecked += 1 with saturating_add

welati:
- C6: Enforce access control on all CollectiveDecisionType variants:
  ConstitutionalReview/Unanimous → Diwan members only
  ExecutiveDecision → Serok only
  HybridDecision → Parliament OR Serok
  VetoOverride → Parliament members only
2026-03-21 21:23:43 +03:00
Kurdistan Tech Ministry f1a7a7f872 fix(security): address critical audit findings in presale and validator-pool pallets
presale:
- Split unbounded finalize_presale distribution into batched batch_distribute()
  extrinsic (same pattern as batch_refund_failed_presale) to prevent block weight
  exhaustion with many contributors
- Fix u128 overflow in calculate_reward_dynamic() by using
  multiply_by_rational_with_rounding() for safe intermediate multiplication
- Fix pre-existing batch_refund test assertion (platform fee deduction was not
  accounted for in expected refund amount)

validator-pool:
- Bound PoolMembers::iter() with .take(MaxPoolSize) in select_validators_for_era()
  to prevent unbounded iteration in on_initialize
- Fix on_initialize weight accounting to include all DB reads/writes from
  do_new_era() and select_validators_for_era() (was only counting 2 reads)
2026-03-21 15:33:25 +03:00
Kurdistan Tech Ministry 420ed35169 feat: add weights, benchmarking, mock and tests for ping and teyrchain-info pallets
- ping: weights.rs (WeightInfo trait + implementations), benchmarking.rs
  (v2-style benchmarks for start/start_many/stop/stop_all), mock.rs
  (test runtime with MockXcmSender), tests.rs (26 tests covering all extrinsics)
- teyrchain-info: mock.rs (minimal test runtime), tests.rs (7 tests for
  genesis config and ParaId getter)
- Updated ping lib.rs to use WeightInfo instead of zero weights
- Added WeightInfo = () to testing runtime Config
2026-03-21 15:19:47 +03:00
Kurdistan Tech Ministry 66a4bfa86b fix(ci): trailing slash in debug Dockerfile COPY, make build-rustdoc non-blocking 2026-03-20 18:35:20 +03:00
Kurdistan Tech Ministry a525696e16 fix(docker): add trailing slash to COPY destination in malus Dockerfile 2026-03-19 18:46:53 +03:00