Skip to main content

UX-CONTENT-PACKS.md

This document defines the UX contract for Content Packs.

Goal:

  • make reusable content packaging simple for authors
  • keep publish/install behavior deterministic and auditable
  • expose lineage clearly so operators can defend provenance without backend knowledge

Capability Baseline (Validated 2026-02-25)​

Backend-live now:

  • pack management:
    • GET /api/v1/content-packs
    • POST /api/v1/content-packs
    • GET /api/v1/content-packs/\{id\}
    • PATCH /api/v1/content-packs/\{id\}
  • item curation:
    • POST /api/v1/content-packs/\{id\}/items
    • PATCH /api/v1/content-packs/\{id\}/items/\{itemId\}
    • DELETE /api/v1/content-packs/\{id\}/items/\{itemId\}
  • publish/install:
    • POST /api/v1/content-packs/\{id\}/publish
    • POST /api/v1/content-packs/\{id\}/revisions/\{revisionId\}/install
  • provenance:
    • GET /api/v1/content-packs/\{id\}/revisions/\{revisionId\}/lineage

Current backend behavior to honor in UX:

  • write operations require Idempotency-Key.
  • pack permission gates currently reuse authoring caps:
    • read: questions.read
    • write: questions.write
  • publish rejects invalid state (for example empty pack).
  • install creates draft evaluations/versions from published revision items.

0. Pack Doctrine (MUST)​

  1. Packs are reusable bundles of evaluation versions, not live links to mutable authoring state.
  2. Publish is the trust boundary: a revision hash and manifest are frozen at publish time.
  3. Install is additive and auditable: it creates imported draft content; it does not mutate source assets.
  4. Lineage is first-class: every install should be traceable back to revision + source evaluation version.
  5. UX must be version-forward and provenance-forward, not hidden behind generic "library" language.

0.1 Packs Interface Guardrails (MUST)​

  • Publish/install flows must be explicit about scope and downstream impact before confirmation.
  • Lineage visibility must remain first-class and accessible (keyboard/screen-reader, clear drilldown links).
  • Idempotent writes must map to deterministic UX outcomes (in-progress/conflict/replay-safe states).
  • Status labels must use canonical wording and avoid ambiguous publish/install synonyms.
  • Mobile/iPad supports list/detail review and safe install actions; dense curation/reorder workflows may be desktop-optimized with explicit handoff.
  • Error states must preserve operator trust by separating validation failures from permission/policy failures.

1. Information Architecture​

Place under authoring > Content Packs.

Primary screens:

  1. Pack List
  2. Pack Detail
  3. Publish Revision modal
  4. Install Revision modal
  5. Revision Lineage view

Supporting surfaces:

  • evaluation version picker drawer for item add
  • install result summary panel

2. Pack List UX​

API:

  • GET /content-packs?page=&limit=

Required table columns​

  • title
  • status (draft, published, archived)
  • latest published revision indicator
  • updated at

Required actions​

  • Create pack
  • row click -> open pack detail

Rules:

  • empty state must include create CTA.
  • pagination driven by meta.page, meta.limit, meta.total.

3. Pack Detail UX​

API:

  • GET /content-packs/\{id\}
  • PATCH /content-packs/\{id\}

Detail is three blocks:

  1. Pack metadata
  2. Items (curation order)
  3. Revisions timeline

3.1 Metadata block​

Editable fields:

  • title
  • description
  • status

Rules:

  • save uses PATCH + Idempotency-Key.
  • invalid empty updates are blocked client-side and server-side.

3.2 Items block​

Item shape:

  • sourceEvaluationVersionId
  • pos
  • metadata

Item actions:

  • add item (POST /items)
  • reorder/update item (PATCH /items/\{itemId\})
  • delete item (DELETE /items/\{itemId\})

Rules:

  • reorder should display explicit order numbers and use optimistic UI with rollback on failure.
  • deleting an item re-sequences remaining positions; UI must re-render returned canonical positions.
  • each item should deep-link to source evaluation/version context when available.

3.3 Revisions block​

Display revisions from GET /content-packs/\{id\}:

  • revision number
  • created at
  • manifest hash
  • quick actions:
    • View lineage
    • Install

4. Publish Revision UX​

API:

  • POST /content-packs/\{id\}/publish

Publish modal requirements​

  • show revision intent summary:
    • item count
    • source evaluation version IDs (or titles if resolved)
  • show warning that publish freezes manifest snapshot and hash.
  • require explicit confirmation action.

Response handling​

  • on success (201), append revision to timeline and mark pack status as published.
  • if validation fails (for example no items), render corrective guidance:
    • "Add at least one item before publishing."

5. Install Revision UX​

API:

  • POST /content-packs/\{id\}/revisions/\{revisionId\}/install

Install modal requirements​

  • show target revision summary:
    • revision number
    • manifest hash
    • item count
  • explain install behavior:
    • imported assets are created as draft evaluations.

Install result rendering​

From response:

  • count
  • items[] with:
    • source evaluation version ID
    • installed evaluation ID
    • installed evaluation version ID

Post-install actions:

  • Open installed evaluation
  • View lineage

Rules:

  • installation is idempotent per key; repeated click retries must reuse the same key.

6. Revision Lineage UX (Critical)​

API:

  • GET /content-packs/\{id\}/revisions/\{revisionId\}/lineage

The lineage screen is the defensibility surface.

Required sections​

  1. Revision header
  • revision number
  • manifest hash
  • created at
  1. Item provenance table
  • pos
  • sourceEvaluationVersionId
  • metadata
  1. Install chain per item
  • install IDs
  • installed evaluation/version IDs
  • created at
  • submission linkage metrics
  1. Summary rollup
  • install count
  • submission count
  • snapshot-linked submission count

UX rules​

  • default sort by pos, then install created-at descending.
  • every entity reference is linkable where allowed.
  • include plain-language explanation of metrics:
    • snapshotLinkedSubmissionCount means submissions where snapshot evaluationVersionId matches installed version.

7. Permission and State Rules​

7.1 Capability gating​

  • if user lacks questions.read: hide packs nav entry.
  • if user has read but lacks questions.write: read-only pack detail, no mutating CTAs.

7.2 Status behavior​

  • draft: editable, publish enabled if valid.
  • published: editable metadata still possible, new revision publish allowed.
  • archived: viewable; write actions should be policy-gated by capability and status rules.

8. Error and Idempotency Contract​

All pack mutations must:

  • attach Idempotency-Key
  • treat duplicate submissions as replay-safe
  • map idempotency conflict/in-progress to deterministic retry guidance

Status semantics:

  • 400: validation input error
  • 404: pack/revision/item not found (or scope-hidden)
  • 409: idempotency conflict/in progress
  • 500: server failure; keep operator context and allow safe retry

UX copy requirements:

  • never show raw SQL or internals.
  • always provide one clear next action.

9. Import and Propagation Contract (Target-State)​

Current backend supports install/lineage but does not yet expose a first-class pack import workflow or authoring propagation workflow.

9.1 Pack Import (Proposed)​

Target UX flow:

  1. Upload pack artifact or provide source reference
  2. Preview import diff
  3. Resolve collisions
  4. Apply import with deterministic idempotent job

Required preview output (target-state):

  • incoming revision manifest hash
  • item count and source IDs
  • conflicts by type:
    • name collision
    • source version already present
    • permission/scope conflict

Collision policies to support:

  • skip
  • create_copy
  • replace_draft_only

9.2 Propagation from Updated Source (Proposed)​

Target UX flow:

  1. Detect published source changes that affect pack items
  2. Show impact summary (which pack revisions/items are affected)
  3. Create new candidate revision with explicit propagation choices
  4. Publish propagated revision and preserve prior revision history

Rules:

  • propagation must always create a new revision; never mutate published revision in place.
  • prior installs remain traceable to the original revision hash.
  • impacted installs/submissions are shown as advisory context, not auto-mutated.

9.3 Suggested Backend Surfaces (Tracked)​

  • POST /api/v1/content-packs/import/preview
  • POST /api/v1/content-packs/import/apply
  • POST /api/v1/content-packs/\{id\}/propagation/preview
  • POST /api/v1/content-packs/\{id\}/propagation/apply

These routes are design placeholders and must be gated until backend contracts exist.


10. Shared Component Contracts​

Packs UI must reuse shared primitives:

  • EntityLink for IDs in lineage/install tables
  • read-only right-drawer peek on drawer-enabled surfaces
  • full-page routes for primary assets (packs/evaluations/submissions)
  • scope/freshness indicators on lineage data

11. Definition of Done (Content Packs UX)​

  1. Pack list/detail/revision/install/lineage flows are documented with concrete endpoint bindings.
  2. Publish and install flows include deterministic confirmation + result states.
  3. Lineage screen exposes provenance chain and metrics as first-class UX, not hidden diagnostics.
  4. Mutation flows honor idempotency key behavior and deterministic retry messaging.
  5. Capability gating and read-only behavior are explicitly defined.
  6. Link contract is applied to source versions, installs, and installed assets.
  7. Target-state import/propagation contracts are explicit and non-conflicting with current install/lineage behavior.