encrypted-pages/.gitignore
saberzero1 efa3032973
feat!: replace visibility with unlisted convention and shadow content index
The previous visibility option on the transformer was a dead flag (nothing
read file.data.encryptedVisibility), and EncryptedPageFilter used shouldPublish
to return false, which removed encrypted pages from the build entirely --
directly contradicting the README promise that pages remain accessible by
direct URL.

This change rips both out and replaces them with a first-class file.data.unlisted
convention plus a companion emitter that writes an encrypted shadow content
index. On client-side decryption, cached passwords are replayed against the
shadow index, and the resolved fetchData object is mutated in place so graph,
explorer, and search pick up decrypted pages for the rest of the browser
session without any Quartz core changes.

BREAKING CHANGES:
- Removed EncryptedPageFilter. It was actively harmful -- it deleted pages
  from the build instead of hiding them from listings. Use unlistWhenEncrypted
  or per-page frontmatter unlisted: true instead.
- Removed visibility option from EncryptedPages transformer. It had no effect.
- Removed EncryptedPagesOptions.visibility and EncryptedPageFilterOptions types.

New API:
- EncryptedPages.unlistWhenEncrypted: boolean (default false) -- marks all
  encrypted pages with file.data.unlisted = true.
- Per-page frontmatter unlisted: true | false overrides unlistWhenEncrypted.
- New EncryptedContentIndex emitter writes static/encryptedContentIndex.json
  as a versioned {version: 1, entries: [...]} wrapper. Each entry is an
  opaque {ciphertext, iterations} blob. Slugs, titles, and link relationships
  never leak -- they live only inside the ciphertext.
- Client-side encrypted.inline.ts fetches the shadow index when cached
  passwords exist, tries each cached password against each blob, batches
  successful patches, awaits fetchData, Object.assigns patches onto the
  resolved object, and dispatches content-index-updated + render events.
- Transformer emits a build-time warning if unlistWhenEncrypted: true but
  EncryptedContentIndex is not registered in plugins.emitters.
- encryptAesGcm, decrypt, SHADOW_INDEX_VERSION, and shadow index types are
  exported for test and extension use.

Plugin ordering: EncryptedPages must run after CrawlLinks (or any other
transformer that populates file.data.links), because it replaces the HAST
tree with an opaque ciphertext container.

Tests: 21 passing (13 transformer + 8 emitter). Covers visibility removal,
unlistWhenEncrypted, frontmatter override precedence in both directions,
shadow index format, roundtrip decryption with per-page iteration counts,
non-encrypted skip, and independent ciphertexts across pages sharing a
password.
2026-04-11 13:48:48 +02:00

42 lines
407 B
Text

# Dependencies
node_modules/
.pnp
.pnp.js
# Build output
build/
*.tsbuildinfo
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Environment files
.env
.env.local
.env.*.local
# IDE/Editor files
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
# Testing
coverage/
.nyc_output
# Package files
*.tgz
# Cache
.cache/
.eslintcache
# Sisyphus working artifacts (plans, research notes)
.sisyphus/