docs(18.1): phase complete - UAT 8/8, security 0 open, released framework v0.2.2, pgsub v0.1.1, pgstripe v0.1.1
This commit is contained in:
@@ -139,6 +139,11 @@ Quality
|
||||
- **Commits**: no co-author tags; one logical change per commit; planning docs and code in separate commits
|
||||
- **Core plugin contracts**: the PHP user, blog, pages and payment plugins are shared across many projects; the Go ports must preserve their contracts and the PHP originals are not changed as part of this project
|
||||
|
||||
Validated in Phase 18.1: Payment Gateway Subscriptions
|
||||
|
||||
- [x] Generic subscriptions core (`sm-paymentgatewaysubscriptions-plugin`, pgsub v0.1.1) and pgstripe's subscription gateway, signed webhook and claim-first River job (pgstripe v0.1.1) on framework v0.2.2; admin plans/subscriptions screens, headless customer API and the layer's Pg subscription components
|
||||
- [x] Live Stripe test-mode UAT 8/8 on a `summer build` demo app: checkout, single `activated` event, 409 on a second subscription, portal and site cancellation, admin sync and reorder; security audit 51 threats, 0 open (`18.1-SECURITY.md`)
|
||||
|
||||
## Key Decisions
|
||||
|
||||
| Decision | Rationale | Outcome |
|
||||
@@ -166,6 +171,7 @@ Quality
|
||||
| The local dev stack is the Nuxt app proxied to the Go binary, guarded fail-closed (`fonoteka.go/scripts/dev-stack.sh`), with dev-only seed and marker route gated on `SUMMER_ENV=local` only | Proves the port in daily use before cutover without touching the production origin; `dev` is refused because shared servers often use that name (review WR-05) | ✓ Good (Phase 14.2, 2026-10-12; gate e2e 17/0/0/0, manual UAT 1-11) |
|
||||
| Framework serves public uploads itself (`storage.uploads.serve`, opt-in) with nosniff, a sandboxing CSP and attachment disposition for non-images | Local runs need WinterCMS upload URLs without nginx; the hardening keeps uploaded HTML or SVG from running on the app origin (review WR-03) | ✓ Good (Phase 14.2) |
|
||||
| The opt-in request log (`http.access_log`) records method, matched pattern, status and duration, never the URL path | Share and invitation tokens travel in paths (review WR-01); an unported route shows as a 404 with an empty pattern | ✓ Good (Phase 14.2) |
|
||||
| Subscription state comes from Stripe, not the event snapshot (Phase 18.1, D-21 amended) | Out-of-order webhooks regressed rows; the job re-retrieves the subscription under a per-subscription advisory lock, and a portal `cancel_at` counts as cancel at period end | ✓ Good (Phase 18.1 UAT, 2026-10-16) |
|
||||
|
||||
## Evolution
|
||||
|
||||
@@ -185,4 +191,4 @@ This document evolves at phase transitions and milestone boundaries.
|
||||
4. Update Context with current state
|
||||
|
||||
---
|
||||
*Last updated: 2026-10-12 after Phase 14.2 completion*
|
||||
*Last updated: 2026-10-16 after Phase 18.1 completion*
|
||||
|
||||
@@ -1156,7 +1156,7 @@ Plans:
|
||||
4. A host test proves checkout, activation, `invoice.paid`, `past_due` with its grace period, cancel and duplicate-event idempotency against a Stripe fake.
|
||||
5. The new code has unit tests, delivered in the phase's last plan.
|
||||
|
||||
**Plans:** 9/9 plans executed
|
||||
**Plans:** 9/9 plans complete
|
||||
|
||||
Plans:
|
||||
**Wave 1**
|
||||
@@ -1385,7 +1385,7 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5 → 6 → 7 → 8 →
|
||||
| 16.3. Backend admin personal API tokens with scopes (INSERTED) | 4/4 | Complete | 2026-10-12 |
|
||||
| 17. Blog companions | 6/6 | Complete | 2026-10-13 |
|
||||
| 18. Payment Gateway | 8/8 | Complete | 2026-10-14 |
|
||||
| 18.1. Payment Gateway Subscriptions | 9/9 | In Progress| |
|
||||
| 18.1. Payment Gateway Subscriptions | 9/9 | Complete | 2026-10-16 |
|
||||
| 19. Chat and ChatChannels | 0/TBD | Not started | - |
|
||||
| 19.1. Chat satellites | 0/TBD | Not started | - |
|
||||
| 19.2. Chat polish against WavePath clients | 0/TBD | Not started | - |
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
---
|
||||
msd_state_version: "1.0"
|
||||
milestone: v1.0
|
||||
current_phase: "19.3"
|
||||
current_phase_name: Framework transport and infrastructure for WavePath (INSERTED)
|
||||
status: Phase 19.3 plans complete; release and whole-phase docs pending in the phase 19.3 main session
|
||||
stopped_at: Completed 19.3-06-PLAN.md (gap closure; release handed off to the phase 19.3 main session)
|
||||
last_updated: "2026-10-16T09:58:01.923Z"
|
||||
current_phase: 19
|
||||
current_phase_name: Chat and ChatChannels
|
||||
status: planning
|
||||
stopped_at: Phase 18.1 complete, ready to plan Phase 19
|
||||
last_updated: "2026-10-16T19:08:06.609Z"
|
||||
last_activity: 2026-10-16
|
||||
last_activity_desc: "Completed quick task 261016-0fm: Admin minors for v0.2.1"
|
||||
state_head: 66fd4ae4b702373adc818324270337796f32d71a
|
||||
last_activity_desc: Phase 18.1 complete, transitioned to Phase 19
|
||||
state_head: c02f2724aeb21135f9077b8037bd72871e74a5e8
|
||||
progress:
|
||||
total_phases: 40
|
||||
completed_phases: 31
|
||||
completed_phases: 32
|
||||
total_plans: 191
|
||||
completed_plans: 188
|
||||
completed_plans: 191
|
||||
percent: 80
|
||||
gsd_state_version: "1.0"
|
||||
milestone_name: milestone
|
||||
---
|
||||
@@ -25,22 +26,22 @@ milestone_name: milestone
|
||||
See: .planning/PROJECT.md (updated 2026-10-12)
|
||||
|
||||
**Core value:** An existing WinterCMS-shaped app can be ported plugin by plugin to a single Go binary without its frontend noticing: the PHP version's API contract is the acceptance test.
|
||||
**Current focus:** Phase 19.3 — Framework transport and infrastructure for WavePath (INSERTED)
|
||||
**Current focus:** Phase 19 — Chat and ChatChannels (Phase 19.3 is being worked on in its own session)
|
||||
|
||||
## Current Position
|
||||
|
||||
Phase: 19.3 (Framework transport and infrastructure for WavePath (INSERTED)) — EXECUTING
|
||||
Plan: 6 of 6
|
||||
Status: Phase 19.3 plans complete; release and whole-phase docs pending in the phase 19.3 main session
|
||||
Last activity: 2026-10-16 - Completed quick task 261016-0fm: Admin minors for v0.2.1
|
||||
Phase: 19 — Chat and ChatChannels
|
||||
Plan: Not started
|
||||
Status: Ready to plan
|
||||
Last activity: 2026-10-16 — Phase 18.1 complete, transitioned to Phase 19
|
||||
|
||||
Progress: [████░░░░░░] 44%
|
||||
Progress: [████████░░] 80%
|
||||
|
||||
## Performance Metrics
|
||||
|
||||
**Velocity:**
|
||||
|
||||
- Total plans completed: 79
|
||||
- Total plans completed: 88
|
||||
- Average duration: 21 min
|
||||
- Total execution time: 104 min
|
||||
|
||||
@@ -62,6 +63,7 @@ Progress: [████░░░░░░] 44%
|
||||
| 16.2 | 7 | - | - |
|
||||
| 16.3 | 4 | - | - |
|
||||
| 14.2 | 4 | - | - |
|
||||
| 18.1 | 9 | - | - |
|
||||
|
||||
**Recent Trend:**
|
||||
|
||||
@@ -245,6 +247,9 @@ Progress: [████░░░░░░] 44%
|
||||
| Phase 19.3 P04 | 60min | 5 tasks | 14 files |
|
||||
| Phase 19.3 P05 | 49min | 7 tasks | 38 files |
|
||||
| Phase 19.3 P06 | 40min | 6 tasks | 24 files |
|
||||
| Phase 18.1 P07 | 20 min | 3 tasks | 18 files |
|
||||
| Phase 18.1 P08 | 24 min | 4 tasks | 30 files |
|
||||
| Phase 18.1 P09 | 60min | 5 tasks | 27 files |
|
||||
|
||||
## Accumulated Context
|
||||
|
||||
@@ -830,6 +835,14 @@ Recent decisions affecting current work:
|
||||
- [Phase 19.3]: Phase 19.3 released as summercms v0.1.27 (Task 7 reply: release); sm-faq-plugin, sm-menu-plugin and sm-journal-plugin require v0.1.27 on origin; app plugin submodule pointers not bumped yet
|
||||
- [Phase 19.3]: Phase 19.3 gate scripts/check-phase19.3.sh is fail-closed: a skipped, missing or red required test fails the stage; miniredis is test-only
|
||||
- [Phase 19.3]: 19.3-06: release of v0.1.28 (tag, plugin require bumps, layer tags v0.3.0/v0.3.0/v0.5.0, pushes) handed off to the phase 19.3 main session with the whole-phase docs update; gap closure pushed and tagged nothing
|
||||
- [Phase 18.1]: 18.1-07: D-21 superseded for event ordering (user decision 2026-10-14): the Stripe webhook job applies the subscription Stripe holds (re-retrieved outside any transaction, serialised by a per-subscription pg_advisory_lock via classes.WithSessionLock/SubscriptionLockKey); a Stripe 404 falls back to the event snapshot
|
||||
- [Phase 18.1]: 18.1-07: ApplyDeleted on an unstored subscription returns classes.ErrSubscriptionNotStored so the job rolls its marker back and River retries the deletion
|
||||
- [Phase 18.1]: 18.1-07: plan resolution order is exact price id, then stripe_product_id, then plan_code (any plan, active or not); contracts.Update gains ProductID and PlanCode
|
||||
- [Phase 18.1]: 18.1-07: Service.SyncSubscription writes only gateway-owned columns of a FOR UPDATE re-read row (plus the plan via the optional contracts.SubscriptionRetriever), never the caller's whole row
|
||||
- [Phase 18.1]: 18.1-08: checkouts bill only the plan's own Stripe price per currency (SubscriptionPlan.CheckoutPriceID, no cross-currency fallback); the yen is unsupported
|
||||
- [Phase 18.1]: 18.1-08: customer checkouts go through Service.CheckoutGuarded (per-subscriber advisory lock, 409 for any open subscription) plus Stripe idempotency keys (10-minute window, parameter hash); users.stripe_customer_id is first-write-wins
|
||||
- [Phase 18.1]: 18.1-08: framework pact.AdminBulkAction.Detached (opt-in, json:"-") runs a bulk action outside the cabana transaction; plan sync uses it; needs framework tag v0.1.27 at plan 09
|
||||
- [Phase 18.1]: 18.1-09: framework release tag is v0.2.1 (v0.1.27 and v0.2.0 already on origin); first plugin tags pgsub v0.1.0 and pgstripe v0.1.0, pgstripe requires pgsub v0.1.0, replace lines kept
|
||||
|
||||
### Pending Todos
|
||||
|
||||
@@ -912,6 +925,6 @@ Items acknowledged and carried forward from previous milestone close:
|
||||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-10-15T21:01:19.601Z
|
||||
Stopped at: Completed 19.3-06-PLAN.md (gap closure; release handed off to the phase 19.3 main session)
|
||||
Last session: 2026-10-16T11:56:16.182Z
|
||||
Stopped at: Phase 18.1 complete, ready to plan Phase 19
|
||||
Resume file: None
|
||||
|
||||
@@ -53,35 +53,55 @@
|
||||
"name": "Admin Vue SPA",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "10.1",
|
||||
"name": "Runtime admin extension point (INSERTED)",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "10.2",
|
||||
"name": "Nest framework packages under modules and write run docs (INSERTED)",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "11",
|
||||
"name": "Jobs, realtime and search infrastructure",
|
||||
"status": "in_progress"
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "11.1",
|
||||
"name": "SummerCMS documentation for humans and AI agents",
|
||||
"status": "in_progress"
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "11.2",
|
||||
"name": "summercms.io Alpha 0.1 landing page on SummerCMS",
|
||||
"status": "in_progress"
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "12",
|
||||
"name": "Płytarium API — Collections and Albums",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "12.1",
|
||||
"name": "User plugin admin screens (INSERTED)",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "12.2",
|
||||
"name": "Admin form fields: date, file upload, relation editing with deferred binding (INSERTED)",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "13",
|
||||
"name": "Płytarium API — wishlist, notifications, CSV, credentials, public routes",
|
||||
"status": "in_progress"
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "14",
|
||||
"name": "Domain jobs and external integrations",
|
||||
"status": "in_progress"
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "14.1",
|
||||
@@ -93,10 +113,15 @@
|
||||
"name": "Local Fonoteka frontend on local SummerCMS backend (INSERTED)",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "14.2.1",
|
||||
"name": "Translate plugin (INSERTED)",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "14.3",
|
||||
"name": "One-command app scaffolding (INSERTED)",
|
||||
"status": "in_progress"
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "15",
|
||||
@@ -106,22 +131,37 @@
|
||||
{
|
||||
"number": "16",
|
||||
"name": "grzybyfunkcjonalne.pl on reusable blog views",
|
||||
"status": "in_progress"
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "16.1",
|
||||
"name": "Journal admin urgent fixes (INSERTED)",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "16.2",
|
||||
"name": "Plugin-provided field types and the Blog Editor formwidget (INSERTED)",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "16.3",
|
||||
"name": "Backend admin personal API tokens with scopes (INSERTED)",
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "17",
|
||||
"name": "Blog companions",
|
||||
"status": "in_progress"
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "18",
|
||||
"name": "Payment Gateway",
|
||||
"status": "in_progress"
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "18.1",
|
||||
"name": "Payment Gateway Subscriptions",
|
||||
"status": "pending"
|
||||
"status": "complete"
|
||||
},
|
||||
{
|
||||
"number": "19",
|
||||
@@ -141,7 +181,7 @@
|
||||
{
|
||||
"number": "19.3",
|
||||
"name": "Framework transport and infrastructure for WavePath",
|
||||
"status": "pending"
|
||||
"status": "in_progress"
|
||||
},
|
||||
{
|
||||
"number": "19.4",
|
||||
@@ -166,8 +206,8 @@
|
||||
],
|
||||
"next": {
|
||||
"command": "/msd:progress --next",
|
||||
"label": "Advance to the next step",
|
||||
"reason": "Phase 18 of 40 · executing"
|
||||
"label": "Advance to the next step (plan phase 19)",
|
||||
"reason": "Phase 19 of 40 — needs a plan"
|
||||
},
|
||||
"updated_at": "2026-10-13T22:19:45.651Z"
|
||||
"updated_at": "2026-10-16T19:08:06.654Z"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user