# Translation-key prefixes/keys that the orphan-key test in
# messages-usage.test.ts treats as covered. Each line is matched as a prefix:
# `foo.bar` covers `foo.bar` and `foo.bar.<anything>`.
#
# Add an entry here only when a key is genuinely dynamic — constructed at
# runtime in ways the regex scanner cannot follow (template literals composed
# across files, enum-driven dispatch, etc.). Static keys, even with template
# literals whose prefix is constant, are already covered by the wildcard scan.

# --- dynamic prefixes ---
metadata

# `roles.${role.toLowerCase()}` in member-table.tsx — the `owner` role is
# never referenced as a string literal because it can't be assigned through
# the UI (only inherited from the org creator), so the regex scanner can't
# see it.
settings.roles.owner

# Notifications written by Convex mutations carry `titleKey` / `bodyKey`
# strings stored on the row; the client looks them up under the
# `notifications` namespace at bell-render time. Server-side string
# literals are not visible to the client-source regex scanner.
notifications.accountLocked
notifications.lockoutDetails
notifications.auditIntegrityFailed
notifications.auditIntegrityFailedDetails
notifications.dsarScheduled
notifications.dsarScheduledBody
notifications.dsarScheduledByBody
notifications.dsarApprovalNeeded
notifications.dsarApprovalNeededBody
notifications.dsarApprovalNeededByBody
notifications.dsarCancelled
notifications.dsarCancelledBody
notifications.dsarCancelledByBody
notifications.dsarPolicyTightened
notifications.dsarPolicyTightenedBody
notifications.dsarPolicyLoosenProposed
notifications.dsarPolicyLoosenProposedBody
notifications.dsarPolicyLoosenApplied
notifications.dsarPolicyLoosenAppliedBody
notifications.dsarPolicyLoosenCancelled
notifications.dsarPolicyLoosenCancelledBody

# `tEntity('searchPlaceholder')` in app/hooks/use-table-config-factory.ts is
# resolved against a runtime `entityNamespace` parameter — the regex scanner
# can't tie the literal `'searchPlaceholder'` back to its callsite namespace.
customers.searchPlaceholder
products.searchPlaceholder
vendors.searchPlaceholder
websites.searchPlaceholder


# `piiTypeLabel(name, tTypes)` in pii-type-labels.ts maps a dynamic pattern
# name (`email`, `phone`, `nl-bsn`, …) onto a translation key. The scanner
# sees `tTypes(key)` with `key` as a runtime variable, so every label entry
# under the `piiTypes` namespace is dynamic from its perspective.
piiTypes

# Canvas runnable renderer + icon-map: `t(CANVAS_TYPE_LABEL_KEYS[type])` and
# `t(`canvas.runStatus.${runStatus}`)` / `canvas.runErrorCode.${runErrorCode}`
# / `canvas.runProgress.${runProgress.kind}` are all driven by the
# CanvasContentType / SandboxRunStatus / SandboxErrorCode unions in
# convex/sandbox/wire.ts. Adding new union members forces a rebuild that
# covers the corresponding label key automatically.
chat.canvas.typeLabel
chat.canvas.runStatus
chat.canvas.runErrorCode
chat.canvas.runProgress

# Projects feature: error codes are constructed at runtime as
# `t('errors.' + error.data.code)` in every mutation try/catch path
# (project-create-dialog, project-settings-tab, project-files-tab,
# project-threads-tab, project-instructions-editor). The full
# error-code catalog lives in convex/projects/mutations.ts and
# convex/projects/queries.ts — keep this prefix while those throw
# ConvexError({ code: ... }) values surfaced via the .errors namespace.
projects.errors

# Projects audit log: action labels are looked up dynamically when
# rendering an audit row whose `action` is e.g. `project.thread.shared`
# (see convex/projects/audit_actions.ts).
projects.auditLog

# Projects UI surfaces planned but not yet wired in v1 — keys live in
# en.json so translators can land copy ahead of the UI without a
# re-translate cycle. Remove these once the corresponding components
# ship (Phase 7+: get-started cards, composer chip, picker, full
# Agents & Models tab with effective-set messaging, files attach UX).
projects.agents.addAgent
projects.agents.addModel
projects.agents.allowedListLabel
projects.agents.emptyAdminBody
projects.agents.emptyAdminCta
projects.agents.emptyAdminTitle
projects.agents.emptyMemberBody
projects.agents.emptyMemberTitle
projects.agents.emptyModelsAdminBody
projects.agents.emptyModelsAdminTitle
projects.agents.emptyModelsMemberBody
projects.agents.emptyModelsMemberTitle
projects.agents.integrationsHeading
projects.agents.recommendedBadge
projects.agents.recommendedListLabel
projects.composer
projects.create.colorLabel
projects.create.iconLabel
projects.create.teamLabel
projects.create.teamPlaceholder
projects.files.addButton
projects.files.attachError
projects.files.attachSuccess
projects.files.title
projects.list.columnChats
projects.list.columnFiles
projects.list.emptyCta
projects.list.sharingTeamPrefix
projects.list.subtitle
projects.list.title
projects.navigation.list
projects.overview.getStartedHeading
projects.overview.getStartedFilesTitle
projects.overview.getStartedFilesBody
projects.overview.getStartedInstructionsTitle
projects.overview.getStartedInstructionsBody
projects.overview.getStartedShareTitle
projects.overview.getStartedShareBody
projects.overview.lastActivity
projects.overview.lastActivityNever
projects.picker
projects.settings.deleteConfirmPhrase
projects.settings.deleteDialogDescription
projects.settings.deleteDialogTitle
projects.settings.deleteCascadeCheckbox
projects.settings.deleteModeCascade
projects.settings.deleteModeDetach
projects.settings.deleteSubmit
projects.settings.iconColor
projects.settings.knowledge
projects.settings.knowledgeMode
projects.settings.knowledgeModeOff
projects.settings.knowledgeModeTool
projects.settings.knowledgeModeContext
projects.settings.knowledgeModeBoth
projects.settings.sharing
projects.settings.alsoSharedWith
projects.settings.alsoSharedWithHelp
projects.settings.owningTeam
projects.settings.owningTeamHelp
projects.settings.visibility
projects.settings.visibilityOrgWide
projects.settings.visibilityShared
projects.settings.visibilityTeam
projects.threads.title
projects.threads.shareSuccess
projects.threads.unshareSuccess
projects.threads.shareError

# Audit-log table renders action / actorType / category / status / resourceType
# from the stored audit row (closed enum sets in convex/audit_logs/schema.ts;
# 109 action codes emitted across convex/**). See
# audit-log-table.tsx + use-audit-log-table-config.tsx.
settings.logs.audit.actionLabels
settings.logs.audit.actorTypeLabels
settings.logs.audit.categoryLabels
settings.logs.audit.resourceTypeLabels
settings.logs.audit.statusLabels

# Projects: additional planned-but-not-yet-wired keys for v1+ surfaces
# (instructions editor save indicators, notFound screen, danger zone, etc.).
# Remove once the corresponding components ship.
projects.instructions.saveError
projects.instructions.savedIndicator
projects.instructions.savingIndicator
projects.navigation.settings
projects.notFound.backCta
projects.notFound.description
projects.notFound.retryCta
projects.notFound.title
projects.overview.statsHeading
projects.overview.statsIndexed
projects.overview.statsShared
projects.settings.dangerZone
projects.settings.deleteButton
projects.settings.deleteDescription
projects.settings.saveSubmitting

# Editor remote-update merge dialog: keys live ahead of the dialog being wired.
common.editor.adoptRemote
common.editor.keepMine
common.editor.remoteUpdateAvailable
common.editor.remoteUpdateDiffTitle

# Settings → Agents: unsaved-changes dialog (keys ahead of dialog wiring).
settings.agents.unsavedChanges.description
settings.agents.unsavedChanges.leave
settings.agents.unsavedChanges.stay
settings.agents.unsavedChanges.title

# Inbox: per-user content notifications. titleKey/bodyKey are stored on the
# userNotifications row and looked up dynamically at render (t(row.titleKey)),
# so the scanner can't tie them to a callsite. Driven by convex/collab/notify.ts.
inbox

# Tasks feature (Milestone 0 backend; board/table UI lands in Milestone 1).
# status/priority/views labels are enum-driven dynamic lookups
# (`t(`tasks.status.${status}`)` etc., driven by the taskStatus/taskPriority
# unions in convex/tasks/schema.ts); the rest land ahead of the UI so
# translators can work in parallel. Remove once the board UI ships.
tasks

# Settings rail sub-section labels. The API sub-pages (REST / MCP / WebDAV)
# are driven by the API_NAV_ITEMS catalog in
# app/routes/dashboard/$id/settings/api/nav-items.ts and rendered via
# `tNav(item.labelKey)` in settings-rail.tsx and the section's mobile tab
# strip. Because the catalog is a data-only module (no `useT` call), the
# scanner can't tie its `labelKey` literals back to the `navigation`
# namespace. (`mcp` is also referenced directly in api/mcp.tsx, so only the
# two catalog-only labels need listing here.)
navigation.apiRest
navigation.webdav
