← Back to docs

Tools API - Changelog

Language: EN | EN | SV

Tools API - Changelog

This changelog highlights user-facing improvements across the Tools platform.


2026-04-01

Social media tools (Facebook admin stats) – rolling 40-day default window

  • The dashboard at /admin/social-media-tools/facebook now defaults to a rolling 40-day range ending today.
  • Example behavior: if today is 2026-04-10, default date_from is 2026-03-01 and date_to is 2026-04-10.
  • User-provided date filters still override the default window exactly as before.

2026-03-31

RSS editor – new visual XPath Lab

  • Added a new editor-side XPath tool at /rss/xpath-lab (permission: rss) for debugging and building XPath rules from pasted HTML snippets.
  • The page shows a visual DOM outline with per-node XPath, key attributes, and text previews to make selector discovery faster.
  • Added optional XPath execution on the same page (xpath_query) with immediate match previews (node path, tag, text, and snippet).
  • Added a SimpleXML-style XML preview block so users can inspect the normalized parser tree before writing elements rules.
  • Added quick navigation from /rss to the new lab and a helper link in the auto-detect HTML-context section.

Feed questions – richer version snapshots + navbar cleanup

  • Version snapshots now include text evidence: version_history.articles[*].versions[*] now includes description and conditional content excerpts (when content is present), not title-only rows.
  • Payload remains compact: excerpts are trimmed and still pass through context-budget trimming to avoid oversized AI requests.
  • Top navbar cleanup: removed My To Do, Whisper, and Whisper Admin shortcuts from the global navbar.
  • Service discovery unchanged: Microsoft To Do and Whisper remain available via /services (permission-aware cards).

Feed admin – configurable default page size for /feed

  • Added a new feed-admin global setting for Public /feed default feeds per page.
  • The public feed page now uses this saved value when no per_page query parameter is provided.
  • Explicit query override still works (/feed?per_page=...) and values remain clamped to safe bounds.

RSS entry admin – per-post import ignore + hard one-row purge

  • Added entry-level admin controls on /feed/entry/{contentId} for noisy posts:
    • Ignore this post at import (feed-scoped or global), implemented as a link block rule.
    • Allow import again to remove that ignore rule.
    • Purge all except one latest row for the link (hard reset).
  • Existing cautious-mode dedup purge is still available and now works alongside import-ignore for problematic links that keep cycling.

Feed user questions – JSON context, version history, period fixes

  • Timeout fix: Version history context for site-focused questions is now cached (5-minute TTL per site), eliminating the 30-second execution timeout on /feed/{urlid} question panels.
  • Monthly period corrected to 31-day rolling window: Monthly feed context now covers 31 days (today minus 30 days) instead of the previous 30-day window.
  • Structured JSON context for site-focused questions: When a question targets ≀10 specific sites, the AI context is now delivered as structured JSON with the following top-level keys:
    • context_type, analysis_note, period_metadata – scope metadata
    • feeds – list of matching feeds with id, title, category, url
    • recent_entries – period-filtered entries with version count annotation
    • version_history – period-independent list of all edited articles with every stored version (v1=oldest, vN=newest), title change notes between adjacent versions, and permalinks
    • top_terms, stats – frequency summary and scope counters
  • Version history is period-independent: version_history.articles covers ALL recorded time regardless of the selected period (daily/weekly/monthly/yearly), so the AI can answer questions about article edits spanning any date range.
  • Prompt updated for JSON context: When context is JSON, the AI is explicitly instructed to use version_history.articles to answer questions about edits, content changes, title evolution, and publishing history.
  • Entry limit reduced for narrow-focus queries: When version history is the primary context, the period-entry sample is capped at 25 items to reduce query load.
  • RSS query performance indexing: Added new RSS DB indexes for buildContextSnapshotFresh() and version-history lookups to reduce latency/timeouts under scoped questions:
    • content(urlid, pubdate, contentid) for period-window entry sampling
    • content(urlid, link, content_hash) for version-count grouping
    • content(urlid, link, pubdate, contentid) for version-history row retrieval
    • urls(deleted, is_hidden, category, title, urlid) (or urls(deleted, category, title, urlid) where is_hidden is absent)
  • Prompt size protection added: Feed-question JSON context is now compacted before sending to OpenAI to avoid TPM/input-limit failures.
  • Version history is now sampled, not fully expanded: Each edited article keeps total version_count, title_change_count, first_published, last_published, and a compact sampled versions[] list instead of every stored revision.
  • Context budget trimming: Large scoped questions now trim low-value sections first (debug_summary, domains, some sources/terms/feeds/recent entries) and then reduce version_history.articles until the JSON payload fits the configured character budget.

2026-03-30

Whisper – Permission-gated transcription queue (web + API + admin)

  • Added a new Whisper transcription tool for authorized users at /whisper (permission:whisper.use).
  • Added admin queue console at /admin/whisper (permission:whisper.manage) with all-user visibility and run-now trigger.
  • Added authenticated API endpoints under /api/whisper/*:
    • GET /status
    • GET /jobs
    • POST /jobs
    • GET /jobs/{jobId}
    • POST /run-now (manager/admin)
  • Added queue persistence table whisper_transcriptions with stage/progress fields, retry metadata, transcript storage, and owner linkage.
  • Added scheduled queue processing (whisper:process --limit=1, every minute) plus host config/env support (WHISPER_*) for binary path, timeouts, retries, and SSL behavior.

Facebook moderation charts – stronger bar colors

  • Increased chart palette contrast and fill intensity for moderation and returning-customer series.
  • Increased series border weight so bars/lines remain easier to distinguish in dark theme and screenshots.

Microsoft To Do – User web UI + authenticated API with bidirectional sync

  • Added a new personal Microsoft To Do integration for authenticated users at /settings/integrations/microsoft-todo.
  • Users can now connect a Microsoft account, browse synced lists, create/edit/delete lists, and create/edit/delete tasks directly inside Tools.
  • Added authenticated API endpoints under /api/microsoft-todo/* for status, sync, list retrieval, task retrieval, and list/task mutations.
  • Sync now runs in both directions: Tools changes are pushed to Microsoft To Do, and remote Microsoft To Do changes are pulled back into Tools.
  • Added a local mirror for lists/tasks plus a scheduled sync job (microsoft-todo:sync) that runs every 15 minutes.
  • Added documentation, OAuth route reference, services discoverability links, and Android API-contract notes for the new endpoint family.

Social Media Tools – SocialGPT-only dashboard history + complete history page

  • The AI prompt and response history panel on /admin/social-media-tools/facebook now shows only SocialGPT history rows.
  • SocialGPT scoping uses request-log metadata (source=social_media_extension, SocialGPT tool slug, and feature_slug=gpt) for both list and detail views.
  • Added a separate admin page for complete request history: /admin/social-media-tools/audit/complete.
  • The complete history page supports filtering by source, tool slug, feature slug, user, status, model, and request mode.
  • Existing log creation/storage is unchanged: all request logs are still persisted as before.

RSS – Restored inbound processing and feed generation helpers

  • Restored missing internal helper methods in RssController that had caused runtime failures during RSS inbound conversion.
  • Fixed /api/rss/update crashes caused by missing canQuery() and handleWordPressRestApi() methods.
  • Restored the related content deduplication, import-rule filtering, JSON/XML conversion, and feed-generation helper chain used by RSS processing.
  • This also restores the controller-side helper path used by /api/rss/feed/* and analytics feed selectors after the accidental method removal.

2026-03-29

Public Feed – Language Switcher Translation Fixes

  • Fixed missing translations in the Ask a question panel across all languages when switching the feed language.
  • JS submit handler now uses the active feed language for all inline status messages, button text (Asking…), the re-rendered answer box labels (Latest answer, Q:, A:), success text, and error messages β€” instead of always showing English.
  • Added five new translatable phrase keys available in all languages (en, sv, da, no, fi):
    • ask_error_required – shown when the question field is left empty.
    • ask_error_captcha – shown when the captcha has not been completed.
    • ask_success_answered – shown after a successful answer is received.
    • ask_error_generic – shown on network/server errors.
  • Fixed missing ask_asking phrase in the Norwegian (no) language entry.
  • Site-specific analytics period headings (Daily, Weekly, Monthly, Yearly) and Read more / Show less buttons now respond to the language switcher.
  • Added site_analytics_title phrase key (site-specific AI analysis summary label) to all languages.

nginx – TLS Hardening

  • Updated TLS configuration in nginx/tools.tornevall.net.conf to remove deprecated TLSv1 and TLSv1.1.

  • Now only TLSv1.2 and TLSv1.3 are accepted.

  • Updated cipher suite to modern ECDHE/CHACHA20/AES-GCM set and set ssl_prefer_server_ciphers off (lets clients negotiate the best mutual cipher).

  • Updated scraper URL selection so always=0 is now agent-aware instead of globally gated by urls.lastscrape.

  • Each scraper agent (agent_id) now tracks per-URL claim state: when it last saw a URL and when it is next allowed to see it.

  • Interval checks for always=0 now use the URL's configured readinterval together with that agent-specific seen state.

  • always=1 now returns all non-deleted/non-noscrape RSS URLs (no interval filtering).

  • Added backend persistence table rs_agent_url_seen (RSS DB) for per-agent URL scheduling state.

Facebook Statistics – Strict Duplicate Report and Safe AJAX Cleanup

  • Added a strict duplicate report to Recent stored moderation events on the Facebook admin dashboard.
  • Duplicate groups are now explicitly marked as either Guaranteed clear or Blocked.
  • Cleanup is now AJAX-driven and removes only guaranteed duplicate rows from the currently filtered scope.
  • A group is clearable only when duplicate identity is strong (client_event_key or network_activity_id) and all key event fields match exactly.
  • Any mismatch (or heuristic-only identity) is blocked from deletion to prevent accidental removal of potentially unique events.

Feed Questions – Period Inference and Empty-Answer Failover

  • Feed question processing now infers context period from question wording (today/day, week, month, year) when no explicit period is selected.
  • Saved question metadata now includes period source (user_selection, question_text, or admin_default) for traceability.
  • Added empty-answer failover in the feed question service: if the primary model returns an empty answer, it retries once with gpt-4o-mini.
  • If the final answer is still empty, the request now returns an error instead of showing a false "Question answered" success state.

Facebook Statistics – Action Type Filter for Charts

  • Added an Action types shown multi-select filter to the Facebook moderation dashboard charts panel.
  • Select one or more outcome types (Approved, Rejected, Removed, Edited, Added, Blocked, Revoked, Observed) to narrow the charts to only those event categories.
  • Leaving the selection empty shows all types (previous default behavior preserved).
  • The filter applies across all three charts (moderation activity, outcome distribution, returning customers).
  • Active outcome filter is shown in the filter status label (e.g. "Types: Approved, Rejected").
  • The outcome type selection is preserved in chart share URLs.
  • Fixed dashboard behavior so selecting action types and pressing Apply filters / Show charts stays in the AJAX flow (no full page reload).
  • Fixed persistence of selected action types so the multi-select no longer clears itself after refreshes and chart rendering.

Public Feedreader – Language Switcher (/feed)

  • Added a browser-aware language switcher to the Tornevall Networks Feedreader header card on the public /feed page.
  • Supported languages: English (EN), Swedish (SV), Danish (DA), Norwegian (NO), Finnish (FI).
  • Language is detected automatically from the browser's navigator.languages preference on first visit, then persisted in localStorage.
  • Flag+code buttons in the header card let users switch at any time without a page reload.
  • All major UI phrases translate on the fly: page title, subtitle, the Ask-AI panel (labels, placeholders, buttons), column headers, category action buttons, analytics section, recent questions card, and read-more controls.
  • Default built-in phrases live in config/feed_phrases.php (editable as code).
  • Administrators can override individual phrases per language without deploying, using the new Phrase Editor section in Feed Admin (/rss-admin β†’ 🌐 Public feed phrase editor).

Public Feedreader UI – Category Card Layout (/feed)

  • Analytics language dropdowns in each category card now follow the active feed language automatically β€” switching the flag in the header also updates all variant language selectors on the page.
  • On page load, analytics dropdowns initialise to the browser/stored language instead of always defaulting to English.
  • Category panel open/closed state is persisted in localStorage and restored on each visit, so the page opens where you left off.
  • Category headers are fully clickable for expand/collapse (keyboard accessible). The toggleCategory() function is now correctly wired.

Feed Questions – Default model and reasoning (/feed)

  • The default AI model for feed questions has been updated to gpt-5.4, which handles reasoning natively.
  • A new Output style / persona instructions field has been added to the feed question settings page (/feed/user-questions). Free-text, max 500 characters, injected directly into the prompt. Use it to enforce plain prose, suppress bullet lists, or shift the output personality without touching the underlying prompt profile.

RSS Inbound Queue Cleanup (/api/rss/update)

  • Updated inbound maintenance so rows marked handled=1 are now purged as soon as they are unlocked (processlock=0) during update runs.
  • Removed the previous one-day retention window for handled inbound rows to keep the inbound table lighter under sustained feed traffic.
  • Clarified lock-safe cleanup behavior so active rows (processlock=1) are not purged.
  • Added a configurable stale lock release window for inbound rows with processlock=1 via RSS admin (/feed-admin, alias /rss-admin) using setting key feed_admin.inbound.processlock_release_minutes.
  • Default stale lock release window is now 30 minutes (bounded to 5..720 minutes) and is applied to both handled and unhandled stuck inbound lock recovery.
  • Stale-lock recovery now evaluates lock age (when a row was lock-claimed) instead of only row creation age, reducing false unlocks for older rows that are actively being processed.
  • Lock claim/release handling now tracks lock timestamps so unlocked/handled paths clear lock age state consistently before cleanup.

Public Feedreader UI – Category Card Layout (/feed)

  • Reorganized the public feed list into clearer per-category card sections so each category is visually separated and easier to scan.
  • Kept category expand/collapse behavior and existing interactive controls (subscriptions, analytics variant selectors, read-more toggles, and AJAX actions) intact.
  • Preserved all existing feed rows and analytics data while improving readability with stronger card framing and category-focused visual hierarchy.
  • Category sections now start collapsed by default and use accordion behavior (opening one category collapses others) for a cleaner reading flow.
  • Category cards now expand/collapse by clicking the category header or arrow button (keyboard-accessible), replacing the separate Show details button.
  • Standardized category action button sizing in the card header to keep controls visually consistent.

Feed Questions – Default model and reasoning (/feed)

  • Updated the default feed-question answer model to gpt-5.4.
  • Feed-question requests now include reasoning_effort=medium for reasoning-capable models (gpt-5*, o1*, o3*, o4*).
  • Increased feed-question output token ceiling to support longer reasoning responses when needed.

2026-03-28

RSS Editor – Improved Auto-detect + AI Fallback + Blogspot Support

  • WordPress-first detection: The "πŸ€– Auto" button in the /rss editor now attempts the WordPress REST API (/wp-json/wp/v2/posts?per_page=100) before any other method. If the site serves valid WP-JSON posts the real_url is set to the REST API endpoint with ?per_page=100 (to retrieve more posts than the default RSS feed) and sitetype is set to wp. Falls through to standard RSS discovery if wp-json is disabled or unavailable.
  • HTML <link rel="alternate"> extraction: If WordPress REST API is not available, the editor now fetches the page HTML and parses all <link rel="alternate" type="application/rss+xml|atom+xml"> tags to discover the canonical feed URL declared by the site itself β€” avoiding guessing.
  • Blogspot/Blogger detection: Sites hosted on *.blogspot.* are now flagged in the auto-detect response. A warning is shown in the editor status line noting that Blogspot RSS output is minimal and that full-HTML scraping may be added in the future.
  • OpenAI AI fallback: If all structural methods fail (no WP-JSON, no <link rel="alternate">, no common feed pattern), the editor now calls OpenAI (gpt-4o-mini via the configured OpenAI provider) with a truncated snapshot of the page content and asks it to suggest a feed URL. The result is used as a fallback and clearly flagged with "πŸ€– AI-suggested URL – please verify" in the UI. Silently skipped if OpenAI is not configured.
  • Blogger default Atom feed (/feeds/posts/default) added to the common feed URL probe list.
  • Status display enriched: The analyze status line now distinguishes between AI-suggested, Blogspot, fully auto-detected, and fallback outcomes with colour-coded messages and an optional detail note.

RSS Extra Content Table (RSS DB)

  • New table extra_content added to the RSS database (migration 2026_03_28_100000_create_rss_extra_content_table).
  • Purpose: store supplementary scraped data for feeds that produce minimal RSS output (e.g. Blogspot), including full-HTML snapshots (html_blob) and screenshot file references (filepath).
  • Columns: urlid, contentid, link, content_hash, scrape_type, filepath, html_blob, scraped_at.
  • No scraper writes to this table yet; the schema is prepared for future extra-scraping workflows.

Feed Question Scope and Period (/feed)

  • Added a per-question Question period selector on /feed (daily, weekly, monthly, yearly) so each question can choose its own analysis window without changing global admin defaults.
  • Updated feed-question context generation to scale breadth by selected period (broader periods include larger context snapshots).
  • Added daily cache reuse for yearly feed-question context snapshots to reduce repeated heavy context assembly during the same day.
  • Updated focus-site selector behavior so the public Focus sites (optional) list excludes hidden feeds.
  • Updated default scope behavior so when no focus categories/sites are selected, question context can include all non-deleted feeds (including hidden) for broader analysis, while hidden feed links/keys are still not exposed in generated context text.

RSS Scraper + Ingest Diagnostics (/api/rss/data)

  • Updated scraper runtime progress output to include feed titles in addition to urlid and URL, improving operator visibility during batch runs.
  • Updated POST /api/rss/data response payload (received) so each row now also includes the feed title from urls.title.
  • Improved RSS/Atom conversion diagnostics with explicit per-inbound summary logging (candidates, converted, and skip counters) to make zero-entry outcomes easier to diagnose.
  • Added Atom/RSS entry-link fallback handling plus Google Alerts redirect normalization (https://www.google.com/url?...) to better preserve destination links during import.

2026-03-27

My Profile (self-service account settings)

  • Added a new authenticated My Profile page at /users/profile where users can update their own name and email.
  • Added optional password setup/change on the same page (current password required for sensitive updates when a password already exists).
  • Moved Google account linking/unlinking management from My API Keys to My Profile to keep sign-in settings in one place.
  • Added a new My Profile shortcut in the navbar for logged-in users.
  • Tightened navbar spacing/wrapping so the new profile link fits without overflow on smaller widths.

Stability fixes (RSS + MCU pages)

  • Fixed /online admin location visibility so tracked request URIs are matched more reliably against active sessions. Page-visit writes now tolerate missing optional columns during partial deployments, and online matching now falls back more safely for user/session/user-agent combinations.
  • Updated /online so authenticated admins/users with users permission now see the detailed location-aware online view on that same URL instead of the simplified public table.
  • Fixed RSS editor runtime error on /rss where legacy Blade flags ($hasProtectedColumn, $hasUseProtectedColumn) could be undefined if deprecated columns are absent.
  • Changed RSS admin access behavior so users without RSS admin permission are redirected to /feed when visiting /rss, /feed-admin, or /rss-maintenance-admin, instead of seeing login/403 pages.
  • Fixed RSS editor table column alignment on /rss by restoring row cells for protected and useProtected, preventing is_hidden/public_hash values from appearing under the wrong headers.
  • Updated RSS editor inline field is_hidden on /rss from a free-text input to a checkbox, with AJAX save now posting explicit 1/0 values.
  • /admin/jobs RSS Analytics Scheduler is now editable (enabled toggles + run_at per period) and includes a manual "Run Scheduler Check Now" action.
  • Added a strict scheduler window guard in rss:generate-analytics: direct cron runs now respect per-period enabled + run_at, skip before slot time, and skip already-completed period keys; manual override remains available via --ignore-scheduler-window.
  • Updated /mcu web route to redirect to the controller-backed MCU editor route (mcu.index) instead of rendering the editor Blade without required view data (which caused $perPage/filter variables to be undefined).

Google OAuth Login / Registration

  • Users can now sign in or register using their Google account from the login and register pages.
  • New users who register via Google are automatically email-verified; no verification email is required.
  • Account sync / linking: if you sign in with Google and your email already exists in the system, the Google account is linked to your existing account automatically on first Google sign-in.
  • Already-logged-in users can link their Google account from the My API Keys page (/keys/mine) β†’ "Google Account" section.
  • Linked accounts can sign in with either Google or email/password.
  • Unlinking is possible from the same page; requires a password to be set first.
  • A single redirect URI (/auth/google/callback) handles both sign-in and linking flows.
  • Setup: add GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, and GOOGLE_REDIRECT_URI to .env (see .env.example).

Visit Statistics – RSS Scraper Exclusion

  • The API Requests Trend chart and total API request counter on /admin/visit-stats now exclude RSS scraper/cron paths by default.
  • Excluded paths: /api/rss/data, /api/rss/urls, /api/rss/update, /api/rss/feed/analytics-*, /api/rss/analytics/run.
  • A toggle button ("πŸ€– Scrapers: excluded / included") is shown next to the date-range selector to switch between filtered and unfiltered views.
  • The chart title and summary card badge reflect the active filter state.

MCU Timeline – Info and Support Links

  • Added "More info & live API" link to tools.tornevall.net and "GitHub / Support" link to https://github.com/Tornevall/mcu-timeline-api at the top of the MCU Timeline editor page.

DNS Editor / DNS API Cache Performance

  • Reworked DNS zone cache storage from a single serialized bulk blob per zone to row-based cache records (dns_zone_cache_records) to support very large AXFR zones with significantly faster paged reads.
  • Added an IP-extra index table (dns_zone_cache_ip_extras) populated for forward A/AAAA records and decoded reverse-owner entries (DNSBL/OPM style), so future CIDR workflows can use indexed IP metadata.
  • Changed record mutation behavior (POST /api/dns/records/add|delete|update|bulk) to synchronize cache rows after confirmed successful master DNS updates instead of invalidating full zone caches.
  • Added per-zone cache invalidation policy settings in dns_zone_settings:
    • cache_invalidate_enabled (default false)
    • cache_invalidate_interval_seconds (default 259200 = every 3 days when enabled)
    • last_invalidated_at
  • Added scheduled command dns:cache:invalidate (hourly scheduler hook) that only invalidates zones where policy is enabled and due.

2026-03-26

RSS Analytics Scheduler Timing

  • Tightened the built-in analytics scheduler so a period only executes at its configured time or as soon as possible after that time if the slot was missed.
  • First-run behavior no longer fires immediately at arbitrary times; it now waits until the configured period slot is actually due.
  • Added a static scheduler status card on /admin/jobs that shows per-period analytics run configuration (enabled, run_at) and latest scheduler state (last_run_at, status, key/reason), so operators can verify timing behavior without opening Feed Admin first.
  • Updated tornevall-tools-cron to run php artisan schedule:run every minute so configured analytics schedule times are actually respected by the scheduler.

Public Landing (/)

  • Expanded the authenticated "Your available tools" shortcut card to include a significantly broader permission-aware tool set (RSS, DNS, jobs, admin/security, messaging, integrations, and user tooling).

Online Sessions (/online admin view)

  • The admin online session list now shows each visitor's latest tracked location (request URI) when available.
  • Added a short recent path trail/backtrack list so admins can see where a visitor has just been moving inside the site.
  • Page visit tracking now stores authenticated user_id consistently and can also store Laravel session_id for more accurate session-to-location matching.

2026-03-25

Feed User Questions (/feed + /feed/user-questions)

  • Guest captcha fix: Fixed guest submissions on /feed so the question form now reuses the shared global Turnstile key when the older feed-specific provider key is missing. The page also now blocks submit until a captcha token is present and shows a clearer temporary-unavailable notice instead of failing silently when captcha keys are not configured correctly.
  • Per-question focus selectors added: When asking a question on /feed, users can now optionally focus the AI's analysis on specific categories or sites using two new multi-select dropdowns:
    • Focus categories (optional): Select one or more categories to narrow the context snapshot (helps de-prioritize less interesting feeds like general news).
    • Focus sites (optional): Select one or more feeds to focus on specific sources.
    • Leaving both empty uses all visible feeds (default behavior). If both are selected, the AI uses either match ("any" logic).
    • These selections override the global admin scope settings for that individual question only and are saved in question history for audit/replay.
  • Focus selection semantics tightened: For /feed user questions, selected focus_site_ids[] now override category focus for that question (instead of category-driven broad matching). This keeps context/query scope aligned with the explicitly selected sites and reduces oversized prompts.

RSS Analytics CLI / Scheduler

  • --force now actually forces overwrite: php artisan rss:generate-analytics now skips unchanged bucket+variant signatures by default and reuses the cached row instead of spending extra AI calls on identical snapshots.
  • Added --overwrite-current as a clearer alias for --force when operators explicitly want to re-run and overwrite the current bucket row.
  • Admin-configurable scheduler control: /feed-admin now includes per-period scheduler controls (daily/weekly/monthly/yearly) with enable/disable and run-time fields. A minute-level scheduler command (rss:run-scheduled-analytics) now handles due/catch-up execution from cron.
  • Robust catch-up + first-run behavior: If a period has never run before (no timestamp), it is executed immediately once. If a configured run time was missed, it executes as soon as possible afterward.
  • Automatic run identity + overwrite semantics: Scheduler-triggered runs use a dedicated auto variant title ([AUTO] Scheduled analytics) and always overwrite the current automatic bucket variant in place.
  • Timestamped analytics log output: rss:generate-analytics now prefixes output lines with date/time, making rss-analytics.log easier to audit per generation.

Public Landing / Services (/ and /services)

  • Unified the public service discovery pages so both / and /services now render the same landing view.
  • Removed the separate authenticated "admin card wall" from the landing page to keep the entry experience focused on public services.
  • Kept one maintained card layout for public services to avoid duplicated UI maintenance across multiple views.
  • Simplified navbar home/services navigation to normal route links (no homepage-only JavaScript branch).

2026-03-24

Menstrual Tracking (/menstrual-tracking)

  • Added a new authenticated user tool for menstrual cycle monitoring with a simple web UI.
  • Users can save profile baseline fields (birth_date, first_period_started_on) and register cycle starts either as exact dates or month-level entries.
  • The tool now shows a basic cycle overview: average cycle length, latest start, estimated next start, and current cycle day.
  • Added paginated cycle history with per-row delete in the same UI.
  • Added service discoverability links from /, /services, dashboard cards, and navbar.
  • Added EN/SV end-user docs page: /docs/en/menstrual-tracking and /docs/sv/menstrual-tracking.

Cron / Runtime Stability

  • Added optional runtime flag PHP_SUPPRESS_DEPRECATIONS in bootstrap to mute noisy PHP deprecation notices (E_DEPRECATED, E_USER_DEPRECATED) on PHP 8.4+ when running older vendor stacks.
  • Added .env.example documentation for the flag.
  • Added troubleshooting section in docs/cron.md for deprecation warnings in cron output.

2026-03-23

Feed User Questions (/feed mini-card + /feed/user-questions)

  • "Read more" for long answers: Recent questions on the /feed page now show a truncated preview (280 chars) of each answer. If an answer is longer, a read more / read less toggle button appears, allowing inline expansion without leaving the page.
  • Custom AI response tone (optional): The feed question settings page now allows tone to be left empty (no longer required). An empty tone falls back to the default neutral instruction when answering questions. Admins can still select: Neutral, Analytical, Brief, Friendly, or Critical from the dropdown.
  • More AI models available: The answer model selector is now a dropdown instead of a free-text field, with options:
    • gpt-4o-mini (default, fast)
    • gpt-4o (general purpose)
    • o1-mini (reasoning)
    • o1 (advanced reasoning)
    • o3-mini (extended reasoning)
    • Reasoning models (o1/o3) automatically fall back to gpt-4o-mini if the model is unavailable or fails, ensuring a graceful recovery without user-facing errors.

RSS Subscriptions (/feed/subscriptions) β€” Stricter Duplicate Filtering

  • Re-delivery of cycling versions prevented: The subscription notifier now tracks every content_hash that has ever been delivered for each link within a subscription. If a new import row has the same hash as any previously reported version of that link (even if it received a new contentid due to cycling content β€” Aβ†’Bβ†’A), it is silently skipped and not re-reported. This prevents notification spam from feeds that repeatedly publish minor or near-identical variations.

RSS Import β€” Global Version Deduplication

  • Cycle-safe global hash check in import: The import dedup guard (canQuery) now also checks whether the new entry's content_hash or meaningful_hash already exists in any previous row for that link, not just the most recent row. This closes the Aβ†’Bβ†’A cycling hole where version A was being reinserted into the content table even though it already existed in older history. Both content_hash and meaningful_hash are checked globally via indexed existence queries, preventing runaway version accumulation from feeds with cycling or near-identical content.

Disney / BAMGRID Scraper (projects/scraper/ondisney.php)

  • original_url fallback always populated: Disney sitemap URLs always carry locale prefixes (e.g. en-be, nl-nl). The scraper previously only set original_url on the rare case of a URL without a locale prefix, meaning most items never had original_url set and were silently dropped by the import engine. Now the scraper falls back to a preferred English locale (en-us β†’ en-gb β†’ en-ca β†’ first en-* β†’ first available) and always sets original_url (and original_title if missing) on each item. Existing elements DB JSON for site 8 is unchanged; the fix is in the scraper output.

Development & Documentation

  • RSS elements format fully documented: Added a complete reference in the internal BAMGRID notes (docs/en/bamgrid-sitemap-extraction-notes.md, docs/sv/bamgrid-sitemap-extraction-notes.md) explaining both supported elements JSON formats:
    • Format A (begin/table): JSON traversal β€” begin navigates from root to the item array; table maps content columns to source keys (string = direct key, array = nested traversal).
    • Format B (XPath pipeline): 4-element array β€” row selector XPath, per-field sub-selectors, value type list, transform table. Used for raw HTML/XML feeds.
    • Included the correct elements DB JSON for Disney/BAMGRID site 8 with field-mapping table and explanation of why all locales need to be considered.

RSS Maintenance Admin (/rss-maintenance-admin)

  • "Mark as cautious" flag: Each suspicious link row now has a ⚠ Mark cautious button. Marking a link stores a persistent flag (rss_cautious_links table) so future imports of that link automatically run the dedup/purge pass after each new insert β€” only distinct meaningful versions are kept.
  • Unmark cautious: A βœ“ Unmark cautious button appears on already-flagged rows to clear the flag.
  • Visual indicator: Cautious-flagged rows are highlighted in the table and show a badge next to the link.
  • AJAX-first interactions: Filter refresh, dry-run purge, purge now, mark cautious, and unmark cautious now run asynchronously in /rss-maintenance-admin (with non-JS form-submit fallback still intact).
  • Fixed mark-cautious request bug: POST /rss-maintenance-admin/mark-cautious now handles omitted reason safely (no more Undefined array key "reason" when the field is not provided).

RSS Feed Entry (/feed/entry/{contentId})

  • Admin actions block: Admins (users with permission:rss) now see an Admin actions panel at the bottom of every entry permalink page with:
    • ⚠ Mark as cautious β€” flag the entry's link so future imports auto-purge noisy duplicates.
    • βœ“ Unmark cautious β€” remove an existing cautious flag.
    • πŸ—‘ Purge noisy duplicates β€” instantly purge redundant versions of this specific entry, keeping the newest row per distinct meaningful hash. No more manual MySQL work.

RSS Subscriptions (/feed/subscriptions)

  • Fixed: save with all channels unchecked now works β€” previously, unchecking all channel checkboxes (Email, Slack, Discord) caused a validation error and the form could not be saved. Now saving with zero channels is allowed and disables all notifications for that subscription.
  • Autosave channel UX (AJAX-first) β€” channel checkboxes now save immediately, webhook/text fields save on blur, and the channel chips/state update inline without requiring a manual "Save channel settings" workflow.
  • Empty channel list now persists correctly β€” explicit channels_json=[] remains "all channels disabled" instead of defaulting back to Email (mail) in UI rendering.

Feed Admin (/feed-admin)

  • Public column visibility moved to feed-admin: The "Public column visibility" settings block has been moved from the public /feed page to /feed-admin. All RSS feed configuration for admins is now in one place. The public feed table column layout still reflects saved settings as before.
  • Segment-level anchor dates in generation cards: Category and site generation cards now include optional per-segment anchor date inputs. Generation precedence is now segment anchor -> global anchor -> current date, making historical runs explicit per card.

RSS Editor (/rss)

  • XPath-only elements visibility: The large elements JSON editor is now shown only for rows where sitetype is xpath, reducing table width pressure for normal RSS/WP rows.
  • Collapsible elements editor: XPath rules are now edited in an expandable/collapsible per-row panel so the main list remains compact.
  • elements save on blur (AJAX): elements textarea changes are now saved when the field loses focus; other inline fields keep instant AJAX save on change.

RSS Feed Analytics

  • Anchor-date calendar for generation: /feed-admin category/site analysis generation now includes an Anchor date picker. Admins can generate daily/weekly/monthly/yearly analytics for earlier periods (for example last week) if a cron run was missed.
  • Generation payload update (web UI): Feed-admin generation requests now send optional anchor_date (YYYY-MM-DD) to target historical period buckets when creating/replacing cached analysis variants.
  • Scheduler cadence aligned to 20:00 daily: app/Console/Kernel.php now schedules rss:generate-analytics --period=daily once per day at 20:00. Weekly/monthly/yearly remain available via manual CLI/API triggers.
  • Overwrite semantics clarified: Re-running generation for the same period bucket and same variant now explicitly documented as an in-place update/replace (no duplicate row for that same variant+bucket).
  • Replace UI fixed for all periods: /feed-admin now shows cached daily variants alongside weekly/monthly/yearly, and regenerate/replace actions refresh the page after save so overwritten category/site variants become visible immediately.

Development & Documentation

  • BAMGRID sitemap extraction notes (internal): Added internal documentation at docs/en/bamgrid-sitemap-extraction-notes.md and docs/sv/bamgrid-sitemap-extraction-notes.md with verified Disney sitemap structure, namespace-safe XPath candidates (url/loc/lastmod/xhtml:link), measured language-coverage impact (en-*-only would drop ~37.1% of unique IDs), and a recommended path toward a dedicated bamgrid import type with canonicalized per-content output.
  • RSS editor xpath/json rule hardening: /rss now exposes explicit xpath/json site types in Add URL flow, supports editing elements JSON rules inline when the column exists, validates elements payload format server-side, and requires elements when sitetype=xpath.

Public Feed UX

  • Feed question submit via AJAX: The Ask about all open feeds card on /feed now submits inline with JSON responses and shows status/answer directly on the page (no full reload). Non-JS fallback form behavior remains supported.
  • Feed question context upgraded + profile fallback: Feed Q&A prompt context now uses analysis-like aggregates from stored rss.content data for all non-hidden feeds (categories, sources, domains, terms, entry examples). Added OpenAI profile fallback handling so missing prompt-profile config no longer hard-fails with "No prompt profile configured".
  • Feed question scope is now configurable: Admins can now restrict /feed question context by period, allowed categories, allowed site ids, context entry cap, answer sentence cap, and mini-history size. The /feed card also shows a small recent-question history inline.
  • Question history pagination: /feed/user-questions now supports practical pagination defaults with configurable rows-per-page to keep large/spammy histories manageable.
  • AJAX delete for question history (admin): Admins can now delete question rows inline on /feed/user-questions via AJAX (DELETE /feed/user-questions/{question}), with non-JS redirect fallback preserved.
  • Q&A answer model + tone settings: Feed question admin settings now include configurable answer model and answer tone (available on both /feed/user-questions and /feed-admin settings blocks), and these settings are applied when OpenAI answers are generated.
  • Admin filters on question history: /feed/user-questions now supports filtering by status, user_id (or guest), ip, and deleted scope (active/deleted/all) to moderate noisy histories faster.
  • Bulk moderation delete with mode: Admins can now delete selected question rows in bulk (POST /feed/user-questions/bulk-delete) and choose hard (permanent) or soft delete mode.
  • Soft-delete persistence for questions: feed_user_questions now stores moderation metadata for soft-deleted rows (deleted_at, deleted_by_user_id, deleted_reason) while preserving hard-delete for irreversible cleanup.
  • Restore/undo support for soft-deleted questions: Admins can now restore soft-deleted rows from /feed/user-questions (POST /feed/user-questions/{question}/restore), including AJAX inline restore actions.

2026-03-22

UI Improvements

  • Navbar size reduced: The site navigation header is now more compact (smaller brand title, tighter padding) so it takes less vertical space.
  • Public feed layout clarity: Site-specific AI analysis rows now have a blue left-border accent and a tinted background to visually attach them to their parent feed entry. Category AI analysis blocks use a stronger border and clearer πŸ“Š Category AI analysis label to distinguish category-level summaries from per-site rows.
  • Retranslate β€” no more language dropdown: In /feed-admin, the Retranslate action now reads the target language directly from the variant's stored label (e.g., a variant marked EN will always retranslate to English). The "Choose language" dropdown is removed β€” the labeled language IS the target.
  • Subscriptions actions via AJAX: /feed/subscriptions now saves channel settings inline and also handles Pause/Resume and Remove via AJAX (no full reload). Non-JS fallback submit remains supported.
  • Cron Admin discoverability: Added explicit Cron Admin/Scheduled Jobs entry points in both / dashboard and /services admin cards (route: /admin/jobs) so cron management is easier to find.
  • Discord OAuth webhook onboarding on subscriptions: /feed/subscriptions now includes Discord OAuth connect flow (/oauth/discord/start -> /oauth/discord/callback), callback URL visibility, and one-click reuse of the latest Discord webhook payload, matching Slack-style onboarding behavior for webhook setup.
  • Feed question mini-card + history: /feed now includes a mini Q&A card for questions about all open feeds. Added /feed/user-questions history page, guest Turnstile enforcement, configurable guest/user daily+weekly quotas, configurable guest concurrent intake guard, admin bypass/unlimited mode, and persistent question/answer audit records (timestamp, IP, actor metadata, status, response meta).

Bug Fixes

  • RSS inbound deadlock fix: Fixed SQLSTATE[40001] InnoDB deadlock on /api/rss/update that occurred when multiple concurrent scraper workers triggered the stale-lock cleanup (UPDATE inbound SET processlock=0 …) at the same time as the batch lock-acquisition. The stale-reset and old-row DELETE are now wrapped in a retryOnDeadlock() helper (up to 3 attempts with randomised back-off). fetchAndLockInboundBatch() is now fully atomic via DB::transaction() + lockForUpdate() (SELECT … FOR UPDATE), so two workers can never pick up the same batch.
  • Safer stale-unhandled inbound policy: /api/rss/update no longer purges old handled=0 rows by default. Purge is now opt-in (RSS_PURGE_STALE_UNHANDLED=true) and limited to abandoned locked rows (processlock=1) with deadlock-safe retries, reducing accidental backlog loss if triggers are paused.
  • SocialGPT API 500 fixed: Resolved Call to undefined method App\Services\OpenAI\RequestLogService::excerpt() on POST /api/ai/socialgpt/respond by restoring safe excerpt handling in request audit logging.
  • RSS inbound deadlock hardening (handled update): setEntryHandled() in RssController now executes through deadlock retry logic and explicitly releases processlock when marking rows handled, reducing SQLSTATE[40001] deadlocks during concurrent /api/rss/update workers.

Development & Documentation

  • Expanded analytics feed selectors + daily support: Analytics feeds under /api/rss/feed/{selector} now support analytics-daily, analytics-weekly, analytics-monthly, analytics-yearly, and analytics-bulk (with corresponding *-analytics aliases). Feed rows now link back to related category/site targets when available. Daily period support was also added to analytics generation flows (rss:generate-analytics, POST /api/rss/analytics/run, and scheduler wiring).
  • RSS DB env alignment (DB_RSS_*): config/database.php now treats DB_RSS_* as canonical while keeping legacy RSS_* fallback compatibility across host/database/username/password/charset/collation/socket/url fields, and .env/.env.example now include explicit DB_RSS_URL/DB_RSS_PORT/DB_RSS_SOCKET entries.
  • Cron trigger docs expanded: Added explicit RSS analytics trigger documentation for scheduler cron (schedule:run), manual artisan execution, and API trigger (POST /api/rss/analytics/run) in EN/SV docs.
  • Google Home API + admin console added: Added permission-gated Google Home endpoints (POST /api/google-home/request, /devices/query, /devices/request-sync) and a new web console at /admin/google-home. Regular users can use it when granted google-home.use permission.
  • Google Home mobile push notifications: Added Google Home push endpoints (/api/google-home/push/tokens/register, /push/tokens, /push/test) so mobile clients can register FCM tokens and receive push notifications when Google Home API calls complete.
  • Retranslate runtime fix: Category/site retranslate actions now use the current OpenAI engine profile API instead of the removed generateText() method, fixing the /feed-admin 500 error (Call to undefined method ... OpenAiEngine::generateText()).
  • nethandle-web planning baseline: Added initial projects/nethandle-ui/README.md + CHANGELOG.md, documented script-preserving migration strategy for web-to-terminal network control, and added runtime env/config scaffold (NETHANDLE_EXEC_*, NETHANDLE_RESOLVER_BASE) in .env, .env.example, and config/services.php.
  • Site analysis custom title field: /feed-admin site-level generation now has a dedicated per-site title input, so site variants no longer depend on the global title field.
  • Cleaner public /feed analytics UI: The Feed Analytics (OpenAI cached) category block now renders only when cached analytics exist for that category, reducing empty UI noise.
  • Concurrent scraper fetches (anti-stall): projects/scraper/scrape.php now fetches feed URLs with bounded curl_multi concurrency so a single slow/hanging site does not block the whole scrape batch. Concurrency/timeout can be tuned via CLI args or SCRAPE_CONCURRENCY and SCRAPE_FETCH_TIMEOUT.
  • Feed-admin variant actions always visible: Existing cached analytics variants (category and site) now show Retranslate and Regenerate (replace) controls directly in /feed-admin, instead of only appearing after a fresh generation in the current browser session.
  • Replace-in-place regeneration improved: Per-variant regenerate actions now force replace_existing for the selected period/variant id, so weekly/monthly/yearly entries are overwritten intentionally instead of silently creating extra variants.
  • Meaningful hash duplicate guard: RSS import duplicate detection now includes meaningful_hash and tiny-change suppression (isTinyMeaninglessChange) to avoid noisy pseudo-updates (markup jitter, micro text drift) creating endless new versions.
  • RSS Maintenance Admin added: New /rss-maintenance-admin page lists suspicious high-churn links and supports dry-run/live noise purge per link, keeping latest representative rows per meaningful change.
  • RSS content schema update: Added migration for content.meaningful_hash with index to support semantic duplicate filtering and maintenance diagnostics.
  • RSS queue diagnostics SQL added: Added SQL/RSS_QUEUE_DIAGNOSTICS.sql with reusable admin/internal queries for pending inbound rows, stale locks, recently handled rows, payload-shape previews, and recent content insert comparisons when /api/rss/update reports errors or stuck pending items.
  • RSS processing info logs: RssController now writes structured Log::info checkpoints for inbound row start/finish and batch summaries, making it easier to correlate pending/error runs with Laravel logs (and Slack-forwarded Laravel log categories when enabled).
  • Immediate RSS subscription delivery: After /api/rss/update converts new rows into content, the backend now performs an immediate targeted subscription-delivery pass for affected feed ids. The existing rss:notify-subscribers scheduler remains as the fallback safety net every 15 minutes.
  • Hidden RSS feeds with hash access: Public feed browsing now supports hidden feeds via urls.is_hidden + urls.public_hash. Hidden feeds are omitted from /feed, but can still be reached directly through /feed/key/{public-hash} and /api/rss/feed/{public-hash} without exposing numeric feed ids publicly.
  • RSS editor visibility controls: /rss now exposes protected, useProtected (when present in schema), is_hidden, and public_hash so alert-style feeds such as Google Alerts can stay scraper-visible but public-list-hidden.
  • Disney scraper without TorneLIB Domain parsing: projects/scraper/ondisney.php no longer depends on TorneLIB\Module\Network\Domain for URL-path parsing. The script now uses native URL parsing, reports sitemap shape samples during the run, and preserves compatibility with the existing JSON import rules by including the expected timestamp field.
  • RSS error logging modernization: Replaced legacy file_put_contents exception traces in RssController with structured Laravel Log::warning/Log::error events (including incomingidx/urlid context), so parser/import failures are centralized in Laravel logs and can be forwarded via the existing Slack log routing.
  • Disney scraper shard handling restored: projects/scraper/ondisney.php no longer assumes only d-sitemap-1..10; it now reads all available shard files from projects/scraper/sitemap-xml when present and otherwise probes remote Disney sitemap shards dynamically, restoring coverage when Disney expands to more XML files.
  • Scraper API metadata alignment: Disney ingest now sends agent_id consistently to /api/rss/data (query + payload), matching the RSS scraper identification contract used by scrape.php/trigger.php and improving backend agent attribution.
  • Disney sitemap helper scripts updated: projects/scraper/sitemap and projects/scraper/sitemap-mini now use dynamic shard discovery with miss-streak stop conditions instead of fixed hardcoded ranges, reducing maintenance when Disney changes shard counts.
  • RSS importer recovery: Restored the missing RSS/WordPress inbound conversion helpers in RssController after the recent cleanup pass. /api/rss/update can now convert queued inbound rows into content again instead of stalling with converted=0/errors>0 while fresh scraper payloads keep arriving.
  • RSS inbound queue hygiene: Handled rows are now cleaned before queue stats are reported, stale processlock=1 rows older than 30 minutes are unlocked for retry, and row-processing errors now catch all Throwables so aborted conversions stop leaving locked backlog behind.
  • AGENTS.md: Updated AI agent coding guide to reflect the full current state of the codebase
    • Corrected database architecture: documented all seven named connections (mysql, rss, mcu, gsm, spamassassin, tornis, irclog, firewall)
    • Added full IRC Memory Lane section covering the public viewer, admin import pipeline, sandbox/production workflow, and service layer
    • Added OpenAI Engine section documenting the shared AI service layer and admin panel
    • Added brief-reference sections for Facebook Admin Stats, Telldus IoT integration, Notifications system, Scheduled Jobs, Metrics/Stats, and Public Weight Tracking share tokens
    • Removed stale line-number references from Route Organization
    • Added RSS local DB schema (subscriptions, analytics, public settings) and orphan management methods
  • Internal docs: Applied admin-only front-matter markers to internal architecture and developer-notes files stored under /docs
  • Requirements: CHANGELOG, Documentation, and Documentation sync requirements now formally extended to projects/sc4a-insights and projects/socialgpt-chrome
  • Slack OAuth callback: Fixed invalid redirect status handling in /oauth/slack/callback (a boolean false was being passed as HTTP status, causing The HTTP status code "0" is not valid.)
  • Slack log routing: Added LOG_FORWARD_DEPRECATIONS setting (default false) so noisy PHP deprecation warnings (for example PHP 8.4 dynamic-property notices) can be excluded from Slack warning forwarding
  • API audit routing to Slack: Added per-API-group audit categories with separate checkboxes in Slack log routing settings. /api/* requests now forward success/error events by endpoint group (for example /api/rss, /api/sms, /api/social-media-tools, etc.) so admins can enable only the API groups they care about.
  • Slack social-media audit enriched: Social media request notifications now include app_host (identifies tools.tornevall.com vs tools.tornevall.net), tokens_in, tokens_out (prompt/completion token split), response_language, feature_slug, and used_fallback_model (yes/no). Short fields are shown side-by-side in Slack for readability.
  • Slack social-media audit: request content: context_excerpt (first 200 chars of context) and user_prompt_excerpt (first 200 chars of user prompt) are now included in the Slack audit message.
  • Slack OAuth: cookie-backed state: OAuth flow state is now stored in both the session and a short-lived HttpOnly/SameSite=Lax cookie. If the session is lost during the Slack redirect (e.g. due to browser SameSite policy), the cookie is used as fallback and the OAuth flow completes normally. Direct navigation to the callback URL without starting the flow shows a clear "Please click Connect Slack again" message instead of a cryptic error.
  • sc4a-insights docs: Added a Contact section in sc4a-insights/README.md with the Slack Marketplace entry for Tornevall Networks Tools (https://tornevall.slack.com/marketplace/A0AN2UJ2C4S-tornevall-networks-tools) to make Slack app/webhook setup easier to find.
  • Slack OAuth callback robustness: Callback handling now supports Slack-managed installs where state may be empty on both sides, while still enforcing strict state validation whenever a state value exists. Token exchange now sends redirect_uri only when it was actually present in the authorize step, matching Slack OAuth v2 parity rules.
  • AGENTS.md implementation locations: Added concrete locations for RSS subscription webhook UI, Slack OAuth return flow, and the public donation completion page so future maintenance sessions can jump straight to the right files.

RSS Feed Analytics UX

  • Public /feed now includes an admin-only Translate button next to each category analysis variant (weekly/monthly/yearly). The action is AJAX-driven and reuses the selected language from the variant language selector.
  • Feed-admin analytics generation now supports a Replace existing mode. When enabled, generation overwrites the currently selected cached variant for the chosen period instead of creating/updating a different variant key.

Social Media Tools Extension (socialgpt-chrome v1.2.9)

  • Context menus restored: Right-clicking anywhere on a page now shows two Toolbox actions:
    • "Open Toolbox" β€” opens the panel; selected text is automatically imported as context
    • "Verify fact with Toolbox" β€” starts fact verification using selected text, link, image URL, or page URL
  • Floating in-page action button renamed from "Fill in with Tools" to "Open Toolbox"
  • SoundCloud 4 Artists insights capture removed from the main extension; it is now handled exclusively by the sc4a-insights companion module

SoundCloud Companion Extension (sc4a-insights 2.0.0)

  • The SoundCloud companion module is now documented as a real 2.0.0 milestone against the original 1.0.0 2025 overlay-only release
  • The extension is now clearly positioned as the dedicated Tools companion for SoundCloud 4 Artists capture rather than a local-only overlay helper
  • New user documentation now covers:
    • personal Tools bearer-token setup
    • dev/prod host switching
    • auto-ingest into /api/social-media-tools/soundcloud/ingest
    • local pending queue and duplicate protection
    • popup diagnostics and debug window usage
    • the supported SoundCloud dataset types

RSS subscriptions

  • Subscription links now prefer Tools entry permalinks: Mail/Slack/Discord digests now include a direct Tools entry URL first (/feed/entry/{contentId}), with the original source URL included as secondary fallback.
  • User-level webhook onboarding: /feed/subscriptions now includes direct helper links for webhook setup:
    • Connect Slack app (get webhook) starts Slack OAuth with incoming-webhook scope and returns to subscriptions
    • How to create a Discord webhook links to Discord webhook setup docs
  • Slack OAuth quick-fill: If a recent Slack OAuth payload contains incoming_webhook.url, users can now click Use latest Slack OAuth webhook to fill the Slack webhook URL (and channel label when empty) directly in subscription settings.
  • Slack setup clarity: /feed/subscriptions now shows whether Slack OAuth is configured on the current host and displays the effective callback URL, making it clearer that TOOLSAPI_SLACK is the global platform webhook while subscription webhooks come from Slack OAuth (incoming_webhook.url).
  • Slack OAuth-first webhook field: When a recent Slack OAuth callback already contains incoming_webhook.url, the Slack webhook URL field is now auto-filled, saved server-side even without manual paste, and shown as readonly in the UI so users do not have to enter it manually.
  • Reuse latest Slack webhook button kept: The explicit button for reusing the latest Slack OAuth webhook remains available in /feed/subscriptions, so users can quickly continue sending notifications to the same Slack channel across subscriptions.

Donations

  • Added a public Thank you for your donation page at /donate/thankyou, intended for payment-provider completion redirects (for example PayPal return/thank-you URLs).
  • Added a public Donation cancelled page at /donate/cancel, intended as the canonical payment-provider cancellation/abort redirect.
  • Kept /donate/farewell as a compatibility alias; it now resolves to the same aborted-donation content via the canonical cancel flow.
  • Added a styled Donate link to the shared navbar, pointing to the hosted PayPal donation URL.
  • Added a prominent donation card at the top of /contact, including a styled PayPal donate button and the current donation QR image.
  • Centralized the hosted PayPal donation target in config/services.php (services.paypal.donate_url) so public donate entry points reuse the same URL.
  • Replaced the empty public/images/index.html with a playful β€œdirectory listing disabled” landing page, so direct browsing of the public image folder no longer lands on a blank file.

2026-03-21

RSS & Feed Experience

  • Public feed pages now show cached site-specific AI analysis directly on each feed row when available
  • Individual feed pages (/feed/{id}) now show site-level analytics variants (weekly/monthly/yearly)
  • Site-specific analysis focus can now be saved and reused in category-level analysis context
  • Feed content rendering now uses safer markdown-normalized output for better readability and more stable layout handling

Social Media Tools

  • SocialGPT verify-mode requests now support configurable reasoning effort for supported reasoning models
  • Verify-mode now retries safely without reasoning effort when a model rejects that parameter
  • Added an admin Social Media Tools Audit page with filters for status, request mode, model, and user
  • Extended SocialGPT API response metadata with request summary and verification context for easier troubleshooting

Documentation & Rendering

  • Added a reusable markdown normalizer service for shared formatting/parsing workflows
  • Documentation front matter parsing now uses the shared markdown normalizer

2026-03-20

Development & Documentation

  • Improved internal contributor documentation and editorial consistency for ongoing maintenance work

2026-03-19

RSS Feed Analytics

  • Added richer RSS category analytics in /feed, /rss, and /feed-admin
  • Feed-admin now supports auto-generating missing category instructions/description from live category flow content via AJAX (English-first output)
  • Feed-admin title handling is now dynamic: suggested analysis titles are generated from current instructions/description in real time when title is empty
  • Long public analytics can now be expanded with Read more / Show less
  • Analytics cards are visually separated by period
  • Markdown in analyses is rendered as readable HTML
  • Weekly, monthly, and yearly analysis periods are supported
  • Manual re-generation now updates the same period record instead of creating duplicate entries
  • Added optional analyst guidance before generation (watch_for)
  • Added category-specific guidance that can be combined with global focus
  • Added support for named analysis variants with different language, tone, and purpose
  • Public /feed can show different saved analysis variants via title/language selectors
  • Public /feed analytics sections are collapsed by default and can be expanded per category
  • RSS admins can now delete cached category analytics variants directly on /feed via AJAX
  • Analysis prompts now include example entry links and stronger activity signals
  • Added a second generation tool for site-level analytics (per writer/news site)

Feed Browsing

  • Public /feed is now sorted by category order
  • First Discovery and Last Discovery are shown for feeds
  • Legacy protected-feed filtering has been decommissioned; feeds are now treated as public by default

Documentation

  • Standardized public documentation page slugs across English and Swedish
  • Added missing public pages for parity between docs/en and docs/sv
  • Refocused documentation toward API usage and web UI workflows instead of internal implementation details
  • Updated changelog through the current release

2026-03-16

Social Media Tools

  • Improved extension settings behavior for faster autosave and cleaner setup
  • Refined SoundCloud capture handling and release notes continuity

2026-03-02

IRC Log Rollback

  • Fixed access handling for rollback features so authorized users can reach them reliably
  • Improved feedback around rollback-related errors

2026-03-01

IRC Log Management

  • Added rollback support for import mistakes
  • Improved import review and format handling
  • Made rollback workflows clearer and safer for administrators

2026-02-13

DNS API and Access

  • Added DNS zone discovery and browsing tools
  • Improved API key authentication and access control
  • Added IP-based allowlist support for selected endpoints
  • Expanded admin tools for key generation and DNS access management

OpenAI and Platform UX

  • Improved OpenAI testing and model selection in the admin UI
  • Expanded dashboard/service visibility so available tools are easier to find
  • Added user registration tracking and more flexible local SSL behavior for development environments

2026-02-11

Security and Administration

  • Added Turnstile CAPTCHA support for authentication flows
  • Improved admin warning flows and access ban management
  • Enhanced user management and API key management screens
  • Continued usability improvements in the OpenAI admin UI

2026-02-10

Dashboard and Editors

  • Improved dashboard/service navigation and overall admin consistency
  • Expanded MCU editor workflows and editor usability
  • Improved dark mode support and form readability
  • Refined RSS listing UI and general navigation

2026-02-09

Permissions and Documentation

  • Introduced permission-based access controls across protected tools
  • Standardized navigation and layout behavior across the platform
  • Added markdown-powered documentation with English/Swedish support

2026-02-08

RSS Watch

  • Expanded the public RSS feed viewer
  • Added history-aware feed viewing and edited-entry detection
  • Improved feed browsing, outbound link handling, and API output flexibility

Earlier Foundations

Earlier releases established the platform basics for:

  • RSS aggregation and feed serving
  • MCU timeline browsing
  • authentication, sessions, and access control
  • multi-database service support
  • markdown documentation and public API publishing

Maintained by: Tornevall Networks
Last updated: 2026-03-22