# Team Settings ## User Perspective The Settings page (`/settings`) covers: - **Team members**: view, invite, change role, remove - **Connected channels**: view connected YouTube channels - **Render settings** (ADMIN+): - Date format for date tokens (`{video.scheduledAt}`, `{video.recordingDate}`) - Timezone - Publishing schedule (weekly time slots for the "Next free slot" feature in the video editor) - Show Canva link in video editor (for teams that use Canva for thumbnails) - Disabled lint rules - Show deleted videos in video list - **Remote conflict detection** (ADMIN+): - Enable scheduled conflict detection (opt-in per team) - Videos per run (batch size) - Only check videos older than N days ## Developer Perspective ### Team Settings Fields | Field | Type | Description | |---|---|---| | `dateFormat` | `String?` | strftime-like format for date tokens | | `timezone` | `String` | IANA timezone string, default "UTC" | | `publishingSchedule` | `Json?` | Array of weekly time slots | | `showCanvaLink` | `Boolean` | Shows Canva search link in video editor | | `disabledLintRules` | `String[]` | Rule codes excluded from lint runs | | `showDeletedVideos` | `Boolean` | Shows the Deleted tab in video list | | `conflictDetectionEnabled` | `Boolean` | Opt-in for the scheduled remote-conflict sweep (default `false`) | | `conflictDetectionBatchSize` | `Int` | Max videos checked per run (1–500, default 50) | | `conflictDetectionMinAgeDays` | `Int` | Skip videos whose `lastSyncedAt` is within N days (≥0, default 7) | ### Disabling Lint Rules (Side Effect) When `disabledLintRules` is updated via `PATCH /teams/:teamId/settings`: 1. All unresolved `LintResult` rows for the newly disabled rules are deleted 2. `Video.lintStatus` is recomputed for all affected videos ### Publishing Schedule Used by the "Next free slot" button in the video editor's Basic Info section. The schedule defines which days/times are available for publishing. `GET /teams/:teamId/next-publish-slot?channelId=` returns the next available ISO datetime. The slot-finder walks candidate slots day by day and checks whether any existing `scheduledAt` on the channel falls within the **collision window**. Two hardcoded constants govern this behavior (`teams.service.ts`): | Constant | Value | Effect | |---|---|---| | Collision window | ±30 minutes | A slot is considered taken if any video on that channel is already scheduled within 30 minutes either side of it | | Lookahead limit | 90 days | If no free slot is found within 90 days, the endpoint returns `{ slot: null }` | These values are not configurable per-team. The 30-minute collision window means teams that publish multiple videos per day with closely spaced slots may find legitimate adjacent slots blocked if a video is already scheduled in between. See the backlog. ### Remote Conflict Detection Settings The three `conflictDetection*` fields control the per-team share of the global sweep queued by `ConflictDetectionScheduler`. The sweep itself only runs if the operator has set `CONFLICT_DETECTION_ENABLED=true` on the worker (see [[02 - Environment Variables]]) — the team toggle alone does nothing without it. Validation in `TeamsService.updateSettings` enforces `1 ≤ batchSize ≤ 500` and `minAgeDays ≥ 0`. See [[05 - Queue System]] for how the processor uses these values, and [[02 - Videos API]] for how detected conflicts are resolved (`POST /videos/:id/accept-remote` vs `POST /videos/:id/sync`). ## Related - [[09 - Teams API]] - [[03 - Metadata Linting]]