Qontak | Platform | One Team Migration — Phase 1: Legacy Team Migration
Product Requirements Document · NEW PRD v1.0
HEADER BLOCK
| Field | Value |
|---|---|
| PM | Qontak PM Group |
| PRD Version | 1.0 |
| Status | DRAFT |
| PRD Type | NEW |
| Epic | BIF-8642 |
| Squad | Bifrost |
| RFC Link | TBD — pending PRD approval |
| Figma Master | TBD — pending design |
| Anchor | Yes — Qontak | Platform | One Team Migration — ANCHOR |
| Labels | epic:qontak-platform | module:usman | feature:one-team-migration |
| Last Updated | 2026-06-22 |
✅ Reformat Complete
This PRD was reformatted from [PRD] Qontak One Team Migration. All gaps resolved as of 2026-06-23. No outstanding flags.
Table of Contents
- HEADER BLOCK
- 3. One-liner + Problem
- 4. Target Users + Persona Context
- 5. Non-Goals
- Scope Changes
- 6. Constraints
- 7. Feature Changes
- 8. New Features
- 9. API & Webhook Behavior
- 10. System Flow + User Stories + ACs
- 11. Rollout
- 12. Observability
- 13. Success Metrics
- 14. Launch Plan & Stage Gates
- 15. Dependencies
- 16. Key Decisions + Alternatives Rejected
- 17. Open Questions
- PRD CHANGELOG
3. One-liner + Problem
One-liner: Migrate existing Chat Divisions and CRM Teams into a unified Launchpad USMAN system for Qontak One Admins, with mandatory team assignment enforced for all new user invitations.
Problem: Chat and CRM currently handle team structures independently — Chat uses "Divisions" and CRM uses "Teams" — with no unified view in Qontak One. This fragmentation forces Admins to manage user memberships across multiple disconnected places, allows new users to be invited without team assignments (creating untracked access), and leaves no common source of truth for team origin. As Qontak One centralizes User Management into Launchpad, all existing team structures must be migrated, clearly labeled by source, and new user invitations must require team assignment to maintain organizational structure going forward.
4. Target Users + Persona Context
| Persona | Role | Goal | Pain | Workaround |
|---|---|---|---|---|
| Primary — Admin | Company admin managing users in Qontak One | Invite new users with proper team categorization; view all team structures in a single Launchpad panel | Teams from Chat (Divisions) and CRM are disconnected — no single place to manage all team structures | Manages teams separately in Chat Divisions settings and CRM Teams settings; no cross-system view |
| Secondary — Backend Developer | Engineer triggering & operating the migration (Launchpad triggers; Chat/CRM push) | Safely migrate legacy team structures without disrupting existing user configurations | No source_identifier or reference_id on existing teams — cannot trace which system a team came from | Manual lookup across Chat and CRM databases to identify team origins |
5. Non-Goals
- This does not migrate individual user memberships — only team structures (Divisions/Teams) are migrated, not user-to-team assignments.
- This does not modify the existing Chat Divisions UI — Chat Divisions continue to function as-is.
- This does not merge duplicate team names across Chat and CRM — each is migrated as a separate Launchpad team with its source prefix.
- This does not migrate inactive or archived Divisions/Teams — active records only.
- This does not enforce team assignment for existing users already in the system — only new invitations.
- The Chat and CRM SUPPORT squad PRDs (API endpoints to provide Division/Team data) are out of scope for this PRD.
- This does not change the billing or quota model for teams.
Scope Changes
- Backend — new
source_identifierandreference_idDB columns on Team table; migration script; invitation validation; General team auto-creation on CID creation. - Frontend — mandatory Team dropdown on
/user/invite; Qontak One Team Sidebar URL change from/qontakcrm/teamto/launchpad/team.
6. Constraints
Feature Flags:
unified_app | default: false— gates Qontak One globally (existing flag). Team migration features only active whenunified_app = true.one_team_migration_enabled | default: false— gates this migration rollout (new flag, global). Mandatory team invitation and migrated team data only visible when this flag is enabled.
Plan Scope: Available to all plans with unified_app = true. No additional plan restriction.
Platform: Web only. No mobile app scope.
Performance SLAs:
- Migration script: processes all active CIDs within 24 hours of execution
- Invitation team validation API response: ≤ 500ms
- General team auto-creation on CID creation: ≤ 2s
Data Limits: To be defined by engineering — see Section 17 (Open Questions).
6.1 Data Lifecycle
The migration is a one-time, idempotent operation — each source squad pushes its mapped teams into Launchpad's create endpoint. The only artifacts produced outside the main data model are migration failure logs (the bulk upload-job records and per-item results).
| Artifact Type | Retention Period | Cleanup Trigger | User-Visible Effect |
|---|---|---|---|
| Migration failure log | 30 days | Nightly cleanup job | None — engineer-visible in logs only |
| Migration run record | Indefinite | Manual cleanup by engineering | None |
7. Feature Changes
CHG-001 — Team Sidebar URL Change
| Field | Value |
|---|---|
| Change Type | Modified routing |
| Page (Before) | /qontakcrm/team |
| Page (After) | /launchpad/team |
| Page Intent | Team management for Admin — view, create, and manage Launchpad teams |
| Element | Before | After |
|---|---|---|
| Team sidebar URL | /qontakcrm/team | /launchpad/team |
| Navigation link target | CRM module | Launchpad module |
| Old URL behavior | Active | Redirects to /launchpad/team |
Figma: TBD — pending design
8. New Features
Feature: Mandatory Team Dropdown on User Invitation Form
| Field | Value |
|---|---|
| URL | /user/invite |
| Access | Admin only |
Component Tree:
InviteUserForm
├── EmailInput (existing)
├── RoleDropdown (existing)
├── TeamDropdown ★ NEW (required field — marked with *)
│ └── TeamOption (one per active Launchpad team for this CID)
└── SubmitButton (existing — disabled until all required fields valid)
UI States:
- Loading: Skeleton/spinner in TeamDropdown while teams are fetching from API
- Empty: "No teams available. Create a team first." — SubmitButton disabled
- Error: "Could not load teams. Try again." + Retry button — SubmitButton disabled until retry succeeds
- Success: TeamDropdown populated with active Launchpad teams; SubmitButton enabled when team selected
Figma: TBD — pending design
9. API & Webhook Behavior
| # | Behavior | Entity Affected | Triggered By | Expected Behavior | Failure Behavior |
|---|---|---|---|---|---|
| 1 | Create Launchpad Team (migration) | Launchpad Team (new record created) | Chat or CRM squad calls Launchpad's bulk/single team-create endpoint with is_migrate = true, app = chat|crm, and the source app_identifier_id (= division/team id) (one_team_migration_enabled = true) | Launchpad persists the team with prefixed name (Chat - [Name] / CRM - [Name]), derives source_identifier from app, stores app_identifier_id as reference_id; idempotent — skips if a team with the same (company, source_identifier, reference_id) already exists; emits a TEAM_MIGRATED Kafka event carrying team_id + app + app_identifier_id (so the source squad can map its division/team to the centralized team) | Records per-item failure with CID + reason in the bulk result; batch continues without aborting |
| 2 | Validate team on user invitation | User invitation payload | Admin submits Invite User form at /user/invite | Rejects submission with validation error if no team selected (per S8 §TeamDropdown required); bypasses validation for existing legacy users without a team | Returns validation error: "Please select a team to continue" |
| 3 | Auto-create General team on CID creation | Launchpad Team (new record created) | New CID successfully created in system | Creates team named "General" with: no members, no parent team, source_identifier = 'Launchpad', reference_id = null | CID creation NOT rolled back; failure logged; team creation retried asynchronously |
| 4 | Fetch teams for invitation dropdown | Launchpad Team list (read) | Invite User form loads at /user/invite | Returns list of active Launchpad teams for the CID | Returns error; frontend shows "Could not load teams. Try again." + retry button |
| 5 | Trigger source-squad migration | Chat Division / CRM Team (owned & read by their squads) | Migration kickoff (one_team_migration_enabled = true) | Launchpad triggers Chat and CRM migration via their endpoints; each squad maps its own active Divisions/Teams and calls Launchpad's bulk/single create (behavior #1) | If a squad's trigger or processing fails, that squad retries/skips on its side; Launchpad is not blocked and records per-item create results |
[Implementation details — HTTP method, path, request/response schema, error codes: to be resolved by Claude during RFC. Migration ownership: each source squad performs its own data mapping and pushes into Launchpad's create endpoints; Launchpad does not read Chat/CRM data directly.]
10. System Flow + User Stories + ACs
10.1 System Flow
Flow: Migration Script + New User Invitation + CID Creation
flowchart TD
subgraph Migration["Migration (push model)"]
A["Launchpad triggers Chat & CRM migration"] --> B{Which squad?}
B -->|Chat| C["Chat maps its active Divisions<br/>then calls Launchpad bulk/single create<br/>(is_migrate, app=chat, reference_id)"]
B -->|CRM| D["CRM maps its active Teams<br/>then calls Launchpad bulk/single create<br/>(is_migrate, app=crm, reference_id)"]
C --> G["Launchpad persists team:<br/>name 'Chat - [Name]', source_identifier='Chat', reference_id=app_identifier_id"]
D --> H["Launchpad persists team:<br/>name 'CRM - [Name]', source_identifier='CRM', reference_id=app_identifier_id"]
G --> K["Emit TEAM_MIGRATED event<br/>(team_id, app, app_identifier_id)"]
H --> K
K --> M["Chat/CRM consume event<br/>map division/team to Launchpad team"]
end
subgraph New User Invitation
I["Admin invites new user via /user/invite"] --> J{Is Team Selected?}
J -->|No| K[Return Validation Error]
J -->|Yes| L["Set source_identifier = 'Launchpad'"]
L --> M[User created and bound to Team]
end
subgraph CID Creation
N[New CID Created] --> O["Auto-create 'General' Team"]
O --> P["source_identifier = 'Launchpad', reference_id = null"]
end
10.2 User Stories
| User Story | Importance | Mockup / Technical Notes | Acceptance Criteria |
|---|---|---|---|
| [OTM-S01] — Mandatory Team Selection for New Users As an Admin, I want the system to require a Team selection when inviting a new user, so that all new users in Qontak One are properly categorized and tracked. | Must Have | Figma: TBD — pending design Data Fields: • team_id (string, required) — selected from TeamDropdown• source_identifier (enum, system-set) — always 'Launchpad' for new invitationsBefore-After Behavior: Before: Admin can submit /user/invite without selecting a team. After: TeamDropdown is required (*); submission blocked with validation error if no team selected. | — Happy Path — • AC-1: Given an Admin is on /user/invite AND one_team_migration_enabled = true, when the page loads, then the TeamDropdown is visible and marked required (*).• AC-2: Given the TeamDropdown is visible and a team is selected, when the Admin submits the form with all required fields valid, then the user is invited successfully with source_identifier = 'Launchpad' and the selected team assignment.— Error / Unhappy Path — • ERR-1: Given the Admin submits the form without selecting a team, when the form validates, then the submission is blocked and inline error shows: "Please select a team to continue." • ERR-2: Given the team list API fails to load, when the Admin opens /user/invite, then TeamDropdown shows "Could not load teams. Try again." with a retry button, and SubmitButton is disabled until teams load successfully.— Permission Model — • CAN: Admin role • CANNOT: Regular users, read-only roles • Unauthorized: TeamDropdown not rendered; no validation error exposed — UI States — • Loading: Skeleton/spinner in TeamDropdown while teams fetching • Empty: "No teams available. Create a team first." — SubmitButton disabled • Error: "Could not load teams. Try again." + retry — SubmitButton disabled • Success: TeamDropdown populated; SubmitButton enabled when team selected — Negative Scenarios — • NEG-1: Given an existing user without a team assignment, when their profile is accessed or updated, then no team assignment is forced and no error is shown. |
| [OTM-S02] — Auto-Create "General" Team on CID Creation As Launchpad, I want to automatically create a "General" team when a new CID is created, so that new users can be immediately assigned to a team and CRM Layout activates. | Must Have | Figma: N/A — backend only, no new UI Data Fields: • team_name (string, system-set) — always "General"• source_identifier (enum, system-set) — always 'Launchpad'• reference_id (null, system-set) — always null for native Launchpad teams• members (empty array) — no initial members• parent_team (null) — no parentBefore-After Behavior: Before: No default team is created when a new CID is created. After: A "General" team with source_identifier = 'Launchpad' is auto-created on every new CID creation event. | — Happy Path — • AC-1: Given a new CID is successfully created, when the CID creation event fires, then a Launchpad team named "General" is created with: no members, no parent team, source_identifier = 'Launchpad', reference_id = null.• AC-2: Given the "General" team is created, when an Admin opens /user/invite for that CID, then "General" appears in the TeamDropdown.— Error / Unhappy Path — • ERR-1: Given the General team creation service is unavailable at CID creation time, when the creation event fires, then the CID creation is NOT rolled back; the failure is logged; team creation is retried asynchronously. — Permission Model — • CAN: System (triggered automatically on CID creation — no user action) • CANNOT: End users cannot trigger or prevent this • Unauthorized: N/A — system-triggered only — UI States — • N/A — backend only |
| [OTM-S03] — Qontak One Team Sidebar URL Change As a user, I want the Team management section to be accessible at /launchpad/team, so that team management is unified under Launchpad navigation in Qontak One. | Must Have | Figma: TBD — pending design Data Fields: N/A — routing change only Before-After Behavior: Before: Team management accessible at /qontakcrm/team. After: Team management accessible at /launchpad/team; old URL redirects to new URL. | — Happy Path — • AC-1: Given a user navigates to /launchpad/team AND unified_app = true AND one_team_migration_enabled = true, when the page loads, then the Launchpad Team management page renders.• AC-2: Given a user navigates to the old URL /qontakcrm/team, when the page loads, then the user is redirected to /launchpad/team.• AC-3: Given the Qontak One sidebar is visible, when the Teams navigation link is clicked, then it navigates to /launchpad/team.— Permission Model — • CAN: Admin and users with team management permission • CANNOT: Users without team management permission • Unauthorized: Redirect to dashboard — UI States — • Loading: Skeleton while team list loads at /launchpad/team• Empty: "No teams yet." • Error: "Could not load teams. Try again." • Success: Team list rendered |
| [OTM-S04] — Track Team Source Identifiers As a Backend Developer, I want source_identifier and reference_id columns on the Team database table, so that we can trace whether a team was migrated from Chat, CRM, or created natively in Launchpad. | Must Have | Figma: N/A — backend DB schema change only Data Fields: • source_identifier (enum, required) — values: 'Chat', 'CRM', 'Launchpad'• reference_id (string/int, nullable) — Chat division_id, CRM team_id, or null for native Launchpad teamsBefore-After Behavior: Before: Team table has no source tracking columns. After: All Team records carry source_identifier (enum: Chat/CRM/Launchpad) and nullable reference_id linking back to the source system. | — Happy Path — • AC-1: Given a team is created natively via Launchpad UI, when the record is saved, then source_identifier = 'Launchpad' and reference_id = null.• AC-2: Given a team is migrated from Chat Divisions, when the migration script creates the record, then source_identifier = 'Chat' and reference_id = [division_id from Chat].• AC-3: Given a team is migrated from CRM Teams, when the migration script creates the record, then source_identifier = 'CRM' and reference_id = [team_id from CRM].• AC-4: Given any Team record, when source_identifier is written, then only 'Chat', 'CRM', or 'Launchpad' are accepted — any other value is rejected by DB constraint.— Permission Model — • CAN: Migration script (system), auto-creation (system) • CANNOT: End users cannot modify source_identifier or reference_id• Unauthorized: N/A — backend columns, not user-editable — UI States — • N/A — backend DB schema |
| [OTM-S05] — Process Pushed Legacy-Team Migration As a Backend Developer, I want Launchpad to trigger each source squad's migration and idempotently process the teams they push (carrying source + reference_id), emitting a team event per creation, so that legacy team structures are centralized without duplicates — while each squad owns the mapping of its own data. | Must Have | Figma: N/A — backend, no new UI Ownership: Chat and CRM each map their own active Divisions/Teams and call Launchpad's bulk/single create endpoint ( is_migrate = true, app = chat|crm, app_identifier_id), then consume the TEAM_MIGRATED event to map their division/team to the centralized Launchpad team. Launchpad does not read Chat/CRM data.Data Fields (what the source squad sends → what Launchpad persists): • Chat: app='chat', app_identifier_id=[division_id] → team_name = 'Chat - [Division Name]', source_identifier = 'Chat', reference_id = [division_id]• CRM: app='crm', app_identifier_id=[team_id] → team_name = 'CRM - [Team Name]', source_identifier = 'CRM', reference_id = [team_id]Before-After Behavior: Before: Chat Divisions and CRM Teams exist only in their respective systems. After: each squad pushes its active records into Launchpad, which stores them as source-tracked teams. | — Happy Path — • AC-1: Given Chat calls Launchpad's create endpoint for a Division named "Support" ( is_migrate, app=chat, app_identifier_id=division_id), when Launchpad processes it, then a team "Chat - Support" exists with source_identifier = 'Chat' and reference_id = [division_id], and a TEAM_MIGRATED event is emitted carrying team_id + app + app_identifier_id.• AC-2: Given CRM calls the create endpoint for a Team named "Sales" ( app=crm, app_identifier_id=team_id), when Launchpad processes it, then a team "CRM - Sales" exists with source_identifier = 'CRM' and reference_id = [team_id], and TEAM_MIGRATED carries app_identifier_id = [team_id].• AC-3: Given a team with the same (company, source_identifier, reference_id) already exists, when the same create call is replayed, then no duplicate is created (idempotency).• AC-4: Given a source squad maps its records, then only ACTIVE Divisions/Teams are submitted to Launchpad — the active-only filter is owned by the source squad. — Error / Unhappy Path — • ERR-1: Given a source squad's migration is unavailable or fails for a CID, when migration runs, then Launchpad is not blocked; the squad retries/skips on its side and Launchpad records per-item create results in the bulk job. — Permission Model — • CAN: Chat/CRM squad services (call the create endpoint); Launchpad (trigger + process) • CANNOT: End users cannot trigger migration • Unauthorized: service-to-service auth between squads and Launchpad |
11. Rollout
Feature Flags:
unified_app | default: false(existing) — Qontak One global gateone_team_migration_enabled | default: false(new, global) — migration rollout gate
Rollout Sequence:
| Phase | Audience | Gate |
|---|---|---|
| Phase 1 — Internal QA | Qontak internal accounts only | one_team_migration_enabled = true for internal CIDs |
| Phase 2 — Staged Rollout | CID batches (after CRM squad migration completes) | Enable one_team_migration_enabled per CID batch |
| Phase 3 — GA | All CIDs with unified_app = true | All staged rollout gates sustained |
Backward Compatibility: Existing users without a team remain unaffected — no retroactive team assignment enforced.
Migration: One-time script, idempotent — safe to re-run without creating duplicates.
Dependency: Phase 2 cannot begin until CRM squad's migration is complete (see Section 15 — Dependencies).
11.1 Migration Transition Window
During staged rollout, CIDs will be in different states simultaneously:
| CID State | Behavior |
|---|---|
one_team_migration_enabled = false | Retains existing behavior; invitation form shows no mandatory team dropdown; /qontakcrm/team still accessible |
one_team_migration_enabled = true, migration not yet run | Invitation form shows mandatory TeamDropdown; if no teams exist yet, dropdown shows "No teams available. Create a team first." |
one_team_migration_enabled = true, migration complete | Invitation form shows mandatory TeamDropdown; migrated teams (Chat/CRM prefixed) and any native Launchpad teams appear |
End state: All CIDs have one_team_migration_enabled = true and migration complete — transition fallback behavior no longer needed.
12. Observability
Key Events:
| Event Name | Trigger | Properties |
|---|---|---|
team_migrated (Kafka TEAM_MIGRATED) | Launchpad persists a pushed migrated team | cid, team_id, source_identifier, app , app_identifier_id (= reference_id), team_name — consumed by Chat/CRM to map their division/team to the centralized team |
team_migration_failed | Script fails to migrate a team | cid, source, reason |
user_invited_with_team | Admin invites a user with team selected | cid, team_id, source_identifier |
invitation_rejected_no_team | Invitation rejected due to missing team selection | cid, admin_id |
general_team_created | General team auto-created on CID creation | cid, team_id |
| Field | Detail |
|---|---|
| Dashboard owner | Bifrost PM + Engineering lead |
| Alerts | Alert 1: team_migration_failed rate > 1% in any migration run → #bifrost-alerts. Alert 2: general_team_created failure > 0 in any 24-hour window → #bifrost-alerts. |
12.1 Post-Launch Monitoring Cadence
Review cadence: Weekly for first 4 weeks post-GA, then monthly. Owner: Bifrost PM + Engineering lead.
Trigger thresholds:
team_migration_failedrate > 1% of total migrations attempted → immediate investigationinvitation_rejected_no_teamspikes unexpectedly post-GA → PM review within 48 hoursgeneral_team_createdfailures exceed 0 in any 24-hour window → engineering escalation same day
13. Success Metrics
Adoption & Migration:
⭐ Primary KPI: % of active CIDs with one_team_migration_enabled = true that have all legacy teams successfully migrated to Launchpad
- Baseline: 0% (pre-migration)
- Target: 100% within 30 days of GA
Quality:
- Migration failure rate (
team_migration_failed/ total teams attempted)- Baseline: N/A (new process)
- Target: ≤ 1%
Enforcement:
- % of new user invitations that include a team assignment (for CIDs with
one_team_migration_enabled = true)- Baseline: N/A (currently unenforced)
- Target: 100% (validation enforced for all enabled CIDs)
14. Launch Plan & Stage Gates
| Stage | Audience | Duration | Success Gate | Owner |
|---|---|---|---|---|
| Internal QA | Qontak internal accounts | 1 week | Migration script completes with 0 duplicates; source_identifier + reference_id correct on all records; invitation validation working; 0 P0/P1 bugs | PM + QA |
| Staged Rollout | Subset of CIDs (after CRM squad migration complete) | 2 weeks | Migration failure rate ≤ 1%; mandatory team dropdown working on /user/invite; General team auto-created on new CIDs; old URL /qontakcrm/team redirects to /launchpad/team | PM + Eng lead |
| GA | All CIDs with unified_app = true | Ongoing | All staged rollout gates sustained for 1 consecutive week; one_team_migration_enabled enabled globally | PM |
15. Dependencies
| Dependency | Owning Team | Deliverable Needed | Blocking? |
|---|---|---|---|
| Chat squad migration | Chat Squad | Chat maps its own active Divisions and calls Launchpad's bulk/single create (is_migrate, app=chat, reference_id); exposes a migration-trigger endpoint Launchpad can call | YES |
| CRM squad migration (mapping) | CRM Squad | CRM maps its own active Teams and calls Launchpad's create endpoint (app=crm, reference_id); exposes a migration-trigger endpoint | YES |
| CRM squad migration (completion) | CRM Squad | CRM Teams migration must complete before Phase 2 staged rollout begins | YES |
16. Key Decisions + Alternatives Rejected
16a — Decisions Made
| Date | Decision | Rationale |
|---|---|---|
| 2026-06-23 | source_identifier uses a fixed enum (Chat, CRM, Launchpad) — not free text | Type-safe, queryable, consistent across migration and invitation flows |
| 2026-06-23 | reference_id stores the original Chat Division or CRM Team record ID | Enables reverse lookup to legacy record without a cross-DB join |
| 2026-06-23 | Name conflict resolution: prefix with Chat- / CRM- — no merge | Merging would conflate users from different team contexts; confirmed via ANCHOR OQ1 |
| 2026-06-23 | General team auto-created on new CID creation — not manually set up | Ensures all new CIDs have at least one team available for mandatory invitation enforcement |
| 2026-06-23 | No rollback path — migration failures fixed forward | A rollback mechanism adds complexity with no clear safe-state to return to; confirmed via ANCHOR OQ3 |
| 2026-06-30 | Migration is push, not pull — each source squad maps its own data and calls Launchpad's existing bulk/single team-create endpoint; Launchpad does not read Chat/CRM data | Source data ownership stays with each squad; reuses Launchpad's existing is_migrate/app bulk-create path; avoids Launchpad coupling to Chat/CRM internal schemas |
16b — Alternatives Rejected
| Alternative | Why Rejected | Date |
|---|---|---|
Free-text source field | Not type-safe and difficult to query consistently across migration and audit tooling | 2026-06-23 |
| Merge conflict teams into one record | Merging teams from different product contexts risks mixing users who belonged to separate workflows | 2026-06-23 |
17. Open Questions
| # | Type | Question | Owner | Deadline |
|---|---|---|---|---|
| OQ1 | TECHNICAL | What is the data volume limit per migration batch run — how many teams can be processed per CID per execution? (noted as TBD in S6 Data Limits) | Bifrost Engineering | Before Phase 1 RFC |
| OQ2 | PRODUCT | Users currently assigned to both a Chat Division and a CRM Team — do they get assigned to both migrated teams in USMAN, or only one? | Bifrost PM + Chat/CRM squads | Before Phase 1 RFC |
| OQ3 | TECHNICAL | Is migration triggered automatically when one_team_migration_enabled is toggled on, or does Engineering run it as a one-time script per CID? | Bifrost Engineering | Before Phase 1 RFC |
PRD CHANGELOG
| Version | Date | By | Section | Type | Summary |
|---|---|---|---|---|---|
| 1.0 | 2026-06-22 | Claude | All | REFORMATTED | Reformatted from [PRD] Qontak One Team Migration to Qontak PRD template v1.1. 2 sections extracted from source (S1, S8 flow), 13 sections filled via coaching interview, 2 flags remaining (S16 Key Decisions, S17 Open Questions). |
| 1.1 | 2026-06-23 | Claude | S12, S16, S17, Flag Summary | FILLED | Added S12 dashboard owner + alert routing (#bifrost-alerts). Filled S16 Key Decisions (5 decisions, 2 alternatives rejected). Added S17 Open Questions (3 questions: migration batch limit, dual-team user assignment, migration trigger mechanism). Flag summary updated to ✅ Reformat Complete. |
| 1.2 | 2026-06-30 | Claude | S9, S10 (flow + OTM-S05), S15, S16 | REVISED | Migration model corrected from pull to push to match service planning: each source squad maps its own data and calls Launchpad's existing bulk/single team-create endpoint (is_migrate/app/reference_id); Launchpad triggers them and processes creation + emits Kafka events. Reworked §9 behaviors #1/#5, §10.1 flow diagram, OTM-S05 story + ACs, §15 dependencies, +§16 decision. |
| 1.3 | 2026-06-30 | Claude | S9, S10.1, S10 OTM-S05, S12 | REVISED | Migration-mapping refinement: bulk/single create accepts optional app_identifier_id (= source division/team id, persisted as reference_id); migrate-mode emits a separate TEAM_MIGRATED Kafka event (vs TEAM_CREATED) carrying team_id+app+app_identifier_id so each source squad maps its division/team to the centralized Launchpad team. Updated §9 #1, §10.1 flow, OTM-S05 ownership/ACs, §12 event. |