Repository navigation
fix(privacy): keep private feed addresses out of generated notes - #454
Merged
Merged
Conversation
Deploying podnotes with
|
| Latest commit: |
e19fd85
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a249de52.podnotes.pages.dev |
| Branch Preview URL: | https://fix-no-secret-in-notes.podnotes.pages.dev |
This was referenced Oct 13, 2026
This was referenced Oct 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Generated notes redact private feed addresses quoted in RSS metadata before Markdown conversion, filename formatting or URI encoding. Redaction also matches terminal-dot hosts and browser-valid slash aliases while preserving distinct episode and signed-media URLs.
An episode opened from an unsubscribed private feed keeps its live address for playback. Its generated note omits
feedUrl, its resume output is empty, and captures, segments and published-transcript timestamps use plain time text. Existing notes are untouched. The feed cache stays device-local and is scrubbed when its metadata reaches a vault output.Fixes #438. Fixes #441. Fixes #449.
Verification
Node 22.23.2. Real Obsidian 1.14.4 on Linux/Xvfb in this worktree's isolated vault. Synthetic Supercast-shaped feeds at
http://priv3.supercast.com:44409/feeds/PRIV4_QUOTED_SENTINEL/feed.xmland/feeds/PRIV4_UNSUBSCRIBED_SENTINEL/feed.xmlserve a 120-second WAV fromhttp://podnotes.test:44409/audio.wav. Both hosts resolve to loopback in the isolated app.9b0eea8feedUrlor resume URL; playback continuesThe final regression tests fail against current-master production sources (
7bb28d3): 29 failed, 164 passed, including API capture and transcript timestamp regressions. The review fixes also had 11 failing regressions before their implementation.The full runtime suite ran once: 122 passed, 1 failed. The failure is the mini-player status-bar overlap in #453; the focused test also fails with an independently built current-master bundle. All privacy and persistence runtime files passed. After the review fixes, the final privacy/persistence run passed all 17 tests.
npm run lintnpm run format:checknpm run typechecknpm run buildnpm run testnpm run test:toolingnpm run docs:buildnpm run test:e2enpm run test:e2e -- private-notes private-feeds sync-persistencenpm run sizeCompared with current master, the bundle adds 596 raw / 225 gzip bytes and has 363 gzip bytes left under the gate. One independent review each from Claude Fable 5.1 and GPT-6 Astra informed the fixes.
Before | After: plain captures and no feed property | After: redacted subscribed note | Fixture, actual note bytes, screenshots and check logs
The initial focused run encountered an Obsidian IndexedDB error. A fresh isolated instance restored loading. The final replay reports no runtime errors.
API changes
Signatures are unchanged.
buildEpisodeResumeLink(episode)returns""when the episode's feed address carries credentials without a subscription placeholder, including when a downloaded copy exists.formatEpisodeTimestampreturns plain configured time text in that case, including when called throughgetPodcastTimeFormattedorgetPodcastSegmentFormattedwithlinkifyenabled. Captures, segment captures and published-transcript timestamps share that behavior. These outputs also omit links when the title or GUID quotes a known private feed address, since redacting the identity inside a link would make it unresolvable. One sharedvaultSafeLinkTargethelper guards both link builders and frontmatter.Release impact
No data schema or settings migration. No existing note rewrite. The URI handler and live episode retain their resolving identity. New vault output uses a subscription placeholder when available and omits an unsafe link otherwise.
Docs at release
notes.mdandtemplates.md: explain private feed redaction in generated episode/feed notes, including metadata quoted in descriptions.templates.md: document empty{{feedurl}}and{{episodelink}}output for unsubscribed credential-bearing feeds, and omittedfeedUrlfrontmatter.api.md: document the unchanged signatures and changed output of the resume-link and linked timestamp APIs.timestamps.md: explain that captures, segment captures and published-transcript timestamps become plain configured text when no safe feed target exists.Follow-ups
Note
Redact private feed addresses from generated notes and transcript output
Adds a private-feed redaction service in privateFeeds.ts and applies it across all template engines, note creation, timestamp/resume-link builders, and published transcript rendering. Private feed addresses are replaced with a saved-feed placeholder where one exists, and unsafe credential-bearing URLs are omitted entirely.
redactPrivateFeedAddressesin privateFeedUrl.ts now recognizes more URL aliases: slash and backslash protocol variants, trailing-dot hostnames, and HTML-encoded query separatorsfeedHtmlToMarkdownin TemplateEngine.ts redacts private addresses in feed HTML attributes and text before Markdown conversionvaultSafeLinkTargetblocks links whose target or episode identity (title/GUID) would expose a private address;buildEpisodeResumeLinkandformatEpisodeTimestampreturn plain text or an empty link for unsafe feeds, even when a downloaded fallback existsvaultSafeLinkTargetand theNoteTemplateEngine/FeedNoteTemplateEnginerenderers if link or URL output changes unexpectedlyMacroscope summarized e19fd85.