Spike: Stripe integration architecture (Payment Links, webhooks, k8s secrets) #128
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type
Spike
Lineage
Informs #125 (Stripe integration) and #124 (admin request management). Child of spike #121. Phase 3. Resolves Open Question #5 from
docs/user-stories-auth.md(webhook vs polling for payment status).Repo
ldraney/landscaping-assistantQuestion
What is the right Stripe integration pattern for admin-generated payment links with webhook-driven status updates, and how do we wire the existing
~/secrets/stripe/credentials into the k8s deployment?/webhooks/stripe), signature verification viaStripe::Webhook.construct_event, idempotency keys. Interaction with Rails CSRF protection (skip_forgery_protection)?~/secrets/stripe/(test-secret-key, test-webhook-secret, plus live equivalents). Path from files to k8s secret to Rails env vars. New pal-e-services entry or manual sealed secret?sk_test_*for dev,sk_live_*for prod. Environment-based switching. Separate Stripe test webhook endpoint registration?stripeRuby gem compatibility with Rails 8.1 and that it's worth the dependency for Payment Links + one webhook.Deliverables
Required outputs:
docs/stripe-integration.mdcreated — architecture decisions covering all questions above, with rationale and tradeoffs. Merged via docs-only PR.Time-box
1 session. If any question requires Stripe API experimentation, note it as a follow-up task rather than blocking the spike. If time-box expires, document findings in the docs file and escalate remaining questions to Lucas for direction.
Related
landscaping-assistant— project slug~/secrets/stripe/— existing Stripe credentials (test + live)Issue #128 Spike Review
TEMPLATE CONFORMANCE
Checked against
template-issue-spikefrom pal-e-docs.ldraney/landscaping-assistantDeliverables format issue: The template requires checkboxes (
- [ ]) for both deliverables. The issue body has two deliverables but they are rendered as plain bullet points without checkboxes. Should be:This is a minor formatting nit, but checkboxes are functional in Forgejo (trackable completion).
Deliverables content issue: The template specifies two required outputs for every spike: (1) a docs file, and (2) "Follow-up tickets created or existing tickets updated." The issue's second deliverable says "#125 acceptance criteria updated" which is close but slightly narrows the scope. The template allows for creating new tickets if scope changes significantly. The issue does mention this ("If scope changes significantly, create additional tickets") so this is acceptable.
CONTENT QUALITY
Framing question: GOOD. The top-level question is clear and specific: "What is the right Stripe integration pattern for admin-generated payment links with webhook-driven status updates, and how do we wire the existing
~/secrets/stripe/credentials into the k8s deployment?" This is answerable and scoped.Sub-questions: COMPREHENSIVE but has overlap with already-answered material. This is the main finding.
Spike #121 (PR #127) already documented several decisions in
docs/user-stories-auth.md:"Payment Links API vs Checkout Sessions" -- The existing doc already states the flow: "Admin sends Stripe payment link / Client gets notification" and "Admin sets price" then client pays. The decision that admin generates payment links is already made. What remains unknown is the API-level choice (Payment Links API vs Checkout Sessions API). The sub-question is valid but should acknowledge that the flow design is settled and frame it as: "Confirm Payment Links API is the right Stripe product for the already-designed admin-generates-link flow."
"stripe gem vs raw HTTP" -- This is a reasonable question, but the answer is almost certainly "use the gem." This sub-question risks spending time on a question with an obvious answer. Consider whether this actually needs spike investigation or can just be stated as a decision.
All other sub-questions (webhook architecture, secrets wiring, test vs live, payment link lifecycle, webhook endpoint registration) -- These are genuinely unknown and well-scoped. Good spike material.
Time-box: GOOD. "1 session" is realistic for a docs-only investigation. The escalation clause ("note it as a follow-up task rather than blocking the spike") is exactly right for preventing rabbit holes.
Related links: VERIFIED. All referenced issues exist:
The
~/secrets/stripe/reference is a filesystem path, not an issue -- appropriate for context.OVERLAP WITH EXISTING DOCS
docs/user-stories-auth.md(lines 267-274) already defines theServiceRequestmodel withstripe_payment_linkfield and the status lifecyclerequested -> quoted -> paid -> scheduled -> completed | declined. Open Question #5 in that doc explicitly asks: "Do we listen for Stripe payment webhooks to auto-update ServiceRequest status, or does admin manually mark as paid? Webhooks are cleaner but need a public endpoint."This spike is well-positioned to answer that open question. The spike should reference Open Question #5 from
docs/user-stories-auth.mdexplicitly, to make it clear this spike resolves that question rather than independently re-discovering it.Recommendation: Add to the Question section or Lineage: "Resolves Open Question #5 from
docs/user-stories-auth.md(Stripe webhook vs polling)."NITS
Lineage says "Informs #125 and #124" but does not mention #121 as the parent spike. #121 is listed in Related but the Lineage should acknowledge the chain: #121 produced the design, #128 digs into the Stripe-specific technical questions that #121 left open.
Sub-question on
skip_forgery_protectionin the webhook section is a good catch -- this is a real Rails footgun. Well done including it.Missing sub-question: The existing data model has
ServiceRequest.stripe_payment_linkas a single string field. The spike should ask whether one link per ServiceRequest is sufficient, or whether re-generation (e.g., expired link) means the model needs astripe_payment_linksassociation or at minimum a link history. This connects to the "payment link lifecycle" sub-question but should be explicit about the data model impact.SOP COMPLIANCE
~/secrets/stripe/is a reference, not a credential)VERDICT: APPROVED
The spike is well-formed, correctly scoped, and asks the right questions. The three recommendations below would improve it but are not blockers:
- [ ]format)docs/user-stories-auth.mdThe sub-question about "stripe gem vs raw HTTP" is low-value (answer is near-certain), but including it in a 1-session time-box is harmless -- it can be answered in one sentence during the spike.