Files
peptide-starter-theme/CHANGELOG.md
peptiderepo cb8b73f4ab v1.5.1: frontend auth hardening — rate limiting, email verification, honeypots, CSV safety
Security-only release per ADR-0001. Closes all six ship-blockers from the
post-v1.5.0 audit: PSEC-001 (no rate limiting), PSEC-002 (account
enumeration via separate error messages), PSEC-003 (registration auto-login
with no email verification), PSEC-004 (ungated "My Data" templates),
PSEC-005 (CSV formula injection on subscriber export), PSEC-006 (no
honeypot/CAPTCHA on public forms).

Adds inc/config.php (single source of truth for all security thresholds,
filterable via peptide_starter_security_config), inc/rate-limiter.php
(Peptide_Starter_Rate_Limiter + Cloudflare-aware client IP resolver,
transient-backed, never stores raw IPs), and inc/email-verification.php
(43-char token, 24h TTL, /verify rewrite, rate-limited resend endpoint).

Auth handlers rewritten to: unify all failure messages, rate-limit before
any expensive check, drop registrations with a filled honeypot silently,
stop auto-login on register, send a verification email instead. The
require_login() helper lives in inc/helpers.php and is applied at the top
of page-tracker.php, page-subject-log.php, and page-protocol-builder.php;
page-calculator.php stays open (no PII, no writes).

Newsletter signup gains: consent checkbox, privacy link, honeypot,
autoload=false on the wp_options blob, unsubscribe token stored per row,
/newsletter-unsubscribe route, merged success+duplicate into a single "ok"
state. Admin export runs every cell through peptide_starter_csv_safe()
which prefixes leading =/+/-/@/tab/CR with a quote.

Contact handler hardens against email-header injection (rejects name
values with \r \n , < >), rate-limits, honors honeypot, tags mail
failures with a request ID for correlation without logging message
content.

Adds Tools → Mail Test (inc/mail-diagnostic.php): a permanent wp_mail
probe so we can check Hostinger outbound deliverability any time it looks
flaky. Adds a one-time admin_init migration that enrols pre-v1.5.1
subscribers into the verification flow (currently a no-op — zero users —
but guarded for the future).

Other cleanup from the audit: fallback primary menu moved out of
header.php into inc/helpers.php (redeclaration risk), placeholder footer
language links replaced with "Translations coming soon", footer copyright
now reads through the customizer getter, settings-panel gains a proper
Tab/Shift+Tab focus trap and saves/restores body overflow, documentation
heading IDs slugified from heading text with collision counters, JS files
standardized on const/let.

Six new PHPUnit suites cover rate limiter lifecycle, auth handler error
unification and rate limits, email verification token generation and
expiry, contact handler header injection + rate limit + honeypot,
newsletter signup consent + CSV safety, and require_login gate behavior.

ARCHITECTURE.md and CONVENTIONS.md updated in the same commit — new
module layout, data flows, security patterns for rate-limiting,
honeypotting, gating, and CSV-safe export.

Version bumped to 1.5.1 in style.css and functions.php.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 13:01:22 +07:00

281 lines
13 KiB
Markdown

# Peptide Starter Theme - Changelog
All notable changes to the Peptide Starter Theme are documented in this file.
## [1.5.1] - 2026-04-14 — Security
Security-only release hardening the frontend authentication surface introduced
in v1.5.0. Governed by ADR-0001 (Frontend authentication and abuse-control
strategy). No breaking changes to public routes, AJAX action names, or nonce
action strings.
### Security fixes
- **PSEC-001** — Rate limiting on login (5/min per IP+email), registration
(3/hour per IP), contact (5/hour per IP), newsletter (3/hour per IP), and
verification resend (2/hour per IP+email). Transient-backed, auto-expiring.
Storage never holds raw IPs — keys are truncated `wp_hash` digests.
- **PSEC-002** — Unified error messages on login and registration. Removed
separate "username exists" / "email exists" / "user not found" branches
that enabled account enumeration via the error-message oracle. All login
failures now return `Invalid email or password.`; all registration
validation failures return `Unable to create account. Please check your
entries and try again.`
- **PSEC-003** — Removed auto-login from the registration handler. New
registrations now go through an email verification flow: a 43-char random
token (stored in user meta with a 24h TTL) is emailed via `wp_mail` and
must be clicked to activate the account. Verification route is `/verify`.
`wp_mail` deliverability can be validated any time via the new admin tool
at Tools → Mail Test.
- **PSEC-004** — `peptide_starter_require_login()` gate applied at the top
of `page-subject-log.php`, `page-tracker.php`, `page-protocol-builder.php`.
Unauthenticated users bounce to `/auth?redirect_to=…`; unverified users
bounce to `/profile?verify_required=1` which surfaces a resend button.
`page-calculator.php` stays open — it holds no PII and does no writes.
- **PSEC-005** — CSV injection fix in the newsletter admin export. Every
cell passed to `fputcsv` routes through `peptide_starter_csv_safe()`,
which prefixes values starting with `=`, `+`, `-`, `@`, `\t`, `\r` with
a single quote so spreadsheet apps won't interpret them as formulas.
- **PSEC-006** — Honeypot fields on all four public forms (login, register,
contact, newsletter). Any non-empty value fakes a success response and
drops the submission. No PII is ever logged — only a sha256-truncated
IP hash so admins can correlate if they need to.
### Added
- `inc/config.php` — single source of truth for every security threshold;
filterable via `peptide_starter_security_config`.
- `inc/rate-limiter.php` — `Peptide_Starter_Rate_Limiter` class with
`check`/`record`/`reset` lifecycle + `peptide_starter_get_client_ip()`
helper (Cloudflare-aware).
- `inc/email-verification.php` — token generation, verification route
handler, user-verified check, and rate-limited AJAX resend endpoint
(`ps_resend_verify`).
- `inc/mail-diagnostic.php` — permanent admin tool under Tools → Mail Test
that exercises `wp_mail` and surfaces duration + PHPMailer error.
- v1.5.0 user migration in `inc/page-setup.php`: existing subscribers are
enrolled into the email verification flow on first admin load after the
upgrade (guarded by `ps_verify_migration_version` option).
- Newsletter consent checkbox + privacy policy link on the signup form.
- Newsletter unsubscribe flow: every subscription now stores a token;
`/newsletter-unsubscribe?token=…` flips the `unsubscribed` flag without
requiring a login.
- Profile page verify-required banner with resend button (AJAX).
- `peptide_starter_render_honeypot()` and `peptide_starter_csv_safe()`
helpers in `inc/helpers.php`.
- PHPUnit suites: `test-rate-limiter.php`, `test-auth-handlers.php`,
`test-email-verification.php`, `test-contact-handler.php`,
`test-newsletter.php`, `test-auth-gate.php`.
### Changed
- `functions.php` loads the five new modules in dependency order.
- Newsletter handler stores entries with `autoload=false` so a large
subscriber list no longer bloats every page load. Admin notice surfaces
once subscribers exceed 1000 (threshold is configurable).
- Newsletter handler collapses `success` and `duplicate` response states
into a single `ok` state — no longer leaks subscription status.
- Contact handler rejects sender names containing `\r`, `\n`, `,`, `<`,
`>` up front (header-injection defence) and tags mail failures with a
request ID so admins can correlate without storing message content.
- Fallback primary-menu function moved from `header.php` into
`inc/helpers.php` to eliminate redeclaration risk.
- Footer placeholder language links (`href="#"`) replaced with a
"Translations coming soon" note. Will render localized links once
per-language blogs exist.
- Footer copyright now renders through `peptide_starter_get_footer_copyright()`
so the customizer control is live (was dead before).
- Settings panel now implements a proper Tab / Shift+Tab focus trap and
saves + restores `document.body.style.overflow` so nested overlays
don't corrupt scroll state.
- Documentation heading IDs are slugified from heading text with a
collision counter so deep links survive reorders.
- `assets/js/auth.js`, `settings-panel.js`, `documentation.js`,
`theme.js`, `navigation.js` standardized on `const` / `let`.
### Removed
- Auto-login on registration (see PSEC-003).
- Placeholder-link spam in the footer (see Changed).
### Documentation
- `ARCHITECTURE.md` updated with the new `inc/` module list, authentication
data flow, security abuse-control overview, and verification route.
- `CONVENTIONS.md` documents the rate-limiter usage pattern, the honeypot
pattern, the `require_login` gate, and CSV-safe export.
- ADR-0001 (Frontend authentication and abuse-control strategy) governs
the trade-offs behind this release.
### Known follow-ups (out of scope; tracked as future ADRs)
- ADR-0003 — consolidate the six duplicated tool templates.
- ADR-0004 — migrate newsletter storage from `wp_options` to a dedicated
table once subscriber count exceeds ~1000.
---
## [1.5.0] - 2026-04-14
Theme extension release: navigation dropdowns, 9 page templates, branded
frontend auth UI, newsletter signup, contact/support panel, footer update,
and Research Modules cards on the front page. Superseded by v1.5.1 on the
same day — v1.5.0 shipped with the auth-surface issues captured in
ADR-0001.
---
## [1.3.2] - 2026-04-12
### Security
- **Newsletter form nonce:** Added `wp_nonce_field()` and server-side nonce verification to the footer newsletter signup form (CSRF protection)
- **Newsletter form handler:** Added `peptide_starter_handle_newsletter_signup()` via `admin_post` action with email sanitization and validation
- **Customizer sanitize callbacks:** Added `sanitize_callback` to all five Customizer settings (hero_title, hero_subtitle, hero_search_placeholder, footer_copyright, dark_mode_default) — prevents unsanitized input from being saved
- **Checkbox sanitizer:** Added `peptide_starter_sanitize_checkbox()` helper for boolean Customizer values
### Added
- **PHPCS in CI:** WordPress-Core coding standard check added to deploy pipeline (blocks deploy on violations)
- **JS syntax check in CI:** `node --check` validation on all JS files in `assets/js/`
- **PHPUnit test scaffold:** Bootstrap, config, and initial test suites covering theme helpers, setup, and sanitizers
- **Composer dev dependencies:** PHPUnit 9, PHPCS 3, WPCS 3 for local development
- **PHPCS config:** `.phpcs.xml.dist` with WordPress-Core standard, text domain, and PHP/WP version constraints
### Changed
- **Deploy safety:** Added excludes for dev-only files in rsync (tests/, vendor/, composer.json, phpunit.xml, .phpcs.xml.dist) — prevents dev tooling from reaching production
- **CI job name:** Renamed from "Validate PHP Syntax" to "Validate PHP & JS" to reflect expanded checks
### Documentation
- Updated ARCHITECTURE.md with testing infrastructure, security details, and CI/CD pipeline description
- Updated CHANGELOG.md with this release
---
## [1.3.1] - 2026-04-10
### Added
- **PRAutoBlogger Integration:** Added `[prautoblogger_posts]` shortcode widget to front page
- Displays 6 auto-generated research articles in "Latest Research & Insights" section
- Appears between hero section and Peptide News feed
- Gracefully hides if PRAutoBlogger plugin is not active
- Uses `.prab-*` namespace for plugin-specific styling
### Changed
- **Deploy Mechanism:** Switched from GitHub Actions direct build to rsync SSH deployment
- No longer requires build step or plugin compilation
- Files deployed directly from repository to Hostinger via rsync over SSH
- LiteSpeed cache purged automatically after deploy
- Theme path on server: `~/domains/peptiderepo.com/public_html/wp-content/themes/peptide-starter/`
- Simpler CI/CD pipeline; no external build dependencies
### Technical Details
- PRAutoBlogger integration uses `shortcode_exists()` for graceful degradation
- Deploy workflow (`deploy.yml`) now runs rsync directly without intermediate steps
- Maintains backward compatibility with all existing features
---
## [1.3.0] - 2026-04-10
### Added
- **Dark Mode Toggle:** Full dark mode support with persistent user preference
- Toggle button in header (sun/moon icons)
- Preference saved to localStorage as `peptide-starter-theme`
- Respects system `prefers-color-scheme` preference
- Customizer option to set dark mode as default on first visit
- Inline script in `wp_head` prevents white flash on page load
- Custom `themechange` event dispatched to plugins for dark mode coordination
- **Plugin Coordination System:** Dark mode and theme state broadcasting
- Custom `themechange` DOM event with `{ theme: 'dark' | 'light' }` payload
- `html[data-theme]` attribute for CSS selectors
- `window.peptideStarterTheme` API for plugin access (getCurrentTheme, setTheme, toggleDarkMode)
- CSS custom properties swap automatically on dark mode toggle
- **Full Plugin Integration Suite:**
- Peptide Search AI shortcode: `[peptide_search]` in hero section
- Peptide News shortcode: `[peptide_news]` on front page
- All plugins respect theme CSS variables and dark mode events
- Graceful fallback for missing plugins (search form, empty sections)
- **Customizer Settings:**
- Hero title, subtitle, search placeholder
- Footer copyright text
- Dark mode default toggle
- **4-Column Footer Widget Areas:**
- Registered: footer-1, footer-2, footer-3, footer-4
- Default fallback content per column (About, Links, Resources, Connect)
- **Template Hierarchy:**
- Front page with hero + plugin widgets
- Generic page template with headers
- CPT support: single-peptide.php, archive-peptide.php
- 404 error page
- Search template with fallback
- **Accessibility (WCAG AA):**
- Skip-to-main-content link
- Proper heading hierarchy (H1-H6)
- Focus indicators (2px outline) on all interactive elements
- 4.5:1+ contrast ratio on all text
- Semantic HTML with proper landmarks
- `aria-label` and `aria-expanded` attributes on buttons
- Keyboard navigation support (Escape closes overlays, Tab through elements)
- **Responsive Breakpoints:**
- Mobile: 320px - 479px
- Tablet: 480px - 767px
- Desktop: 768px - 1023px
- Large: 1024px - 1439px
- Extra Large: 1440px+
- **Design System:**
- Typography: Inter font with 1.125x modular scale, 8px grid base
- Colors: Blue primary (#0066CC light, #3B82F6 dark)
- Component library: buttons, cards, forms, badges, alerts, pagination
- CSS custom properties for all design tokens
- No `!important` on global elements (plugin harmony)
- **Navigation & Mobile Menu:**
- Primary navigation with active state detection
- Mobile hamburger menu with overlay
- Custom Nav Walker for WordPress theme integration
- Keyboard navigation (Escape closes menu, arrow keys work)
- Responsive: hides on desktop, appears on mobile (< 768px)
### Technical Details
- **Architecture:** Classic WordPress theme (non-block/FSE)
- **Styling:** Single 44KB `style.css` with no build step
- **JavaScript:** Vanilla ES6+ in 2 files (navigation.js, theme.js)
- **Plugin Namespaces:** `.pn-*` (Peptide News), `.psa-*` (Peptide Search AI), `.prab-*` (PRAutoBlogger)
- **Browser Support:** Chrome, Firefox, Safari (latest 2), iOS Safari 12+
- **Requires:** WordPress 6.0+, PHP 7.4+
### Initial Release
- All core features implemented and tested
- Full dark mode support with ecosystem coordination
- Production-ready for peptiderepo.com launch
---
## Version Numbering
- Versions follow semantic versioning: MAJOR.MINOR.PATCH
- Current: v1.3.2
- Defined in: `style.css` header (line 7) and `functions.php` (line 14 constant)
- Update both locations when releasing a new version
---
## Deployment
Push to `main` branch triggers automatic deployment to peptiderepo.com via GitHub Actions.
**Process:**
1. Push to `main`
2. GitHub Actions workflow `deploy.yml` runs
3. Files synced via rsync to Hostinger
4. LiteSpeed cache purged
No manual FTP uploads needed.