[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6GYRYGRCN9MGPDVRWR76S0C":3,"skill-same:01M6GYRYGRCN9MGPDVRWR76S0C":79},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":16,"sourceHtmlUrl":17,"categories":18,"keywords":19,"publishedAt":37,"linkOnly":38,"markdownContent":39,"markdownBody":40,"frontMatter":41,"refName":42,"commitSha":43,"skillDirectory":44,"forksCount":45,"repositoryHtmlUrl":46,"repositoryHomepageUrl":6,"ownerHtmlUrl":47,"ownerBlogUrl":48,"ownerDescription":49,"updatedAt":50,"install":51,"resources":64},"01M6GYRYGRCN9MGPDVRWR76S0C","gate-destructive-plans-behind-approval",null,"Use when an apply can delete or replace resources in a shared environment. Routes plans that contain destroys to a human approval and keeps additive changes on auto-apply.","jiayaoqijia\u002Fcryptoskill","jiayaoqijia","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1453879?v=4","01M6GMYTX7Q7S504VC6E756ENR","YQ","01M6GMYV1QKJ1CC75MTTGT9PR0",81,"MIT","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-gate-destructive-plans-behind-approval\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-gate-destructive-plans-behind-approval\u002FSKILL.md",[],[20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],"approval","gate","gate destructive plans behind approval","plans","replace","delete","when","apply","changes","can","contain","resources","shared","human","auto","use","environment","2026-11-10 10:12:30",false,"---\nname: gate-destructive-plans-behind-approval\ndescription: Use when an apply can delete or replace resources in a shared environment. Routes plans that contain destroys to a human approval and keeps additive changes on auto-apply.\n---\n\n# Gate destructive plans behind approval\n\nAuto-apply is fine for additive changes and dangerous for destructive ones. Gate on the plan's content, not on the branch name.\n\n## Procedure\n\n1. In CI compute the destructive set before apply and expose it as an output:\n       COUNT=$(terraform show -json tf.plan | jq '[.resource_changes[]|select(.change.actions|index(\"delete\"))]|length')\n       echo \"destroys=$COUNT\" >> \"$GITHUB_OUTPUT\"\n2. Route `destroys > 0` to a manual approval environment; keep `destroys == 0` on auto-apply:\n       environment: ${{ steps.plan.outputs.destroys != '0' && 'prod-approval' || 'prod-auto' }}\n3. Require the approver to be a different identity than the apply author (four-eyes); a pipeline cannot approve its own plan.\n4. Attach the plan artefact and the destroy count to the approval so the approver reviews content, not a summary.\n5. Guard stateful resources at the code layer too: `lifecycle { prevent_destroy = true }`, so even an approved pipeline cannot drop a database without a code change.\n6. Expire approvals (24 h); an approval applied after unrelated commits is not approval of what runs.\n7. Log the approver identity and timestamp next to the plan hash for audit.\n8. Dry-run the gate on a branch that deletes a scratch resource before trusting it on prod.\n\n## Pitfalls\n\n- Approving on \"the pipeline is green\", when green includes the destroy.\n- A single environment with one approver who is also the author: four-eyes in name only.\n- Counting destroys from a plan regenerated after approval (a provider bump changes it).\n- No `prevent_destroy`, so the only thing between a typo and an empty prod database is a human reading a diff.\n- Approvals that never expire, applied days later on top of other merges.\n\n- The destroy count read from a plan generated before a `git pull`, so it does not match what is applied.\n- An approval environment without branch protection, so any collaborator can self-approve.\n\n## Verification\n\n    grep -q 'destroys=0' ci.outputs || echo \"manual approval required\"\n    terraform show -json tf.plan | jq '[.resource_changes[]|select(.change.actions|index(\"delete\"))|.address]'\n\nReport: the gate rule, the destroy count that tripped it, the approver identity, and the plan hash applied.\n","# Gate destructive plans behind approval\n\nAuto-apply is fine for additive changes and dangerous for destructive ones. Gate on the plan's content, not on the branch name.\n\n## Procedure\n\n1. In CI compute the destructive set before apply and expose it as an output:\n       COUNT=$(terraform show -json tf.plan | jq '[.resource_changes[]|select(.change.actions|index(\"delete\"))]|length')\n       echo \"destroys=$COUNT\" >> \"$GITHUB_OUTPUT\"\n2. Route `destroys > 0` to a manual approval environment; keep `destroys == 0` on auto-apply:\n       environment: ${{ steps.plan.outputs.destroys != '0' && 'prod-approval' || 'prod-auto' }}\n3. Require the approver to be a different identity than the apply author (four-eyes); a pipeline cannot approve its own plan.\n4. Attach the plan artefact and the destroy count to the approval so the approver reviews content, not a summary.\n5. Guard stateful resources at the code layer too: `lifecycle { prevent_destroy = true }`, so even an approved pipeline cannot drop a database without a code change.\n6. Expire approvals (24 h); an approval applied after unrelated commits is not approval of what runs.\n7. Log the approver identity and timestamp next to the plan hash for audit.\n8. Dry-run the gate on a branch that deletes a scratch resource before trusting it on prod.\n\n## Pitfalls\n\n- Approving on \"the pipeline is green\", when green includes the destroy.\n- A single environment with one approver who is also the author: four-eyes in name only.\n- Counting destroys from a plan regenerated after approval (a provider bump changes it).\n- No `prevent_destroy`, so the only thing between a typo and an empty prod database is a human reading a diff.\n- Approvals that never expire, applied days later on top of other merges.\n\n- The destroy count read from a plan generated before a `git pull`, so it does not match what is applied.\n- An approval environment without branch protection, so any collaborator can self-approve.\n\n## Verification\n\n    grep -q 'destroys=0' ci.outputs || echo \"manual approval required\"\n    terraform show -json tf.plan | jq '[.resource_changes[]|select(.change.actions|index(\"delete\"))|.address]'\n\nReport: the gate rule, the destroy count that tripped it, the approver identity, and the plan hash applied.\n",{"name":5,"description":7},"main","3df1d0d67b30ff15236561f8c0f9f06d33f42dfd","skills\u002Fpayments\u002F0xklen-gate-destructive-plans-behind-approval",17,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia","https:\u002F\u002Feth2030.com","Hardcore infra. Building @alt-research and applied cryptography.","2026-11-12 02:28:42",{"source":8,"skillName":5,"commands":52,"prompt":62,"zipAvailable":63},[53,56,59],{"tool":54,"command":55},"npx","npx skills add jiayaoqijia\u002Fcryptoskill --skill gate-destructive-plans-behind-approval",{"tool":57,"command":58},"bunx","bunx skills add jiayaoqijia\u002Fcryptoskill --skill gate-destructive-plans-behind-approval",{"tool":60,"command":61},"pnpm","pnpm dlx skills add jiayaoqijia\u002Fcryptoskill --skill gate-destructive-plans-behind-approval","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-gate-destructive-plans-behind-approval\u002FSKILL.md",true,[65,69,75],{"path":66,"resourceType":66,"resourceTypeDesc":67,"sizeBytes":68,"sourceHtmlUrl":16},"LICENSE","许可证",1063,{"path":70,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":73,"sourceHtmlUrl":74},"SOURCE.md","REFERENCE","参考文档",364,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-gate-destructive-plans-behind-approval\u002FSOURCE.md",{"path":76,"resourceType":71,"resourceTypeDesc":72,"sizeBytes":77,"sourceHtmlUrl":78},"TRUST.auto.yaml",2251,"https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-gate-destructive-plans-behind-approval\u002FTRUST.auto.yaml",[80,108,131,149,162,172],{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":84,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":37},"01M712C436EQYE43342Q4E7GG1","recipe-performance","Diagnose a specific MetaMask user flow's real-app performance and Sentry critical-user-flow telemetry with deterministic mm-harness recipes. Use for CUF boundaries, cold\u002Fwarm\u002Fbackground-resume behavior, latency regressions, lifecycle tags, duplicate or blocking network requests, long tasks, layout\u002Fpaint cost, screen redraws, React rerenders, or browser trace analysis where tests alone cannot prove the real app.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fwallets\u002Fmetamask-official-recipe-performance\u002FSKILL.md",[],[88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107],"performance","recipe performance","recipe","mm","sentry","harness","app","deterministic","recipes","flow","cold","critical","analysis","tasks","react","browser","layout","screen","network","metamask",{"skillNo":109,"name":110,"nameZh":6,"description":111,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":112,"licenseFileUrl":113,"sourceHtmlUrl":114,"categories":115,"keywords":116,"publishedAt":37},"01M70XT2F8A5CQZ81JBP98KSW3","mexc-spot-websocket","MEXC Spot WebSocket workflows for public streams, protobuf handling, depth maintenance, listen keys, and private streams without exposing API keys.","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-websocket\u002FSKILL.md",[],[117,118,119,120,121,122,123,124,125,126,127,128,129,130],"mexc spot websocket","spot","websocket","api","workflows","public","listen","streams","depth","keys","for","api keys","maintenance","protobuf",{"skillNo":132,"name":133,"nameZh":6,"description":134,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":112,"licenseFileUrl":135,"sourceHtmlUrl":136,"categories":137,"keywords":138,"publishedAt":37},"01M70XT0MBXN3WZY1BKN0CPNKR","mexc-spot-rest","MEXC Spot REST workflows for public data, signed account requests, orders, wallet\u002Fadmin actions, and secure signing without exposing API keys.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-spot-rest\u002FSKILL.md",[],[139,118,140,141,142,143,144,128,127,126,145,146,147,122,148,121,120],"mexc spot rest","REST","admin","signing","Wallet","requests","actions","secure","data","orders",{"skillNo":150,"name":151,"nameZh":6,"description":152,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":112,"licenseFileUrl":153,"sourceHtmlUrl":154,"categories":155,"keywords":156,"publishedAt":37},"01M70XSYSVZ2N0N91XCAR2CAK0","mexc-futures-websocket","MEXC Futures WebSocket workflows for public streams, private account\u002Forder\u002Fposition streams, ping\u002Fpong, subscriptions, and depth maintenance.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fexchanges\u002Fmncrftfrcnm-mexc-futures-websocket\u002FSKILL.md",[],[157,158,119,159,160,129,127,161,125,124,122,121],"mexc futures websocket","futures","position","ping","subscriptions",{"skillNo":163,"name":164,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":165,"sourceHtmlUrl":166,"categories":167,"keywords":168,"publishedAt":37},"01M6H0ZWHVE5W04WG2DKQE2SQC","0xklen-version-and-refresh-sanctions-lists","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-version-and-refresh-sanctions-lists\u002FSKILL.md",[],[169,170,171],"refresh","0xklen version and refresh sanctions lists","version",{"skillNo":173,"name":174,"nameZh":6,"description":175,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":176,"sourceHtmlUrl":177,"categories":178,"keywords":179,"publishedAt":37},"01M6H0Z28Q3R8J0S799GJQWXM3","verify-tests-cover-changed-lines","Use when a PR adds code that the existing suite may not exercise. Measures patch coverage — the share of newly changed lines hit by tests — before approving.","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fjiayaoqijia\u002Fcryptoskill\u002Fblob\u002Fmain\u002Fskills\u002Fpayments\u002F0xklen-verify-tests-cover-changed-lines\u002FSKILL.md",[],[180,181,182,183,184,185,186,35,187,188,189],"tests","cover","verify tests cover changed lines","verify","coverage","pr","exercise","patch","code","share"]