-
WEB3_STRICT_MODE=true — the Hadron stub raises on missing credentials in prod REGARDLESS of the flag [INF.11 harden 2026-07-10: Rails.env.production? || STRICT_MODE, BOTH methods — KYC check + RWA asset-registration; call-time lazy, NOT at boot] + the oracle-callback HMAC fail-fast (SEC.5; audit §04 2026-07-04: oracle_callbacks+helium_sos HMAC now ALSO fail-closed in prod regardless of the flag — Rails.env.production? || STRICT_MODE, mirroring IoTeX below — the old comment claimed "blocks prod" but code only blocked under STRICT_MODE). Chainlink dispatch is NOT strict-gated anymore [ARCH.53 demote]: Chainlink::OracleDispatchService = local correlation-marker (no RPC, no credentials; a spec pins "never touches RpcConnectionPool"); PATH 1 callback never arrives (DON unwired; closure REFUSED — founder 2026-07-19, ARCH.53 archived §🗄️, superseded by Merkle-lineage ARCH.12/MRV.1) → the live mint is PATH 2 tokenomics (L0-custodial + ex-post clawback, canon 05_02 trust-origin). Other nuances: IoTeX SHA256-fallback is banned in ANY production env (Rails.env.production? || STRICT_MODE — OR, so prod raises even with STRICT_MODE=false); Solana has no stub mode — signing credentials (WALLET_KEYPAIR, FEE_PAYER_PUBKEY, USDC_MINT_ADDRESS) raise unconditionally if blank; SOLANA_RPC_URL falls back to Devnet (a real endpoint) in non-production rather than raising. None of this is gated by STRICT_MODE. Dev/test stubs Hadron by default. [2026-07-12 SEC.1-нора] the signer-boot guard now ALSO presence-checks the Solana four-var set + the silent-address set (DAO_TREASURY_ADDRESS/SCC/SFC — their read-sites swallow config bugs under RPC-rescue umbrellas: tax silently off, chain-audit false "clean", fallback price) — Web3NetworkGuard.address_violations/solana_violations, canon 04_02 §8.
-
manual_review state — BlockchainTransaction AASM has a manual_review state = DOUBLE-SPEND GUARD. tx_hash exists but outcome unknown → funds locked until manual check. Don't auto-resolve.
-
batchMint Binary Search — on dry-run revert, BlockchainMintingService bisects the batch to isolate poisoned records (MAX_DEPTH=6). Don't bypass the dry-run step. [E.60 Фаза 1б, 2026-07-19] mint/batchMint тепер 4-арг (+bytes32 archiveRoot, симетрично SCC+SFC — один ABI): transact-цикл іде per-archive_batch-підгрупою («один виклик = один root»; bisect У МЕЖАХ підгрупи), root = mint-anchored батч (Mrv::TelemetryArchiveBatchService, set-once tx.archive_batch_id); zero32 = «без witness-клейму» (windowless/fail-open), НЕ «порожньо». Батч-стани (mismatch/superseded/…) живуть на TelemetryArchiveBatch — НЕ на tx-AASM, money-периметр недоторканий. One-Home механіки = 05_02 §E.60; runbook = 06_08 §4.7.
-
Dynamic Tax — default 2% to DAO_TREASURY when DAO-treasury balance < threshold (default 100,000 SCC), checked at mint time. [S6.17] Rate AND threshold are governance-aware via SystemParameter ← on-chain ProtocolParameters.sol (NOT hardcoded). Only batchMint applies it — single mint() does not. Failsafe on RPC error = false (don't tax during degradation). [2026-07-04] Tax is aggregated into ONE DAO_TREASURY array entry per batch (N+1), not one per tx (2N) — OPTIMAL_BATCH_SIZE == on-chain MAX_BATCH_SIZE == 100, and tax is ON from genesis (treasury=0<100k), so the old 2N would revert any carbon batch >50 tx from day one. Keep the aggregation if you edit build_batch_arrays. The tax is an OFF-CHAIN split (backend builds the array); the SCC contract has no tax logic.
-
Solana reward formula — 10,000 + growth_points * 100 lamports. ATA resolved via getTokenAccountsByOwner. Ed25519 signing (not secp256k1).
-
Partition-aware BlockchainTransaction — RANGE partitioned. Use find_with_partition_pruning(id, created_at).
-
Solana batch payouts [E.61] — when solana_batch_threshold_usdc (SystemParameter) > 0, SolanaMicroRewardWorker accumulates rewards per-wallet in Kredis instead of sending per-event; hourly SolanaBatchPayoutWorker pays the lot via transferChecked. Threshold 0 → per-event (default). Rationale: docs/05_01 §8.
-
Slashing fires ONLY on positive Cat-A [SLASH-1 §3.2] — irreversible slash() (BlockchainBurningService) needs DIRECT tamper proof (Slashing::CauseEvidence#positive_a?); absent → :frozen + Field Audit (Cat-C default), NOT a burn. vandalism_breach has NO auto-writer: wire status=3 = vm_error→firmware_fault (software fault, NOT tamper — mruby returns 0..2; the real chainsaw rides panic→chainsaw_detected); it's created only by manual Field-Audit C→A escalation (06_08 §4.6) → auto-slash is freeze-only until the A-set gains a validated source (gate wired, honestly-empty). Don't fire slash on indirect signals. Decode / A-set / widening → 05_05 §3.2 + 00_07 SLASH-1.
-
Slashing penalty de-correlation [SLASH-1 §6] — penalty_factor uplift (#calculate_penalty_factor) combines correlated comms-signals via max(), NOT sum; independent negligence is additive. INERT behind SystemParameter :slash_cause_uplift_enabled (default off). ⚠️ Predicate asymmetry (know which you touch): comms_no_ack? = whitelist (a new type never joins), critical_unmaintained? = blacklist (every new critical type is IN by default → answer the blacklist question when adding one). Machine-latched signals (the machine creates+resolves them → read as negligence forever) are all routed through EwsAlert.escalate_field_audit! (One-Home dedup, partial-unique per cluster; all 5 sites). Full asymmetry rationale + machine-latch policy → 05_05 §6 + 00_07 SLASH-1.
-
Money-path idempotency [ARCH.45/48/50/51/64/65] — persist the :pending intent-marker BEFORE the on-chain transact (else a crash/retry double-acts); a recent-window guard then reconciles on-chain, never blind re-pay/re-slash. unsettled_within treats :manual_review as age-unbounded (an ambiguous escalation must block re-fire FOREVER — else the daily cron re-fires past the 2h/7d window = deterministic double-burn/pay, a calendar bug not a race). On-chain :not_found ≠ authoritative (RPC lag) → escalate :manual_review. TOCTOU burn-guard = non-blocking Kredis.lock claim (slash:claim:{id}; Rails.cache/unique_for were rejected — SolidCache unless_exist is not atomic for an absent row, unique_for = Enterprise shim no-op). ⚠️ EVM-mint is NOT intent-marker'd: the batch paths filter :pending, but BlockchainMintingService#initialize filters .where.not(status: :confirmed) — so a DIRECT .call([id]) on a recovered :sent/:processing orphan CAN re-mint (crash-orphans are swept → :manual_review, never blind re-mint). Self-masking (a dedup-skip on retry makes the job report "success", DeadSet silent) = the worst class → per-worker recovery matrix (Celo/Hadron/Filecoin reconcile crons; ask each money-worker: retries_exhausted-hook? cron? intent-marker? — none = candidate hole). Mechanics / per-instance ARCH.* → 04_02 §4/§10 + 00_07 ARCH.* + §🗄️.
-
Governance read-path is LIVE [GOV.1 2026-07-04] — the whole economic set is DAO-live via SystemParameter ← ProtocolParameters.sol: TokenomicsEvaluatorWorker.emission_threshold (One-Home reader — selector + EvaluateTreeBatchWorker conversion + OracleVisions; MintingRollbackService legacy-fallback deliberately stays on the constant), AiInsight.slash_stress_threshold (shared trigger+damage-sizing, ARCH.46), the slash_threshold fraction in ContractHealthCheckService (Rational(v.to_s) keeps Rational(1,5) exactness), slash_gamma/slash_penalty_factor_max, scc_per_tonne_co2, scc_fallback_price_usd. ParameterSyncWorker syncs the economic keys with bounds-reject (out-of-bounds vote → previous value stays + ERROR log + silkennet_governance_param_rejected_total); the 8 Lorenz keys are DCI-locked — NOT synced, NOT seeded, tripwire-WARN if voted (FW.7 bit-parity). [GOV.2 2026-07-17] the whole bridge is keccak-STRING equality, so scripts/governance_key_sync.rb (HARD docs.yml) pins it: KEY_LORENZ_* ⟷ DCI_LOCKED_KEYS and the remaining KEY_* ⟷ PARAMETER_MAP, compared as SEPARATE sets — a Lorenz key MOVED into the sync map leaves a union check green while handing governance the FW.7-parity lever. Adding an economic parameter = edit BOTH sides or CI goes red (by design); the economic COUNT is deliberately unpinned (it grows legitimately — a pinned tally would flag every honest addition). [GOV.3 2026-07-17] the sibling gate scripts/governance_bounds_sync.rb pins the OTHER axis of the same worker mirror — the min/max/value_type/category the 9 synced keys write MUST match their db/seeds.rb defaults (canon 05_06 §7 "One-Home меж = PARAMETER_MAP ↔ db/seeds.rb"; the review-caught E.64 stress_threshold 0.5-seed-vs-0.65-map drift class). Directional PARAMETER_MAP ⊆ seeds — a synced key with no seed default is also caught (SystemParameter.current nil-until-first-sync → hardcoded fallback). Canon: docs/05_06 §7 + 00_06 §3.
-
Mint KYC-gate = BENEFICIARY status [KYC.1 2026-07-04] — Wallet#kyc_approved_for_minting?: own crypto_public_address → own hadron_kyc_status; custodial (no own address, mints to the org address) → inherits organizations.hadron_kyc_status. Guard does per-tx SKIP (S2), tx stays :pending. Approval path: binding/changing the address (Wallet OR Organization) → after_commit → HadronKycVerificationWorker (dev/no-key = simulate-approve; prod strict = real API); an address CHANGE resets the status to pending (KYC attaches to the address). Institutional-only narrowing was REJECTED by the founder (it would weaken the only live PATH 2 guard pre-clawback).
-
Every BlockchainTransaction status change enqueues AuditLogWorker [MRV.1 2026-07-04; hook re-based ARCH.57 2026-07-13] — tamper-evident per-org hash-chain trail (actor = oracle_executioner; skipped with a WARN when the system user/org is absent). The hook is after_update_commit if: :saved_change_to_status?, NOT AASM after_all_transitions — the AASM callback fires PRE-persistence (phantom row on rollback: the Sidekiq push doesn't roll back) and misses raw update! writes; event-name is preserved with a freshness-guard, fallback = blockchain_tx_to_<state>. Spec implication: tests counting Sidekiq jobs around money transitions must account for it. Wallet#destroy ABORTS while settled/in-flight tx exist (guard_mrv_evidence!, prepend: true); a permitted destroy (empty/pending-only wallet) now NULLIFIES tx rows instead of deleting them (dependent: :nullify [ARCH.57] — orphan rows are valid by design). Slash VERDICTS (burn/frozen/evasion + cause/ratios) also write chain-only audit rows from BlockchainBurningService [ARCH.57]; the IPFS/Filecoin outbox perimeter stays money-tx-transitions-only (archive flag on record_async!). [2026-07-11 MRV.1] org resolves wallet&.organization_id || cluster&.organization_id — cluster-sourced money (celo reward + last-tree slash, wallet=nil, org via cluster) previously wrote ZERO audit-row (the MOST material moves); fix + regression-spec both families.
-
slashUpTo(investor, maxAmount, bytes32 contextHash) [SLASH.2 + CONTRACT.1] — the live burn path (atomic clamp to balanceOf; full pre-slash drain → escalate_evasion!, no doomed revert-tx). contextHash = bytes32(intent BlockchainTransaction.id) — the subgraph attributes the on-chain event straight to the backend intent; manual DAO/Timelock slash() emits bytes32(0). Events TokenSlashed/GovernanceSlashed carry the field. Incident/one-shot procedures (reorg, rogue-MINTER, key compromise, manual_review console recipe, deploy-smoke, pause) → docs/06_08 §4.
-
Money-path aggregate stop-loss [ARCH.62 + INS.2, 2026-07-06] — two inert-by-default (SystemParameter 0/false) systemic guards that complement per-tx guards + MAX_SUPPLY. [ARCH.62] Treasury::MonitorService (15-min pass) samples rolling-1h mint volume per token_type (gauge silkennet_mint_volume_window_scc) vs :mint_volume_hourly_max_scc; breach → deduped system_fault alert + per-token Kredis flag mint:circuit_broken:<token>. BlockchainMintingService reads it per token-group and HOLDS that token's batch as :pending (re-runnable next cycle, NOT escalated — a clean never-broadcast tx must not be orphaned in manual_review), fail-open on Redis error (money liveness > optional stop-loss). [INS.2] Insurance::ReserveGate gates Internal-mode insurance payouts (NOT Etherisc — external USDC) with a 24h aggregate correlated cap + reserve-adequacy (30d Internal-mint vs DAO_TREASURY balance × ratio); breach → HOLD manual_review, transient RPC (:eval_error) → raise (Sidekiq retry, not permanent park), current tx excluded (no double-count). One-Home Web3::Erc20Reader collapses the balanceOf ABI/fetch/cache (shared treasury cache-key dao_treasury_balance_wei → 1 RPC/window). All 4 thresholds are LOCAL SystemParameter (default 0/false, NOT on-chain ProtocolParameters-synced, ParameterSyncWorker skips them) — 👤 calibrates before arming. Canon: 05_02 §Модель довіри + 06_03 §2.8 + 07_01 §7.
-
Anchor confirmation-lifecycle [ARCH.66, 2026-07-07] — the weekly L1 state-root anchor is NO longer fire-and-forget. StateAnchorService#anchor_to_l1! enqueues EthereumAnchorConfirmationWorker.perform_in(30s, anchor.id) after :sent; the poller drives :sent→:confirmed (reorg-depth gate ETHEREUM_ANCHOR_MIN_CONFIRMATIONS=64 — finality, not first-receipt like the money path) / :failed (revert + ethereum_anchor_reverted_total) / retry (:pending), and on polling-exhaustion → escalate_to_review! (:manual_review). EthereumAnchor is plain enum (NOT AASM) — confirm!/mark_failed!/escalate_to_review! are with_lock+status_sent?-guarded (idempotent, transition ONLY from :sent; new status manual_review=4). NEVER blind re-broadcast a stuck anchor — nonce IS persisted (ethereum_anchors.nonce, written before transact) so resume re-broadcasts the SAME slot → replace/already known/nonce too low = ≤1 on-chain tx per anchor, never N+1 (contract's rootTimestamps[root]==0 + 6-day MIN_ANCHOR_INTERVAL also revert any dup); de-stuck = operator same-nonce gas-bump (console). StuckSentAnchorSweeperWorker (cron :40) only re-arms the poll READ-ONLY via EthereumAnchor.stuck_sent. detect_missed_anchor_weeks! counts [:confirmed] only (a live poller makes :sent transient → a stuck :sent must not mask the gap). stuck_sent_depth gauge sampled by Treasury::MonitorService (15-min). Activation gated on contract deploy (SEC.1) → both workers natural-inert pre-deploy. Companion nonce-persist + classify-escalate SHIPPED (F2a crash-window closed: node-rejection RpcError<IOError → escalate_pending_ambiguous!→:manual_review on resume, mirrors money-path AMBIGUOUS_PATTERNS). Canon: 05_04 §5.1.
-
Parametric insurance dual-trigger [INS.1] — a payout fires ONLY on TWO independent triggers: our AI stress_index arm_candidate! (:triggered, NOT a payout) + an INDEPENDENT confirmation (dClimate FIRMS :verified / human Field-Audit) via InsurancePayoutWorker#awaiting_independent_confirmation?. :rejected_fraud ≠ confirmation (paying on our own AI alone = moral-hazard; it once paid → simultaneous slash+payout). Non-fire perils (drought/pest) → Field-Audit, NEVER rejected_fraud. All behind kill-switch :parametric_insurance_oracle_enabled (default OFF, like slash_cause_uplift_enabled). Policy → 05_05 §4 + 00_07 INS.1.