Skip to content

feat: harden workspace and content management workflows

Stefan Dröschler requested to merge gk/demo_bugfixes-rebased into sd/demonstrator

Summary

  1. Make Assets, Bundles, Workspaces, Users, Dashboard, Chat, Login, and Settings use the same page, form, status, feedback, confirmation, and navigation patterns.
  2. Make asset preparation, bundle deletion, workspace environment changes, contribution uploads, role changes, and ownership transfers explicit and race-safe.
  3. Publish the updated API contracts, contributor guidance, CI gate, and regression coverage for these workflows.

Why

Several management flows could show stale status, lose an in-progress draft, accept an out-of-date mutation, or leave users unsure about the effect of a destructive action. Asset and bundle state also lacked consistent metadata and useful explanations for known text-recognition failures. The affected pages used different controls and native browser prompts for equivalent actions, which made review and recovery harder.

What changed

Shared interface and navigation

  • Add shared page headers, search fields, refresh controls, status badges, notices, list-row styles, accessible dialogs, destructive confirmations, and presentation helpers. Replace page-specific and native confirmation flows with these components.
  • Add a shared unsaved-changes guard. Settings, Users, and Workspaces can save or cancel before navigation, and workspace saves preserve edits that arrive while a request is in flight.
  • Keep the shell, dashboard, chat, login, and management pages consistent across desktop and narrow viewports. Cancel obsolete privilege requests during navigation and logout.

Assets and bundles

  • Show asset version, size, upload time, authoritative preparation state, and stable user-facing diagnostics for known text-recognition failures. Serialize status polling, keep PARTIAL nonterminal, and bound repeated INCOMPLETE polling by document identity.
  • Make add-to-bundle behavior explicit when a bundle already follows the latest version or is pinned to an older version. New versions selected by an unpinned bundle use the backend reconciliation contract; the browser does not issue a second hidden request.
  • Canonicalize bundle identifiers, reject unknown mutation fields, preserve strict item validation, and require a valid upstream deletion acknowledgement before local cleanup.
  • Show unavailable bundle items, keep large item lists scrollable, and require count-aware confirmations for asset deletion and remove-everywhere bundle deletion. Deleting a bundle leaves its assets intact.

Workspaces and users

  • Default new workspace chat environments to Chat with references, call out zero selected reference bundles, and let members add assets directly to a workspace-owned contribution bundle. Preserve successfully uploaded assets when workspace linking fails and report the partial result.
  • Require complete, revision-checked workspace environment updates. Serialize ownership, contribution-role, and reference-access mutations; validate assignment targets; and keep refreshes from overwriting local drafts.
  • Ask how to handle a contributor's bundle before removing the role that grants direct contributions. The user can keep it as workspace references or remove workspace access without deleting the contributor's assets.
  • Default user creation to membership in the active tenant, while keeping deliberate creation without tenant membership available. Keep system administration restricted to global user privileges and preserve form drafts during saves.

Contracts and regression coverage

  • Update the OpenAPI snapshot, generated frontend types, BFF validation, service client, public interface guidance, feature documentation, and workspace debug journey for the final request shapes.
  • Add focused backend, frontend, PostgreSQL, mocked-browser, and multi-user coverage for reconciliation, deletion, stale writes, concurrent role and ownership changes, grounded references, and the shared interface behavior.

Review notes

  • Review backend/workspace_routes.py, backend/workspace_rbac.py, and backend/workspace_contributions.py first for revision checks, transaction boundaries, authorization, and mutation serialization.
  • Review backend/bundle_routes.py and backend/bundle_identifiers.py for strict request validation, canonical identifiers, deletion acknowledgements, and cleanup ordering.
  • Review src/common/navigation/UnsavedChanges.tsx and the Assets, Bundles, Workspaces, and Users pages for draft ownership, stale-response handling, and destructive-action targets. backend/openapi.yaml and src/services/api-types.gen.ts are generated or mirrored contract output.
  • The branch changes no database schema, migration, runtime dependency, secret, application configuration, container contract, or Kubernetes manifest.

UI evidence

All images below are new after-state captures from Chrome with a local Vite frontend and fully mocked BFF responses. The fixtures use synthetic users, tenants, workspaces, bundles, and assets. They prove rendered behavior only, not server authorization, persistence, transactionality, or backend correctness.

Shared desktop and responsive presentation

Dashboard and shared shell after state

Chrome, 1440 x 1000: dashboard, shared shell, quick actions, consistent list metadata, and attention states.

Responsive shell drawer after state

Chrome, 390 x 844: narrow viewport with the application drawer open and primary destinations reachable.

Assets

Asset status and metadata after state

Chrome, 1440 x 1000: asset metadata and DONE, PARTIAL, and failed preparation states, including the stable text-recognition input-limit explanation.

Pinned asset transition after state

Chrome, 1440 x 1000: add-to-bundle dialog for an asset pinned to an older version, with the explicit Use latest transition.

Asset deletion impact after state

Chrome, 1440 x 1000: permanent asset-deletion confirmation with affected bundle and workspace counts.

Bundles

Bundle availability after state

Chrome, 1440 x 1000: scrollable bundle detail with live and unavailable items and the cleanup control enabled.

Bundle deletion impact after state

Chrome, 1440 x 1000: remove-everywhere bundle confirmation with workspace impact and explicit asset retention.

Workspaces

Workspace environment after state

Chrome, 1440 x 1100: default Chat with references environment, zero-reference warning, audience controls, and direct-contribution upload area.

Workspace link incomplete after state

Chrome, 1440 x 1100: partial-success contribution state showing that the asset remains in Assets when workspace linking fails.

Contribution bundle decision after state

Chrome, 1440 x 1000: contributor-role removal decision with keep-as-references and remove-from-workspace choices.

Users and unsaved changes

User tenant membership after state

Chrome, 1440 x 1000: user-creation confirmation with active-tenant membership selected and no internal login.

Unsaved changes guard after state

Chrome, 1440 x 1000: shared navigation guard after editing Settings, with save and cancel choices.

Verification

All source results below apply to clean EthelApp revision b3ecb74c4fdb99480720d66c2514d273f87ab6b1 unless stated otherwise.

  • A focused regression set passed 76 tests.
  • make gate passed 474 backend tests with 10 configured PostgreSQL skips, OpenAPI and route/client checks, lint, type, generated-type and format checks, and 356 frontend tests.
  • The mocked browser suite passed all 10 tests. The current final diff also passes git diff --check.
  • A clean exact-revision application image passed runtime-content checks and the focused headed grounded-reference story. The complete eight-story headed suite passed seven stories. The remaining direct-image assertion asks a deterministic text-only test provider to infer a marker present only in PNG pixels; its grounded PDF path passed, and the request evidence confirmed one image input without an ambiguous reference.
  • A disposable dual-stack check used this EthelApp revision with EthelFlow revision 28200137db16a9005a42f30ec3c93c4fa41c883b. Both isolated stacks reached readiness without restarts and passed persistence and isolation checks; the eight-story result repeated the same seven passes and deterministic text-provider limitation.
  • The 12 UI images above were rendered from the clean revision with synthetic fixtures, zero unhandled API requests, and visual inspection of every capture.

CI

  • Replace the placeholder job with a required gate job for merge-request and default- branch pipelines.
  • Run make gate with Python 3.13, Node 22, and PostgreSQL 16, using the pinned backend development requirements and dependency caches.

Docs

  • Add INTERFACE_GUIDELINES.md as the source for shared frontend interaction patterns.
  • Update the root, backend, service, feature, test, and multi-user documentation for bundle deletion, derivation diagnostics, workspace contributions, request contracts, and maintained verification journeys.

Out of scope / follow-ups

  • Visual interpretation is not added to the deterministic text-only system-test provider. The direct-image transport path is covered, but that provider cannot assert content drawn only in image pixels.
  • No database migration or installation-specific rollout change is included.

Developer notes

  • Read INTERFACE_GUIDELINES.md before changing frontend interactions and use the shared components for equivalent page, form, feedback, status, dialog, and navigation states.
  • Run make gate before review. After intentional backend route or schema changes, run make openapi-generate, regenerate frontend API types, and rerun the gate.
  • Send expected_rev with a complete workspace environment update. Ownership-transfer clients must send the observed current owner, and contribution-role changes must use the contribution-bundle decision contract.
  • Treat bundle deletion as a remove-everywhere operation. Perform local cleanup only after the upstream acknowledgement identifies the requested bundle; do not duplicate reconciliation or workspace-detachment logic in the browser.
  • Keep the workspace debug journey and multi-user stories synchronized with these request shapes when the API changes.
Edited by Stefan Dröschler

Merge request reports

Loading