Skip to content

Phase 3: fold in #303 landing-page seeding on portable generators (#427) #433

Description

@melvincarvalho

Phase 3 of the umbrella plan in #427.

Scope

Resurrect the landing-page seeding work from #276 / PR #303 onto the new portable generators (Phase 1 of #427). Now that accessTo/default are emitted relatively, seedServerRoot becomes portable by construction — no further design tension between its public-read root ACL and the single-user createRootPodStructure ACL.

Changes:

  • New src/ui/server-root.html — minimal landing-page template (operator-overridable).
  • New src/ui/server-root.js — renderer + seeder. Uses generatePublicReadAcl from src/wac/parser.js (Phase-1 portable form).
  • src/server.js — gains an onReady hook (skipped in read-only mode) that calls seedServerRoot with current server context (mode, IDP, enabled features).
  • New test/server-root.test.js.

Closes #303 / supersedes its branch (origin/issue-276-server-root-landing). The original PR was open since Apr 23 and went conflicting against gh-pages.

Why

Multi-user JSS deployments currently land on a raw container listing at /. New pod providers had to build their own landing page from scratch. Single-user deployments served index.html only when the operator wrote one — which fonstr does, but a bare jss start --single-user does not.

Behavior

  • Skip-if-exists for /index.html, /.acl, and /index.html.acl — operator customisation is never overwritten.
  • Public read only at the root — no public write. Operators edit /index.html on disk, not via the web. (A future --admin-webid could relax this.)
  • Mode-aware rendering:
    • multi-user + IDP → "Create a pod" + "Sign in"
    • single-user + IDP → "Sign in" (no Create-a-pod)
    • both → "Docs" link + version + mode + enabled-feature pills
  • Read-only deployments skip the seeder entirely (no DATA_ROOT mutation).
  • Failure isolation: HTML write failure aborts ACL seeding, so the server never ends up with a public root ACL but no index page.

Carry-over from PR #303 review

PR #303 had Copilot review pickups already addressed on its branch:

  • generatePublicReadAcl reuse (no inline ACL JSON)
  • skip in read-only mode
  • check storage.write returns
  • real IDP routes (/idp/register, /idp — not the non-existent /.account/new and /idp/auth)
  • full error logging (with stack)
  • terminal feature flag
  • resilient package.json read
  • restore process.env.DATA_ROOT after tests

One remaining nit from that review thread: String.prototype.replace with a string interprets $&, $1 etc. as substitution patterns. Interpolated values like the singleUserName-derived subtitle could in principle contain $ characters. Phase 3 will switch the template substitutions to the function form (replace(/{{key}}/g, () => value)) to side-step this entirely.

Tests

Carry forward + adapt the tests from PR #303:

  • seeds /index.html so GET / serves HTML — fresh test server, GET /
  • landing page is publicly readable — direct GET /index.html
  • does not overwrite operator-provided /index.html — pre-write a custom file, assert preservation
  • renderServerRoot — mode-specific output (5 tests) — multi-user+IDP, single-user+IDP, multi-user-no-IDP, single-user subtitle includes pod name, feature listing
  • interpolates version + escapes version to prevent injection

Plus one new test for the $& regression: renderServerRoot should emit a singleUserName containing $ characters intact.

Acceptance

  • Three new files (src/ui/server-root.{html,js}, test/server-root.test.js) and the onReady hook in src/server.js.
  • All existing tests pass.
  • All new tests pass, including the $& regression.
  • PR feat: default landing page + ACL at server root (#276) #303 closed (this issue's PR notes the supersession).

Out of scope

  • Cross-host owner write (Phase 4 — separate design issue).
  • --admin-webid / web-edit access for the landing page (future iteration).

Refs #427.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions