ADRs
ADR 0071 — Sorgente gets a real `project` row for Workflow/Screen persistence
  • Status: Accepted
  • Date: 2026-07-16
  • Deciders: maintainer
  • Scope: prj-arno-sorgente-seed, workflow_artboard (ADR 0066), apps/web/src/lib/use-workflow-artboards.ts

Context

prj-arno-sorgente-seed is a synthetic, well-known project id (ADR 0054) used to enter the Sorgente surface via /app/library. It deliberately has no row in the project table — ADR 0054 resolves its display name and pinned project-list card statically, specifically so a test-DB reset or rotation can't silently drop them.

workflow_artboard (ADR 0066) FKs to project.id, and the API's ownership gate (requireOwnedProject) 404s any project id with no row. So every GET/PUT of Sorgente's Workflow/Screen composition artboards 404'd: on load (silently falling back to the in-memory default seed every mount) and on every debounced save (silently dropped). Net effect: editing a screen for Sorgente under Workflow/Screen (ADR 0066/0067/0069) never persisted anything, indistinguishable from a UI bug where "switching tabs resets your edits."

A same-day fix (c32c959, 5fc906d) special-cased isSorgenteProject(id) inside useWorkflowArtboards to skip the network round-trip entirely, formalizing "Sorgente's Workflow data is permanently session-only, never saved." This ADR reverses that fix.

Decision

Give prj-arno-sorgente-seed a real project row, owned by the maintainer, instead of teaching every Workflow-adjacent feature to special- case it. Sorgente's sorgente.* schema (tokens/brand/composition, ADR 0052) is untouched and stays the source of truth for the design-system surface — this row exists only so workflow_artboard's ownership check passes, letting Sorgente use Workflow/Screen like any other project.

Why this over the skip-persistence fix: the maintainer and Arno's own interface developers use Sorgente as a real project to design Arno's own screens (not only as a token showroom) — the actual requirement is that those edits do persist. Special-casing isSorgenteProject inside useWorkflowArtboards directly defeats that: it makes persistence impossible by design, and every future Workflow-adjacent feature (component- library persistence, ADR 0068; anything built on top of workflow_artboard) would have to remember the same exception. A real row collapses the problem to "Sorgente is an ordinary owned project for this one concern" — no branch anywhere.

No duplicate on the projects list. projects-list.tsx (ADR 0054 §5) already looks up a matching project row by SORGENTE_PROJECT_ID and folds it into the pinned SorgentePinned card instead of also listing it in the regular grid — a real row supplies the card's display name + "updated" date, it does not add a second entry. Verified live on arno-test-active.

Seeded via one-shot (seed-sorgente-project-row.yml, removed after use per this repo's convention): INSERT ... ON CONFLICT (id) DO NOTHING, owner_id resolved from the vadimpianov login. Re-running the same insert on another env (dev/prod) needs the same one-shot re-created if this surface ships there.

Consequences

  • Workflow/Screen composition artboards for Sorgente persist exactly like any other project's (verified end-to-end: edit → reload survives).
  • useWorkflowArtboards carries no isSorgenteProject branch — restoring that branch is a regression of this ADR, not an optimization.
  • ADR 0054's "resolved statically, not from a projects-table row" still governs the display name and pinned-card visibility gate (useSorgenteState().available) — those stay independent of this row so a DB rotation before the row is re-seeded doesn't drop the card. Only Workflow/Screen persistence depends on the row existing.
  • If Sorgente's test-Neon project is ever rotated to a fresh Neon project restored from a stale-enough dump, the row travels with the dump like any other data — no separate re-seed step, unless the dump predates this ADR.

Alternatives considered

  • Keep the skip-persistence special case (c32c959/5fc906d) — rejected: directly contradicts the stated need (Sorgente used as a real project for Arno's own interface work) and accretes an exception every future Workflow-adjacent feature must repeat.
  • Loosen requireOwnedProject to allow prj-arno-sorgente-seed without a row — rejected: touches a security-relevant auth gate shared by every owned-resource endpoint, for the benefit of one id, when an additive one-shot INSERT achieves the same result with zero code risk.