{"id":"stripe-create-subscription","version":"1.0.0","primitive":"code_execution","description":"Stripe Price ID to subscribe to (price_...)","registry_refs":["stripe"],"tags":[],"solves":[],"auth_required":true,"verified":false,"last_verified":"null","next_check":"2026-07-30","eval_result":"null","eval_env":"null","mast":[],"ref":"https://arxiv.org/abs/2503.13657","inputs":[{"name":"STRIPE_SECRET_KEY","required":true,"description":"Stripe secret key (sk_test_... for test mode)"},{"name":"STRIPE_PRICE_ID","required":true,"description":"Stripe Price ID to subscribe to (price_...)"}],"executable":"# ============================================\n# checklist:     stripe-create-subscription\n# version:       1.0.0\n# primitive:     code_execution\n# description:   Create a Stripe subscription for a customer with a price, verify status and invoice generation\n# registry_refs: stripe\n# auth_required: true\n# verified:      false\n# last_verified: null\n# next_check:    2026-07-30\n# eval_result:   null\n# eval_env:      null\n#\n# inputs:\n#   - name: STRIPE_SECRET_KEY\n#     required: true\n#     description: Stripe secret key (sk_test_... for test mode)\n#   - name: STRIPE_PRICE_ID\n#     required: true\n#     description: Stripe Price ID to subscribe to (price_...)\n#\n# OUTPUTS:\n#   subscription_id — Stripe subscription ID (sub_...)\n#   status          — subscription status\n#   customer_id     — customer created for test\n#   invoice_id      — first invoice ID if generated\n#\n# MAST FAILURE MODES ADDRESSED:\n# FM-1.1 Disobey Task Specification        — payment_behavior=default_incomplete for SCA compliance\n# FM-3.2 No or Incomplete Verification     — subscription status verified after creation\n#\n# ref: https://arxiv.org/abs/2503.13657\n# ============================================\n\nimport sys\nimport os\nimport subprocess\nimport time\nimport urllib.request\nimport json\n\n# ─────────────────────────────────────────\n# PRE_EXECUTION\n# ─────────────────────────────────────────\n\nfor attempt in range(2):\n    try:\n        req = urllib.request.Request(\n            \"https://checklist.day/api/registry/stripe\",\n            headers={\"User-Agent\": \"checklist-agent/1.0\"}\n        )\n        with urllib.request.urlopen(req, timeout=10) as resp:\n            registry = json.loads(resp.read())\n            break\n    except Exception as e:\n        if attempt == 1:\n            print(f\"ABORT: registry unreachable — {e}\")\n            sys.exit(1)\n        time.sleep(2)\n\nwarnings = registry.get(\"warnings\", [])\nif warnings:\n    print(\"[stripe] WARNINGS:\")\n    for w in warnings if isinstance(warnings, list) else [warnings]:\n        print(f\"  ⚠ {w}\")\n\n# ─────────────────────────────────────────\n# EXECUTION\n# ─────────────────────────────────────────\n\nsubprocess.check_call([sys.executable, \"-m\", \"pip\", \"install\", \"-q\", \"stripe>=7.0.0\"])\n\nimport stripe\n\nSTRIPE_SECRET_KEY = os.environ.get(\"STRIPE_SECRET_KEY\")\nSTRIPE_PRICE_ID   = os.environ.get(\"STRIPE_PRICE_ID\")\n\nif not STRIPE_SECRET_KEY:\n    print(\"ABORT: STRIPE_SECRET_KEY not set\"); sys.exit(1)\nif not STRIPE_SECRET_KEY.startswith(\"sk_test_\"):\n    print(\"ABORT: use test mode key (sk_test_...)\"); sys.exit(1)\nif not STRIPE_PRICE_ID:\n    print(\"ABORT: STRIPE_PRICE_ID not set (price_...)\"); sys.exit(1)\n\nstripe.api_key = STRIPE_SECRET_KEY\n\n# Create test customer with payment method\ncustomer = stripe.Customer.create(\n    email=\"checklist-sub-test@example.com\",\n    payment_method=\"pm_card_visa\",\n    invoice_settings={\"default_payment_method\": \"pm_card_visa\"},\n)\ncustomer_id = customer.id\nprint(f\"  customer: {customer_id}\")\n\nsubscription_id = None\ninvoice_id      = None\n\ntry:\n    # FOOTGUN: payment_behavior=default_incomplete required for SCA — don't use error_if_incomplete\n    subscription = stripe.Subscription.create(\n        customer=customer_id,\n        items=[{\"price\": STRIPE_PRICE_ID}],\n        payment_behavior=\"default_incomplete\",\n        expand=[\"latest_invoice.payment_intent\"],\n        idempotency_key=f\"checklist-sub-{int(time.time())}\",\n    )\n\n    subscription_id = subscription.id\n    status          = subscription.status\n    invoice_id      = subscription.latest_invoice.id if subscription.latest_invoice else None\n\n    print(f\"  subscription: {subscription_id} (status={status})\")\n    print(f\"  invoice: {invoice_id}\")\n\n    # Cleanup\n    stripe.Subscription.cancel(subscription_id)\n    print(f\"  cancelled: {subscription_id}\")\n\nfinally:\n    stripe.Customer.delete(customer_id)\n    print(f\"  deleted customer: {customer_id}\")\n\n# ─────────────────────────────────────────\n# POST_EXECUTION\n# ─────────────────────────────────────────\n\nassert subscription_id and subscription_id.startswith(\"sub_\"), f\"FAIL: invalid subscription ID {subscription_id}\"\nassert status in (\"incomplete\", \"active\", \"trialing\"), f\"FAIL: unexpected status '{status}'\"\n\nresult = {\n    \"subscription_id\": subscription_id,\n    \"status\":          status,\n    \"customer_id\":     customer_id,\n    \"invoice_id\":      invoice_id,\n}\nprint(json.dumps(result, indent=2))\nprint(\"PASS\")\n"}