Free

ترك Claude ينشر إلى الإنتاج

أخطاء النشر بلا أعراض. أربعة حواجز — ملفات credentials منفصلة، سكربتات EDITOR، تحقق بالقراءة، تبديل env وقت التشغيل — لاستخدام Claude دون أن يحرق كل شيء.


الفرق الأكبر بين النشر وكتابة الكود: النشر ضربة واحدة، ومخاطره عالية، والرجوع عنه مؤلم. اكتب سطراً معطوباً من الكود، يلتقطه اختبار واحد. اكتب سطراً معطوباً من الـ credentials، لن تعلم إلا عند فشل أول دفعة حقيقية — المستخدمون دفعوا من بطاقاتهم، المال لم يصل إلى حسابك، السجلات كلها 400.

مؤخراً أخذت how2claude من التطوير المحلي إلى الإنتاج مع Claude: حساب Stripe live، محفظة x402 mainnet، Google OAuth، Kamal secrets. Claude لا يعرف أي القيم للاختبار وأيها حقيقية. لا يعرف أن sk_live_ مقابل sk_test_ فرقٌ من حرف واحد بعواقب نهاية العالم. الحواجز تبنيها أنت.

الحاجز #1: ملفات credentials منفصلة لـ dev و prod

Rails يأتي افتراضياً بـ config/credentials.yml.enc، يُفَك بـ config/master.key. إن استخدمت هذا الافتراضي فقد خسرت.

إن وضعت sk_live_xxx في هذا الملف ثم شغّلت الاختبارات محلياً، فكود الاختبار لديك يستخدم Stripe الإنتاج. كل تشغيلة اختبار تسحب من بطاقة حقيقية.

اقسم إلى اثنين:
- config/credentials.yml.enc + config/master.key: dev/test، يحمل sk_test_xxx
- config/credentials/production.yml.enc + config/credentials/production.key: prod، يحمل sk_live_xxx

كلا ملفَّي .key في .gitignore، وكلا .enc يُرفعان. production.key يعيش فقط على آلة النشر.

ثم يجب أن تشير Kamal secrets إلى الملف الصحيح:

 # .kamal/secrets
-RAILS_MASTER_KEY=$(cat config/master.key)
+RAILS_MASTER_KEY=$(cat config/credentials/production.key)

داخل الحاوية، RAILS_MASTER_KEY يشير الآن إلى مفتاح الإنتاج، وما يُفَك هو credentials الإنتاج. راقبت Claude وهو يكتب هذا السطر — قالب Kamal الافتراضي هو config/master.key (الخاص بـ dev)، الذي ينشر بصمت مفتاح Stripe الخاص بـ dev إلى الإنتاج.

الحاجز #2: استخدم سكربت EDITOR، لا نسخ ولصق

bin/rails credentials:edit --environment production يفتح محرراً تفاعلياً. Claude لا يستطيع قيادة محرر تفاعلي. ولا ترغب أنت أيضاً بلصق عشرات الأسرار يدوياً (خطأ مطبعي واحد يُسقط كل شيء).

استخدم هذا النمط:

EDITOR="ruby script/set_prod_webhook_secret.rb" \
  bin/rails credentials:edit --environment production
rm script/set_prod_webhook_secret.rb

script/set_prod_webhook_secret.rb يبدو هكذا:

# ARGV[0] هو مسار ملف YAML المؤقت المفكوك
file = ARGV[0]
require "yaml"
data = YAML.load_file(file) || {}
data["stripe"] ||= {}
data["stripe"]["webhook_secret"] = "whsec_GHWObNAKFh2HPOlJpbGmlYfIiKz1C8EY"
File.write(file, data.to_yaml)

Rails يكتب الـ YAML المفكوك إلى ملف مؤقت، ويستدعي "EDITOR" الخاص بك ممرراً المسار كوسيطة، ثم يعيد التشفير عند الخروج. "EDITOR" الخاص بك هو مجرد سكربت Ruby يعدّل مفتاحاً واحداً جراحياً ويحفظ.

لماذا هو جيد:
- دقيق: يلمس stripe.webhook_secret فقط، لا شيء آخر.
- مكرر بلا أثر: تشغيله مرتين كتشغيله مرة.
- قابل للتدقيق: السكربت هو الـ diff. يكتبه Claude، تلقي نظرة، فتعرف بالضبط ما سيتغير.
- يختفي عند الحذف: بعد rm، لا credential نص عادي على القرص، ولا لصق whsec_... في سجل الـ shell.

سكربت لكل credential: set_stripe_live_key.rb, set_webhook_secret.rb, set_price_ids.rb, set_wallet_address.rb. rm كلٌّ منها مباشرةً بعدها.

الحاجز #3: تحقق بإعادة القراءة عبر Rails runner

بعد الكتابة، لا تثق بأنه كتب بشكل صحيح. اقرأ ثانيةً:

bin/rails runner -e production "
c = Rails.application.credentials
puts 'sk_live set: ' + c.dig(:stripe, :secret_key).to_s.start_with?('sk_live_').to_s
puts 'webhook_secret set: ' + c.dig(:stripe, :webhook_secret).to_s.start_with?('whsec_').to_s
puts 'wallet prefix: ' + c.dig(:x402, :wallet_address).to_s[0..5]
puts 'wallet len: ' + c.dig(:x402, :wallet_address).to_s.length.to_s
"

المهم فحص البادئة والطول، لا مجرد طباعة القيم.

  • الـ Stripe live secret تبدأ دائماً بالبادئة sk_live_. إن قرأت ثانيةً sk_test_، فـ Claude وضع test key في ملف prod — خطأ لن تكتشفه قبل أول دفعة حقيقية.
  • الـ Webhook secrets تبدأ دائماً بـ whsec_. صحة الصيغة بلمحة.
  • عناوين محافظ EVM دائماً 42 حرفاً، 0x.... طول خاطئ يعني أن حرفاً آخر تسلل.

إضافة فحوص البادئة تحجب معظم الأخطاء المطبعية، الحقول الناقصة، والبيئات المختلطة.

الحاجز #4: قلّب في زمن التشغيل بحسب env، لا يدوياً عند النشر

من المغري التفكير بـ "سأغيّر الشبكة إلى mainnet قبل النشر". مثل هذا التبديل يعتمد على الذاكرة البشرية، وعاجلاً أم آجلاً سيحرقك.

اخبز القاعدة في الـ initializer:

# config/initializers/x402.rb
X402.configure do |c|
  c.wallet_address = Rails.application.credentials.dig(:x402, :wallet_address)
  c.chain = Rails.env.production? ? "base" : "base-sepolia"
end

الكود نفسه، testnet (sepolia) في dev، mainnet (base) في prod. لا شيء يتغيّر عند النشر. Claude لا يستطيع "نسيان التبديل" لأن التبديل ليس عمله.

نفس الحيلة لـ basescan_tx_url، لرؤية الخطط (الخطط الخاصة بـ dev لا تُعرض في prod)، لاختيار Stripe price ID، وهكذا. أي شيء يختلف بين dev و prod، قلّبه بـ Rails.env. لا تعتمد على التذكر وقت النشر.

الخطوة الأخيرة: سر أنت على التدفق الحقيقي

بعد تركيب الحواجز الأربعة، يبقى عليك أن تضغط على زر الدفع الحقيقي بنفسك أول مرة.

في المقال السابق تصحيح الأخطاء الصامتة مع Claude، وصفت أول نقرة دفع x402 في الإنتاج: invalid_string at payTo في الـ console. الحرف الـ43 من عنوان المحفظة كان علامة استفهام بالعرض الكامل تسللت من IME صيني. فحوص البادئة لم تلتقطها (الـ 0x لا يزال هناك)، الاختبارات لم تلتقطها (الاختبارات لا تُطلق معاملات حقيقية)، ولم يُظهرها إلا نقرة حقيقية.

حواجز النشر ليست لأجل Claude. هي لأجلك — أتمت ما يمكن أتمتته (البوادئ، الأطوال، تبديلات env) ليذهب الانتباه الذي توفره إلى التفاعلات الحقيقية التي لا تغطيها الأتمتة.


التدفق الكامل لـ Claude-deploy:

  1. افصل credentials بين dev و prod في ملفات .enc + .key منفصلة.
  2. لكل قيمة تريد ضبطها، اكتب سكربت Ruby لمرة واحدة، غذِّه عبر EDITOR=script، احذفه فوراً.
  3. بعد كل كتابة، اقرأ ثانيةً بـ Rails runner، تحقق من البوادئ والأطوال.
  4. قلّب كل فروق dev/prod عبر Rails.env، لا عند النشر.
  5. اضغط على زر الأموال الحقيقية بنفسك أول مرة.

النشر ليس "كتابة الكود برهانات أعلى". النشر هو "كتابة الكود حيث لا أحد يخبرك أنك مخطئ". الحواجز موجودة لتحويل "لا أحد يخبرك" إلى "تعرف خلال 15 ثانية".