16 Commits

Author SHA1 Message Date
25e9bfe8da chore: release v0.3.0 v0.3.0 2026-10-10 19:28:05 +02:00
03a90e952d fix: forward the visitor address on route-cached renders
Nitro's cached handler renders from a header-less copy of the request, so
under swr route rules useJournalApi, /rss.xml and the sitemap source
forwarded only the Nuxt peer and every cache miss shared one Journal API
rate-limit bucket (deferred in Phase 16). A Nitro plugin records
x-forwarded-for plus the peer in event.context.journalForwardedFor on the
request hook; the three callers forward it. Same key as the host app's
workaround, which keeps working. The acme SSR smoke's x-forwarded-for check
on the now route-cached playground is the test.
2026-10-10 18:40:25 +02:00
4f55511ece test: site cache purge authorization, purge, body parsing and revalidation
- exact names: purge auth disabled, proxied before the token, missing or
  wrong bearer; purge removes every route cache entry and only those
- parsePurgeEvent kinds, control characters, 200-character cap, non-objects
- privateRevalidate with and without max-age, the 304 form, static values
2026-10-10 18:36:13 +02:00
0a01bfeae4 feat: browsers revalidate route-cached pages; document the site cache purge
- privateRevalidate sets max-age=0 on cache-control values with s-maxage
- server/plugins/journal-revalidate.ts wraps res.setHeader per request, so
  Nitro's 200 and h3's 304 answers both carry it
- purge-check: max-age=0 on 200 and 304, purged _payload.json, a second
  purge after re-caching, X-Real-IP refused, 404 on a server without a token
- README: cachePurgeToken row and a Site cache purge section
2026-10-10 18:27:12 +02:00
a03e076c62 feat: token-protected site cache purge route
- POST /api/__journal__/cache/purge removes every Nitro route-cache entry
- 404 without a 32-character token or behind a proxy, 401 on a wrong bearer
  token (constant-time over sha256 digests)
- routeRules keep /api/__journal__/** out of the route cache
- runtimeConfig.journal.cachePurgeToken (NUXT_JOURNAL_CACHE_PURGE_TOKEN)
- fixture API reload(); testing/purge-check.mjs proves a cached page shows
  a change after a purge; the playground caches with swr 300
2026-10-10 18:19:58 +02:00
782aa4da7d test: pin embed expansion order and the editor policy mirror
- expansion runs last at the sinks, never in payload transforms
- only the exact placeholder serialization expands; stable across calls
- the Go policy negatives are stripped the same way in the mirror
2026-10-10 16:03:08 +02:00
759e684e86 chore: release v0.2.0 v0.2.0 2026-10-10 12:19:24 +02:00
a6ee443885 feat: keep Blog Editor markup in the sanitizer and expand Journal embed placeholders into privacy-enhanced iframes
- htmlGate.ts mirrors the four editor-output rules of the Go policy:
  figure data-embed (^youtube$) and data-id (^[A-Za-z0-9_-]{11}$),
  img alt with any text, ol start (integer)
- embeds.ts: EMBED_PROVIDERS (youtube on youtube-nocookie.com),
  EMBED_PLACEHOLDER and expandEmbeds
- JournalPostBody and JournalCategoryHeader render
  expandEmbeds(sanitizeJournalHtml(html)); payload transforms only sanitize
- .journal-embed styles (16 / 9 block, borderless iframe)
- tests: byte copy of the editor corpus, mirror and pipeline cases;
  acme hello-acme carries a placeholder and the SSR smoke checks the iframe
- README Embeds section and decision note Policy amendment
2026-10-10 12:19:00 +02:00
294a8d8b19 test: post page view sanitizes the body and drops sources
- body sanitized with its safe text kept, source, translations and
  related post bodies out of the payload, null body as an empty string
v0.1.1
2026-10-10 00:01:01 +02:00
5beb1c5634 fix: sanitize journal HTML instead of blanking it on a regex match
The three-regex gate could be bypassed (an attribute without a space,
<svg/onload>, entity-encoded or tab-split javascript: URLs, MathML
xlink:href, base, meta refresh, forms) and it blanked a whole post or
category when ordinary text such as "Data: 12 maja 2024" matched.

- sanitizeJournalHtml runs sanitize-html with the Journal plugin's
  bluemonday policy: UGC elements plus footer, class, schema.org
  microdata, four validated inline styles, footnote roles, dir=auto,
  two chat transcript data attributes; http, https, mailto and
  relative URLs only
- gateJournalHtml and isSafeJournalHtml keep their signatures; html is
  always the sanitized value and is never blanked
- post body, category content and both page payloads are sanitized;
  the blocked notice, its style and string, and the blocked props and
  content_blocked field are removed
- toPostView moves to postView.ts so list pages and cards do not load
  the sanitizer
- tests cover every bypass from the review, the Data:/metadata: text
  and an imported author footer; the SSR smoke expects the unsafe
  sample's safe paragraphs
2026-10-10 00:01:01 +02:00
3275a267f6 docs: decision note for sanitize-html in the layer
- sanitize-html over isomorphic-dompurify: same parser and output on
  server and client, no jsdom, and a declarative policy that mirrors
  the Journal plugin's bluemonday allow-list
- the policy, sanitize-not-blank, and the client bundle cost
2026-10-10 00:00:53 +02:00
b2069e10bd chore(deps): add sanitize-html 2.18.0 for journal HTML
- sanitize-html 2.18.0 as a dependency, @types/sanitize-html 2.16.2
  for development, both pinned exactly
2026-10-10 00:00:53 +02:00
a4dca42d77 test(16-05): Journal layer util tests
- node --test over routes, client (fake fetcher, include_empty=1),
  pagination, htmlGate (Go FormatHTML parity cases), sitemap, seo and
  pl/en i18n parity
- package script test and a Testing line in the README
2026-10-09 20:03:46 +02:00
783426c5d8 feat: Journal author and tag pages, SEO, sitemap source and RSS route
- author pages resolve slug or login and canonicalise to the slug
- tag pages, per-page SEO meta and canonicals that keep ?page=N
- sitemap source pages the API and builds locs from journal.routes
- /rss.xml proxies the API feed with x-forwarded-for
- neutral README; version 0.1.0
v0.1.0
2026-10-09 18:06:20 +02:00
c408eeb2ca feat: Journal list, category pages, pagination, tokens and pl/en strings
- index and category pages paginate with ?page=N and 404 out of range
- category content renders above the list through the html gate
- related posts fall back to the latest posts
- --journal-* tokens and neutral base styles
- pl/en strings registered only for locales the app enables
2026-10-09 18:02:48 +02:00
6f6792f51c feat: scaffold Journal layer with configurable post route and git-install check
- journal module registers the Journal pages at journal.routes paths
- typed anonymous-GET client, html gate, SSR x-forwarded-for forwarding
- fixture API, built-server SSR smoke and git-tag install check
v0.0.1
2026-10-09 17:31:45 +02:00