Skip to content

m8.9: top-level membership, de-duplicated rollups, and a hardening sweep

Latest

Choose a tag to compare

@WilliamSmithEdward WilliamSmithEdward released this 20 Jun 08:45

The dimension-editor and hardening release: editable MDX queries; Copy/Move/Pin and
explicit top-level membership in the structural dimension editor; de-duplicated
consolidation rollups and a lowercase, display-name-decoupled on-disk layout; the
suppress-zeros split and a consolidated view-save flow; plus a wide adversarial
hardening pass (an app-wide error boundary, WebSocket-reload data-loss guards,
accessibility, and performance) and the security fixes below.

Added

  • Editable MDX queries in the cube view. The "MDX for this view" dialog is now
    an editable textarea with a Run button that executes a full
    SELECT … ON COLUMNS / ON ROWS FROM [cube] [WHERE ( … )] query against the cube
    and renders the resulting cellset, surfacing parse/validation errors inline. The
    epiphany-mdx parser gained a SELECT-query layer (parse_query) above its set
    sublanguage, and a new POST /api/v1/cubes/{cube}/mdx endpoint executes it through
    the same Read authorization and element-masking path as the ad-hoc cellset query.
  • Copy to / Move to for dimension members. The member action menu now offers
    Copy to (add the member to another consolidation as an alternate rollup, keeping
    its existing parents; a consolidation it already belongs to is greyed as "already
    contains") and Move to (reparent it under exactly one consolidation or the top
    level, with a confirm when that would drop its other rollups). Self and descendant
    targets are excluded so a cycle can't be formed.
  • Separate zero-suppression for rows and columns. The single "Suppress zeros"
    option is now two independent toggles, Suppress zero rows and Suppress zero
    columns
    , on the cube viewer's Save dialog and the view editor. Views saved before
    this map a legacy suppress_zeros: true to both flags.
  • Explicit top-level membership (ADR-0038). A member can be pinned to the top level
    so it shows as a display root while still rolling up under its consolidations - it
    appears both at the top and under each parent (the latter carry a "(pinned)" badge).
    Pin via the row menu's Copy to -> Top level or a discoverable drag-to-top-level
    drop zone; copying a top-level member into a consolidation auto-pins it so it stays at
    the top; Move to -> Top level is the exclusive variant (reparent to a standalone
    root). A display-only marker: no edge, weight, or value changes. Full stack - a
    per-element flag (core), a name-addressed WAL record (persist), a pinned_to_top DTO
    field + pin/unpin edit ops (api), and the editor + pivot rendering.
  • Expand all / Collapse all in the dimension editor toolbar, matching the cube
    viewer and the model tree.

Changed

  • Views are created from the cube viewer. The duplicative "Add view..." authoring
    path was removed; arrange a layout in the cube viewer and use Save view to create
    one. The Views workspace now opens and edits existing views in place.
  • Consolidation rollups de-duplicate (ADR-0039). A member reachable via more than
    one path to a consolidation - e.g. a direct child of a total that is also a child of
    one of that total's sub-consolidations - is now counted ONCE in that total, at its
    most-direct (fewest-hops) path weight, instead of summed per path. It flows through
    every consolidated read, spreading, and element-security masking, and makes the
    multi-parent / pinning structures safe from accidental double-counting.
  • On-disk cube folders are lowercase, filesystem-safe slugs decoupled from the
    display name (ADR-0037).
    A cube "Sales" persists under cubes/sales/ while still
    presenting as "Sales" (the engine reads the name from the snapshot, not the folder).
    Existing folders migrate by rename on first start (resilient: never deletes; a real
    slug collision is left intact and logged), and cube names are now unique
    case-insensitively. For cross-platform (Linux, case-sensitive filesystem) consistency.

Fixed

  • Cube view: pivot rows/cells no longer duplicate or strand cells under an
    alternate rollup (a member reachable from two consolidation parents). Rows, cells,
    and header spans are keyed by each member's drill path instead of its bare name,
    and saved-subset member lists are de-duplicated.
  • Cube view: the "Who can see it" dropdown in the Save-view dialog now paints
    above the dialog instead of behind it (the dropdown layer ranked below the modal
    overlay in the z-index scale).
  • Dimension editor: right-clicking a member opens the action menu at the cursor
    (it previously anchored to the row's ⋯ button).
  • Cube tab strip: removed the spurious vertical scroll arrows.
  • Durability: a checkpoint can no longer lose data on a crash. The snapshot is
    fsynced (file and directory) before the write-ahead log is cleared, and a
    reindexing dimension edit (reorder/delete/insert) folds outstanding writes and
    empties the WAL before rewriting the snapshot, so recovery can never replay a
    stale element index onto the new layout. A WAL truncated below its header by a
    crash is now treated as fresh rather than failing the open.
  • A failed model-definition commit no longer leaks into the next one. If
    persisting a definition change fails midway, the in-memory model is rolled back
    to the last published version, so the partial change cannot ride out on a later
    successful commit.
  • What-if sandbox overrides now follow structural dimension edits. Reordering,
    inserting, or deleting a member remaps each sandbox override to its member's new
    index (and drops overrides on a deleted member) instead of leaving them on the
    wrong member or panicking the checkpoint.
  • Flows: the TypeScript stripper no longer drops switch case bodies such as
    case 0: break; (a case/default colon was mistaken for a type annotation), and
    no longer corrupts interface used as an ordinary identifier.
  • Dimension aliases: reassigning an alias no longer leaves the old one
    resolvable
    (which also falsely blocked another member from claiming the freed
    name).
  • Cube view: an alternate-rollup member can now be expanded independently under
    each parent
    (expansion is keyed by drill path, not member name); a slow cell
    read can no longer overwrite a newer one; and a set that fails to resolve surfaces
    the error instead of silently blanking the axis.
  • Dimension editor: rapid keyboard and context-menu structural edits are gated
    so they cannot race a prior in-flight edit, and member-table range selection
    survives a re-sort or filter.
  • A non-admin schedule author can open the jobs workspace again (the admin-only
    run list no longer fails the whole load), and opening a saved view no longer
    drops its layout when the cube loads slowly.
  • Windows service: a failed startup now reports a non-zero exit to the SCM
    instead of a clean stop.
  • Dimension editor: drag-and-drop is a reliable, parent-aware move. A member can
    now be dragged into a consolidation, and every drag emits the minimal, duplicate-free
    edits: dropping onto a consolidation moves the dragged occurrence there while keeping
    the member's other rollups, and the additive add runs before the detach so an
    interrupted multi-step move can never orphan a member. Editor and pivot now agree on
    child order, and the drop-inside target band is larger and recomputed at release.
  • Login: you stay signed in after reloading the page. The session is restored from
    the cookie on load (it was previously held only in memory), including the forced
    password-change screen, and the duplicate password-manager autofill prompt is gone.
  • Login: Enter signs you in, and autofilled credentials work. The form submits on
    Enter even when a password manager swallows the browser's implicit submission, and the
    submit reads the live field values, so a manager that fills the fields without firing
    the usual events no longer sends blank credentials.
  • The what-if sandbox bar no longer shows in the structural dimension editor
    (what-if overlays cell values; editing members and edges has no cells to override).
  • Dimension editor: a row's label click expands but never collapses (only the caret
    collapses), and dragging a multi-parent member to the top level reports honestly
    ("Removed X from Y" when it still rolls up elsewhere) rather than a misleading "moved
    to the top level".
  • A render error in one pane no longer blanks the whole app. A new error boundary
    shows a recoverable fallback for the affected pane and leaves the tab strip and tree
    usable; switching or closing the tab clears it.
  • No more silent data loss from background reloads. Unsaved rule edits survive a
    WebSocket reload caused by activity in another tab; editing a flow or schedule that
    was deleted elsewhere now disables Save (so it is not silently re-created) and says so;
    entering the Administration view honors the unsaved-edit guard; and deleting an open
    object no longer pops a nonsensical post-delete discard prompt.
  • Object tree stays correct under concurrent loads and search. A slower, stale
    response can no longer overwrite freshly loaded children, and a delete or rename during
    a search no longer leaves a stale row in the results.
  • Dimension editor robustness and accessibility. Adding a member as a child is now
    all-or-nothing (a declined conversion or a failed step no longer strands an orphan with
    the form trapped on a duplicate-name error), duplicate names are caught before the
    round-trip, an empty dimension shows guidance, successful edits and keyboard moves are
    announced to screen readers, and a pathological cyclic edge set can no longer overflow
    the tree builder.
  • Cube viewer: stale numbers are not shown during a refresh. While re-querying after
    a layout or filter change the grid dims and announces "Refreshing", so a previous
    slice's values are never read as the current ones, and an empty row axis shows an
    explicit "No data" row.
  • Accessibility: closing the active tab moves keyboard focus to a neighbor (rather
    than losing it on the document body), and the Administration sub-nav is now a correct
    button group instead of a malformed tabs widget.

Security

  • The last administrator can no longer be deleted or demoted, which would have
    locked everyone out of the admin control plane.
  • Sandbox lifecycle endpoints now require cube access (Read to list/create/get/
    discard, Write to commit), matching the data endpoints; a user with no grant on a
    cube could previously enumerate and operate sandboxes there.
  • Deleting a user, resetting their password, or an admin setting their password
    now revokes that user's sessions
    , so a stale token stops working immediately.
  • The session cookie is marked Secure when the server serves over TLS, so it
    is never sent on a plain-HTTP request.
  • Serving plain HTTP on a non-loopback address now logs a warning that the API
    and login are exposed unencrypted.