ultimate-jekyll-manager 1.9.4 → 1.9.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/CLAUDE.md +6 -0
  2. package/dist/assets/css/core/_utilities.scss +5 -2
  3. package/dist/assets/js/libs/form-manager.js +7 -8
  4. package/dist/commands/install.js +2 -2
  5. package/dist/commands/setup.js +2 -1
  6. package/dist/defaults/.github/workflows/build.yml +3 -1
  7. package/dist/defaults/dist/_includes/core/body.html +1 -7
  8. package/dist/defaults/dist/_includes/themes/classy/frontend/sections/footer.html +9 -1
  9. package/dist/defaults/dist/_layouts/blueprint/admin/calendar/index.html +1 -1
  10. package/dist/defaults/dist/_layouts/blueprint/admin/firebase/index.html +2 -2
  11. package/dist/defaults/dist/_layouts/blueprint/admin/studio/index.html +1 -1
  12. package/dist/defaults/dist/_layouts/blueprint/admin/users/index.html +2 -2
  13. package/dist/defaults/dist/_layouts/blueprint/admin/users/new.html +1 -1
  14. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/account/index.html +13 -13
  15. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/reset.html +2 -2
  16. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signin.html +3 -3
  17. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signup.html +3 -3
  18. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/blog/index.html +1 -1
  19. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/contact.html +1 -1
  20. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/download.html +1 -1
  21. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/feedback.html +1 -1
  22. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/index.html +2 -6
  23. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/payment/checkout.html +1 -1
  24. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/portal/email-preferences.html +2 -3
  25. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/status.html +1 -1
  26. package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/blog/index.html +1 -1
  27. package/dist/defaults/dist/_layouts/themes/newsflash/frontend/pages/contact.html +1 -1
  28. package/dist/defaults/dist/pages/test/libraries/form-manager.html +31 -31
  29. package/dist/lib/safe-install.js +13 -0
  30. package/package.json +8 -1
  31. package/.nvmrc +0 -1
  32. package/CHANGELOG.md +0 -792
  33. package/CLAUDE-ATTRIBUTION.md +0 -215
  34. package/PROGRESS.md +0 -27
  35. package/TODO-ATTRIBUTION2.md +0 -753
  36. package/TODO-AUTH-TESTING.md +0 -165
  37. package/TODO-BACKEND.md +0 -13
  38. package/TODO-CHAT1.md +0 -41
  39. package/TODO-CONSENT-LIVETEST.md +0 -201
  40. package/TODO-NEW.md +0 -21
  41. package/TODO-themes.md +0 -34
  42. package/TODO-tracking.md +0 -69
  43. package/TODO-tracking2.md +0 -103
  44. package/TODO.md +0 -415
  45. package/_notes/CLAUDE-pages.md +0 -19
  46. package/_notes/CLAUDE-pages2.md +0 -18
  47. package/_notes/LOGOS.md +0 -1
  48. package/_notes/NOTES-app.md +0 -92
  49. package/_notes/NOTES-sub-2.md +0 -42
  50. package/_notes/NOTES-sub-ai.md +0 -165
  51. package/_notes/NOTES-sub-endpoints.md +0 -44
  52. package/_notes/NOTES-sub-example.md +0 -92
  53. package/_notes/NOTES-sub-plan.md +0 -36
  54. package/_notes/NOTES-sub-status.md +0 -123
  55. package/_notes/TODO-Claude.rtf +0 -105
  56. package/_notes/TODO-FileStructure.md +0 -249
  57. package/_notes/TODO-checkout.md +0 -33
  58. package/_notes/TODO-frontend.md +0 -61
  59. package/_notes/TODO-legacy.md +0 -18
  60. package/_notes/TODO-template-system.md +0 -73
  61. package/_notes/TODO-theme.md +0 -17
  62. package/logs/test.log +0 -144
@@ -1,165 +0,0 @@
1
- # TODO: Automated Tests for the Auth System
2
-
3
- ## Why
4
-
5
- The consent-guard / `sendUserSignupMetadata` ordering bug that shipped in v1.3.1 (and was fixed in v1.3.2) is exactly the kind of regression that should never reach production. The bug was:
6
-
7
- - Page-load consent guard ran BEFORE `sendUserSignupMetadata`
8
- - Brand-new signups had `consent.legal.status: 'revoked'` (BEM schema default)
9
- - Guard saw `'revoked'` → signed user out → metadata POST never fired → user permanently orphaned
10
-
11
- Discovered only via live testing on Somiibo. Should have been caught by a unit test.
12
-
13
- This file proposes a layered test strategy so the next refactor + every future change is safe.
14
-
15
- ## Strategy: three tiers, mostly mocked
16
-
17
- ### Tier 1 — Unit (JSDOM + mocked Firebase, fast)
18
-
19
- Run from UJM. Add to the existing `test/tests/**/*.test.js` harness. No real Firebase, no network. Covers ~80% of bugs including the v1.3.1 regression.
20
-
21
- Files to write:
22
-
23
- ```
24
- test/tests/auth-consent-capture.test.js
25
- • captureSignupConsent() reads consent-legal + consent-marketing checkboxes
26
- • writes the right shape to webManager.storage() under key 'consent'
27
- • label text is captured verbatim (so BEM gets the exact string the user saw)
28
-
29
- test/tests/auth-consent-validate.test.js
30
- • validateConsent() blocks submit when consent-legal is unchecked
31
- • surfaces the inline error + wrapper outline
32
- • does NOT block submit when both boxes are checked or only marketing is unchecked
33
-
34
- test/tests/auth-guard-ordering.test.js ← THIS WOULD HAVE CAUGHT v1.3.1
35
- • on a fresh user (account < SIGNUP_MAX_AGE) with consent.legal.status: 'revoked'
36
- → sendUserSignupMetadata is called
37
- → guard does NOT sign out
38
- • on an old user (account > SIGNUP_MAX_AGE) with consent.legal.status: 'revoked'
39
- → guard signs out
40
- → notification is shown
41
- • on any user with consent.legal.status: 'granted'
42
- → guard does NOT fire regardless of age
43
-
44
- test/tests/auth-reverse-signup.test.js
45
- • reverseAccidentalSignup() calls user.delete() THEN signOut() THEN clears authReturnUrl
46
- • formManager.showError fires with the right message
47
- • if user.delete() throws, signOut still runs (best-effort)
48
-
49
- test/tests/auth-policy-redirect.test.js
50
- • policy='authenticated' + no user → redirect to unauthenticated URL
51
- • policy='unauthenticated' + user → redirect to authenticated URL (honoring authReturnUrl)
52
- • policy='disabled' → no-op
53
-
54
- test/tests/auth-metadata-payload.test.js
55
- • sendUserSignupMetadata builds the right payload shape
56
- • includes consent, attribution, context
57
- • skips when account is old or signupProcessed flag is set
58
- • sets signupProcessed flag after successful POST
59
- ```
60
-
61
- Mocking contract:
62
-
63
- ```js
64
- // Mock webManager
65
- const fakeWebManager = {
66
- auth: () => ({ listen, signOut, getIdToken }),
67
- storage: () => ({ get, set }),
68
- utilities: () => ({ showNotification }),
69
- config: { auth: { config: { policy, redirects, roles } } },
70
- };
71
-
72
- // Mock Firebase auth functions
73
- // - createUserWithEmailAndPassword
74
- // - signInWithEmailAndPassword
75
- // - signInWithPopup / signInWithRedirect
76
- // - getRedirectResult
77
- // - sendPasswordResetEmail
78
- // - user.delete()
79
- // - getAuth().signOut()
80
-
81
- // Mock FormManager (or use the real one — it's mockable already)
82
- const fakeFormManager = { showError, showSuccess, ready, ... };
83
- ```
84
-
85
- Approach: load `src/assets/js/core/auth.js` and `src/assets/js/libs/auth.js` into JSDOM
86
- with all imports stubbed (Jest/Mocha module mocks or rewire). For HTML-aware tests
87
- (captureSignupConsent), load `src/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signup.html`
88
- into JSDOM and exercise the real DOM.
89
-
90
- ### Tier 2 — Integration against Firebase Emulator (slower, optional)
91
-
92
- Run from UJM. Boot `firebase emulators:start --only auth,firestore` before the suite.
93
- Extend the existing `test/fixtures/consumer-site/` with:
94
-
95
- - `firebase.json` configured for emulator ports
96
- - Canned Firebase web config pointing at `localhost:9099` / `localhost:8080`
97
- - Test user seeding via Admin SDK helpers
98
-
99
- Covers: full email-signup round-trip, the storage-survives-redirect path, real
100
- auth-state-listener firing, real Firestore reads in the guard.
101
-
102
- **Skip OAuth at this tier.** Firebase emulator's auth emulator doesn't speak to
103
- real Google. OAuth tests stay manual (Tier 3).
104
-
105
- This is OPTIONAL — only worth building if a bug slips through Tier 1.
106
-
107
- ### Tier 3 — Manual smoke (don't automate)
108
-
109
- Google OAuth + cross-provider webhooks stay manual. Reasons:
110
- - Google actively blocks scripted browsers (even Puppeteer with stealth plugins)
111
- - Real 2FA flows
112
- - Provider UI rolls and tests break
113
- - Cost/value is terrible
114
-
115
- Keep the live-test checklist (see [TODO-CONSENT-LIVETEST.md](TODO-CONSENT-LIVETEST.md))
116
- as the authoritative manual smoke procedure.
117
-
118
- ## Where the tests live
119
-
120
- Run from UJM. NOT from a host project. Reasons:
121
- - `core/auth.js` + `libs/auth.js` are owned by UJM
122
- - Host project tests would re-test framework internals, wrong layering
123
- - UJM's existing 60-test Mocha harness is already fast (~6s)
124
-
125
- Default config (Firebase emulator + a fake brand) baked into
126
- `test/fixtures/` so contributors don't need their own Firebase project.
127
-
128
- ## Sequencing
129
-
130
- 1. **First**: do the libs/auth.js refactor (split into `auth.js` + `auth-providers.js` + `auth-consent.js`).
131
- - See the auth-audit findings in this session's notes.
132
- - Refactor first means we write tests against the FINAL shape, not throw-away.
133
- - Each new file gets a focused test file.
134
-
135
- 2. **Then**: Tier 1 unit tests for the new shape.
136
- - Target: every test file from the list above, green.
137
- - Should take ~half a day.
138
-
139
- 3. **Optional later**: Tier 2 emulator-backed tests, only if Tier 1 misses a class
140
- of bugs in practice. Probably won't be needed.
141
-
142
- 4. **Never**: Tier 3 automation. Stays manual via [TODO-CONSENT-LIVETEST.md](TODO-CONSENT-LIVETEST.md).
143
-
144
- ## What about Ultimate Jekyll for the test site?
145
-
146
- Tempting but NO. Reasons:
147
- - UJ build is heavy (Jekyll + webpack), test boot would be 10+ seconds
148
- - Circular dependency risk (UJM testing UJM via UJ which uses UJM)
149
- - UJM's existing Mocha harness is the right tool
150
-
151
- The test harness should stay vanilla Mocha + JSDOM + fixture HTML files.
152
-
153
- ## What this DOESN'T cover
154
-
155
- - Google OAuth UI flows (manual only)
156
- - Cross-provider unsubscribe webhooks (manual + BEM tests already exist)
157
- - Beehiiv webhook setup (blocked on plan upgrade; manual when ready)
158
- - Firebase Auth SDK bugs (not our code, not our problem)
159
-
160
- ## Done criteria
161
-
162
- - All 6 test files above written and green
163
- - `npm test` in UJM runs them as part of the standard suite
164
- - The v1.3.1 bug (consent guard ordering) is caught by `auth-guard-ordering.test.js` — verify by reverting the v1.3.2 fix in a branch and watching the test fail
165
- - Documented in `docs/test-framework.md` so contributors know to add auth tests when touching auth code
package/TODO-BACKEND.md DELETED
@@ -1,13 +0,0 @@
1
- BACKEND TODO
2
- make the mobile menu toggle appear in place ont he logo/brand (the one on the topbar), not down in the bottom right corner
3
-
4
- does it hav eto be aside? or can it be nav? id prefer if it was nav
5
-
6
-
7
- the breadcrumbs at the top are not needed. pelase move them inside the MINIMAL layout. on that note, please design the minimal layout page. it should look liek the screenshot attached with the page.meta.title, then under that is the breadcrumbs, then under that is the page content. on the right side, there is a button
8
-
9
-
10
- ok our dashboard needs some work. just look at the screenshot.
11
- - the DASHBAORD text is way too huge. the icon next to it is way too small.
12
- - also, that whole section needs a HR below it or a border or something to separate it from the content below. also, we need to make
13
- - also, the LOGO section in top left should match the bg color of the sidebar.
package/TODO-CHAT1.md DELETED
@@ -1,41 +0,0 @@
1
- where could we put a small section about how to use the defualt css classes? some come with bootstrap and some come from our core, and some come from the theme. when building websites, we should be using the premde classes not creating copies of custom classes that do the same thing
2
-
3
- Looking at the CLAUDE.md structure, I think the best place for a CSS classes section would be after the "CSS Guidelines" section (which currently only covers Theme-Adaptive Classes). We could expand that section or add a new subsection. Let me check what's currently in the CSS Guidelines section and the surrounding context:
4
- Grep "## CSS Guidelines" (in /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-manager/CLAUDE.md)
5
- 51 lines of output
6
- The CSS Guidelines section is currently small (lines 423-443), focusing only on theme-adaptive classes. I'd recommend expanding this section with a new subsection about class hierarchy and usage. Here's where I'd suggest placing it and what it could contain: Suggested location: After "Theme-Adaptive Classes" (line 443), before "Page Loading Protection System" (line 445) Suggested content:
7
- ### CSS Class Hierarchy
8
-
9
- When styling elements, always prefer existing classes over creating custom ones. Classes come from three sources (in order of precedence):
10
-
11
- **1. Bootstrap Classes (Foundation)**
12
- Use Bootstrap's utility classes for common patterns:
13
- - Spacing: `m-*`, `p-*`, `mt-3`, `px-4`, `gap-2`
14
- - Flexbox: `d-flex`, `justify-content-center`, `align-items-center`
15
- - Grid: `row`, `col-*`, `container`, `container-fluid`
16
- - Text: `text-center`, `fw-bold`, `fs-5`, `text-muted`
17
- - Display: `d-none`, `d-md-block`, `visually-hidden`
18
-
19
- **Documentation:** https://getbootstrap.com/docs/5.3/utilities/
20
-
21
- **2. UJ Core Classes (Global)**
22
- Located in `src/assets/css/global/` and `src/assets/css/core/`:
23
- - Theme-adaptive: `bg-body`, `btn-adaptive`, `text-body`
24
- - Utilities: (list common ones here)
25
-
26
- **3. Theme Classes (Theme-Specific)**
27
- Located in `src/assets/themes/[theme-id]/`:
28
- - Theme-specific components and overrides
29
-
30
- ### Best Practices
31
-
32
- **DO:**
33
- - Search existing classes before creating new ones
34
- - Use Bootstrap utilities for spacing, layout, typography
35
- - Use UJ adaptive classes for theme compatibility
36
-
37
- **DON'T:**
38
- - Create `.my-centered-text` when `text-center` exists
39
- - Create `.my-margin-top` when `mt-3` exists
40
- - Duplicate functionality that Bootstrap or UJ already provides
41
- Would you like me to add this section to the CLAUDE.md file? I can also explore the actual CSS files to document the specific UJ core utility classes that are available.
@@ -1,201 +0,0 @@
1
- # TODO: Consent System End-to-End Live Test Checklist
2
-
3
- ## Context
4
-
5
- End-to-end manual smoke for the marketing-consent + cross-provider-unsub
6
- pipeline. Run after each new BEM/WM/UJM deploy that touches auth, consent,
7
- email-preferences, or webhook code paths.
8
-
9
- Each step depends on state set up by earlier steps. Run top-to-bottom.
10
-
11
- Live test target: **Somiibo** (`somiibo.com` + `api.somiibo.com`).
12
- Parent BEM: **ITW** (`itwcreativeworks.com` + `api.itwcreativeworks.com`).
13
-
14
- ## Pre-flight
15
-
16
- - [ ] **Use a fresh email** (`consent-test+1@yourdomain.com` or a Gmail alias) so the signup is genuinely new
17
- - [ ] **Have a separate Google account ready** that has never signed up here (for the reverse-signup test)
18
- - [ ] **Open multiple browser windows side by side**:
19
- - Somiibo signup page
20
- - SendGrid Marketing → Contacts
21
- - Beehiiv dashboard → Somiibo publication subscribers
22
- - [ ] **Tail BEM logs in terminal**:
23
- ```bash
24
- cd /Users/ian/Developer/Repositories/Somiibo/somiibo-backend/functions
25
- npx mgr logs:tail
26
- ```
27
- - [ ] **Confirm current package versions live**:
28
- - BEM: `^5.2.2`
29
- - web-manager: `^4.2.0`
30
- - UJM: `^1.3.2`
31
- - [ ] **Confirm last Somiibo backend + website deploys** were AFTER the BEM/UJM version bumps
32
- - [ ] **Delete any stale test accounts** from previous attempts:
33
- ```bash
34
- npx mgr auth:get "<test-email>" # find the uid
35
- npx mgr auth:delete "<uid>" --force
36
- npx mgr firestore:delete "users/<uid>" --force
37
- ```
38
-
39
- ## Tests
40
-
41
- ### ☐ Test 1 — Signup with marketing consent granted (golden path)
42
-
43
- **Action:** Sign up at `somiibo.com/signup` with both checkboxes checked.
44
-
45
- **Verify:**
46
- - [ ] Account created, redirected to logged-in dashboard
47
- - [ ] `npx mgr firestore:get users/<uid>` shows:
48
- - `consent.legal.status: 'granted'`
49
- - `consent.legal.grantedAt.source: 'signup'`
50
- - `consent.legal.grantedAt.ip` populated (not null)
51
- - `consent.legal.grantedAt.text` is the actual label string
52
- - `consent.marketing.status: 'granted'`
53
- - `consent.marketing.grantedAt.source: 'signup'`
54
- - `consent.marketing.revokedAt.timestamp: null`
55
- - [ ] SendGrid Contacts: new contact exists with this email
56
- - [ ] Beehiiv Subscribers: new subscriber exists
57
- - [ ] BEM logs: search for `buildConsentRecord: legal=granted, marketing=granted`
58
-
59
- **Capture the uid** for use in later tests.
60
-
61
- ### ☐ Test 2 — Signup with marketing UNCHECKED
62
-
63
- **Action:** Sign out. Sign up with a different fresh email. Legal checked, marketing UNCHECKED.
64
-
65
- **Verify:**
66
- - [ ] `consent.marketing.status: 'revoked'`, `revokedAt.source: 'signup'`, `grantedAt.timestamp: null`
67
- - [ ] SendGrid: contact NOT created
68
- - [ ] Beehiiv: subscriber NOT created
69
- - [ ] BEM logs: `buildConsentRecord: legal=granted, marketing=revoked` — `mailer.sync()` should NOT have been called
70
-
71
- ### ☐ Test 3 — Signup with legal UNCHECKED (validation blocks)
72
-
73
- **Action:** Try to submit signup with legal box UNCHECKED.
74
-
75
- **Verify:**
76
- - [ ] Submit button is disabled OR clicking submit shows the inline error + red outline around the consent group
77
- - [ ] No Firebase auth user created
78
- - [ ] No request fired to `/user/signup` (browser DevTools network tab)
79
-
80
- ### ☐ Test 4 — Google sign-in with a NEW (nonexistent) Google account on /signin
81
-
82
- **Action:** On `somiibo.com/signin` (NOT `/signup`), click "Continue with Google" and authenticate with a Google account that has never been used here.
83
-
84
- **Verify:**
85
- - [ ] Inline error appears: "This account doesn't exist. Try signing up first or use a different account."
86
- - [ ] User stays on `/signin` (no redirect away)
87
- - [ ] Firebase Auth dashboard: the user does NOT persist (created then deleted)
88
- - [ ] Firestore: no orphan user doc remains (`users` collection)
89
- - [ ] BEM logs: look for `Reversing accidental signup from /signin` warning
90
- - [ ] `sendUserSignupMetadata` should NOT have run (no `/user/signup` POST in logs)
91
-
92
- ### ☐ Test 5 — Account-page opt-out
93
-
94
- **Action:** Sign in as the Test 1 user. Go to `/account` → notifications section. Toggle marketing OFF.
95
-
96
- **Verify:**
97
- - [ ] Toast/UI confirms the change
98
- - [ ] `consent.marketing.status: 'revoked'`, `revokedAt.source: 'account'`, `revokedAt.timestamp` is recent, `revokedAt.ip` populated
99
- - [ ] `consent.marketing.grantedAt` is UNTOUCHED (original signup grant info preserved)
100
- - [ ] SendGrid: contact removed from list
101
- - [ ] Beehiiv: subscriber removed
102
-
103
- ### ☐ Test 6 — Account-page opt-in (re-grant)
104
-
105
- **Action:** Same user. Toggle marketing back ON.
106
-
107
- **Verify:**
108
- - [ ] `status: 'granted'`, `grantedAt.source: 'account'`, `grantedAt.timestamp` newer than original
109
- - [ ] `revokedAt` UNTOUCHED (informational, still shows the Test 5 revoke)
110
- - [ ] SendGrid: contact re-added
111
- - [ ] Beehiiv: subscriber re-added
112
-
113
- ### ☐ Test 7 — SendGrid webhook → cross-provider sync via parent forwarder
114
-
115
- **Action:** In SendGrid dashboard → Marketing → Contacts, find Test 1 user's contact and manually unsubscribe (or add their email to the Global Unsubscribe list via Suppressions).
116
-
117
- **Verify (allow up to ~30s for delivery):**
118
- - [ ] ITW BEM logs: `POST /backend-manager/marketing/webhook/forward?provider=sendgrid` with 200
119
- - [ ] Somiibo BEM logs: `POST /backend-manager/marketing/webhook?provider=sendgrid` from parent forwarder
120
- - [ ] Somiibo Firestore: `consent.marketing.status: 'revoked'`, `revokedAt.source: 'sendgrid'`
121
- - [ ] Beehiiv: subscriber removed (cross-provider sync)
122
- - [ ] ITW Firestore `marketing-webhooks/{eventId}` doc exists (idempotency record)
123
- - [ ] Repost the same event manually with curl → second receipt short-circuits on `eventId`
124
-
125
- ### ☐ Test 8 — Beehiiv webhook (DEFERRED until Beehiiv plan upgraded)
126
-
127
- **⏸️ Blocked**: Beehiiv webhook API requires a paid Beehiiv tier (currently 403 `ACCESS_FORBIDDEN`).
128
-
129
- When unblocked:
130
- - Run `npm start -- --service beehiiv` in OMEGA to auto-configure all publications
131
- - OR manually add the webhook in each publication's settings:
132
- - URL: `https://api.itwcreativeworks.com/backend-manager/marketing/webhook/forward?provider=beehiiv&key=<BACKEND_MANAGER_WEBHOOK_KEY>`
133
- - Events: `subscription.unsubscribed`, `subscription.deleted`, `subscription.paused`
134
- - Publications: Somiibo (`pub_60fa806e...`), StudyMonkey (`pub_0716e341...`), shared devbeans (`pub_69c961a7...`)
135
-
136
- Then test: unsub via Beehiiv's "Manage subscription" link → verify symmetric flip on Firestore + SendGrid.
137
-
138
- ### ☐ Test 9 — Page-load consent guard (ENFORCE_CONSENT_GUARD = true)
139
-
140
- **Action:** Manually edit Test 1 user's Firestore doc via `npx mgr firestore:set users/<uid>` to flip `consent.legal.status` to `'revoked'`. Refresh the Somiibo page.
141
-
142
- **Verify:**
143
- - [ ] User is signed out (with notification toast: "This account hasn't completed setup. Please sign up first.")
144
- - [ ] Lands on public site
145
- - [ ] Browser console warning: `[Auth] Signing out user with no legal consent on record`
146
- - [ ] **Restore** `consent.legal.status` to `'granted'` so the user can use Somiibo again
147
-
148
- **Important caveat from v1.3.2 fix:** the guard only fires for accounts older than `SIGNUP_MAX_AGE` (5min). For this test to work, the Test 1 user must have signed up more than 5 minutes ago. If you just signed up and immediately ran this, the guard won't fire — wait 5 minutes or use an older test account.
149
-
150
- ### ☐ Test 10 — HMAC anonymous unsubscribe link (from a marketing email)
151
-
152
- **Action:** Trigger a marketing email send (or grab an existing unsub link from a previous email). Click it.
153
-
154
- **Verify:**
155
- - [ ] Unsub confirmation page loads
156
- - [ ] User's `consent.marketing.status: 'revoked'`, `revokedAt.source: 'sendgrid'` (or `'beehiiv'` depending on link origin)
157
- - [ ] SendGrid: removed
158
- - [ ] Beehiiv: removed
159
-
160
- ## Commands cheat-sheet
161
-
162
- ```bash
163
- # All from Somiibo backend dir
164
- cd /Users/ian/Developer/Repositories/Somiibo/somiibo-backend/functions
165
-
166
- # Logs (live tail)
167
- npx mgr logs:tail
168
-
169
- # Logs (one-shot)
170
- npx mgr logs:read --limit 100
171
- npx mgr logs:read --filter "consent" --limit 50
172
- npx mgr logs:read --filter "marketing/webhook" --limit 50
173
- npx mgr logs:read --filter "<uid>" --limit 100
174
-
175
- # Firestore
176
- npx mgr firestore:get "users/<uid>"
177
- npx mgr firestore:query "marketing-webhooks" --limit 10 # idempotency records (run from ITW backend, the parent)
178
- npx mgr firestore:set "users/<uid>" '{...partial...}' --merge
179
- npx mgr firestore:delete "users/<uid>" --force
180
-
181
- # Auth
182
- npx mgr auth:get "<email-or-uid>"
183
- npx mgr auth:delete "<uid>" --force
184
- ```
185
-
186
- ## Progress log
187
-
188
- Track which tests have been run + when. Mark with date once you've verified end-to-end.
189
-
190
- - [ ] Test 1 — Signup, marketing GRANTED
191
- - [ ] Test 2 — Signup, marketing UNCHECKED
192
- - [ ] Test 3 — Signup, legal UNCHECKED (validation blocks)
193
- - [ ] Test 4 — Google new account on /signin (reverse-signup)
194
- - [ ] Test 5 — Account opt-out
195
- - [ ] Test 6 — Account opt-in (re-grant)
196
- - [ ] Test 7 — SendGrid webhook → cross-provider
197
- - [ ] Test 8 — Beehiiv webhook (deferred)
198
- - [ ] Test 9 — Page-load guard
199
- - [ ] Test 10 — HMAC unsub link
200
-
201
- Last attempted: 2026-05-22, got blocked on Test 1 by the v1.3.1 consent-guard ordering bug. Fixed in v1.3.2. Ready to restart from Test 1 after Somiibo redeploys against `ultimate-jekyll-manager@^1.3.2`.
package/TODO-NEW.md DELETED
@@ -1,21 +0,0 @@
1
- ALSO!!!
2
- I THINK THE SIGNUP EVENT IS NOT FIRING (the manual send that comes from the user to the server)
3
-
4
- also, singup takes a while to go thru make go fstrrrr
5
-
6
- on BEM, we need to store the brand data somewhere else besides ITW because thats stupid and takes too long to load
7
-
8
- also,, need to handle the auth error for too many signups that we manually throw via beforeCreate
9
-
10
-
11
- FOR ATTRIBUTION FIXES LOOK AT
12
- /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-manager/src/assets/js/core/auth.js
13
- /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-manager/src/assets/js/core/query-strings.js
14
- /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-manager/src/assets/js/core/exit-popup.js
15
- /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-manager/src/assets/js/pages/payment/checkout/modules/tracking.js
16
- and anywhere else with attribution.!!!!
17
-
18
- FOR TRACKING FIXES (JSUTSEARCH FOR TRACKING EVENTS)
19
-
20
- CHECK OUT LEGACY!!!
21
- /Users/ian/Developer/Repositories/_Legacy/ultimate-jekyll-legacy/.github/workflows/build.yml
package/TODO-themes.md DELETED
@@ -1,34 +0,0 @@
1
- I want you to COMPLETELY REDESIGN CLASSY'S THEME. You are creating a WHIOLE NEW theme for a SaaS website.
2
-
3
- HTML
4
- /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-manager/src/defaults/dist/_layouts/themes/classy/frontend/pages
5
-
6
- INCLUDES
7
- /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-manager/src/defaults/dist/_includes/themes/classy
8
-
9
- THEME JS,CSS, ETC
10
- /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-manager/src/assets/themes/classy
11
-
12
-
13
- So when you make your NEW theme, you should COPY THIS STRUCTURE, but with your NEW THEME NAME
14
-
15
- It should primarily be darkmopde, but support light mode as well. THe design should be WARM, MODERN, SIMPLE, BUT PROFESSIONAL.
16
-
17
- For the purposes of testing this theme, you only need to make the following pages
18
-
19
- index
20
- pricing
21
- signup + signin
22
- account
23
-
24
-
25
- Today i want you to build a new theme for our framework, ultimate jekyll.
26
-
27
- See the consuming project which has the theme set in config
28
- /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-website/src/_config.yml
29
-
30
- here is a page that uses the BLUEPRINT
31
- /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-website/src/pages/index.md
32
-
33
- WHICH IS THIS
34
- /Users/ian/Developer/Repositories/ITW-Creative-Works/ultimate-jekyll-manager/src/defaults/dist/_layouts/blueprint/index.html
package/TODO-tracking.md DELETED
@@ -1,69 +0,0 @@
1
- TODO
2
- * Does signup work with BEM 5.0?? keeps ssying cannot resolve user after i sign up and try to go into accout :(
3
-
4
-
5
- FIX ATTRIBUTION
6
- https://claude.ai/share/bae8e516-e74c-4e77-9a85-e58277908b43
7
-
8
- i want to also add my own "itm" tags which are set by internal things. can we process those too?
9
-
10
- // attribution.js - load this on every page
11
- (function() {
12
- const params = new URLSearchParams(window.location.search);
13
-
14
- // Check if this pageview has any attribution params
15
- const hasAttribution = params.get('fbclid') || params.get('gclid') ||
16
- params.get('ttclid') || params.get('utm_source');
17
-
18
- if (hasAttribution) {
19
- const attribution = {
20
- fbclid: params.get('fbclid'),
21
- fbc: getCookie('_fbc'),
22
- gclid: params.get('gclid'),
23
- ttclid: params.get('ttclid'),
24
- utm_source: params.get('utm_source'),
25
- utm_medium: params.get('utm_medium'),
26
- utm_campaign: params.get('utm_campaign'),
27
- utm_content: params.get('utm_content'),
28
- utm_term: params.get('utm_term'),
29
- landingPage: window.location.pathname,
30
- capturedAt: new Date().toISOString(),
31
- };
32
-
33
- // Only save if we don't already have attribution (first-touch)
34
- if (!localStorage.getItem('attribution')) {
35
- localStorage.setItem('attribution', JSON.stringify(attribution));
36
- }
37
- }
38
- })();
39
-
40
-
41
- TODO
42
- fix tiktok pixel events (look at this)
43
-
44
- Test deletion account flow
45
-
46
-
47
- PROBLEM
48
- navigatin to https://192.168.86.69:4000/reset?authSignout=true
49
-
50
- WHILE SIGNED IT signs you out (GOOD) but then it KICKS you back to INDEX (BAD) istead of STAYING O THE PAGE
51
-
52
- FIX FORM MANAGER
53
-
54
- FIX TIKTKO PIXELS TRACKING ID NOT CORRECT
55
-
56
- output: {
57
- filename: '[name].[contenthash].js',
58
- sourceMapFilename: '[name].[contenthash].js.map',
59
- },
60
- devtool: Manager.isProd() ? 'hidden-source-map' : 'eval-source-map',
61
-
62
-
63
- signout on homepage
64
- * sign up / singin button does NOT reappear (there is just no button)
65
-
66
-
67
- try not to expose Manager??
68
-
69
-
package/TODO-tracking2.md DELETED
@@ -1,103 +0,0 @@
1
- TODO
2
- - google tag optimization
3
- https://support.google.com/analytics/thread/352854513/gtag-click-tracking-causes-reflow-due-to-reading-a-innertext-a-textcontent?hl=en
4
-
5
-
6
- - SW update error (devtools check update on reload, then reload, notice it goes forever and then logs an error
7
- // Private: Set up update handlers
8
- _setupUpdateHandlers(registration) {
9
- // Listen for updates
10
- registration.addEventListener('updatefound', () => {
11
- const newWorker = registration.installing;
12
-
13
- if (!newWorker) return;
14
-
15
- newWorker.addEventListener('statechange', () => {
16
- if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
17
- // New service worker available
18
- this._notifyUpdateCallbacks({
19
- type: 'update-available',
20
- worker: newWorker
21
- });
22
-
23
- // Automatically skip waiting and activate new worker
24
- if (this.manager.config.serviceWorker?.autoUpdate !== false) {
25
- this.skipWaiting();
26
- }
27
- }
28
- });
29
- });
30
-
31
- - tiktok error (CHECK UJ LEGACY CODE FOR TIKTOK EXAMPLES)
32
- Click
33
- console.js:36 📊 gtag: {command: 'event', event: 'cookie_consent_auto_accepted', params: {…}, fullArgs: Array(3)}
34
- console.js:36 📘 fbq: {command: 'trackCustom', event: 'CookieConsentAutoAccepted', params: {…}, fullArgs: Array(3)}
35
- console.js:36 [TikTok Pixel] - Missing 'content_id' paramter
36
- Issue: The 'content_id' parameter isn't being received. This is required for Video Shopping Ads (VSA).
37
- Suggestion: Include the 'content_id' parameter in your source code. This is required for Video Shopping Ads (VSA). See https://ads.tiktok.com/help/article/standard-events-parameters?redirected=2 for more information.
38
- eval @ console.js:36
39
- iC @ main.MTE0NjY3MDc0MQ.js:1
40
- r.warn @ main.MTE0NjY3MDc0MQ.js:1
41
- r.handleEventPayloadValidate @ main.MTE0NjY3MDc0MQ.js:1
42
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
43
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
44
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
45
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
46
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
47
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
48
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
49
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
50
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
51
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
52
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
53
- u @ main.MTE0NjY3MDc0MQ.js:1
54
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
55
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
56
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
57
- e.track @ main.MTE0NjY3MDc0MQ.js:1
58
- i.track @ main.MTE0NjY3MDc0MQ.js:1
59
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
60
- trackCookieAutoAccepted @ cookieconsent.js:354
61
- eval @ cookieconsent.js:126
62
- sentryWrapped @ helpers.js:93
63
- setTimeout
64
- eval @ browserapierrors.js:95
65
- autoAcceptHandler @ cookieconsent.js:124
66
- sentryWrapped @ helpers.js:93Understand this warning
67
- console.js:36 [TikTok Pixel] - Invalid content type
68
- Issue: The content type for one or more of your events is not valid. Content type must be either "product", "product_group", "destination", "hotel", "flight" or "vehicle".
69
- Suggestion: Go to your source code and update the content type. See https://ads.tiktok.com/help/article/standard-events-parameters?redirected=2 for more information.
70
- eval @ console.js:36
71
- iC @ main.MTE0NjY3MDc0MQ.js:1
72
- r.warn @ main.MTE0NjY3MDc0MQ.js:1
73
- r.handleEventPayloadValidate @ main.MTE0NjY3MDc0MQ.js:1
74
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
75
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
76
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
77
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
78
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
79
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
80
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
81
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
82
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
83
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
84
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
85
- u @ main.MTE0NjY3MDc0MQ.js:1
86
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
87
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
88
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
89
- e.track @ main.MTE0NjY3MDc0MQ.js:1
90
- i.track @ main.MTE0NjY3MDc0MQ.js:1
91
- (anonymous) @ main.MTE0NjY3MDc0MQ.js:1
92
- trackCookieAutoAccepted @ cookieconsent.js:354
93
- eval @ cookieconsent.js:126
94
- sentryWrapped @ helpers.js:93
95
- setTimeout
96
- eval @ browserapierrors.js:95
97
- autoAcceptHandler @ cookieconsent.js:124
98
- sentryWrapped @ helpers.js:93Understand this warning
99
- console.js:36 📊 gtag: {command: 'event', event: 'cookie_consent_accepted', params: {…}, fullArgs: Array(3)}
100
- console.js:36 📘 fbq: {command: 'trackCustom', event: 'CookieConsentAccepted', params: undefined, fullArgs: Array(2)}
101
- console.js:36 [TikTok Pixel] - Invalid content type
102
- Issue: The content type for one or more of your events is not valid. Content type must be either "product", "product_group", "destination", "hotel", "flight" or "vehicle".
103
- Suggestion: Go to your source code and update the content type. See https://ads.tiktok.com/help/article/standard-events-parameters?redirected=2 for more information.