Skip to content

Latest commit

 

History

History
211 lines (170 loc) · 8.77 KB

File metadata and controls

211 lines (170 loc) · 8.77 KB

Roadmap

Status: Phases 0–7 shipped and running in production, followed by continuing security, operations, and admin work. Phase 8's external identity-provider integrations are optional and demand-driven. For the narrative, up-to-date version with a timeline diagram, see the Roadmap chapter on the docs site. The phase checklists below are the original planning detail; every item in Phases 0–7 has since shipped, so their boxes are ticked. Phase 8 shows what remains.

Phased plan from "config parsing only" to "production-ready ShinyProxy replacement".

Each phase has a clear deliverable. Skip ahead if a phase doesn't apply to your use case (e.g. skip phase 4 if you don't need a dashboard).

Phase 0 — Scaffolding (DONE)

Status: ✅ shipped.

  • Cargo workspace with 6 crates
  • YAML schema covering ShinyProxy + Ruscker extensions
  • Env var interpolation (${VAR}, ${VAR:-default})
  • Two-phase validation (raw text scan + typed model checks)
  • CLI binary with validate, show, inspect
  • Integration tests against the real application.yml
  • Per-crate developer docs (module-level)
  • Mockups in docs/mockups/
  • Architecture, roadmap, ADRs

Deliverable: ruscker validate examples/application.yml produces a useful report.

Phase 1 — Landing page (1 week)

Goal: replace the Thymeleaf-based ShinyProxy landing with Askama templates enhanced by HTMX and Alpine.js. Specs and template properties drive what gets rendered.

  • Add a new ruscker-web crate (or fold into ruscker-admin)
  • Askama templates matching docs/mockups/landing-page.html
  • Type badge colors and access icons driven by template properties
  • Filter chips with counts (matching docs/mockups/landing-filters-cards-refined.html)
  • Light/dark theme toggle (cookie + system preference)
  • Image library: serve static assets from a configurable directory
  • Browser assets with zero Node build step

Deliverable: visit localhost:8080 and see the bundled examples/application.yml portal rendered, looking visually equivalent to today but in Tailwind. Cards are not yet clickable (no proxy yet).

Phase 2 — Persistence + admin CRUD (3 weeks)

Goal: edit specs via web UI, no YAML editing required.

  • SQLite schema + sqlx migrations
  • Importer: ruscker import application.yml --db ruscker.db
  • Exporter: ruscker export --db ruscker.db > application.yml
  • Database-backed user login plus a break-glass environment token
  • Apps list page (filter, search, bulk actions)
  • Add/Edit spec form with type-driven fields (mockup: admin-add-edit-app.html)
  • Image library: upload, convert to WebP, optimize
  • Credentials store: named entries, encrypted at rest
  • Landing-page section editor (mockup: admin-landing-editor.html)
  • Audit log of all admin actions

Deliverable: the operator can fully manage Ruscker via web UI without touching files.

Phase 3 — Proxy + Docker backend (3 weeks)

Goal: actually run apps. The technically hardest phase.

  • LocalDockerBackend via bollard
    • Image pulling with registry credentials
    • Container spawn with resource limits, env, volumes
    • Health-check polling (TCP followed by HTTP readiness)
    • Graceful stop (drain → SIGTERM → SIGKILL)
  • HTTP request forwarding via hyper
  • WebSocket upgrade hijack + bidirectional pump
  • Path rewriting for Shiny's relative URLs
  • Sticky session cookie signing (HMAC-SHA256 via ring)
  • Session store (DashMap impl of SessionStore)
  • Replica pool per spec with selection in routes::proxy
  • Auto-scaler: spawn when utilization > threshold, retire when under threshold for grace period
  • Heartbeat handling (per-spec timeout overrides, -1 = never)
  • API spec branch: HTTP-only, round-robin, no cookie

Deliverable: end-to-end Shiny session works. Open Aurora Prime card on the landing, app loads, reactivity works, session survives page refresh.

Phase 4 — Monitoring dashboard (2 weeks)

Goal: visibility into running containers.

  • /admin/dashboard page (mockup: admin-dashboard.html)
  • Metric cards: containers, sessions, memory, CPU
  • Live container table with utilization bars (short polling via GET /admin/dashboard/snapshot)
  • Sessions-over-24h sparkline chart
  • Recent events feed
  • Logs streaming page with filter + regex + follow mode
  • Container detail view: live CPU/mem charts, environment, logs
  • Alert notification webhook (#930) — spawn-failed / replica-down / saturated events POST JSON to an operator-configured URL (admin System tab), with retry, cooldown dedup and a test button
  • Prometheus metrics endpoint at /metrics

Deliverable: open the dashboard, see everything that's running, drill into any container.

Phase 5 — Production polish (1 week)

  • Graceful shutdown (drain active sessions before exit)
  • structured logging via tracing + tracing-subscriber
  • Rate limiting on API specs (token bucket)
  • CORS support for API specs
  • Configurable max body sizes
  • Health endpoint /healthz
  • Readiness endpoint /readyz
  • Multi-stage Dockerfile for Ruscker itself
  • systemd unit file
  • Documentation: deployment guide, migration guide from ShinyProxy, troubleshooting

Deliverable: ready to drop into production.

Phase 6 (optional) — Multi-host scheduling

  • MultiHostDockerBackend (talks to multiple Docker hosts)
  • Bin-pack vs spread strategies
  • Per-spec anti-affinity ("replicas must be on different hosts")

Phase 7 (optional) — HA / multi-instance

  • Postgres SessionStore implementation
  • PostgreSQL-backed admin catalog matching the SQLite schema
  • Coordination via Postgres advisory locks
  • Failover testing

Phase 8 (optional) — Auth

  • OIDC integration (Keycloak, Auth0, Google)
  • SAML for enterprise
  • LDAP directory integration
  • Role-based access control (Viewer / Editor / Admin) — shipped
  • Per-spec access lists (only group X can use this app) — shipped in Phase 6
  • Per-app step-up MFA — one user-owned TOTP factor, recovery codes, trusted-device grants, and per-spec proof-freshness policy
  • Opt-in identity headers for signed-in users on HTTP and WebSocket — ShinyProxy-compatible user/group headers plus selected profile claims

Only the external identity-provider items (OIDC / SAML / LDAP) remain; the database-backed role model, per-spec access lists, step-up MFA, and identity forwarding already ship.

Continuing shipped work

  • Scheduled jobs — Admin Schedules page, cron ETL semantics, no fire-on-create, collapsed downtime catch-up, leader-only HA firing, the spec's image/environment/volumes/credentials, optional command override, run history/log tail, one-hour default timeout, and the job-failed alert webhook
  • Named-volume management — Admin Disk Volumes card with live reference counts; create labels Ruscker-owned volumes, and remove is offered only for Ruscker-created volumes with zero live references and no catalog reference
  • Users-page scaling — 50-row server-side pagination and server-side accent-aware, case-insensitive search across username, groups, and profile fields on SQLite and Postgres
  • Password policy and password generator
  • Consolidated per-user edit page, including profile, groups, role, password reset, 2FA status/reset, and deletion
  • Clearer admin navigation and titles: Containers and Activity/Atividades, with management-oriented page titles
  • Cookie-boundary hardening for shared-origin apps: reserved Set-Cookie filtering and cookie-clearing Clear-Site-Data neutralization
  • ruscker.yml as the canonical service config, with application.yml retained for ShinyProxy import/fallback

What we explicitly defer / don't do

  • Kubernetes backend — possible, but not until there's demand. KubernetesBackend is a long-term aspiration, not a phase.
  • App ecosystem features — pause/resume, snapshots, etc. These are ShinyProxy Pro features. Not in MVP.
  • Multi-tenancy — separate organizations / billing. Possibly a commercial extension; not in open source.
  • Public marketplace of apps — outside scope.

Definition of "ready to replace ShinyProxy"

After Phase 5, Ruscker can be deployed as a drop-in replacement for existing ShinyProxy installations. The migration path:

  1. ruscker import application.yml --db /var/ruscker/ruscker.db
  2. Stop ShinyProxy
  3. Start Ruscker on the same port
  4. Verify with the same browser URL

Phases 6+ are for organizations with more demanding needs.