- 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
- 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
- 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
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
- 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
- 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
- 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