Wipes all other users and upserts a single admin with the given email +
password. Use after the rename when you want a clean slate.
docker compose -p loreal-prod-tracker exec app \
npx tsx scripts/create-admin.ts admin@loreal.com 'YourPasswordHere'
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four phases shipped together. Each is a logical deploy unit on its own;
keeping the diff atomic so the rename runbook + migrations stay aligned.
Phase 1 — restore HP's formal review workflow
- Prisma: FeedbackItem, ReviewSession, ReviewSessionItem + enums
- New ApprovalType (NONE | SIMPLE | FORMAL) on PipelineStageDefinition
and PipelineStageTemplate. Stage row UI branches per type.
- feedback-service + review-session-service ported from HP (no ColorProbe)
- annotation-service auto-creates a FeedbackItem; revision-service
carries forward unresolved action items into the new revision.
- API: /api/reviews/*, /api/stages/[id]/feedback, /api/feedback/[id]
- Hooks: use-feedback, use-review-sessions
- UI: feedback-checklist, feedback-item-card, feedback-progress-bar,
create-session-dialog, session-builder, session-presenter,
session-summary, plus a new stage-review-panel
- Pages: /reviews list + detail, deliverable annotation review page
- Pipeline editor gets the approvalType select; sidebar gets Reviews
Phase 2 — full Dow Jones → L'Oréal rebrand + slug rename
- URL slug /dow-prod-tracker → /loreal-prod-tracker (next.config,
base path, redirects)
- docker-compose name + DB → loreal_prod_tracker; server path
/opt/loreal-prod-tracker; apache template renamed
- All visible strings → L'Oréal; sidebar bg #002B5C → black
- docs/RENAME_RUNBOOK.md describes the one-shot server migration
- Internal modules dow-excel-service/dow-import + OMG webhook domain
dowjones.com deliberately preserved (orthogonal to the rebrand)
Phase 3 — external /api/v1 for projects + deliverables
- API-key auth already in middleware; finished idempotency support
via new IdempotencyRecord model + src/lib/api/idempotency.ts
- Default-pipeline fallback in createProject when no template id given
- POST/GET /api/v1/projects + POST /api/v1/projects/[id]/deliverables
- docs/EXTERNAL_API.md with curl examples
Phase 4 — Box bidirectional integration
- JWT app-auth via jose (no extra deps). Config mounted as a docker
compose secret; deploy.sh stubs an empty {} so compose can start
before the operator drops the real JSON.
- Outbound: pushDeliverableToBox auto-fires on !APPROVED → APPROVED
in deliverable-status-service; "Send to client (Box)" manual button
on the approval stage row. Folder naming
{omgJobNumber}_{slug}_v{round}. 3-attempt exp backoff. BoxPushLog
audit.
- Inbound: /api/webhooks/box receives Box's signed events, matches by
OMG # + slug, creates a new Revision, routes to assignee or notifies
project owner. BoxInboundLog audit + two new NotificationType
values (BOX_UNMATCHED_FILE, NEW_FILE_AWAITING_REVIEWER).
- Naming-convention logic isolated in external-delivery-service so an
OMG-API transport can swap in later without touching matchers.
- Admin /settings/box page surfaces config status + recent activity.
Three Prisma migrations to apply on next deploy:
20260512000000_restore_review_workflow
20260512100000_idempotency_records
20260512200000_box_integration
URL rename is a one-shot — see docs/RENAME_RUNBOOK.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Root cause of the mismatch: Deliverable.status is a denormalised
column that was only written at create-time (default NOT_STARTED)
and never refreshed when stages moved. The Projects board read it
live and showed "Not Started" while the pipeline ring + dominant-
stage view correctly showed "at Client Feedback (6/11 stages
complete)".
Fix in two parts:
1. New deliverable-status-service with:
- computeDeliverableStatus(stageStatuses[]) — pure function with
the summary rule:
all stages terminal → APPROVED
any IN_REVIEW → IN_REVIEW
any IN_PROGRESS/CHANGES_REQUESTED → IN_PROGRESS
else → NOT_STARTED
ON_HOLD is producer-managed and never overwritten.
- recomputeDeliverableStatus(deliverableId, txClient?) —
executes the rule + writes if different. Accepts an optional
Prisma tx client so callers can run inside their own
transaction.
2. Wired into every stage-write path:
- stage-service.updateStageStatus (single-stage transitions)
- stage-service bulk transaction (bulkUpdateStages) — dedups
touched deliverable IDs so we don't recompute twice.
- stage-transition-service forward + rework (board drag) —
inline inside the same $transaction so the board bucket is
correct on the next refetch.
3. Backfill script scripts/recompute-deliverable-statuses.ts —
one-off sweep to fix existing stale rows:
npx tsx scripts/recompute-deliverable-statuses.ts
Run once after deploy.
Two complementary safety nets for the business-critical DB:
1. Host-side nightly backup
- scripts/backup-db.sh drives pg_dump through docker compose exec,
gzips to /srv/backups/dow-prod-tracker/, auto-prunes >30 days.
Env-overridable (BACKUP_DIR / RETAIN_DAYS / COMPOSE_DIR / PGUSER
/ PGDATABASE) for anyone running a different layout.
- Runs from host cron at midnight; crontab snippet + restore
procedure + optional off-site (S3 / rsync) pattern documented
in DEPLOY.md.
2. On-demand admin XLSX export
- New GET /api/projects/export?format=xlsx — ADMIN-only; builds a
two-sheet workbook via new buildFullExportWorkbook():
- "Job Tracker": one row per project, header strings chosen to
round-trip through the Dow bulk-import endpoint so a dump can
be re-ingested in a worst case. Owner / Risk / OMG Number /
Team / etc., mirroring the importer's fuzzy HEADER_MATCHERS.
- "Deliverables": one row per deliverable with project OMG #,
status, priority, dates, CMF/SKU, current stage, assignees,
notes — enough to reconstitute pipeline state.
Respects visibility scoping (ADMIN sees everything).
- Dashboard shows an "Export Full XLSX" button in the header for
admins; streams the workbook with a date-stamped filename using
the standard blob-download pattern from ExportButton.
Both are additive — no schema, no migration, no deploy breakage.
- basePath /dow-prod-tracker, DB name dow_prod_tracker
- docker-compose: name: dow-prod-tracker (volume isolation on shared server), ports 3002/5492
- OMG webhook env vars (secret + insecure toggle)
- NEXT_PUBLIC_AUTH_ENTRA_ENABLED feature flag (MVP uses local auth)
- Dow logo at public/navbar-logo.png
- apache/hp-prod-tracker.conf → apache/dow-prod-tracker.conf
- Text rebrand across README, SETUP, CLAUDE.md, docs, UI labels
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Implemented `stage-resolver.ts` to unify old and new pipeline stage definitions.
- Created `org-scope.ts` for organization access verification and scoping queries.
- Added role-based permissions management in `permissions.ts` and `rbac-service.ts`.
- Introduced invitation management in `invitation-service.ts` with validation schemas.
- Developed custom field and notification rule services with respective validators.
- Established pipeline template CRUD operations in `pipeline-template-service.ts`.
- Added Zustand store for managing pipeline builder state in `pipeline-builder-store.ts`.
- Added CalendarDayDetail component for displaying detailed event information for a selected day.
- Created CalendarEventPill component to represent individual events in a compact format.
- Introduced CalendarFilters component to filter events by project, stage type, and status.
- Developed CalendarGrid component to render the calendar layout and manage event interactions.
- Implemented CalendarView component to manage the overall calendar state and navigation.
- Added useCalendar hook to fetch calendar events based on specified filters.
- Created calendar-service to handle fetching events from the database with filtering capabilities.
- Updated data model to include necessary fields for calendar events and filters.
- Added system prompt and tools for AI assistant to manage calendar-related tasks.
- Implemented Smart Search Panel component for enhanced project and deliverable search functionality.
- Introduced useSemanticSearch and useOllamaHealth hooks for managing search queries and AI availability.
- Developed embedding-service to generate and store vector embeddings for projects and deliverables.
- Created semantic-search-service to handle vector search, structural query detection, and LLM summarization.
- Added support for hybrid search combining structural filters and semantic queries.
- Integrated UI components for displaying search results and user interactions.