Skip to content

EYAS v0.8.14-beta — Shape your own landing page

Choose a tag to compare

@eyssen eyssen released this 26 Aug 08:01
· 1 commit to main since this release

The landing page stops being something you're handed and becomes something you shape. The fixed
dashboard is gone; a nine-tile grid takes its place, and the extension point it's built on had
been sitting declared and unused since before this feature existed.

Home

  • Widget grid at /: drag to move, drag a corner to resize, remove a tile, or open a drawer
    and add one — including tiles from disabled modules, shown dimmed so you can see what could be
    there. Layout is per user and per breakpoint (lg/md/sm arrange independently) and saves
    itself ~800ms after you stop dragging.
  • Factory nine: Pulse, Attention, Running agents, Schedule, Conversations, Board, Briefing,
    Cost, System. No stored layout means the factory layout applies — so a later release that adds
    a tile reaches everyone who never customised, automatically. A customised user is instead
    offered any newly-added factory widgets ("Add" / "No thanks"), never handed them silently.
  • Tiles fail alone. A per-tile error boundary means a broken module shows "Unavailable" on
    its own tile; the other eight keep working.
  • Disabled-module tiles survive. A tile from a disabled module drops out of the rendered grid
    but keeps its stored position and config, and returns intact when the module is re-enabled.
  • The widget extension point is alive. FrontendManifest.widgets / WidgetRegistration
    (src/core/types.ts) were declared and typed but nothing populated or read them. The new
    home module now collects them from the module loader and serves them at
    GET /api/v1/home/widgets; a contract test forbids a manifest-declared widget with no frontend
    component, or the reverse.
  • Setup requests collapse: SetupRecommendationsCard fired 10 requests on every open
    (providers, projects, prompts, agents, search sources, backups, ingress, autonomy, vault,
    communication). It now calls one server-cached aggregate, GET /api/v1/home/setup-status.
  • Dead code removed: AutonomyNudgeCard — never imported, never rendered — is deleted, along
    with the fixed dashboard page it used to live on.
  • Handbook: daily/home documents the grid, edit mode, add/remove/resize, restoring the factory
    layout, and the new-widget offer, in en, hu, de, es, fr and tlh.

Security

  • The home endpoints were never authenticated. home created its routes in onRegister, which
    runs for every module before any module's onStart — where auth mounts its middleware. Hono
    composes middleware in registration order, so nothing auth registered could ever apply: every
    /api/v1/home/* request failed with 401 and the UI bounced the user straight back to the login
    screen. Routes now mount in onStart and home declares auth as a dependency, which forces the
    order through the loader's topological sort. CSRF pairing added for the mutating layout routes.
  • A contract test now asserts what a route test structurally cannot. Every route test in this
    repo installs its own c.set('userId', …), i.e. simulates a world where auth already ran — which
    is why thousands of green tests never saw the above. api-auth-coverage.contract.test.ts runs the
    real dependency resolver over the real registration order and fails if a module that mounts routes
    lands before auth, or if an /api/v1 segment is neither covered nor on a named public list.

Fixed

  • Each breakpoint keeps its own arrangement. The grid loaded the layout once at lg and never
    reloaded, so crossing a width threshold made the library derive an md layout from the lg one
    and save it — creating a stored row for someone who never customised (which stops future factory
    widgets reaching them) and flattening a deliberately arranged desktop layout on the way back.
  • Tiles stay inside their tiles. Content larger than its cell escaped the frame and painted over
    neighbouring panels; it is now contained, with a visible scroll affordance where it scrolls. Pulse
    stays readable at its minimum height instead of clipping its own figures.
  • A failed fetch no longer reads as good news. Attention, Conversations, Briefing and Board
    rendered a backend failure as a successful empty state — a dead approvals endpoint said "Nothing
    needs your attention". All nine tiles now report an unavailable source as unavailable.

Known issues

  • The Privacy page bounces to login, for the same reason the home page did: privacy registers
    before auth, so /api/v1/privacy/* never passes through the auth middleware. Its handlers use
    requirePermission, so the endpoints fail closed rather than being exposed — but the page is
    unusable. Not fixed here: privacy's registration position is load-bearing for model wrapping.
  • 17 route segments with mutating endpoints have no CSRF pairing (a2a, artifacts, client-wiki,
    connections, costops, data-port, federation, ideas, intel, internal, ops, privacy, prompt-coach,
    skill-generation, system, team-sessions, voice). Pre-existing; frozen in a self-checking baseline
    so the list cannot grow unnoticed.
  • Disabling auth would start every module unprotected. startAll never checks that a live
    module's declared dependencies are enabled, and EyasModule.required is declared but read nowhere.
  • Visual layout was verified by a human on one screen size only; jsdom performs no layout, so no
    automated test covers rendering, drag-and-drop or resize.