diff --git a/.changeset/dangling-competitor-grants.md b/.changeset/dangling-competitor-grants.md new file mode 100644 index 000000000..f85ea0dcf --- /dev/null +++ b/.changeset/dangling-competitor-grants.md @@ -0,0 +1,10 @@ +--- +'hotcrm': patch +--- + +Remove the four profile grants on `crm_competitor`, an object that no longer +exists. `main` failed `pnpm validate` with four cross-reference errors: #547 +added the grants while the competitor module was still present, the demo-only +competitor module was removed separately, and the two merged cleanly on text +while contradicting each other on meaning. `sales_rep`, `sales_manager`, +`marketing_user` and `system_admin` no longer reference the removed object. diff --git a/src/profiles/marketing-user.profile.ts b/src/profiles/marketing-user.profile.ts index 8d6968457..b5884f180 100644 --- a/src/profiles/marketing-user.profile.ts +++ b/src/profiles/marketing-user.profile.ts @@ -21,9 +21,8 @@ export const MarketingUserProfile = { // the campaigns this profile can already read; deleting membership history // stays a manager/admin privilege, matching every other object here. crm_campaign_member: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false, viewAllRecords: false, modifyAllRecords: false }, - // Read-only reference: competitive intel for positioning, knowledge - // articles for campaign copy. Both are public_read catalogs. - crm_competitor: { allowCreate: false, allowRead: true, allowEdit: false, allowDelete: false, viewAllRecords: true, modifyAllRecords: false }, + // Read-only reference: knowledge articles for campaign copy + // (public_read catalog). crm_knowledge_article: { allowCreate: false, allowRead: true, allowEdit: false, allowDelete: false, viewAllRecords: true, modifyAllRecords: false }, }, fields: { diff --git a/src/profiles/sales-manager.profile.ts b/src/profiles/sales-manager.profile.ts index 5409b52aa..cfb2e5d02 100644 --- a/src/profiles/sales-manager.profile.ts +++ b/src/profiles/sales-manager.profile.ts @@ -20,8 +20,6 @@ export const SalesManagerProfile = { crm_campaign: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false, viewAllRecords: true, modifyAllRecords: false }, crm_case: { allowCreate: false, allowRead: true, allowEdit: false, allowDelete: false, viewAllRecords: true, modifyAllRecords: false }, crm_task: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, viewAllRecords: true, modifyAllRecords: true }, - // Competitive-intel catalog (public_read OWD): managers curate battlecards. - crm_competitor: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: false, viewAllRecords: true, modifyAllRecords: false }, // The forecast IS the manager's job: they read every rep's snapshot and // adjust the committed number, so this is org-wide read AND write on a // private object (#488 — the object had no grant at all). diff --git a/src/profiles/sales-rep.profile.ts b/src/profiles/sales-rep.profile.ts index d60fc65d6..b319d19cd 100644 --- a/src/profiles/sales-rep.profile.ts +++ b/src/profiles/sales-rep.profile.ts @@ -28,10 +28,8 @@ export const SalesRepProfile = { crm_campaign: { allowCreate: false, allowRead: true, allowEdit: false, allowDelete: false, viewAllRecords: true, modifyAllRecords: false }, crm_case: { allowCreate: false, allowRead: true, allowEdit: false, allowDelete: false, viewAllRecords: false, modifyAllRecords: false, readScope: 'own' as const }, crm_task: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, viewAllRecords: false, modifyAllRecords: false, readScope: 'own' as const }, - // Reference catalogs (public_read OWD): reps read battlecards and knowledge - // articles, and may file a new competitor they ran into in a deal, but the - // battlecard content itself is curated by managers. - crm_competitor: { allowCreate: true, allowRead: true, allowEdit: false, allowDelete: false, viewAllRecords: true, modifyAllRecords: false }, + // Reference catalog (public_read OWD): reps read knowledge articles, which + // are authored by service. crm_knowledge_article: { allowCreate: false, allowRead: true, allowEdit: false, allowDelete: false, viewAllRecords: true, modifyAllRecords: false }, // Forecast snapshots are written by the nightly `forecast.hook` job and the // `revenue_forecasting` skill, never by hand — read-only, and only the rep's diff --git a/src/profiles/system-admin.profile.ts b/src/profiles/system-admin.profile.ts index ec0195a4f..e9847e47f 100644 --- a/src/profiles/system-admin.profile.ts +++ b/src/profiles/system-admin.profile.ts @@ -24,11 +24,9 @@ export const SystemAdminProfile = { crm_campaign: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, viewAllRecords: true, modifyAllRecords: true }, crm_case: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, viewAllRecords: true, modifyAllRecords: true }, crm_task: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, viewAllRecords: true, modifyAllRecords: true }, - // The six objects below shipped with navigation, views, hooks and seed - // data but no grant in ANY permission set (#488): "Knowledge" and - // "Forecasts" were permission-denied nav items for every user, admins - // included, and `crm_competitor` was the same story behind the Sales group. - crm_competitor: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, viewAllRecords: true, modifyAllRecords: true }, + // The objects below shipped with navigation, views, hooks and seed data + // but no grant in ANY permission set (#488): "Knowledge" and "Forecasts" + // were permission-denied nav items for every user, admins included. crm_forecast: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, viewAllRecords: true, modifyAllRecords: true }, crm_knowledge_article: { allowCreate: true, allowRead: true, allowEdit: true, allowDelete: true, viewAllRecords: true, modifyAllRecords: true }, // Detail rows. Their RECORD-level access derives from the master