Skip to content

Git scratchpads — instant, ephemeral, Solid-authed git remotes #322

Description

@melvincarvalho

TL;DR

Push to a URL that doesn't exist yet → JSS materializes a fresh git repo, hands you back the clone URL, auto-cleans it up after the TTL expires. Authenticated by your existing Solid identity. No pre-provisioning, no dashboards, no tokens to mint.

$ git remote add scratch https://alice.solidweb.app/git/scratch/feature-x.git
$ git push -u scratch main
# JSS materialized the repo on first push.
# Repo will auto-delete in 24h unless you bump the TTL or persist it.

That's the whole feature.

Why

AI agents and pipeline tooling want disposable git remotes that exist only for as long as the work does. Today the options are:

  • GitHub/Gitea: heavyweight to provision per task; agents need API tokens; cleanup is manual.
  • gitfork.app: nails the ergonomics, but uses Basic Auth and lives outside the user's pod.
  • A self-hosted git server: works but every team rolls their own, no persistence story, no integration with the user's identity.

JSS sits in a sweet spot: it already speaks git smart-HTTP (src/handlers/git.js), already has Solid auth, already has per-pod storage and quotas. Adding "auto-materialize on first push, auto-expire on TTL" turns every JSS pod into a personal disposable-git endpoint that Just Works for any Solid-authenticated agent.

What it would look like

Use cases

  • Agent workspaces: an autonomous agent clones, mutates, pushes, walks away. No cleanup script, no leaked branches, no token rotation.
  • CI scratch repos: pipelines build a temporary repo from artefacts, point Snapshotting / e2e tooling at it, let it expire.
  • Share-and-forget: drop a snapshot of a work-in-progress for a peer to clone over IRC/Matrix; expires in 24 hours.
  • Reproducible bug reports: minimal-repro repo materialized on the spot with a one-week TTL.
  • Solid-native ephemeral state: stores that need git semantics (history, branches, refs) but don't deserve permanent storage in the pod.

URL shape

https://<pod>.solidweb.app/git/scratch/<name>.git
  • Lives under a fixed /git/scratch/ namespace per pod — segregated from regular pod data.
  • <name> is whatever the agent chooses on first push.
  • The pod owner authenticates as themselves; agents authenticate with their Solid token.

Lifecycle

Event Behaviour
First git push to a nonexistent scratch URL Repo is created, push proceeds, TTL clock starts.
Subsequent operations (clone, fetch, push) Behave like any git remote, optionally extend TTL on activity.
TTL expiry Repo deleted in the next sweep (configurable cadence).
Manual persistence POST /git/scratch/<name>.git/persist flips the repo to permanent — pod-owner only.
Manual deletion DELETE /git/scratch/<name>.git — owner only.

Configuration

{
  "gitOnDemand": true,
  "gitScratchDefaultTtl": "24h",
  "gitScratchMaxTtl": "30d",
  "gitScratchMaxRepos": 100
}

Identity & access

Solid auth all the way down. No HTTP Basic. Three rules:

  1. Anyone with a valid Solid token for the pod's namespace can push to a new scratch URL.
  2. Existing scratch repos follow standard pod ACL — the creator is owner; sharing is via WAC.
  3. Persistence requires pod-owner auth — agents can't unilaterally turn ephemeral repos into permanent storage.

Design choices worth getting right

  • Auto-create only under /git/scratch/ — never on arbitrary pod paths. Prevents typo-squatting, keeps the feature contained.
  • No upstream seeding by default — the gitfork "seed from URL" feature is nice but is an SSRF vector. Add later behind an allow-list config.
  • Anonymous push: opt-in only — by default agents must identify with a Solid token (auditability). Operators who want true gitfork-style anonymity flip a flag.
  • TTL sweeps as a background pm2-friendly task — periodic, not per-request, so push latency stays unaffected.
  • Quota integration — scratch repos count against the pod's quota. Same .quota.json machinery (Intermittent 500 on concurrent PUTs to different trackers (pilot drag-drop) #309 work).

Why this fits JSS

JSS already has the building blocks:

  • Git smart-HTTP (src/handlers/git.js): clone, fetch, push, pull all work today.
  • Solid auth (src/auth/middleware.js): one identity story across HTTP, WebSocket, and git.
  • Per-pod quota (src/storage/quota.js): atomic, race-safe (post Intermittent 500 on concurrent PUTs to different trackers (pilot drag-drop) #309).
  • Notifications (src/notifications/events.js): could emit git.scratch.created / git.scratch.expired events for tooling that wants to subscribe.

Adding scratchpads turns those primitives into a feature with a clear elevator pitch:

Every JSS pod is a personal, ephemeral git server.

Acceptance criteria

  • git push to https://<pod>/git/scratch/<name>.git materializes the repo on first push, with the pushing identity recorded as creator.
  • Configurable default and max TTL.
  • Background sweeper deletes expired repos and emits a notification.
  • POST /git/scratch/<name>.git/persist (owner-only) prevents expiry.
  • DELETE /git/scratch/<name>.git (owner-only) removes immediately.
  • Scratch repos count against pod quota; over-quota pushes return 507.
  • No HTTP Basic Auth path; all access goes through existing Solid auth middleware.
  • Documentation: a one-page guide showing the agent workflow.

Related

Status

This issue is exploratory — opening it to capture the design before momentum builds. Happy to iterate before any implementation begins.

Metadata

Metadata

Assignees

No one assigned

    Labels

    pluginCould be implemented as a plugin (#206); core/plugin line defined in #564

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions