Skip to content

42 — mgmt.ctrl — Management Command Center (envisioning)

Working label mgmt.ctrl (short form of management.ctrl; used interchangeably below). Not a user-facing commitment — revisit against Sonnance branding before any public string.

Envisioning doc — needs confirmation. Governed by 00-ROADMAP.md. Created 2026-06-27 (owner-raised). The ask: a Power-BI-grade eagle-view for managers / A&R / project planners / admins / execs to read the health of the whole catalog (roster → artist → project → track → version) — status, pending approvals, release-readiness, notes, listening engagement — without drilling node-by-node — and to act on it (add / edit / delete, in bulk) from the same surface. Not a per-user-type home; the manager lens on the one dashboard (doc-20). Placement: top-nav destination (Home is being re-designed concurrently).

Six decisions locked at envisioning (2026-06-27, owner):

  1. New doc that extends doc-38. doc-38 is the analytics engine (telemetry backbone, engagement bands, heatmap, privacy); doc-42 is the eagle-view product surface that consumes it. doc-38's role-gated "Workspace Insights" is the embryo this grows into.
  2. One unified surface — operational + analytical envisioned & shipped together (not phased apart). Honest dependency: analytical widgets light up only when doc-38 capture exists; operational widgets run on today's schema.
  3. Platform-agnostic envisioning — calm stacked cards on phone that densify into a matrix/grid on wide screens; lead platform chosen at build-slice time (respects iOS-first without forcing a dense BI grid onto a phone).
  4. Hero = the cross-catalog Activity Command Timeline — a live feed where every row is a navigable portal to its source with a provenance breadcrumb (doc-36 peek-then-go).
  5. Read and WRITE (incl. bulk) — inline-edit one record · per-row decision actions · bulk actions across a filtered/multi-select set. Wraps existing mutation endpoints; no new write semantics.
  6. "LEGO" configurable attributes = companion, out of scope here → future doc-43. This surface reads/writes whatever attributes exist (fixed today, configurable later), so it does not block on the attribute engine. See §8.

Lineage — this is doc-17 §5, revived

management.ctrl is not greenfield. It is the modern realization of 17-UX-ARCHITECTURE-ACTOR-DRIVEN.md §1 "The Lego OS" and §5 "Hierarchical Management Control" — a write-capable /manage route (hierarchy tree + detail panel, drill-down, edit at every level), parked there as "Phase 3+" and shelved by doc-20 for the MVP. doc-42 revives, modernizes, and supersedes doc-17 §5, reconciled with everything shipped since (roster + lenses doc-26, approval-as-a-dimension doc-32, provenance/peek-then-go doc-36, analytics doc-38, sort/filter doc-40, records/audit/status doc-41). The doc-17 conglomerate fantasy (Organization › Label › Artist) is not required: roster (doc-26) is the soft grouping facet we actually have, and management.ctrl is the synthesis layer above it.

One line: Portals (doc-26 Layer 4) are the bottom-up ingredient — one node's detail. This is the top-down synthesis of many nodes. Roster is the one hierarchy level without a portal yet; management.ctrl is effectively the roster-and-above portal, plus cross-catalog analytics and bulk action.

What triggered this

The owner wants a place to take decisions from data — to see, in one surface, "the notes pending to approve on this track," "the status of this project," "where in the timeline a comment landed and who replied," "the listening heatmap of v2 vs v1," "the health of a whole roster or a filtered selection" — without going track-by-track, artist-by-artist. The reference points are Power BI, but "even more dynamic and UX-friendly, with WOW impact" — analytical, executive, creative, and actionable: not a read-only report, but a command center you also operate from.

Relationship to the existing docs (reconciliation)

doc-42 invents no new telemetry and no new status semantics. It composes existing axes into a cross-catalog read+write surface. Boundaries:

DocRelationship to management.ctrl
doc-17 §1/§5Origin. doc-42 revives & supersedes the "Lego OS" / /manage Management Control vision.
doc-38 AnalyticsEngine it consumes. Events backbone, engagement bands, waveform heatmap, privacy model. doc-38's "Workspace Insights" is the embryo.
doc-37 HomeSibling, not the same. Home = "what needs my attention" triage (top-N + "see all"). management.ctrl = "the whole catalog's state, cross-actor" — an eagle-view destination reached from Home, not Home itself.
doc-20 UI simplificationThe framing law. One dashboard, role-driven content — management.ctrl is the manager/Owner/Admin lens, role-gated, not a per-user-type home.
doc-26 Identity/Sharing/NavLenses + roster. Reuses the roster grouping + access lenses (hierarchy/role/status/tag/share-direction).
doc-32 / doc-29 ApprovalPer-dimension approval state (audio/cover/tracklist/metadata) is what the health matrix + approvals queue read.
doc-33 NotesRolled-up unresolved notes (digest, not firehose) per node.
doc-36 InteractionProvenance + peek-then-go. Every row carries roster › artist › project › track › V# and is a portal to its source.
doc-40 Sort/Filter/SearchThe lens/filter bar scoping the eagle-view (whole workspace / one roster / one artist / a selection).
doc-41 Records/Audit/StatusLifecycle statusCode, state, audit createdBy/modifiedBy are the operational columns; bulk writes stamp modifiedBy.
doc-43 (proposed)Configurable "LEGO" attributes — the long-term substrate management.ctrl reads/writes. Out of scope here (§8).

The two data dimensions — one surface

management.ctrl reads two kinds of signal and presents them as one surface. The split matters only for build feasibility, not for the user's mental model.

A. Operational — buildable on today's schema (no telemetry needed):

  • Lifecycle statusCode — Artist active/archived · Project draft/active/released/archived · Track draft/published/archived (doc-41, src/shared/lifecycle-status.ts).
  • Approval state per dimension — Track.releaseStatus.{title,version,cover}, per-version File.reviewStatus (+ by/at), Project.tracklistStatus release gate (doc-32/29).
  • Release-readiness rollup — read-time computation: every final audio Approved + cover Approved + tracklist locked + metadata complete (doc-32).
  • Notes — rolled-up unresolved/tagged counts per node (CommentService.getUserRollup, doc-33).
  • Audit — createdBy / modifiedBy / updatedAt, soft-delete state isDeleted (doc-41).
  • Roster grouping (doc-26).

B. Analytical — rides the doc-38 telemetry backbone (lights up when capture ships):

  • Plays · unique listeners · listen-through % · minutes · opens.
  • Engagement bands — impression / sample / listen / complete → hook-rate, skip/completion-rate (doc-38).
  • Most-listened-part heatmaps on the waveform; version-vs-version comparison.
  • Guest/cohort breakdown (link-attributed, coarse location, opt-in identified — doc-38 privacy).

Every analytical widget is rendered with a clear "needs doc-38 telemetry" state until the backbone lands — the surface ships whole, the engagement cells fill in when the engine is wired.

The surface — hero + orbiting widgets

Platform-agnostic: on a phone these are calm stacked cards; on a wide screen they densify into a matrix / multi-pane grid. Lead platform chosen at slice time.

HERO — Activity Command Timeline (cross-catalog)

A live, filterable feed of everything happening across the catalog. Each row = what · who · when + provenance breadcrumb, and is a portal to its source (doc-36 peek-then-go: tap → expand in place → "Open in {location} →").

ACTIVITY  ·  whole workspace ▾   [roster ▾] [artist ▾] [type ▾] [today ▾]
──────────────────────────────────────────────────────────────────────────
 ▲ Ben uploaded v4 audio        Pop › Ava › LP1 › "Tidewater"        3m
 ✎ Cy requested changes · cover Urban › Cy › "Single"                1h   [open]
 ✓ Mara approved · final mix    Pop › Ava › LP1 › "Tidewater" v4    2h
 ◷ Tracklist submitted          Pop › Ben › EP                       5h   [✓][✗]
 ♪ 3 plays from Berlin (link)   Urban › Cy › "Single" v2            6h   ·doc-38·
──────────────────────────────────────────────────────────────────────────

Sources: domain writes (uploads/approvals/comments — already persisted) + notifications (doc-35) now; true listen events when doc-38 lands. (See §9 on the interim feed source.)

Catalog Health Matrix — "mission control"

A roster → artist → project → track grid; every cell encodes status + approval + release-readiness as colour + glyph. Scan the whole catalog's health in one glance; drill into any cell.

ROSTER  ARTIST   PROJECT        REVIEW   STATUS      READY?    PLAYS·doc-38
─────────────────────────────────────────────────────────────────────────
 Pop    Ava      LP1            ●●◐○     active      ▓▓▓░ 72%   1.2k  ▁▂▅█▇▅▂
 Pop    Ben      EP             ●●●●     released    ▓▓▓▓ ✓     4.0k  ▁▂▃▂▁
 Urban  Cy       Single         ◐        draft       ▓░░░ 25%   310   ▁▁▅█▇
        ● approved   ◐ under review   ○ draft/none

Approvals Command Queue — "inbox for decisions"

Cross-catalog, prioritized queue of everything awaiting a decision, with requester + age + one-tap actions. Extends today's single-user GET /mobile/dashboard pendingApprovals to the manager's full owned + collaborator + shared set.

PENDING DECISIONS  ·  cross-catalog        sort: oldest ▾
──────────────────────────────────────────────────────────
 ◷ Cover v3      Pop › Ava › LP1            2d   [✓ approve][✗]
 ◷ Final mix     Pop › Ben › EP › "Run"     5h   [✓ approve][✗]
 ◷ Tracklist     Urban › Cy › Single        1d   [lock][✗]
──────────────────────────────────────────────────────────
 ☑ select all under "Pop" →  [ Approve 4 ]   ← bulk (see §6)

Release-Readiness board

Per-project release-gate rollup (doc-32, read-time): what's blocking each project from release, across the selection. The headline managers chase to ship.

Engagement board (doc-38-gated)

Heatmaps, hook/skip rates, version-vs-version listen-through, listener cohorts. The most novel "BI wow", rendered in a needs-telemetry state until doc-38 capture ships.

Filter / lens bar

Reuses doc-26 lenses + doc-40 view-config (roster / role / status / tag / type / date), scoped to whole workspace · one roster · one artist · a saved selection. Saved Views persist server-side (doc-26); display prefs persist per-device (doc-40).

View modes & the action model — composable, open (not hooked-in)

The widgets above are not a fixed wall of panels — mgmt.ctrl is a multi-view command center with a view switcher, a scope/group control, and a contextual action model. The design intent (owner, 2026-06-27): keep the view/action set open and composable — driven by a registry, not hard-wired — so views, widgets, and actions can be added/removed/reordered (and later per-workspace configured, doc-43) without rewiring the surface. This is the LEGO ethos applied to the cockpit itself, and it does not depend on doc-43 — a static default registry ships first.

1 · View switcher (the modes). Segmented control; Timeline is the default. Each mode is the same data through a different lens:

ModeQuestion it answersPrimary widget
◷ Timeline (default)"What's happening across the catalog?"Activity Command Timeline (hero)
▦ Matrix"What's the health of everything at a glance?"Catalog Health Matrix
☑ Queue"What needs a decision from me / my team?"Approvals Command Queue
▤ Board"What's blocking each project from release?"Release-Readiness board
♪ Insights (doc-38-gated)"What's engaging listeners?"Engagement heatmaps / cohorts
★ Saved"My pinned cross-cutting views"any of the above + a stored lens (doc-26/40)

2 · Scope + Group-by + Filter (shared across modes). A persistent control bar: Scope (whole workspace · roster · artist · selection), Group-by (roster · artist · project · status · owner · date), Filter/lens (doc-26/40 chips), Search (.searchable, incl. comments/notes). Changing mode keeps the active scope/filter — you re-frame the same slice, you don't lose it.

3 · Action model (three altitudes, all role-gated, doc-20).

GLOBAL  (toolbar)   new saved view · export · refresh · configure widgets ▸

ROW     (per node)  open ▸ (peek-then-go, doc-36) · set status · approve/reject ·
   │                assign · resolve note · edit inline

BULK    (multi-select / "select all in filter")
        set status · approve · assign · archive · retag · export
        → confirmation + undo + partial-failure report (§6)

4 · "Open, not hooked-in" — the composability contract. Views, widgets, and actions are declared in a registry (a list the surface renders), each entry carrying its id, the read endpoint it binds to, the actions it exposes, and the role gate. Consequences: a new widget = a new registry entry, not a refactor; a mode the workspace doesn't use can be hidden; placeholder/fixture data (see §12) plugs in at the binding layer so the whole surface is designable/testable before any /management/* endpoint exists. When doc-43 lands, the registry becomes per-workspace configurable — the same seam, no rewrite. Keep widgets decoupled (each fetches its own slice, fails independently — a dead Insights tile never blanks the Timeline).

6. It writes, too — read+write command center

management.ctrl is not read-only BI. Three write tiers, all from the eagle view, all reusing existing endpoints — doc-42 adds a batch wrapper + cross-workspace selection, not new write semantics:

TierWhatReuses
a. Inline editRename, set lifecycle status, edit metadata on one record without leaving the surfacestatus/metadata PUTs
b. Per-row decisionApprove / reject a version, lock tracklist, resolve a notePATCH /track/:id/release-status, per-file PATCH /track/:trackId/file/:fileId/review-status, comment resolve
c. Bulk actionSet status / approve / assign / archive / retag across a multi-select or filtered seta new batch wrapper that fans out to the above

Guardrails (must be in the doc): role-gated per node (a bulk op silently skips nodes the actor can't write — doc-20 cascade); every write stamps modifiedBy (doc-41); confirmation + undo for destructive bulk ops (archive/delete); partial-failure reporting ("approved 11 of 14; 3 skipped — no permission"). Bulk = orchestration over per-node permission checks, never a permission bypass.

7. Actors & use cases

Role-gated per doc-20 (one dashboard, role-driven). management.ctrl is the manager lens — surfaced to Owner/Admin (and manager-shaped collaborators); Editors/Viewers see Home, not this.

ActorComes forLands on
Manager / label opsWhole-roster health, what's blocking release, who's behindHealth Matrix + Release-Readiness
A&RWhich projects/tracks engage listeners; signal to act onEngagement board + Activity
Admin / coordinatorClear the approvals backlog, bulk-advance statusApprovals Queue + bulk actions
ExecOne-glance portfolio state; data for decisionsHealth Matrix (rolled to roster level)
Creative directorCover/art approvals across releasesApprovals Queue (cover dimension)

Higher altitude shows less, louder (digest, not firehose — doc-33 principle).

8. Companion — the "LEGO" configurable-attribute model (out of scope here → doc-43)

The owner's "LEGO software" idea: entities carry different attribute sets; the same attribute can live at different hierarchy levels per workspace; catalogs are per-workspace definable — and management.ctrl manages not just the data but, eventually, which attributes exist where. This is the right long-term substrate for a command center (Airtable/Dataverse-style composability).

Finding — it is net-new, with no foundation today:

  • All schemas are fixed @Prop; src/main.ts forbidNonWhitelisted: true actively rejects unknown fields on write.
  • Only seeds: an unused File.metadata: any (file.schema.ts:68) and freeform tags[].
  • The lifecycle catalog is hard-coded with a deferral note: "a per-workspace custom catalog is a deferred layer" (lifecycle-status.ts:6).
  • Already the deferred customization layer across doc-17 (Lego OS), doc-20 §4 (templates/saved views/theming), doc-41 (per-workspace status catalog), doc-31 (customization ≈ future premium / monetization-deferred).

Posture: management.ctrl is designed to consume whatever attribute model exists — fixed defaults today, a configurable catalog later — so it does not block on this. The configurable-attribute engine (attribute definitions, per-workspace catalogs, attribute-at-any-level, the validation rework around forbidNonWhitelisted, and migration) is its own concern — now specified in 43-CONFIGURABLE-ATTRIBUTES.md (authored 2026-06-27: typed attributes bag + per-workspace AttributeDefinition catalog · global presets + workspace override · quick-add here + full Workspace Settings editor). When it lands, the mgmt.ctrl view/widget/action registry becomes per-workspace configurable through the same seam — no surface rewrite.

9. Backend implications (the real net-new work — name, don't build)

  • No cross-workspace aggregation exists today. Queries are per-resource; the only aggregate is GET /mobile/dashboard (mobile.service.ts), and only for one user's own tracks. management.ctrl needs cross-roster/artist/project aggregation endpoints — e.g. GET /management/overview, /management/matrix, /management/approvals, /management/activity — composing existing services (ArtistSpaceService.getDistinctRosters, TrackService.findAllByUser, CommentService.getUserRollup, the MobileService pending-approvals logic at mobile.service.ts:87–130) over the caller's full owned + collaborator + shared set.
  • Bulk-write endpoint — a batch wrapper (e.g. PATCH /management/bulk) that fans out to existing per-node mutations with per-node role checks + partial-failure results. No new write semantics.
  • Activity Timeline needs an event log. Today only createdBy/modifiedBy audit fields + the notification stream exist. Interim: derive the feed from notifications + audit timestamps. Proper: the doc-38 events backbone becomes the activity SoT once it lands (this is the hero's hard dependency — see §Sequencing).
  • Engagement widgets ⇒ doc-38 Event store + GET /track/:id/insights + GET /analytics/workspace.
  • Scale lever (doc-14): aggregate-on-read first; materialized rollups only if the matrix/timeline queries get slow at volume.

10. Privacy & calm posture

Inherits doc-38 wholesale: aggregate-by-default, identified visibility opt-in + role-gated via the Teams/Role model, guest plays attributed to the share link with coarse city/country (derived location, not raw IP — GDPR), raw events TTL'd. Framed per doc-31 professional calm / no-surveillance — this is a decision-support cockpit, not a monitoring tool. Higher altitude = digest, not firehose (doc-33).

11. Decisions resolved (2026-06-27, owner) + remaining

Resolved this round:

  1. Naming — working label is mgmt.ctrl (short form of management.ctrl) "for now." Not a user-facing commitment yet; revisit against Sonnance branding before any public string.
  2. Placementtop-nav destination for now. Home is being re-designed concurrently, so the eventual Home→mgmt.ctrl entry point (pulse line / drawer) is settled when that redesign lands; until then it stands on its own in top-nav.
  3. View/action modelowner deferred to recommendation: build it open/composable (view + widget + action registry, decoupled widgets) rather than a fixed panel wall — see §"View modes & the action model." Default mode = Timeline.
  4. Interim dataplaceholder/fixture data first. Design and test the whole surface against mock /management/* responses now (plugged in at the registry binding layer), so UI work proceeds ahead of the real aggregation + doc-38 telemetry. The interim real activity feed (notifications + audit) and the doc-38 event log swap in behind the same bindings later.

Remaining / to confirm:

  • MVP mode subset — if "one surface" is too large to ship atomically, the minimum-lovable centre is Timeline + Queue (both buildable pre-telemetry). Confirm at slice time.
  • doc-43 greenlight — the LEGO configurable-attribute model is not clearly specified by current docs (scattered/deferred across doc-17/20/41/31, no engine designed), so a dedicated 43-CONFIGURABLE-ATTRIBUTES.md is warranted. Owner's "makes sense if not clear" → greenlit; author it as the next envisioning (separate task, does not block mgmt.ctrl).

12. Sequencing

Placeholder-data-first. The surface is built and tested against fixture data at the registry binding layer, so design/UX proceeds immediately — independent of backend readiness. Real data swaps in behind the same bindings, per widget, as it lands.

The fully-live surface slots after the active doc-37 (Home redesign) + the standing first-byte perf priority + the doc-38 telemetry backbone (consistent with the roadmap). Operational read+write widgets could go live before telemetry, but the owner chose one unified surface, so the doc-38 engine gates the fully-live release (engagement cells render in a needs-telemetry state until then). doc-43 (LEGO attributes) is independent / parallelmgmt.ctrl does not wait on it; when it lands, the view/widget/action registry becomes per-workspace configurable through the same seam.

13. iOS MVP slice — requirements (locked 2026-06-27, owner)

The first built mgmt.ctrl surface. iOS is the priority; web is deferred to a phase after the iOS MVP. Backend is complete (Activity · Approvals · Overview · Matrix · Board · Insights + bulk).

  • Placement & gating: a native SwiftUI screen reached from the avatar drawer as a new AppSection.mgmtCtrl ("management.ctrl"), role-gated to Owner/Admin via the dashboard userRole → the drawer's allowedSections. A separate screen from Home (Home stays the personal "what needs my attention"; this is the cross-catalog manager lens).
  • Views (4 of 6 this slice): an Overview KPI header (always on top) + a segmented switcher over Timeline · Queue · Board. Matrix (dense roster→track grid, not phone-native) and Insights (heatmaps, needs accumulated telemetry) are deferred to a later iOS slice.
    • Overview ← GET /management/overview → KPI tiles (artists · projects · tracks · pending · ready · notes).
    • Timeline ← GET /management/activity → calm rows (what · who · when + provenance breadcrumb); tap → open the source track (peek-then-go, doc-36).
    • Queue ← GET /management/approvals → rows (dimensions + requestedBy + age).
    • Board ← GET /management/board → per-project readiness cards (ready? + audio/cover/tracklist), most-blocked first.
  • Actions: per-row approve / request-changes from the Queue (PATCH /track/:id/release-status, already owner/admin-gated) + multi-select bulk (PATCH /management/bulk) with a bulk action bar; partial-failure surfaced (succeeded / skipped / failed).
  • Data & form: live /management/* via APIClient; LoadState (loading/empty/error) + pull-to- refresh; calm cards on the phone, composed only from DesignSystem (TrackRow · SectionHeader · StatusPill · LifecycleStatusPill · ApproveBar · ScreenBackground · .snCard · Tokens). New Decodable models mirror the backend shapes (nonisolated struct … Sendable).
  • Bulk RBAC prerequisite (decided): bulk's per-node can() only needs the resolver to know the caller's role — it does not require flipping the global PERMISSION_ENFORCE. To make it correct for all resources (incl. ones created after a backfill), PermissionService gains a grant-or-legacy fallback (grant first, else the resource's owner/collaborators). Hazard flagged: flipping global enforce before write-paths create grants would 403 new resources — the fallback removes that hazard, so backfill + enforce flip stay optional hardening, not a blocker.
  • Out of this slice: Matrix grid, Insights heatmap UI, web (post-iOS-MVP), bulk write-path grant creation (the fallback covers the transition).

§13 follow-ups (noted 2026-06-27, owner — after first live run)

  1. Richer activity provenance — created / updated / deleted with who · what · when. The interim /management/activity (notifications + one coarse track:updated per track, actor name often missing) is too thin. Fix = granular domain events through the doc-38 event store ("action events" — create / update / delete on Artist/Project/Track/File/Comment), resolving the actor name and the what (field/dimension changed), grounded in doc-41 createdBy/modifiedBy/timestamps. Upgrades the hero feed from a digest to a true audit timeline.
  2. Filter · search · order-by on every view (doc-40). mgmt.ctrl needs the per-view view-config — filter (roster / artist / status / date / who), sort (recently updated, oldest pending, plays), and search — applied across Timeline / Queue / Board (and Matrix). Reuse the doc-40 LensBar model.

Status: envisioning + ▶ iOS MVP slice building (2026-06-27). Backend complete; iOS Overview + Timeline + Queue + Board with per-row + bulk actions is the active build (§13). doc-43 recommended, not yet authored.

Ctrl-Audio Platform Documentation