Skip to main content

platform-custom-setting-generate

Use to create, generate, or validate Salesforce Custom Setting metadata. Trigger on custom settings (hierarchy/list), customSettingsType, SetupOwnerId, per-profile/per-user config overrides, feature flags/toggles, kill switches, or admin on/off switches (e.g. bypass triggers during a data load); also "create a custom setting" or a setting that silently deployed as a regular object. A kill switch is just a checkbox on a hierarchy setting — generate ONLY the setting, never an Apex trigger/handler. DO NOT TRIGGER for Custom Metadata Types (use platform-custom-metadata-type-generate), business-record objects (use platform-custom-object-generate), or secrets/tokens (use a Named Credential).

معلومات المصدر

المستودع
forcedotcom/sf-skills
آخر نشاط في المصدر
١٥ أكتوبر ٢٠٢٦ في ٠٧:٥٧
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
١٬١١١
التفرعات
٣٧٩

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
platform-custom-setting-generate
description
Use to create, generate, or validate Salesforce Custom Setting metadata. Trigger on custom settings (hierarchy/list), customSettingsType, SetupOwnerId, per-profile/per-user config overrides, feature flags/toggles, kill switches, or admin on/off switches (e.g. bypass triggers during a data load); also "create a custom setting" or a setting that silently deployed as a regular object. A kill switch is just a checkbox on a hierarchy setting — generate ONLY the setting, never an Apex trigger/handler. DO NOT TRIGGER for Custom Metadata Types (use platform-custom-metadata-type-generate), business-record objects (use platform-custom-object-generate), or secrets/tokens (use a Named Credential).
metadata
{"version":"1.0","minApiVersion":"60.0","domains":["Platform"],"relatedSkills":["platform-custom-field-generate","platform-custom-metadata-type-generate","platform-custom-object-generate","platform-metadata-api-context-get"],"cliTools":[{"tool":"[Truncated]","semver":">=2.136.8"}]}
# Salesforce Custom Setting Generator and Validator ## When to Use This Skill Use this skill when you need to: - Create a Hierarchy or List custom setting - Generate custom setting metadata XML - Add or validate fields on an existing custom setting - Populate custom setting **values** (these are data, not metadata — see Section 6) - Troubleshoot custom setting deployment errors > **A trigger bypass / kill switch is a Custom Setting — not Apex and not a `__mdt`.** When the user wants a > switch admins can flip to turn behavior on or off — "disable my Account triggers during a data load", a > feature toggle, a maintenance-mode flag — generate **only** a hierarchy custom setting with a `Checkbox` > field (e.g. `Disable_Triggers__c` / `Bypass__c`). Do **not** author the Apex trigger, handler, or test > that reads it, and do **not** model it as a Custom Metadata Type: the per-profile/per-user override a > bypass flag needs is exactly what a hierarchy custom setting gives you and a `__mdt` does not. The Apex > that checks the flag is the developer's to write — this skill generates the setting only. --- For authoritative Metadata API type, field, and enum details beyond this skill, use the `platform-metadata-api-context-get` skill. ## 1. Overview and Purpose This document defines the mandatory constraints for generating Custom Setting metadata. A custom setting is a `CustomObject` with `<customSettingsType>` set — it is **not** a distinct metadata type. **File extension:** `.object-meta.xml` **File path:** `force-app/main/default/objects/<Name>__c/<Name>__c.object-meta.xml` **API name suffix:** `__c` (identical to a regular custom object — the suffix does **not** distinguish them) > **Values are data, not metadata.** You can generate the setting's *definition* as XML, but you cannot > deploy its *values* that way. There is no source-format equivalent of `customMetadata/` for custom > settings. Never generate a file that claims to carry setting values — see **Section 6** for what to do > instead. --- ## 2. Syntactic Essentials (Tier 1) ### `<customSettingsType>` is mandatory — CRITICAL **This is the single highest-severity rule in this skill.** Omitting `<customSettingsType>` does not produce a "you forgot customSettingsType" error. The component silently stops being a custom setting and is validated as a plain custom object. The failure is dangerous because it is *recoverable in the wrong direction*: an agent that omits the element, then obediently fixes each error the platform reports, ends up with a **green deploy and completely the wrong kind of component**. | What you see | What it means | |---|---| | `Must specify a non-empty plural label for the CustomObject` | You are **NOT** building a custom setting. `customSettingsType` is missing. Add it — do **not** add `pluralLabel`. | | `Cannot specify: nameField for CustomSettings` | You **ARE** building a custom setting. Remove the named element. | These two strings are mutually exclusive tells. The giveaway in the first is the phrase **`for the CustomObject`** and the absence of any mention of custom settings. **If a deploy reports `Must specify a non-empty plural label for the CustomObject` on something the user asked to be a custom setting, never satisfy that error by adding `<pluralLabel>`.** Adding it (plus `nameField`, `deploymentStatus`, and `sharingModel`) makes the deploy succeed and creates a regular custom object that the user did not ask for. ### Required and Allowed Elements | Element | Requirement | Notes | |---------|-------------|-------| | `<customSettingsType>` | **Required** | `Hierarchy` or `List` — see Section 3 | | `<label>` | **Required** | Singular UI name | | `<visibility>` | Always include | `Public`, or `Protected` only in a dev/sandbox/scratch org (Section 5) | | `<description>` | Always include | Explain what the setting controls and who edits it | | `<enableFeeds>` | Optional | Accepted | | `<listViews>` | Optional | Accepted — permitted despite `recordTypes` and `compactLayouts` being forbidden | ### Forbidden Elements Every element below produces `Cannot specify: <element> for CustomSettings`: | Forbidden element | Note | |---|---| | `<pluralLabel>` | **Required on a regular custom object, forbidden here.** Exactly inverted. | | `<nameField>` | The `Name` field exists implicitly on List settings | | `<deploymentStatus>` | | | `<sharingModel>` | Custom settings are not shared records | | `<enableActivities>` `<enableReports>` `<enableHistory>` `<enableSearch>` | | | `<validationRules>` | Enforce these in Apex instead | | `<recordTypes>` | | | `<compactLayouts>` | | **INCORRECT** — carries a regular custom object's required elements: ```xml <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata"> <customSettingsType>Hierarchy</customSettingsType> <label>Feature Flags</label> <pluralLabel>Feature Flags</pluralLabel> <!-- WRONG: forbidden on custom settings --> <sharingModel>ReadWrite</sharingModel> <!-- WRONG: forbidden --> <deploymentStatus>Deployed</deploymentStatus> <!-- WRONG: forbidden --> <nameField> <!-- WRONG: forbidden --> <label>Name</label> <type>Text</type> </nameField> <visibility>Public</visibility> </CustomObject> ``` **Errors:** `Cannot specify: pluralLabel for CustomSettings` · `Cannot specify: sharingModel for CustomSettings` · `Cannot specify: deploymentStatus for CustomSettings` · `Cannot specify: nameField for CustomSettings` **CORRECT** — minimum valid custom setting: ```xml <?xml version="1.0" encoding="UTF-8"?> <CustomObject xmlns="http://soap.sforce.com/2006/04/metadata"> <customSettingsType>Hierarchy</customSettingsType> <label>Feature Flags</label> <description>Per-profile and per-user toggles for beta features in the ordering app. Edited by admins in Setup.</description> <visibility>Public</visibility> </CustomObject> ``` Note there is no `<fullName>`. A root-level one is tolerated and ignored, but omit it — the API name comes from the directory and filename. `<customSettingsType>List</customSettingsType>` deployed without needing the "Manage List Custom Settings Type" toggle in Setup. That toggle exists in some orgs, so if a List setting is rejected on a `customSettingsType` grounds in a different org, check Schema Settings before assuming the XML is wrong. --- ## 3. List vs Hierarchy Decision (Tier 2) `<customSettingsType>` has exactly two values, and the choice changes how rows are addressed. | | `Hierarchy` | `List` | |---|---|---| | **Use when** | The value can vary per profile or per user, with an org-wide fallback | The setting is a small keyed reference table, the same for everyone | | **Row key** | `SetupOwnerId` (Organization, Profile, or User) | `Name` | | **Resolution** | User value → Profile value → org default | Look up by `Name` | | **Apex read** | `MySetting__c.getInstance()` / `getOrgDefaults()` | `MySetting__c.getValues('Key')` / `getAll()` | | **Typical case** | Feature flags, per-profile limits, debug toggles | Country codes, tax rates by region, integration endpoints by key | **Default to `Hierarchy`** when the user describes toggles, limits, or anything that "can be overridden." Choose `List` when they describe a lookup table with named rows. If the user asks for a keyed reference table that should be **deployable between orgs**, a List custom setting is usually the wrong answer — its rows are data and will not travel with the deploy. Route to `platform-custom-metadata-type-generate` instead (Section 7). --- ## 4. Field Rules Fields on a custom setting are ordinary `CustomField` components at `objects/<Name>__c/fields/<Field>__c.field-meta.xml`. **This skill owns the custom-setting-specific deltas only** — the supported-type allowlist and the `fieldManageability` prohibition below. For everything generic (`<fullName>` derivation, `<label>`, `<description>`, `<inlineHelpText>`, precision/scale, `<length>`, `externalId`), follow `platform-custom-field-generate`. ### Supported Field Types `Checkbox`, `Currency`, `Date`, `DateTime`, `Email`, `Number`, `Percent`, `Phone`, `Text`, `TextArea`, `Url` `required`, `unique`, `externalId`, and `defaultValue` are accepted on custom setting fields. Whether a given one applies to a given type is a generic field rule — defer to `platform-custom-field-generate`. ### Unsupported Field Types `Picklist`, `MultiselectPicklist`, `LongTextArea`, `Html`, `Lookup`, `MasterDetail`, `AutoNumber`, `Location`, `Time`, `EncryptedText`, and **Formula** (a `<formula>` element on any type). Every one of these fails with the same bare, uninformative string: ```text Invalid data type. ``` **This error names neither field nor type.** On a multi-field deploy, read `componentFailures[].fullName` from the `--json` output to find the culprit — do not guess. **Roll-up summary fields are structurally impossible here** — a `Summary` needs a master-detail child, and `MasterDetail` is itself rejected on a custom setting. Don't generate one; the error text varies, so don't match on a specific string. **Picklist is the common trap.** Users frequently ask for a picklist on a custom setting. It is not supported. Use `Text` and enforce the allowed values in Apex, or route the request to `platform-custom-metadata-type-generate` — CMDT *does* support Picklist. Near-inversion vs CMDT: `Currency` works here but not on CMDT; `Picklist`/`LongTextArea` work on CMDT but not here. Never carry field-type assumptions across the two families. ### `<fieldManageability>` is forbidden That element belongs to CMDT fields only. On a custom setting field it fails with: ```text Field manageability cannot be set on this entity. ``` --- ## 5. Visibility, Secrets, and the No-Silent-Downgrade Rule ### `Protected` is org-type dependent `<visibility>Protected</visibility>` deploys only in a developer, sandbox, or scratch org. Anywhere else: ```text You can't set the visibility for a Custom Setting to Protected unless you are in a developer, sandbox, or scratch org. ``` ### The no-silent-downgrade rule — CRITICAL **If `Protected` fails because of the org type, never "fix" it by switching to `Public`.** A silent downgrade turns a deliberate confidentiality choice into a world-readable component with no signal. Report it plainly: the org does not permit `Protected`, so the options are a dev/sandbox/scratch org or accepting `Public` — let the user decide. This applies to any visibility narrowing, not just this error. ### Secrets do not belong in a custom setting Custom settings are **not** a secret store. Values are readable by anyone who can query the object, and `Protected` does not change that for code in the same namespace. When a user asks to store an API key, password, token, client secret, or certificate in a custom setting: 1. **Warn prominently and first** — before generating anything — that a custom setting is the wrong place for a credential and the value will be readable. 2. **Recommend the right component** — a **Named Credential** with an **External Credential** for callout auth. Say plainly that this skill does not generate those. 3. **If the user still insists, comply** — generate the setting but keep the warning in the response. Do not silently refuse, and do not silently obey. Never route a secret to `Protected` visibility as a compromise: if `Protected` is unavailable (above), the no-silent-downgrade rule applies with full force, because the downgrade would publish the secret. --- ## 6. Setting Values Are Data, Not Metadata **A custom setting's rows cannot be deployed as XML.** There is no `customMetadata/`-style folder for them. Only the object definition and its fields are metadata. When a user asks to create a setting *with values* — "add a feature flag setting with Beta enabled for admins" — do all of the following: 1. Generate the object and field XML as normal. 2. **State the limitation in one line:** setting values are data, not metadata, so they are not deployed. 3. **Give ready-to-run commands inline in the chat response**, fully substituted with the real object and field API names and the actual values — not a placeholder template, and not written to a file. All three shapes below are verified working. ### Hierarchy — org-wide default row **Omit `SetupOwnerId`.** It defaults to the Organization Id, which is exactly the org-default row. No Id lookup is needed. ```bash sf data create record --sobject Feature_Flags__c \ --values "Enable_Beta__c=true Max_Retries__c=3" \ --target-org <alias> ``` ### Hierarchy — profile or user override This one **does** need an Id, so it is two steps. A user-level override uses the same shape with a `User` Id in place of the Profile Id (extrapolated from the profile case, not separately verified). ```bash sf data query --query "SELECT Id FROM Profile WHERE Name='System Administrator'" --target-org <alias> sf data create record --sobject Feature_Flags__c \ --values "SetupOwnerId=00eXXXXXXXXXXXXXXX Enable_Beta__c=false" \ --target-org <alias> ``` An override row coexists with the org-default row; it does not replace it. ### List — one row per key `Name` is the row key and is required. ```bash sf data create record --sobject Country_Codes__c \ --values "Name='US' Iso_Code__c='USA' Dial_Prefix__c='+1'" \ --target-org <alias> ``` ### Quoting Wrap the whole `--values` argument in double quotes; single-quote any value with a space or shell-special character (`Environment_Label__c='org default'`). Plain numbers, booleans, and Ids need no inner quotes. ### Consuming a setting in Apex Values are read through the generated typed class — cached, so reads cost **no SOQL** and are safe inside loops and triggers. For a **Hierarchy** setting: ```apex Feature_Flags__c cfg = Feature_Flags__c.getInstance(); // running user: user → profile → org default Feature_Flags__c org = Feature_Flags__c.getOrgDefaults(); // org-default row only, no hierarchy Feature_Flags__c forProfile = Feature_Flags__c.getInstance(profileId); // a User Id works too Boolean beta = cfg.Enable_Beta__c; ``` `getInstance()` and `getOrgDefaults()` **never return null** (API ≥ 22) — a missing record comes back as an empty row, so test `org.Id != null` when you need to know whether a real record actually exists. For a **List** setting, use `getValues('Key')` for one row or `getAll()` for the `Map<String, Feature_Flags__c>` of every row. ### The in-transaction DML rule Populating or changing values is **runtime DML** (Apex `insert`/`update`/`upsert`, or the `sf` commands above) — there is no metadata path. That is the operational face of "values are data," and it has two consequences worth stating to the user: - **Writes count against DML governor limits; reads do not.** In a trigger over 200 records, never `upsert` the setting once per record — hoist the write out of the loop and do it once. - **Cross-transaction propagation lags.** After a write, other transactions may briefly read the previous value while the org cache propagates; within the same transaction the new value is visible immediately. --- ## 7. Choosing the Right Component Before generating, confirm a custom setting is actually what the user needs. If it is not, say so and name the right skill rather than building the wrong thing. | If the config is… | Use | Why | |---|---|---|
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub