MOPC-App/docs/codex-architecture-redesign.../04-unified-domain-model-and...

10 KiB

04. Unified Domain Model And Config Contracts

1) Objectives

This target model turns the Monaco flow into strict, reusable contracts while preserving the current pipeline infrastructure.

Goals:

  1. Minimize schema churn where current models are already correct.
  2. Remove ambiguity for jury identity, assignment policy, round bundles, mentoring promotion, and final lock.
  3. Keep customization through explicit policy layers, not ad hoc conditionals.

2) Proposed Domain Additions

2.1 Stage Purpose Contract

Add To Stage

  • purposeKey (enum/string, required after migration)

Proposed purpose enum values:

  • submission_r1_intake
  • eligibility_filter
  • jury1_evaluation
  • submission_r2_intake
  • jury2_evaluation
  • jury3_live_finals
  • final_confirmation
  • results_publication
  • award_evaluation
  • award_results

Rule:

  • StageType remains coarse technical type.
  • purposeKey controls business behavior and policy validation.

2.2 Jury As First-Class Entity

New Jury

Fields:

  • id, programId, purposeKey, code, displayLabel, kind (MAIN, AWARD), isActive

Examples:

  • code=main-semifinal, displayLabel=Technical Semi-Final Jury
  • code=main-finalist, displayLabel=Grand Jury
  • code=award-blue-innovation, displayLabel=Blue Innovation Prize Jury

New JuryMembership

Fields:

  • juryId, userId, roleInJury (CHAIR, MEMBER), activeFrom, activeTo, status

New JuryStageBinding

Fields:

  • juryId, stageId, isPrimary, permissionsJson

Use:

  • controls which juries are allowed to evaluate/vote in each stage
  • allows overlap across juries and awards

2.3 Assignment Policy Contract

New AssignmentPolicy (stage + jury scoped)

Fields:

  • stageId
  • juryId
  • requiredReviews
  • defaultCap
  • defaultCapMode (HARD, SOFT)
  • softBuffer (default 10, configurable)
  • categoryBiasPolicyJson (startup/concept mix preference weights; non-deterministic)
  • overflowPolicy (manual_queue, expand_pool, reduce_reviews)
  • isActive

New JudgePolicyOverride

Fields:

  • assignmentPolicyId
  • userId
  • cap, capMode, softBuffer
  • startupBiasWeight, conceptBiasWeight
  • biasDisclosureAcceptedAt (onboarding acknowledgement that bias is suggestive only)
  • source (ADMIN_SET, JUDGE_ONBOARDING)

New AssignmentIntent

Purpose:

  • records desired assignments created before assignment materialization (e.g., from member invite page)

Fields:

  • stageId, juryId, userId, projectId, intentSource, status

New AssignmentException

Purpose:

  • explicit record for manual over-cap assignments

Fields:

  • assignmentId, policyId, exceptionType, reasonCode, reasonText, approvedBy

2.4 Submission Round Bundle Contract

New SubmissionRound

Fields:

  • id, stageId, roundKey, name, openAt, closeAt, latePolicy, lateGraceHours, editabilityPolicy

Evolve FileRequirement

Add:

  • submissionRoundId (nullable transitional, required after migration)
  • slotKey (stable requirement slot identifier)

Evolve ProjectFile

Add:

  • submissionRoundId
  • submissionSlotKey
  • sourceType (DIRECT_UPLOAD, MENTOR_PROMOTION, ADMIN_REPLACEMENT)
  • sourceReferenceId (e.g., mentor file id)
  • isOfficial

New SubmissionBundleState

Fields:

  • projectId, submissionRoundId, status (DRAFT, SUBMITTED, LOCKED), lockedAt, lockedBy

2.5 Mentoring Collaboration + Promotion

New MentorWorkspaceFile

Fields:

  • projectId, mentorId (nullable for team upload), file storage metadata, visibility, status

New MentorWorkspaceComment

Fields:

  • workspaceFileId, authorId, threadKey, content, timestamps

New SubmissionPromotionEvent

Fields:

  • projectId, workspaceFileId, targetSubmissionRoundId, targetSlotKey
  • promotedById, promotedAt
  • resultProjectFileId
  • approvalState (if mentor/admin approvals required)

Invariant:

  • promotion always creates immutable provenance link from mentoring artifact to official submission slot.
  • promotion authority is limited to team lead and admin.

2.6 Special Award Governance Contract

Extend SpecialAward

Add:

  • participationMode (SEPARATE_POOL, DUAL_TRACK)
  • routingBehavior (PULL_FROM_MAIN, KEEP_IN_MAIN)
  • routingConfirmationMode (AUTO, ADMIN_CONFIRMED) // Monaco default: ADMIN_CONFIRMED for pull-out
  • requiresDedicatedJury (bool)
  • winnerDecisionMode (JURY_CONFIRMATION, SINGLE_JUDGE_DECIDES)
  • singleJudgeUserId (nullable, required when winnerDecisionMode=SINGLE_JUDGE_DECIDES)
  • winnerCandidateSource (ELIGIBILITY_REMAINING_POOL, CUSTOM_SHORTLIST) // Monaco single-judge awards use eligibility remaining pool
  • submissionRequirementMode (REUSE_MAIN, CUSTOM)

New AwardStageBinding

Fields:

  • awardId, filterStageId, evaluationStageId, resultStageId

2.7 Final Confirmation Contract

New FinalConfirmationSession

Fields:

  • stageId (final confirmation stage)
  • status (OPEN, PENDING_ADMIN_APPROVAL, FINALIZED, CANCELLED)
  • decisionRule (UNANIMOUS, SUPERMAJORITY, SIMPLE_MAJORITY, SINGLE_JUDGE_DECIDES)
  • quorumPolicy (ACTIVE_MEMBERS_ONLY, ALLOW_REPLACEMENT)
  • requiredApprovalsCount (resolved from active quorum after absence/replacement decisions)
  • scope (CATEGORY, AWARD)
  • isAdminOverridden (bool)
  • overrideReasonCode, overrideReasonText, overriddenByAdminId, overriddenAt
  • finalizedByAdminId, finalizedAt

New FinalConfirmationParticipant

Fields:

  • sessionId, juryMemberId
  • status (REQUIRED, ABSENT_EXCUSED, REPLACED, REPLACEMENT_ACTIVE)
  • replacedByJuryMemberId (nullable)
  • absenceReasonCode, absenceReasonText
  • updatedByAdminId, updatedAt

New FinalConfirmationVote

Fields:

  • sessionId, juryMemberId, projectId/category/awardScope, decision, comment

New ResultLock

Fields:

  • sessionId, programId, lockVersion, lockedAt, lockedBy, snapshotJson

New ResultUnlockEvent

Fields:

  • resultLockId, programId
  • unlockedBySuperAdminId, unlockedAt
  • reasonCode, reasonText
  • relockVersion (nullable until relock)

Invariant:

  • once ResultLock is created, winner outputs are immutable except via explicit super-admin unlock workflow with mandatory audit reason.

3) Policy Precedence Model

Order of precedence (highest to lowest):

  1. Explicit admin override action (with reason)
  2. Per-user override policy (e.g., judge cap override)
  3. Stage+jury policy
  4. Program-level default policy
  5. System default

All runtime evaluators must return:

  • resolved value
  • source layer
  • explanation payload for audit/debug UI

4) Access Contract (Role + Context)

Replace scattered checks with resolveAccess(user, context) where context includes:

  • programId
  • trackId
  • stageId
  • stagePurposeKey
  • juryId (if applicable)
  • projectId (if applicable)
  • submissionRoundId (if applicable)

Returns typed permissions:

  • canViewProject
  • canUploadSubmissionSlot
  • canViewPreviousRoundDocs
  • canAssignProjects
  • canVoteLive
  • canConfirmFinalWinners
  • etc.

5) Assignment Engine Contract

Input:

  • projects eligible in stage
  • jury members bound to stage
  • resolved per-judge policy (cap mode, cap, buffer, category-bias preference)
  • required reviews
  • COI and availability constraints

Required behavior:

  1. satisfy hard-cap constraints strictly
  2. satisfy soft-cap targets before using buffer
  3. apply startup/concept distribution as a soft scoring bias (never a strict blocker)
  4. when all soft-cap members hit cap+buffer, place remainder in manual queue
  5. never silently drop unassigned projects

Output:

  • assignment set
  • unassigned queue with explicit reasons
  • policy-compliance summary

6) Document Contract

For every stage with submission behavior:

  • active SubmissionRound must exist
  • all required slots represented by FileRequirement.slotKey
  • applicant write rights only for active round if open
  • previous round slots read-only in applicant scope
  • judges see current + previous according to stage policy
  • admins full mutate rights with replacement provenance

7) Invite + Onboarding Contract

7.1 Admin Member Invite

  • Invitations create User + optional JuryMembership.
  • Jury selection uses program-defined custom jury labels, while binding to explicit stage-purpose contracts.
  • Pre-assignment supports both modes:
    • intent-first mode via AssignmentIntent (default recommended)
    • direct assignment mode via Assignment (explicitly enabled and policy-validated)

7.2 Team Invite

  • Team lead invites create/attach TeamMember
  • invite token acceptance path remains, but post-accept routing resolves to proper applicant/team context

7.3 Accept Invite Routing

After acceptance:

  • if user has jury memberships pending onboarding -> jury onboarding journey
  • if mentor -> mentor onboarding
  • if applicant team member only -> applicant team dashboard

8) Event/Audit Contract

Every significant workflow event emits:

  • business event type (assignment.generated, final_confirmation.finalized, etc.)
  • actor
  • entity scope
  • policy snapshot
  • before/after state where relevant

Override events must include:

  • reason code
  • reason text
  • impacted policy key
  • reviewer chain (if applicable)

9) API Contract Evolution (Router-Level)

9.1 Keep and Evolve

  • Keep existing routers (pipeline, stage, assignment, evaluation, file, mentor, live-voting, decision, user, etc.)
  • Add new endpoints for purpose/policy/jury/final confirmation and deprecate ambiguous patterns progressively

9.2 New Endpoint Families

  • jury.*: CRUD memberships/bindings
  • assignmentPolicy.*: configure and inspect effective policy
  • submissionRound.*: lifecycle and bundle state
  • mentorWorkspace.*: files/comments/promotion
  • finalConfirmation.*: create/collect/finalize lock, handle quorum fallback, and manage juror replacement/absence
  • resultUnlock.*: super-admin unlock/relock workflow with audit capture
  • access.*: debug effective permissions (admin-only)

10) Migration Safety Rules

  1. Additive migrations first.
  2. Backfill purposeKey and policy references from existing configs.
  3. Dual-read / single-write transition windows where needed.
  4. Feature flags for critical runtime path switches.
  5. No silent behavior changes in production without compatibility mode.

11) End State

A coherent operating model where all functions, pages, and APIs are consistent with Monaco flow and each key behavior is explainable, testable, and auditable.