Commit Graph

17 Commits

Author SHA1 Message Date
Jakub Zych
b553fc2937 feat: rendered comparison through headless Chrome
- github.com/chromedp/chromedp v0.21.0 (decision note
  2026-10-28-chromedp-rendered-crawl.md): with golem15.seo.crawl_chrome_path
  the crawl renders up to golem15.seo.crawl_render_max pages (200) and
  compares them with the raw HTML; without a path it records skipped
- guard: site host and www twin resolved and checked with
  fetchguard.IsPrivateAddr, pinned through --host-resolver-rules with a
  final MAP * ~NOTFOUND; Fetch-domain interception fails every request
  outside the site (third-party scripts never load); fresh temporary
  profile removed on Close; downloads denied; one tab, 20 s, 5 MiB DOM
- a relative or non-executable path, a private address or a Chrome that
  does not start records render_status failed; the crawl still finishes
- config keys documented; README Rendered comparison section
- TestChromeRenderer (runs with a local Chromium) and TestRendererGuards
2026-11-04 15:58:36 +01:00
Jakub Zych
96963c3067 docs: crawler and site audit in README
- the crawler: seeds, fetchguard limits, trusted mode, limits, cancel and
  the crawls kept
- every check with its severity, the raw-HTML checks against the CMS, fix
  routes, ignores, check again, staging and the nightly schedule
- the crawl and issue tools, Site audit, Crawls and the Site audit
  settings tab, crawl_trusted, seo:crawl and the API reference
2026-11-04 15:56:21 +01:00
Jakub Zych
d38049a956 docs: structured data, breadcrumbs, hreflang and pagination in README 2026-11-04 14:38:38 +01:00
Jakub Zych
df93c86001 docs: registry, site endpoint, llms.txt and links in README
The sitemap filter and the golem15.sitemap requirement, the page registry
and its route report, the site answer, llms.txt, the Sitemap line from the
index, the Links tab and outbound, the site-cache purge after SEO writes,
the new MCP tools, config keys, API identifiers and tests.
2026-11-04 13:47:12 +01:00
5c2ad6aee1 fix: element tests drive the widget host protocol; the image element gets tests (WR-25)
The transfer element's busy and state=error handling is now tested
through the fake widget host, and golem15-seo-image gets tests for the
upload id matching, the error display, Remove and the disabled state.
The README's test gate runs npm test.
2026-10-27 15:44:22 +01:00
ed2d919aee fix: the CSV round trip keeps values that start with an apostrophe before a formula character (WR-21)
escapeCell left '=x as it was and unescapeCell then dropped its
apostrophe on import. A value of apostrophes followed by a formula
character now gets one more apostrophe on export, and the import drops
exactly one, so unescapeCell is the inverse of escapeCell.
2026-10-27 15:39:23 +01:00
d8aa989dfc fix: entry generation applies an unseen address change instead of overwriting it (WR-19)
refreshEntry set entry.url to the descriptor's address unconditionally, so
a slug change the job saw before any RecordSaved listener lost its 301 for
good. An entry whose URL differs now goes through AddressChanged (via
auto), which creates the 301 and moves the URL; an empty URL is filled.
2026-10-27 15:38:15 +01:00
cab1b9aef4 fix: document that the frontend server must be a trusted proxy for the public buckets (WR-15)
The resolve and 404 buckets key on the client IP, which is the SSR
server's address unless it is in http.trusted_proxies and forwards
X-Forwarded-For; otherwise they cap the whole site at 600 requests a
minute. The README and the Buckets comment now say so. An authenticated,
unthrottled resolve call would need a new token and a framework way to
skip a bucket, so it is left for a decision.
2026-10-27 15:34:01 +01:00
c2ba33ee94 fix: the runtime cycle log is keyed by rules and bounded (WR-13)
redirectHopsLogged was a never-evicted map keyed by the anonymous
request's URL with its query, so requests to a looping address with fresh
query strings grew it without limit and logged each one. The log is now
keyed by the cycle's rule ids, repeats at most once an hour and starts
over at 1024 keys.
2026-10-27 15:32:29 +01:00
c2f136ad7d fix: serialise redirect writes so concurrent saves cannot store a loop (WR-10)
The save-time simulation read the rules at READ COMMITTED without a lock,
so A -> B and B -> A written concurrently both passed. CheckRedirect,
AddressChanged and every batch now take a transaction-level advisory lock
before they read the rules.
2026-10-27 15:29:08 +01:00
cb614cb1fb fix: address changes run the loop simulation and validate their addresses (WR-09)
AddressChanged wrote its 301 and re-pointed rules without Problems or the
save-time simulation, and removed only an exact rule whose source equals
the new address literally. It now removes every exact rule that matches
the new address with its options, simulates the 301 and the re-pointing
with the stored rules and writes nothing when that loops, stores an
absolute old address on the site as its path, and skips an address that
is not a path on the site.
2026-10-27 15:27:21 +01:00
58b2504fe3 fix: an exact redirect with a query wins over the path-only rule (WR-08)
Match tried the path-only key before the path?query key, so a rule for
/products?id=5 never fired while /products had one.
2026-10-27 15:25:39 +01:00
b19cd069a5 chore: require SummerCMS v0.5.1 2026-10-27 14:02:14 +01:00
ab3b219fec feat: batches with dry run, undo, and CSV import and export
- POST /_seo/api/v1/batch runs changes in one transaction: dry_run
  answers the diff and the conflicts (loops, chains, noindex on a
  published record, canonicals to redirected or noindex addresses) and
  rolls back; a refused change refuses the batch (D-12)
- undo of a change or a whole batch from History and through MCP, with
  the undo_stale, undo_loop and undo_gone refusals (D-13)
- CSV export and import of redirects, rules and records by URL: BOM,
  comma or semicolon, formula cells escaped, a dry-run preview, all or
  nothing with via import; the screen's apply token is HMAC-SHA256 over
  the file and a fingerprint of the data (transfer.stale)
- Import and export singleton with the seo_transfer widget action,
  History record actions undo and undo_batch, navigation entry
- MCP tools undo_change, undo_batch, apply_batch, export_csv, import_csv
- TestBatch, TestUndo, TestCSVTransfer, TestLoopRefused mcp and import
2026-10-27 12:35:26 +01:00
aa0c3bcacf feat: management API and an MCP tool per SEO admin operation
- /_seo/api/v1 routes for the effective SEO of a URL with sources and
  owner, URL rules, redirects (loops refused with redirect_loop), the
  404 log actions, robots.txt and its tester, settings and history
- the CMS-data issue report: missing and duplicate titles and
  descriptions, rules over records, redirect chains, canonicals to
  noindex or redirected addresses, noindex addresses robots.txt blocks
- 24 MCP tools on those routes (backend guard, golem15.seo.manage)
- AdminOperations maps every admin operation to its tool;
  TestEveryAdminOperationHasTool and TestMCPReadToolsAreGET guard drift
- robots.txt writes go through classes.SaveRobots from the admin too
2026-10-27 12:17:36 +01:00
b3981614cb docs: robots.txt, AI bots and verification files in README
- redirects, address changes, the 404 log and its report endpoint, URL
  normalisation, strict URLs and the redirect decision of resolve
- robots.txt, AI bots, verification files, the new config keys and the
  grobotstxt dependency
2026-10-27 11:54:02 +01:00
b38eb4bf66 docs: plugin README 2026-10-27 11:04:42 +01:00