Disco DeDisco
410664fb0f
feat: shop PaymentIntent flow — shop_buy + shop_confirm + stripe_webhook — Chunk 3 of [[project-wallet-shop-expansion]]. Three-endpoint split per the locked Stripe design: webhook is authoritative for fulfillment (resilient to 3DS, browser closes, network drops); sync /shop/confirm is a best-effort UX speedup (fulfills immediately when Stripe.js confirms client-side, no waiting for webhook delivery); both call Purchase.fulfill() which is idempotent — whichever lands first wins, the other becomes a no-op via the status==SUCCEEDED guard. **POST /dashboard/wallet/shop/buy** (form-encoded shop_item_slug): looks up active ShopItem (404 if missing/inactive); enforces max_owned via is_available_for(user) (409 if cap hit, eg already-owned BAND); requires a saved PaymentMethod (402 otherwise — picks most-recent via order_by('-pk').first() per the open-Q note in the scope doc); creates Stripe PaymentIntent (amount=item.price_cents, currency=usd, customer=user.stripe_customer_id, payment_method=pm.stripe_pm_id, automatic_payment_methods={enabled, allow_redirects=never} for in-window 3DS); creates Purchase w. pi.id; backfills pi.metadata.purchase_id via PaymentIntent.modify so the webhook handler can resolve back to the row; returns {client_secret, purchase_id} JSON for Stripe.js confirmCardPayment. **POST /dashboard/wallet/shop/confirm** (form-encoded purchase_id): retrieves PI from Stripe, if status=='succeeded' calls purchase.fulfill(); returns {status} JSON. 404 if the purchase doesn't belong to request.user. Idempotent — re-firing after fulfill is a safe no-op. **POST /stripe/webhook** (csrf_exempt, mounted at root /stripe/webhook so the URL stays stable across app-routing refactors w. Stripe's dashboard config): verifies signature via stripe.Webhook.construct_event against STRIPE_WEBHOOK_SECRET env var (400 on mismatch — Stripe won't retry on 4xx, only 5xx); on payment_intent.succeeded looks up Purchase by metadata.purchase_id w. fall-back to stripe_payment_intent_id (both unique). Unknown event types are no-op 200 (Stripe sends charge.dispute.created etc. + would retry indefinitely on 5xx). New STRIPE_WEBHOOK_SECRET = os.environ.get(...) setting; user swaps it on staging+prod per the live-mode env-var-only decision. TDD — 17 ITs in test_shop_views.py across 3 classes: ShopBuyViewTest (7 cases — login required, success path creates PI + Purchase w. correct shape, PI.create called w. correct args, unknown slug 404, inactive item 404, max_owned 409, no PM 402); ShopConfirmViewTest (5 cases — login required, succeeded PI triggers fulfill, processing PI leaves PENDING, idempotent on already-SUCCEEDED, other user's purchase 404); StripeWebhookViewTest (5 cases — sig mismatch 400, succeeded event triggers fulfill, unknown event type 2xx no-op, duplicate delivery idempotent, unknown purchase_id 2xx no-op). All Stripe API calls mocked via mock.patch('apps.dashboard.views.stripe'). 1208 IT/UT green
...
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-22 00:42:09 -04:00
Disco DeDisco
ca169be0fb
fix: CI Postgres teardown — RobustCompressorTestRunner.teardown_databases now force-closes lingering connections before Django's DROP. CI step test-UTs-n-ITs (python manage.py test apps, full suite incl. channels-tagged tests) was failing post-test even when all 1165 tests passed — psycopg2.errors.ObjectInUse: database "test_python_tdd_test" is being accessed by other users / DETAIL: There is 1 other session using the database. Two-step leak: (1) core.settings.DATABASES['default']['conn_max_age']=600 keeps Postgres connections alive in the per-thread pool for 10 min (prod-perf default); (2) Channels' database_sync_to_async (16 call sites across apps.epic.tests.integrated.test_consumers's CursorMoveConsumerTest + SigHoverConsumerTest) runs in a process-wide asgiref threadpool — each worker thread accumulates its own DB connection that outlives the test + sits idle in the pool when teardown fires. Postgres refuses DROP while ANY session targets the row. Local dev unaffected: --exclude-tag=channels skips the consumer tests + SQLite has no DROP step. **Fix** lives entirely in core/runner.py's teardown override — connections.close_all() covers the main thread's runner connection; iterating old_config + running SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = %s AND pid <> pg_backend_pid() against each test DB kicks any worker-thread session still pinning the row. Both safe on a green run (DB about to be dropped anyway) + scoped to vendor == "postgresql" so SQLite local-dev is a clean no-op. Prod CONN_MAX_AGE=600 untouched — fix lives in the test runner, NOT in settings. 19/19 lyric UTs green via the new runner path (smoke verify the override is benign on SQLite); Postgres-side validated next CI run. Trap captured: [[feedback-test-teardown-conn-leak]] — symptom signature Ran NNNN tests / OK / Destroying.../ObjectInUse: ... belongs in CI-fail triage notes so future flakes get diagnosed in seconds instead of test-hunting
...
ci/woodpecker/push/pyswiss Pipeline was successful
ci/woodpecker/push/main Pipeline failed
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-21 14:24:41 -04:00
Disco DeDisco
599d40decd
auth urls: mount apps.lyric.urls under /dashboard/ to mirror gameboard/epic & billboard/drama convention
...
- core/urls.py: replace `path('lyric/', …)` with second `path('dashboard/', include('apps.lyric.urls'))` alongside existing dashboard mount; no path-name collision (lyric paths: send_login_email, login, logout, dev-login/<key>/)
- IT test URL strings flipped /lyric/ → /dashboard/ (test_views.py)
- setup_sig_session + setup_sea_session pre-auth URL builders updated
- CLAUDE.md doc note updated
- Templates use unnamespaced `{% url 'logout' %}` / `{% url 'send_login_email' %}` so they auto-resolve; no template edits needed
- /admin/lyric/user/ admin URL untouched (driven by app_label, not URL conf)
Code architected by Disco DeDisco <discodedisco@outlook.com >
Git commit message Co-Authored-By:
Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-04 00:18:36 -04:00
Disco DeDisco
de4ac60aec
tooltips app TDD spike + kit bag refactor to .tt
...
- New apps.tooltips: TooltipContent model, {% tooltip data %} inclusion
tag, _tooltip.html partial with .tt/.tt-title/.tt-description etc.
class contract; 34 tests green
- Kit bag panel (_kit_bag_panel.html): .token-tooltip → .tt + child
class renames (tt-title, tt-description, tt-shoptalk, tt-expiry)
- game-kit.js attachTooltip: .token-tooltip → .tt selector
- SCSS: .tt added alongside .token-tooltip for display:none default +
hover rules in _wallet-tokens.scss and _game-kit.scss
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-15 22:16:50 -04:00
Disco DeDisco
cc2ab869f1
wired PySwiss microservice deployment: env-driven settings, gunicorn pinned, PYSWISS_URL in main settings, test-pyswiss CI stage
...
ci/woodpecker/push/woodpecker Pipeline was successful
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-04-13 21:55:58 -04:00
Disco DeDisco
3800c5bdad
fixed attribution of .fa-hand-pointer cursor color scheme to ordering according to token-drop sequence instead of seat sequence; updates to accomodate this throughout apps.epic.models & .views, plus new apps.epic migration; assigned #id_sig_cursor_portal a z-index value corresponding to a high position but still beneath the #id_tray apparatus; minor semantic reordering of INSTALLED_APPS in core.settings
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-08 22:53:44 -04:00
Disco DeDisco
40a55721ab
major navbar overhaul: .btn-primary.btn-xl now reads CONT GAME and links to the user's most recently active game; log out functionality transferred to new BYE .btn-abandon abutting login spans; tooltips for each asserted via new FTs.test_navbar methods to appear w.in visible area
2026-04-05 16:00:52 -04:00
Disco DeDisco
ca38875660
fixed reverse chronological ordering in a pair of FTs clogging the pipeline; added ActivityPub to project; new apps.ap for WebFinger, Actor, Outbox views; apps.lyric.models now contains ap_public_key, ap_private_key fields + ensure_keypair(); new apps.lyric migration accordingly; new in drama.models are to_activity() w. JoinGate, SelectRole, Create compat. & None verb support; new core.urls for /.well-known/webfinger + /ap/ included; cryptography installed, added to reqs.txt; 24 new green UTs & ITs; in sum, project is now read-only ActivityPub node
ci/woodpecker/push/woodpecker Pipeline was successful
2026-04-02 15:22:04 -04:00
Disco DeDisco
8538f76b13
new core.middleware sets cookie for scroll timestamp view to local browser time, w. new corresponding tests in core.tests.UTs.test_middleware; apps.lyric.templatetags.lyric_extras determines timestamp format based on duration elapsed since timestamp; apps.bill.tests.ITs.test_views renamed, now also asserts scroll renders event body and time in columns
ci/woodpecker/push/woodpecker Pipeline failed
2026-04-02 14:51:08 -04:00
Disco DeDisco
cc02419e8d
actually bubbles up original error w.o pickling TypeErrors wrapping it
ci/woodpecker/push/woodpecker Pipeline was successful
2026-03-23 22:56:10 -04:00
Disco DeDisco
f1b5ba2a71
given flaky --parallel FT pipeline fails, new fix in core.runner, incl. _Py313SafeRemoteTestRunner, so that errors bubbling up don't read as generic TypeError: cannot pickle 'traceback' object
ci/woodpecker/push/woodpecker Pipeline was successful
2026-03-21 23:08:21 -04:00
Disco DeDisco
91e0eaad8e
new DRAMA & BILLBOARD apps to start provenance system; new billboard.html & _scroll.html templates; admin area now displays game event log; new CLAUDE.md file to free up Claude Code's memory.md space; minor additions to apps.epic.views to ensure new systems just described adhere to existing game views
ci/woodpecker/push/woodpecker Pipeline was successful
2026-03-19 15:48:59 -04:00
Disco DeDisco
01de6e7548
Django Channels role-select sprint: turn_changed, roles_revealed, role_select_start consumer handlers; WS URL changed from room_slug to room_id UUID; TableSeat model - room, gamer, slot_number, role, role_revealed, seat_position fields; Room.table_status field with ROLE_SELECT, SIG_SELECT, IN_GAME choices; migration 0006_table_status_and_table_seat; pick_roles and select_role views; _role_select_context helper; _notify_turn_changed, _notify_roles_revealed, _notify_role_select_start notifiers; all gate-mutation views now call _notify_gate_update; ChannelsFunctionalTest base class with serve_static, screenshot, dump helpers; SQLite TEST NAME set to file path for ChannelsLiveServerTestCase; InMemoryChannelLayer added to test CHANNEL_LAYERS settings; FT 5 and FT 6 now passing - active seat arc and turn advance via WS, no page refresh; room.js, gatekeeper.js, role-select.js added to apps/epic/static; applets.js, game-kit.js, dashboard.js, wallet.js relocated to app-scoped static dirs; room.html: hex table, table-seat arcs, card-stack, inventory panel, role-card hand, WS scripts; _room.scss: room-shell flex layout, .table-hex polygon clip-path, .table-seat and .seat-card-arc, .card-stack eligible/ineligible states, .card flip animation, .inv-role-card stacked hand, .role-select-backdrop; gear btn and room menu always position: fixed; 375 tests, 0 skipped
2026-03-17 00:24:23 -04:00
Disco DeDisco
dddffd22d5
covered some test lacunae; gatekeeper now waits for +6 gamers to commit tokens to unblock game room
2026-03-13 22:51:42 -04:00
Disco DeDisco
5773462b4c
massive additions made thru somewhat new apps.epic.models, .urls, .views; new html page & partial in apps/gameboard; new apps.epic FT & ITs (all green); New Game applet now actually leads to game room feat. token-drop gatekeeper mechanism intended for 6 gamers
2026-03-13 00:31:17 -04:00
Disco DeDisco
681a1a4cd0
seeded apps.epic for backend gameboard logic; core.asgi & .settings now accomodate Channels via Redis; several new libraries in reqs to accomodate
2026-03-12 15:05:02 -04:00
Disco DeDisco
69fea65bf9
new core.runner helper to avoid local caching issues w. coverage tests; .settings, apps.dash.tests.ITs.test_wallet_views updated accordingly
ci/woodpecker/push/woodpecker Pipeline was successful
2026-03-12 14:23:09 -04:00
Disco DeDisco
791510b46d
many styling fixes, esp. for both landscape & portrait mobile UX tooltips & navbar; core.settings now permits another device on local net to access dev server
ci/woodpecker/push/woodpecker Pipeline was successful
2026-03-10 14:11:53 -04:00
Disco DeDisco
97601586c5
new applets app for cross-board usage of Applet() & UserApplet() models; dashboard migrations reset and apps reseeded w. new default specs; core.settings & many tests thru-out suite updated accordingly
ci/woodpecker/push/woodpecker Pipeline was successful
2026-03-09 16:08:28 -04:00
Disco DeDisco
bd72135a2f
full passing test suite w. new stripe integration across multiple project nodes; new gameboard django app; stripe in test mode on staging
ci/woodpecker/push/woodpecker Pipeline failed
2026-03-09 01:07:16 -04:00
Disco DeDisco
c099479740
'theme_switcher,' 'theme-picker' & 'theme' renamed everywhere to simply 'palette'; new urls & views & their corresponding ITs ensure applet menu checkbox functionality
2026-03-05 14:45:55 -05:00
Disco DeDisco
9548a2cd15
added locally hosted htmx dependency; updated base.html template & req's files accordingly; wrote new FT (failing) in test_dashboard that calls for this lib
2026-03-04 15:13:16 -05:00
Disco DeDisco
b53c0b9849
small compress fixes to help serve scss on staging server and avoid persistent 500 errors
ci/woodpecker/push/woodpecker Pipeline failed
2026-03-02 16:02:47 -05:00
Disco DeDisco
eebc355f95
themes initialized! many new partials and scss integrations across most templates; core.settings contains COMPRESS test fallback; apps.dashboard.views updated for new alerts and styling
ci/woodpecker/push/woodpecker Pipeline was successful
2026-03-02 15:45:12 -05:00
Disco DeDisco
e142e5d4d7
new FT test_theme for theme switcher functionality; theme-switcher content added to home.html, several dashboard views & urls, all appropriate ITs & UTs; lyric user model saves theme (migrations run); django-compressor and django-libsass libraries added to dependencies
2026-03-02 13:57:03 -05:00
Disco DeDisco
143e81fc41
updated new username feature to api app; restructured api urlpatterns for more sustainable pahts
ci/woodpecker/push/woodpecker Pipeline was successful
2026-03-01 21:44:30 -05:00
Disco DeDisco
94f3120add
refactored to green: all references in urlpatterns thruout project to apps/ dir now skip it & point directly to the app contained w.in (i.e., not apps/lyric/ or apps/dashboard/, but lyric/ or dashboard/ now
ci/woodpecker/push/woodpecker Pipeline was successful
2026-02-22 22:08:34 -05:00
Disco DeDisco
87ef197823
enabled redis alongside celery, but waiting on true caching functionality—flash messages will behave better w. cache_page after they rely on htmx library, not current full-page reload
ci/woodpecker/push/woodpecker Pipeline was successful
2026-02-21 23:13:23 -05:00
Disco DeDisco
04e28b96c8
offloaded some apps.lyric.views responsibilities to new Celery depend fn in .tasks; core.celery created for celery config; CELERY_BROKER_URL added to .settings & throughout project; some lyric view IT responsibility now accordingly covered by task UT domain
ci/woodpecker/push/woodpecker Pipeline failed
2026-02-21 21:35:15 -05:00
Disco DeDisco
9bdc358e59
commenced DRF efforts w. package installation, creation of apps.api, w. UTs & ITs to ensure core efficacy; core.settings & .urls changed to accomodate
ci/woodpecker/push/woodpecker Pipeline failed
2026-02-20 16:37:48 -05:00
Disco DeDisco
4b558020af
added staging & prod https support to core.settings
ci/woodpecker/push/woodpecker Pipeline was successful
2026-02-20 13:33:11 -05:00
Disco DeDisco
025a59938b
reenabled admin area; outfitted apps.lyric.models w. AbstractBaseUser instead of custom user class; many other fns & several models updated to accomodate, such as set_unusable_password() method to base user model; reset staging db to prepare for refreshed lyric migrations to accomodate for retrofitted pw field
ci/woodpecker/push/woodpecker Pipeline was successful
2026-02-19 20:31:29 -05:00
Disco DeDisco
d26196a7f1
added CSRF_TRUSTED_ORIGINS to core.settings, now that https added
ci/woodpecker/push/woodpecker Pipeline was successful
2026-02-18 23:32:43 -05:00
Disco DeDisco
84fd0554bd
moved adman magic link to howdy.earthmanrpg.com, in anticipation of having to mirror the prod server location; staging server preserved, along w. gitea & woodpecker, on earthmanrpg.me
ci/woodpecker/push/woodpecker Pipeline failed
2026-02-18 23:04:21 -05:00
Disco DeDisco
a1e7ae8071
added coverage dependency; 99 percent test coverage (only lacking admin, currently by design); commenced postgresql db integration
ci/woodpecker/push/woodpecker Pipeline was successful
2026-02-18 20:18:56 -05:00
Disco DeDisco
5d0a1401d8
created new dir for STATICFILES_DIRS in core.settings; all Jasmine test files transferred to new dir src/static_src/; new FT test_jasmine executes Jasmine test runner as part of CI pipeline & base FT has dobules MAX_WAIT to 10s; some cleanup of unused imports in text_simple_list_creation
ci/woodpecker/push/woodpecker Pipeline failed
2026-02-11 14:42:38 -05:00
Disco DeDisco
8190317c21
nginx compatibility added to serve static files on server; whitenoise installed to catch static file serving in local docker container, also added to core.settings middleware; console logs & print statements removed from dashboard.js & functional_tests.container_commands; ansible playbook and nginx config file support nginx w.in deployment workflow
2026-02-08 17:55:09 -05:00
Disco DeDisco
10ba5b84e4
after many diversions and forlorn pivot from copilot to claude, new infra/ structure contains group_vars and ansible vaults; requests added to dev and prod dependencies; apps.lyric.views and core
...
.settings both abandon django's send_mail(); instead incorporate requests to target Mailgun's HTTP API (DigitalOcean's SMTP blocker thwarted previous magic login link email attempts, but this issue has been resol
ved with this commit)
2026-02-07 18:58:17 -05:00
Disco DeDisco
449b40e12e
new functional_tests.container_commands file discerns local from server containers; .base calls now calls reset_database() therefrom; .test_my_lists also discerns test server location for different session keys; functional_tests restored as app in core.settings
2026-02-03 22:14:55 -05:00
Disco DeDisco
55bb589f61
added functional_tests to installed apps in core.settings (but only when debug is true); created management dir to contain new django cmds & listed in .dockerignore; created management.create_session cmd; recreated container.db.sqlite3; tweaked test_server setup in functional_tests.base; added test_server failsafe to magic link login testing in .test_login
2026-02-03 14:54:37 -05:00
Disco DeDisco
2db1c0e3fc
temp. favicon 204 silencer added to core.urls; functional_tests.test_my_lists now tests authenticity of login compared to queried list
2026-02-01 20:18:42 -05:00
Disco DeDisco
36f4182a4f
core/base.html & settings.py updated for email-based login & logout
2026-02-01 16:19:07 -05:00
Disco DeDisco
f002cc5c84
auth backend defined in core.settings
2026-01-30 19:35:45 -05:00
Disco DeDisco
4b1906b1ee
new apps.lyric.urls, .tests.test_views files to test & execute mock email sending; apps.lyric.models, .tests.test_models now test & execute unique token autogen to integrate w. magic link login using only email; core.settings updated w. new urlpatterns to accommodate
2026-01-30 16:21:32 -05:00
Disco DeDisco
d724e03c3c
custom user model that maintains id as pk
2026-01-30 15:04:47 -05:00
Disco DeDisco
4b137db317
manage.py changed to lf; FTs tweaked to accomodate WSL2 ansible deployment
2026-01-13 20:58:05 -05:00
Disco DeDisco
eb38722a53
ansible playbook commenced; deployment aimed at staging.earthmanrpg.me
2026-01-13 00:35:28 -05:00
Disco DeDisco
53099f630d
added LOGGING params to core.settings, tho with USER nonroot commented-out of Dockerfile, not sure this does anything yet
2026-01-06 14:28:13 -05:00
Disco DeDisco
b2fe1c0d52
restored from the fool's errand that was WSL virtualization
2026-01-06 13:57:34 -05:00
Disco DeDisco
18d28600c9
collectstatic cmd added to Dockerfile build, despite no static files yet being part of project; static dir added to .gitignore; if/else clause added to core.settings to handle debug, secret key & allowed host values when debug is true & otherwise
2026-01-05 00:32:41 -05:00