Skip to content

Release: multi-host vault support (GitHub / Codeberg / Forgejo) + audit fixes - #269

Merged
thetechjon merged 8 commits into
mainfrom
dev
Jul 23, 2026
Merged

Release: multi-host vault support (GitHub / Codeberg / Forgejo) + audit fixes#269
thetechjon merged 8 commits into
mainfrom
dev

Conversation

@thetechjon

Copy link
Copy Markdown
Collaborator

Merges dev into main.

Contents

Effect

Clears open Dependabot alert #85 (brace-expansion, GHSA-3jxr-9vmj-r5cp) on the default branch and unblocks the 11 open Dependabot PRs currently failing the npm audit --audit-level=high gate.

Supersedes #266, which carries the same audit fix against main.

🤖 Generated with Claude Code

rotecodefraktion and others added 7 commits July 7, 2026 23:47
Introduces the host-abstraction seam for vault sync (GitHostProvider
interface, HostKind/HostRepo/HostUser/FileChange types), a GitHubProvider
that wraps the existing github.ts helpers plus the ETag-conditional cache,
and a ForgejoProvider that talks to the Gitea REST API (reads via git-data
endpoints, writes via the ChangeFiles batch endpoint). Adds
makeGitHostProvider() to pick a provider from a connection's host kind.

githubStore gains host/baseUrl connection state (default 'github'/null,
reset on disconnect, no persist version bump needed since Zustand merges
a legacy blob with no host key over the initial default).
syncPush.ts (syncToGitHub) now builds a host-neutral FileChange[] and hands
it to provider.commitChanges instead of calling the GitHub blob/tree/commit/
ref primitives directly; the write path uses the provider's plain (non-
cached) reads so a stale tree can never cause a non-fast-forward commit.
Delete/update FileChanges carry the remote blob sha (Forgejo's ChangeFiles
batch endpoint requires it; GitHub ignores it).

syncPull.ts (pullFromGitHub / pullFromZipball) now takes a GitHostProvider
and reads through its cached variants (getTreeMapCached / getBlobContentCached
/ fetchArchive), preserving GitHub's ETag-conditional caching behind the seam
instead of calling githubETagCache directly.

useGitHubSync builds the provider per call via makeGitHostProvider({host,
token, baseUrl}) read from the githubStore connection state, so a refreshed
token is always honored and the GitHub path behaves identically to before.
Mirrors e2eSyncLive.test.ts but drives the pipeline through ForgejoProvider
against a real Codeberg repo (pull/push/update/no-churn/delete plus a
concurrency probe on the ChangeFiles write path). Self-skips without
CODEBERG_TEST_TOKEN so CI stays green without secrets. Adds the
e2e:sync:codeberg npm script that loads the token from
~/.config/noteser/codeberg-test-token.env and runs only this file.
connect-src now statically includes https://codeberg.org (the built-in
Forgejo preset). Self-hosted Forgejo/Gitea is allow-listed at deploy time
via the new NEXT_PUBLIC_FORGEJO_BASE_URL env var (deriveGitHostOrigin, same
posture as deriveCollabWsOrigin: a single validated origin, never a
wildcard). Adds docs/codeberg.md and the README env-var entry.
The connect modal now opens to a host picker (GitHub / Codeberg / Forgejo).
GitHub keeps the existing device-flow + fine-grained-PAT path unchanged.
Codeberg and self-hosted Forgejo go through a new PAT form (Forgejo also
takes a base-URL field, type=text so the custom https:// validation always
runs instead of being pre-empted by native URL constraint validation). On
a valid PAT, makeGitHostProvider().getAuthenticatedUser() validates it,
then setHost() is called before setSession(), then the repo picker opens.

GitHubRepoModal is now host-blind: it lists/creates repos through the
active host's provider (HostRepo fields replace the GitHub-specific repo
shape); the modal title and disconnect label are host-neutral.

GitHub-only features are hidden when the connection isn't GitHub:
'View history' and 'Publish as gist' in ContextMenu, the RecentCommits
block in SourceControlPanel. SourceControlPanel's repo web-link is
host-aware (Forgejo uses the Gitea /src/branch/ path instead of GitHub's
/tree/, and the tooltip reads 'Open in browser' for non-GitHub hosts).
…Codeberg / Forgejo)

Integrate the fork PR onto dev for staging then promotion to prod,
independent of the contributor. Sole conflict was in GitHubRepoModal.tsx:
resolved in favour of the PR's host-neutral HostRepo model
(repo.isPrivate / repo.defaultBranch / key), keeping main's Tailwind
shrink-0 shorthand.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…yaml, sharp) (#268)

* chore(deps): clear high-severity audit findings in root and collab-server

Root (lock-only, no package.json change):
- brace-expansion 1.1.14 -> 1.1.16 and 5.0.6 -> 5.0.7 (GHSA-3jxr-9vmj-r5cp,
  the advisory range widened to cover the versions we were pinning).
- js-yaml 4.2.0 -> 4.3.0 (GHSA-52cp-r559-cp3m), same npm audit fix run.

collab-server: override sharp to ^0.35.0 (GHSA-f88m-g3jw-g9cj, libvips CVEs).
Bumping wrangler does not fix this: miniflare still pins sharp 0.34.5 as of
4.20260721.0, so every wrangler >=4.16.0 is affected and `npm audit fix --force`
would downgrade wrangler 4.110.0 -> 4.15.2. PR #256 (wrangler 4.112.0) does not
clear the advisory either. sharp only serves miniflare's local Images binding
emulation, which this Worker does not use, and it never ships to the Worker.

Verified: root typecheck, eslint, 3232 jest tests; collab-server typecheck,
11 vitest tests, `wrangler deploy --dry-run`, and `wrangler dev` serving 200.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(deps): override sharp at root too, clearing the last audit gate

CI runs `npm audit --audit-level=high` as a blocking step, so leaving the
root next -> sharp advisory (GHSA-f88m-g3jw-g9cj, the same libvips CVEs as
collab-server) kept the check job red. `npm audit fix --force` would have
downgraded next to 14.2.35, so override sharp to ^0.35.0 instead, matching
the collab-server fix and the existing overrides block here.

next declares sharp as an OPTIONAL dependency at ^0.34.3, and nothing in
this repo uses it: there is not a single `next/image` import: every mention
of it in src/ is a comment explaining why we deliberately use a plain <img>
instead (blob: URLs from IndexedDB attachments, animated GIFs). Image
optimization is never exercised, so the out-of-range bump has no runtime
surface here.

Gate (all green, .next cleared first per CLAUDE.md's overrides note):
lint, typecheck, 3232 jest tests, production build, and
`npm audit --audit-level=high` reporting 0 vulnerabilities at root.

Note: `npm audit fix` in the previous commit also took next 15.5.18 ->
15.5.21 (a patch bump inside the existing ^15.5.18 range, lock-only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(deps): keep next at 15.5.18, drop the incidental patch bump

The `npm audit fix` in f3aa243 also carried next 15.5.18 -> 15.5.21 along
for the ride. Nothing asked for it and no advisory needs it: the only
next-related finding was the transitive sharp one, which the override in
8f36dee fixes independently of the next version. `npm audit` still reports
0 vulnerabilities with next pinned back.

It is also not free. Jest transforms through `next/jest` (jest.config.js),
so a next bump swaps the SWC transform and shifts transpile timing — the
exact mechanism the comment in publishGistModal.test.tsx:219-227 already
blames for this suite's modal tests unmounting mid-test under CI load
("body collapsed to <div/>"). Two CI runs on 15.5.21 tripped two different
userEvent modal tests (taskEditModal, then publishGistModal) with that
signature; both pass locally and on dev at 15.5.18.

That test fragility is a real latent problem worth fixing on its own, but
it is not this PR's job, and a dependency-audit change should not be
carrying an unrequested framework bump that destabilises CI.

Lock delta vs origin/dev is now exactly the intended set: brace-expansion,
js-yaml, sharp (+ its platform binaries), and a transitive semver patch.

Gate: lint, typecheck, 3232 jest tests, build, audit 0 vulnerabilities.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: noteser-agent <noteser-agent@claude>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…270)

npm audit fix (lockfile-only). Clears the Next.js advisory batch published
2026-07-22 (GHSA-m99w-x7hq-7vfj, GHSA-89xv-2m56-2m9x, GHSA-68g3-v927-f742,
GHSA-4633-3j49-mh5q, GHSA-4c39-4ccg-62r3, GHSA-p9j2-gv94-2wf4,
GHSA-q8wf-6r8g-63ch, GHSA-955p-x3mx-jcvp), which fail the CI audit gate.

Stays within the existing ^15.5.18 range; no package.json change.
The @tailwindcss/oxide-wasm32-wasi bundled-dependency entries are churn from
npm 12 re-expanding the tree, not a dependency change.

Co-authored-by: noteser-agent <noteser-agent@claude>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@thetechjon
thetechjon merged commit fd5ca5b into main Jul 23, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants