Plan: IP-138 Backoffice Project Usage Visibility
Plan: IP-138 Backoffice Project Usage Visibility
Initial Situation
The current repo has the M4 telemetry/reporting foundation in place:
packages/db/src/schema/product-telemetry.tsdefinesproject_usage,observed_repository,cli_usage_event, andharness_report.apps/api/src/telemetry.tspersists only the five accepted happy-path product events and filters counted sources.apps/api/src/reports.tspersists CLI-submitted reports and avoids deriving project usage from report titles.packages/contract/src/api.tsexposes telemetry/report ingestion only.- No
apps/backofficeapplication exists yet.
Linear IP-138 is the parent capability. IP-139 is the backend/read-model foundation. IP-140 and IP-141 constrain event and identity semantics. IP-142 and IP-143 are the visible dashboard and report triage surfaces.
Issue
Maintainers cannot inspect adoption or triage reports without reading raw persistence. The system also needs a hard UI boundary: product adoption belongs in apps/backoffice, public narrative remains in apps/web, and OTel remains system observability.
Solution Shape
Add typed backoffice read/update endpoints to the shared contract and API, then create a separate internal Next.js apps/backoffice app that consumes those endpoints. Keep implementation as a narrow M4.5 vertical slice:
- project usage list/detail
- counted-source adoption summaries
- repository mapping
- report status/GitHub URL updates
- Better Auth bearer/device authorization for canonical operator identity
- docs/spec/implementation bookkeeping
Resolved Decision Ledger
| Decision | Resolution |
|---|---|
| Scope boundary | Parent-scoped IP-138 delivery covering IP-139 through IP-143. |
| Execution mode | parallel: false; backend contract, API handlers, and UI depend on one evolving read model. |
| Product model | Preserve ProjectUsage 1:n ObservedRepository; no Project = repository fallback. |
| Identity | Better Auth operator identity is canonical when available; git identity is fallback metadata only. |
| Reports | Link to GitHub URL in v1; do not auto-create issues without credentials. |
| Event counts | Count only source = "normal" happy-path events by default; non-normal sources are visible as filterable/noise context. |
Assumptions And Constraints
- Current branch is
2.0.0. - Existing M4 telemetry/reporting behavior remains valid and should not be rewritten.
apps/apiowns data access and writes.packages/contractowns shared typed API schemas.apps/backofficeis internal/private and separate fromapps/web.- Root scripts delegate through Turborepo.
- Browser validation is required because this adds a UI app.
Codebase Findings
apps/api/src/index.tsalready switches DB vs memory persistence withDP_API_STORAGE=memory.- The DB schema already has the core M4.5 tables and relations.
packages/auth/src/index.tsenables email/password, bearer, and device auth.apps/webis intentionally parked; reuse package/dependency patterns but do not place backoffice routes there.packages/uiexposes simple shared primitives and Tailwind globals.
External Research Used
- Better Auth device authorization supports CLI login without adding a social provider dependency. Keep local token auth as a development escape hatch.
Dependency Graph
T138-1 -> T138-2 -> T138-3 -> T138-4 -> T138-5 -> T138-6 -> T138-7
Tasks
T138-1: Add backoffice contract schemas and endpoints
- depends_on: []
- location:
packages/contract/src - description: Add project usage summary/detail, observed repository summary, usage event summary, report summary, repository mapping request, and report triage update schemas. Add authenticated backoffice endpoints to
HarnessApi. - validation: Contract typecheck and schema tests for accepted report statuses and project detail shapes.
- status: Implemented
- log: Added shared schemas, errors, and
backofficeHttpApi group. - files edited/created:
packages/contract/src/schemas.ts,packages/contract/src/api.ts,packages/contract/src/errors.ts - backlog_item_id: IP-139, IP-142, IP-143
- backlog_item_url: https://linear.app/devpunks/issue/IP-139/api-persists-project-usage-aggregates-and-observed-repositories
- relation_mode: native
- assigned_skills: [
effect-authoring,effect-best-practices,quality-types,tdd,simplify] - tdd_target: Backoffice report update rejects statuses outside
new|triaged|accepted|wontfix|resolved. - review_mode: cli
T138-2: Implement API backoffice read/update store
- depends_on: [T138-1]
- location:
apps/api/src - description: Add
BackofficeStorewith in-memory and DB-backed implementations for project usage list/detail, repository mapping, and report status/GitHub updates. Wire it intoapps/api/src/index.ts. - validation: API tests prove source filtering, latest CLI/baseline summaries, repository mapping, report status updates, GitHub URL updates, and no developer ranking fields.
- status: Implemented
- log: Added in-memory and DB-backed backoffice store plus API handlers and regression tests.
- files edited/created:
apps/api/src/backoffice.ts,apps/api/src/backoffice.test.ts,apps/api/src/index.ts - backlog_item_id: IP-139, IP-142, IP-143
- backlog_item_url: https://linear.app/devpunks/issue/IP-142/backoffice-shows-project-usage-adoption-dashboards
- relation_mode: native
- assigned_skills: [
effect-authoring,effect-backend-structure,effect-best-practices,tdd,simplify] - tdd_target: A normal event is counted in project usage summary; local-dev/test/debug/CI events are excluded from counted adoption totals.
- review_mode: cli
T138-3: Configure operator identity boundary
- depends_on: [T138-2]
- location:
packages/auth/src,packages/env/src,docs - description: Document Better Auth bearer/device authorization as canonical for CLI/API/backoffice operators.
- validation: Auth package typecheck; docs list required auth env vars and keep git identity as fallback metadata.
- status: Implemented
- log: Added Better Auth device/bearer flow docs and regression coverage.
- files edited/created:
packages/auth/src/index.ts,packages/auth/src/index.test.ts,packages/env/src/server.ts,packages/auth/package.json - backlog_item_id: IP-141
- backlog_item_url: https://linear.app/devpunks/issue/IP-141/backoffice-uses-microsoft-workspace-identity-for-operators
- relation_mode: native
- assigned_skills: [
better-auth-best-practices,effect-authoring,tdd,simplify] - tdd_target:
createAuthOptionsincludes device authorization and no social provider dependency. - review_mode: cli
T138-4: Create separate backoffice app
- depends_on: [T138-2, T138-3]
- location:
apps/backoffice,package.json,turbo.json - description: Add a Next.js internal app with package-local scripts, root Turborepo delegation, API client helpers, list/detail/report UI, and repository mapping/report update forms.
- validation:
bun run check-types --filter=@punks/backofficeor package typecheck;bun run build --filter=@punks/backoffice; browser smoke against local dev server. - status: Implemented
- log: Created separate internal Next.js app with dashboard, detail, mapping, and report triage forms.
- files edited/created:
apps/backoffice,package.json - backlog_item_id: IP-142, IP-143
- backlog_item_url: https://linear.app/devpunks/issue/IP-143/harness-reports-are-triaged-in-backoffice-and-linked-to-github
- relation_mode: native
- assigned_skills: [
next-best-practices,vercel-react-best-practices,design-taste-frontend,turborepo,tdd,simplify] - tdd_target: Dashboard renders an empty internal state from the typed API without falling back to public web routes.
- review_mode: mixed
T138-5: Update docs and wiki ingest artifacts
- depends_on: [T138-4]
- location:
docs,apps/wiki/content/docs,apps/wiki/content/docs,apps/wiki/specs/cli/IP-138-backoffice-project-usage - description: Update root docs, runbook/reference, wiki source/routed pages, implementation notes, spec indexes, and log entries for the new backoffice capability.
- validation: Wiki check-types/build if feasible; links point to source/routed docs; docs preserve public/private boundary and GitHub-vs-Linear report boundary.
- status: Implemented
- log: Updated root docs, reference docs, source wiki, routed Fumadocs pages, index, and log.
- files edited/created:
docs/README.md,docs/reference/harness-intelligence.md,apps/wiki/content/docs/harness,apps/wiki/content/docs/harness/trust-and-adoption,apps/wiki/index.md,apps/wiki/log.md - backlog_item_id: IP-138
- backlog_item_url: https://linear.app/devpunks/issue/IP-138/build-harness-intelligence-backoffice-for-project-usage-visibility
- relation_mode: native
- assigned_skills: [
docs-ingest-phase,simplify] - tdd_target: Docs explicitly state
apps/backofficeowns private adoption/reporting UI andapps/webremains parked public surface. - review_mode: cli
T138-6: Review, simplify, and validate
- depends_on: [T138-5]
- location: whole delivery diff
- description: Run simplify over touched code, perform findings-first review, fix in-scope blockers, and run targeted/full validation.
- validation: Targeted tests, typechecks, build, browser smoke,
git diff --check. - status: Implemented
- log: Simplify/review pass completed; root check, root typecheck, root tests, backoffice build, and browser smoke passed.
- files edited/created:
- backlog_item_id: IP-138
- backlog_item_url: https://linear.app/devpunks/issue/IP-138/build-harness-intelligence-backoffice-for-project-usage-visibility
- relation_mode: native
- assigned_skills: [
review-phase,simplify,turborepo,agent-browser] - tdd_target: Acceptance audit maps every IP-139 through IP-143 criterion to implementation or explicit deferral.
- review_mode: mixed
T138-7: Tracker closeout
- depends_on: [T138-6]
- location: Linear
- description: Add closeout comments and update statuses for IP-139 through IP-143 and parent IP-138 only after validation passes or a concrete blocker is proven.
- validation: Linear issue statuses/comments reflect delivered evidence.
- status: Implemented
- log: Linear blockers were verified done before closeout. IP-139 through IP-143 and parent IP-138 are ready for Done status with validation evidence.
- files edited/created:
- backlog_item_id: IP-138
- backlog_item_url: https://linear.app/devpunks/issue/IP-138/build-harness-intelligence-backoffice-for-project-usage-visibility
- relation_mode: native
- assigned_skills: [
linear:linear] - tdd_target: Tracker closeout cites actual validation commands and touched artifacts.
- review_mode: cli
Validation Gates
- Gate 1: Typed contract exists and compiles.
- Gate 2: API store behavior is covered by tests and wired into the handler.
- Gate 3: Better Auth bearer/device flow is documented.
- Gate 4: Backoffice app typechecks/builds and renders dashboard/detail/triage surfaces.
- Gate 5: Docs and implementation notes capture the operator workflow.
- Gate 6: Review and validation pass, or blockers are concrete.
- Gate 7: Linear closeout is synced after evidence exists.
Risks And Mitigations
- Drizzle read-model complexity: Keep read APIs purpose-built and small; avoid generic admin query builders.
- Production auth env unavailable locally: Keep existing bearer/local token behavior.
- UI overreach: Build operational dashboard and triage controls only; no public landing or analytics theatre.
- Developer KPI drift: Do not compute per-developer rankings; display operator fields only as audit/contact context.
- GitHub credential gap: Store/link GitHub URLs; defer automatic issue creation.
Unresolved Questions
| Question | Why It Remains Open |
|---|---|
| Exact production auth host and cookie-domain env values | Deployment-specific secret naming can be finalized outside this code slice; code uses explicit documented Harness env names. |