Commit graph

2 commits

Author SHA1 Message Date
41d4e59899 fix(browse): refresh tree after workflow moves, guard double-submit, fix modal listener leaks
Workflow data-consistency cleanup across the transmittal modules.

Stale-tree / re-trigger hazard: Stage, Unstage, and Accept reported success
with "reload to see the move" and never refreshed, leaving the moved item at
its old location in the tree — inviting the user to re-fire the action on a
folder the server had already moved. They now refresh the current listing on
success. This also revealed that events.refreshListing was never exported,
so upload.js's comment-upload refresh (which guards on it) was silently a
no-op — exporting it fixes that path too.

Non-atomic stage: "New folder" does mkdir then a separate move; if the move
failed after the mkdir succeeded the user got a generic "move failed" with an
unexplained empty folder left behind. invokeStage now tracks whether it
created the folder and says so, and refreshes so the orphan is visible.

Double-submit: Accept / Plan Review / Stage / Unstage take a module-level
busy guard so a second menu click while a POST is in flight is ignored.

Modal listener leaks (verified): the Escape keydown handler in accept,
plan-review, and create-transmittal was only removed on the Escape path —
cancel / overlay-click / submit all leaked a live document listener bound to
a detached modal. Bound once and removed in close() (matching history.js).

history.js restore: split the PUT from the post-restore refetch so a refetch
error can no longer surface a misleading "Restore failed" after the restore
has already persisted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:59:23 -05:00
690d185dc2 feat: reviewing/ lifecycle — Plan Review endpoint, virtual received window, browse context-menu workflows
Two layers shipped together since the second builds on the first.

LAYER 1 — reviewing/ + Plan Review scaffolding

- reviewing/ is now a real folder under each project, populated by the
  Plan Review composite endpoint. The old reviewing/ virtual aggregator
  handler is retired.
- POST /<project>/archive/<party>/received/<tracking>/ with X-ZDDC-Op:
  plan-review scaffolds physical workflow folders under reviewing_root
  and staging_root, each carrying .zddc.received_path pointing back at
  the canonical submittal. Idempotent re-runs match by received_path
  and re-converge the ACL.
- Virtual received window: when listing or writing under
  <workflow>/received/, the server resolves through the canonical
  archive/<party>/received/<tracking>/ via the workflow's
  .zddc.received_path. Writes get rewritten to
  <workflow>/<base>+C<n><suffix> so review comments land in the
  workflow folder and never touch the WORM archive.
- Cascade defaults declare on_plan_review per project so the
  reviewing_root and staging_root are configurable.

LAYER 2 — browse context-menu workflows

- Accept Transmittal: right-click a transmittal folder in
  archive/<party>/incoming/ → validates ZDDC folder + filename
  conformance, atomic-renames the folder to
  archive/<party>/received/<tracking>/ (WORM zone), and optionally
  chains into Plan Review in the same composite request. Re-acceptance
  with a different revision merges file-by-file; WORM forbids
  overwrite of an existing filename.
- Stage / Unstage: right-click files in working/<…>/ → "Stage to…"
  with picker of existing staging transmittal folders + inline
  "New transmittal folder…" create; right-click files in
  staging/<…>/ → "Unstage to working/" defaulting to the user's
  working/<email>/ home. Reuses the file-API move primitive.
- Create Transmittal folder: right-click the staging/ pane → prompts
  for a ZDDC-conforming folder name with live validation; mkdir,
  then navigate to the new folder URL where the transmittal tool
  serves the editor.
- Supporting infrastructure: new CanonicalFolderAt cascade lookup +
  X-ZDDC-Canonical-Folder response header so the browse SPA can
  scope-gate menu items without re-implementing the cascade
  client-side.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 16:08:04 -05:00