cite-wide 0.0.1.2 Published

Dependabot Cleanup + Tanuj-Intent Port — Removed 3 Unused Deps, Forced 4 Transitive CVE Patches, Ported Explicit Save Flow

Two-commit cleanup that eliminates the bulk of the 28 open Dependabot alerts on this repo and absorbs the intent of TanujKS's August 2025 work (which we force-pushed past in 2026-05-01_02 — his commits are archived on the auto-rescued `feature/save-all-citations` branch). First commit removes fastify, @modelcontextprotocol/sdk, and zod (zero imports across src/ and main.ts since they were added in 644582d) and forces patch/minor bumps on four surviving dev-tool transitive CVEs via pnpm.overrides. Second commit ports the explicit save flow — `autoSaveUrlCitations` setting (default off), 'Save All Hex Citations' command, modal-level 'Save All Hex (N)' button, per-citation 'Save to Citations' button — without any of his `any` types. Build clean throughout.

Why Care?

Two thematically separate but practically coupled cleanups landed in quick succession on development after the force-push that overwrote TanujKS's three Aug-2025 commits:

  1. Dependabot was screaming at us — 28 open alerts, dominated by transitive CVEs from three direct dependencies (fastify, @modelcontextprotocol/sdk, zod) that had been carried in package.json since commit 644582d but never imported by any plugin code. grep across src/ and main.ts returned zero matches for all three. They were paying the security-alert tax without delivering any feature.

  2. Tanuj's intent was on the day's task list — making Citations/ a curated archive rather than a side-effect of every URL extract. The user's broader "evaluate how to use bases for canonical source citations" framing wants explicit curation ("some, not all"). Tanuj's commits already implemented this; the force-push removed them from development; this changelog records absorbing the same intent into our refactored, type-safe code.

The two changes ship together because they touch related plumbing (package.json edits + a settings-driven flow change to citation file creation) and dropping the unused deps cleared the conceptual deck for thinking about what citations should be saved when.

What Was Built

Commit ad88cd9chore(deps): remove unused fastify/MCP/zod; pnpm overrides for transitive CVEs

Removed direct deps (zero imports — confirmed by grep across src/ and main.ts):

PackageDirect alert(s)GHSA IDs
fastify4GHSA-247c-9743-5963, GHSA-jx2c-rxcm-jvmq, GHSA-444r-cwp2-x5xf, GHSA-mrq3-vjjr-p77c
@modelcontextprotocol/sdk3GHSA-345p-7cg4-v4c7, GHSA-8r9q-7v3j-jr4g, GHSA-w48q-cv73-mx4w
zod0 (current)— flagged for removal in 2026-05-01_01.md already

Removing fastify also dropped these transitively-vulnerable packages entirely from the dependency graph: path-to-regexp, body-parser, qs — three more alerts gone for free, with no further action.

Lockfile size: 74k → 43k (~40% smaller).

pnpm.overrides added to force safe versions of four surviving transitive packages whose vulnerable versions remained pinned via older eslint/typescript chains:

JSON
"pnpm": {
  "overrides": {
    "ajv@<6.14.0":      "^6.14.0",
    "js-yaml@<4.1.1":   "^4.1.1",
    "minimatch@<3.1.4": "^3.1.4",
    "flatted@<3.4.2":   "^3.4.2"
  }
}
PackageBefore overrideAfter overrideCloses alert
ajv6.12.66.15.0GHSA-2g4f-4pwh-qvx6
js-yaml4.1.04.1.1GHSA-mh29-5h37-fv8m
minimatch3.1.2, 10.2.53.1.5, 10.2.5GHSA-7r86-cg39-jmmj, GHSA-23c5-xmqv-rm74, GHSA-3ppc-4f35-3m26
flatted3.3.33.4.2GHSA-25h7-pfq9-p65f, GHSA-rf6f-7fwh-wjgh

These four are dev-tool transitives — they only execute at lint/build time and are never bundled into the runtime plugin by esbuild — so the practical risk was always near-zero. The override existence is mostly about silencing Dependabot rather than closing real exposure.

.npmrc got ignore-workspace=true added. The cite-wide repo sits inside /Users/mpstaton/code/lossless-monorepo/, whose pnpm-workspace.yaml lists site and content as workspace members. pnpm 10 was nonetheless treating cite-wide as a workspace member when invoked from within it, which kept blocking installs on a "will remove parent monorepo's node_modules — proceed?" prompt.

The .npmrc setting alone wasn't enough — pnpm 10 only respects workspace-isolation as a CLI flag (--ignore-workspace) for some operations. The working invocation became:

pnpm install --ignore-workspace --no-frozen-lockfile

The .npmrc entry stays as documentation and a forward-compat hook in case pnpm later reads it from config consistently.

Commit c3c8717feat(citations): explicit save flow + autoSaveUrlCitations setting

The intent, in one sentence: Citations/ is a curated canonical archive, not a side-effect of every URL extract.

Three save paths now exist, in order of "least to most user effort":

  1. Settings-toggle auto-saveSettings → Cite Wide → Auto-save URL Citations. Off by default (matches the user's "some, not all sources should be canonicalized" framing). When on, the URL extract still triggers createCitationFile as before. When off, the URL extract only updates the document; the user explicitly canonicalizes later.

  2. Bulk command — palette command "Save All Hex Citations to Citation Files" walks the active document, finds every [^hexId] group, and persists each as a citation file. Reports saved / updated / errors counts in a single Notice.

  3. Per-citation in modal — open the Citations modal (existing Show Citations in Current File command); each hex group now has a "Save to Citations" button (in place of the no-op "Convert to Hex" that previously rendered for hex groups), and the modal header shows "Save All Hex (N)" alongside the existing "Convert All (N)" — each conditional on the matching count being greater than zero.

Type-safety improvements over Tanuj's original:

  • His saveHexCitationFromGroup(group: any, ...) → ours saveHexCitationGroup(group: CitationGroup, ...).

  • His group.matches.find((match: any) => ...) → ours typed as CitationMatch.

  • His await import('./citationService') (workaround for an imagined circular dep) → ours uses a static import { citationService }. Confirmed by inspection: citationService.ts has zero imports, so there's no cycle to dodge.

API additions to citationFileService:

TS
export interface SaveAllHexResult {
    saved: number;
    updated: number;
    errors: number;
}

class CitationFileService {
    public async saveAllHexCitationsFromContent(
        content: string,
        sourceFile?: string
    ): Promise<SaveAllHexResult>;

    public async saveHexCitationGroup(
        group: CitationGroup,
        sourceFile: string | undefined
    ): Promise<'saved' | 'updated' | 'error'>;
}

The per-group method is public so the modal can call it directly without rebuilding a content slice — cleaner than Tanuj's draft, which had a parallel saveHexCitationToFile in the modal class duplicating the service logic.

Skipped from Tanuj's commits: the visual polish (citation-id badge, inline citation-text preview panel inside expanded groups, hover transforms, citation-text section, separator). Best handled as a separate styles pass when we next touch styles.css — keeps this commit's scope tight to the behavioral change.

Verification

Build clean across both commits: tsc -noEmit -skipLibCheck && eslint . && esbuild production. Type- safety pass from 2026-05-01_02 is preserved — no any introduced.

What Changed in Approach (the meta-lesson)

Pattern this rejectsPattern this adopts
Carry unused dependencies "in case we need them later"Audit imports periodically; remove deps with zero references — they're paying security tax for no feature
Treat Dependabot alerts as a single yes/no — fix all or ignore allTriage by exposure: direct vs transitive, runtime vs build-time. Force versions on the latter via pnpm overrides; don't block on theoretical lint-tool ReDoS
Auto-create canonical artifacts on every related eventDefault to no auto-creation; require an explicit gesture (button, command, setting toggle) so the user's curation intent is preserved
Trust the previous author's await import() as evidence of a real circular depVerify the dependency graph yourself before replicating workarounds
Pull in three contributors' commits when the contributor's intent is clearer than their implementationForce-push past, archive their work on a rescue branch (auto-created here as feature/save-all-citations), and re-implement the intent fresh in the cleaner codebase

The generalizable point: dependency hygiene and feature curation are the same kind of move — both push back on default "yes" behavior that accumulates surface area without paying for it. The unused deps were paying for nothing. The auto-save default was creating archive files the user didn't want yet. Both got the same treatment — opt out by default, opt in by explicit gesture.

Open Items

  • Push to remote. Both commits are local on development only; Dependabot won't see the lockfile changes (and won't close the alerts) until the branch is pushed. Deferred per the established session pattern (no shared-state mutation without explicit user confirmation). User push when ready: git push origin development (regular non-force — fast-forward only since the force-push in 2026-05-01_02 already aligned local with remote at 688bb55).

  • Visual polish from Tanuj's commit 8a9f3c6 — citation-id badge, inline citation preview panel, hover transforms, separator. Available verbatim in context-v/workflow/2026-05-01_Refactor.md and on the rescued origin/feature/save-all-citations branch. Pick up in a separate styles commit.

  • Orphan citation files from dedup. Carried over from 2026-05-01_03.md open items: when dedupe-citations-by-url collapses [^def456][^abc123], the Citations/def456.md file remains on disk. A "Garbage Collect Orphan Citation Files" command would handle this; still unscheduled.

  • Inheriting usage stats during dedup. Same as above — canonical's usageCount / filesUsedIn aren't merged from eliminated hexes. Right time to do this is during the dedup apply phase, before deleting the duplicate reference line.

  • feature/save-all-citations branch on remote. Auto-rescued by GitHub when the force-push in 2026-05-01_02 removed Tanuj's commits from development. Now that his intent is absorbed (commit c3c8717), the branch is purely archival. Decision pending: delete after some safety window, or keep as a permanent contributor-attribution record.

  • Bigger "evaluate Bases" thread. This commit only ports the curation gesture; the deeper question of whether citation files should be reshaped to be Obsidian Bases-compatible (or treated as the foundation of a future RAG/KAG context store) is unresolved. Hold for a separate spec session.

Files Touched

cite-wide/
├── package.json                               (modified — removed 3 deps; added pnpm.overrides)
├── pnpm-lock.yaml                             (regenerated; 74k → 43k)
├── .npmrc                                     (added ignore-workspace=true)
├── main.ts                                    (modified — gated auto-save; new save-all-hex-citations command)
├── src/
│   ├── settings/
│   │   └── CiteWideSettings.ts                (added autoSaveUrlCitations + toggle UI)
│   ├── services/
│   │   └── citationFileService.ts             (added SaveAllHexResult,
│   │                                            saveAllHexCitationsFromContent,
│   │                                            saveHexCitationGroup)
│   └── modals/
│       └── CitationModal.ts                   (Save All Hex header button;
│                                               per-group Save to Citations;
│                                               conditional Convert All)
└── changelog/                                 (originally created at context-v/changelogs/; relocated to repo-root changelog/ on 2026-05-17)
    └── 2026-05-01_04.md                       (this file)

Reference

  • Commits in this entry: ad88cd9, c3c8717 on development.

  • Predecessors that set up the conceptual deck: 2026-05-01_01.md (deps refresh; flagged unused deps for removal), 2026-05-01_02.md (type-safety pass; force-pushed past Tanuj's branch), 2026-05-01_03.md (dedupe by URL).

  • Tanuj's archived work: origin/feature/save-all-citations (auto-rescued at force-push), commits ef99b16, 37995cd, 8a9f3c6. Full source captured for reference in context-v/workflow/2026-05-01_Refactor.md.

  • Dependabot UI: https://github.com/lossless-group/cite-wide/security/dependabot — alert closure won't reflect until the lockfile is pushed.