Skip to content

Upstreaming audit: the path to 'a new jspod-type thing in ~100 LOC on jss' #77

Description

@melvincarvalho

Audit of jspod's ~900 LOC of wrapper code (index.js + lib/) against the jss 0.0.204 surface, toward the goal: a new jspod-type distribution should be buildable as little more than a pages dir + a defaults object + a banner. No code changes proposed here — this is the map. Sequencing is deliberately slow (jspod is in daily use).

A. Already upstream — jspod side now redundant (delegate when comfortable)

  1. Install plumbing (~250 LOC)runInstall, parseAppSpec, loadBundle/resolveBundleSource, install help. jss 0.0.204 ships jss install with the same spec forms (name, org/repo, URL, #ref, =rename), --bundle (JSON-LD, schema:itemListElement), bearer + NIP-98 auth, dual-push. This is Refactor: delegate jspod install to jss install (consolidate install plumbing) #48; its hold conditions (--bundle landed, releases passed) now look satisfied. Keep jspod's policy (bare install → default bundle) as a one-liner.
  2. Token-secret management (~30 LOC) — jss now has its own persisted secret (src/auth/token-secret.js: ~/.jss/token.secret, atomic write, 0600, TOKEN_SECRET env wins). jspod still maintains a parallel implementation at <root>/.token-secret and injects TOKEN_SECRET into the child env. Two secret files on disk, duplicated logic. Caution: existing pods have working <root>/.token-secret files — any consolidation needs a migration story (e.g. upstream a --token-secret-file flag so per-pod scoping survives, then delete jspod's copy).

B. Not in jss — generic wrapper machinery that should go upstream

These are the bits every jspod-type thing would otherwise reimplement (verified absent from jss 0.0.204):

  1. Seed/branding hook — the big one. jss's seedServerRoot() seeds only its own /index.html (skip-if-exists), with no template-override hook; jspod must overwrite pages after boot (seedPodFiles(), 33 LOC + the race it implies). Upstream proposal: --seed-dir <path> (or createServer({seedDir})) taking a directory of pages with an overwrite/skip-if-exists manifest. A distribution then ships pages, not seeding code.
  2. Free-port finding (12 LOC) — jss binds and dies on EADDRINUSE. Upstream --port-retry N (Vite-style shift-up).
  3. Readiness signal (15 LOC of HTTP polling) — no /health endpoint, no structured ready marker on stdout; wrappers must poll. Upstream either a /health route or a machine-readable READY line.
  4. First-run bundle bootstrap (20 LOC) — jspod spawns install --bundle default after first boot. Upstream --bootstrap-bundle <source> on jss start so distros get first-run apps declaratively.
  5. Browser auto-open + TTY/CI/SSH heuristics (24 LOC) — classic dev-server nicety; upstream --open.
  6. In-process start — jss's createServer(options) already covers the full feature set (IdP/git/nostr/MCP in-process), so Embeddable in-process start (no spawn) so jspod can wrap JSS on mobile/single-process runtimes #58 is mostly a jspod-side mapping of jssArgs → options. The one upstream gap: onReady-style hooks aren't reachable by callers, which matters once seeding (item 3) is composable.

C. jspod product identity — stays in the wrapper (what a new distro would swap)

Banner/help (~150 LOC), opinionated defaults (port 5444, me/me, git on), the pages themselves (756 LOC of HTML/ACL), data-browser assets + CDN version pinning (549 LOC), apps/pilot bundle, choice of default bundle, MCP dev tools.

End state

With A delegated and B upstreamed, jspod's lib/start.js collapses to roughly: defaults → map options → createServer()/spawn → done. A new jspod-type thing = jss dep + seed-dir of pages + defaults + banner ≈ 100 LOC.

Suggested order (low risk first)

  1. Upstream items 4, 5, 7 (additive jss flags; jspod unchanged until ready)
  2. Upstream 3 (--seed-dir), then switch jspod to it and delete seedPodFiles()
  3. Upstream 6, switch jspod's bootstrap to the flag
  4. Refactor: delegate jspod install to jss install (consolidate install plumbing) #48 (install delegation) — already specced
  5. Token-secret consolidation (2) — last, needs migration care
  6. Embeddable in-process start (no spawn) so jspod can wrap JSS on mobile/single-process runtimes #58 in-process mode — unlocked by the above

Refs: #48, #58, #60, JSS#464

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions