sf-intelligence 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1302 -28
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/index.js
CHANGED
|
@@ -55506,6 +55506,444 @@ var init_concept_model = __esm({
|
|
|
55506
55506
|
{ label: "Apex Developer Guide \u2014 Triggers and Bulk Request Triggers", url: "https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_bulk_requests.htm" },
|
|
55507
55507
|
{ label: "Apex Developer Guide \u2014 Running Apex within Governor Execution Limits", url: "https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm" }
|
|
55508
55508
|
]
|
|
55509
|
+
},
|
|
55510
|
+
"concept:validation-rule-inactive": {
|
|
55511
|
+
id: "concept:validation-rule-inactive",
|
|
55512
|
+
kind: "firing-condition",
|
|
55513
|
+
label: "An inactive validation rule never enforces its constraint and must be excluded from save-failure analysis",
|
|
55514
|
+
summary: 'A VALIDATION RULE whose `active` flag is FALSE is DEAD enforcement: Salesforce never evaluates its error-condition formula on insert or update, so it can neither block a save nor surface its error message until an admin re-activates it. It must be EXCLUDED from save-order-of-execution analysis (validation runs in the system-validation phase), from "what could reject this write" reasoning, and from required-field / collision gate counts \u2014 treating a deactivated rule as a live guard would cry wolf about a constraint that cannot fire, while treating it as protection would falsely assure that bad data is blocked. This is grounded from the rule\'s own always-present `active` boolean; it names the non-enforcing STRUCTURAL fact, NOT whether the rule WOULD reject a specific record if activated (the error-condition formula is not evaluated offline) and NOT why it was deactivated. Only active validation rules belong in save-failure and enforcement surfaces.',
|
|
55515
|
+
docs: [
|
|
55516
|
+
{ label: "Salesforce Help \u2014 Define Validation Rules", url: "https://help.salesforce.com/s/articleView?id=sf.fields_defining_field_validation_rules.htm" }
|
|
55517
|
+
]
|
|
55518
|
+
},
|
|
55519
|
+
"concept:workflow-rule-inactive-dead": {
|
|
55520
|
+
id: "concept:workflow-rule-inactive-dead",
|
|
55521
|
+
kind: "firing-condition",
|
|
55522
|
+
label: "An inactive workflow rule never runs its actions and is dead legacy automation",
|
|
55523
|
+
summary: 'A WORKFLOW RULE whose `active` flag is FALSE is DEAD legacy automation: Salesforce never evaluates its criteria and never runs its associated actions \u2014 field updates, email alerts, outbound messages, or time-dependent actions \u2014 until it is re-activated. It must be EXCLUDED from save-order-of-execution analysis (an active workflow field update runs in its own save-order phase and can re-trigger automation), from field-writer-collision reasoning, and from "what fires on save" impact counts; counting a deactivated rule would overstate the automation load, while assuming its field updates still run would misattribute a value change. This is grounded from the rule\'s own always-present `active` boolean; it names the non-running STRUCTURAL fact, NOT whether an equivalent Flow has replaced it (migration lineage is org-specific) and NOT whether the rule WOULD match a given record if activated (criteria remain unevaluated offline). Only active workflow rules belong in save-order and automation-impact surfaces.',
|
|
55524
|
+
docs: [
|
|
55525
|
+
{ label: "Salesforce Help \u2014 Activate Workflow Rules", url: "https://help.salesforce.com/s/articleView?id=sf.workflow_rules_activating.htm" }
|
|
55526
|
+
]
|
|
55527
|
+
},
|
|
55528
|
+
"concept:field-longtext-richtext-not-filterable": {
|
|
55529
|
+
id: "concept:field-longtext-richtext-not-filterable",
|
|
55530
|
+
kind: "field-provenance",
|
|
55531
|
+
label: "Long Text Area and Rich Text (Html) fields cannot be filtered, sorted, grouped, or indexed",
|
|
55532
|
+
summary: "A LONG TEXT AREA or RICH TEXT (Html) field belongs to a data-type class that Salesforce does NOT index \u2014 such a field is not filterable, not sortable, and not groupable, so it cannot appear in a SOQL WHERE / ORDER BY / GROUP BY clause, a list-view filter, or a report filter, and it cannot be marked as an external id or as unique. It can be referenced in a SELECT clause and rendered as body content, but any attempt to filter, sort, group, or index on it is rejected by the platform. This is grounded from the field's own always-present `dataType` (LongTextArea or Html); it names the STRUCTURAL platform restriction that follows from the field's type class, NOT whether any specific SOQL query, list view, or report currently references the field (that is a usage question the offline snapshot does not answer here) and NOT the field's length or stored content. Only the queryability class is asserted, never a proven failure of a particular query.",
|
|
55533
|
+
docs: [
|
|
55534
|
+
{ label: "Salesforce Help \u2014 Custom Field Types", url: "https://help.salesforce.com/s/articleView?id=sf.custom_field_types.htm" }
|
|
55535
|
+
]
|
|
55536
|
+
},
|
|
55537
|
+
"concept:duplicate-rule-bypass-sharing-match": {
|
|
55538
|
+
id: "concept:duplicate-rule-bypass-sharing-match",
|
|
55539
|
+
kind: "access-mechanism",
|
|
55540
|
+
label: "A duplicate rule set to bypass sharing matches against records the running user cannot see",
|
|
55541
|
+
summary: "A DUPLICATE RULE whose `securityOption` is BYPASS SHARING RULES runs its duplicate-matching query in SYSTEM CONTEXT: it compares an incoming record against records the RUNNING USER cannot see under the org's sharing model, so a save can be blocked or alerted by a duplicate the user has no visibility into and cannot open to resolve. The alternative, ENFORCE SHARING RULES, restricts matching to records the running user can already access. This is grounded from the rule's own declared `securityOption` scalar; it names the DECLARED sharing-context posture only. It does NOT assert the rule is active (`isActive`), that any matching records exist, that a particular save would actually surface a hidden duplicate, or which specific records lie outside the user's visibility \u2014 those depend on runtime record data and per-user sharing the offline vault cannot evaluate.",
|
|
55542
|
+
docs: [
|
|
55543
|
+
{ label: "Metadata API Developer Guide \u2014 DuplicateRule", url: "https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_duplicaterule.htm" }
|
|
55544
|
+
]
|
|
55545
|
+
},
|
|
55546
|
+
"concept:duplicate-rule-references-inactive-matching-rule": {
|
|
55547
|
+
id: "concept:duplicate-rule-references-inactive-matching-rule",
|
|
55548
|
+
kind: "automation-collision",
|
|
55549
|
+
label: "An active duplicate rule that points at an inactive matching rule does no duplicate detection",
|
|
55550
|
+
summary: "A DUPLICATE RULE reuses a MATCHING RULE to decide which records count as duplicates. When an ACTIVE duplicate rule references a matching rule whose ruleStatus is NOT Active (Inactive, Draft, Deactivating, ActivationFailed, and the like), that matcher runs NO comparison \u2014 so on that path the duplicate rule detects nothing and duplicate records save SILENTLY, with no alert and no block, even though the duplicate rule itself looks enabled. The honest signal conjoins the duplicate rule's own `isActive` flag with the `ruleStatus` of each matching rule it references. HONEST BOUNDARIES: this is grounded from declared metadata flags only \u2014 it does NOT prove any duplicate records currently exist in the org, does NOT prove a specific save would have been caught had the matcher been active, and does NOT check whether another ACTIVE matching rule on the same duplicate rule still covers the object. It names a silently-disabled detection SHAPE, not a proven missed duplicate.",
|
|
55551
|
+
docs: [
|
|
55552
|
+
{ label: "Salesforce Help \u2014 Duplicate Management", url: "https://help.salesforce.com/s/articleView?id=sf.duplicate_management.htm" }
|
|
55553
|
+
]
|
|
55554
|
+
},
|
|
55555
|
+
"concept:approval-process-final-lock-record-readonly": {
|
|
55556
|
+
id: "concept:approval-process-final-lock-record-readonly",
|
|
55557
|
+
kind: "access-mechanism",
|
|
55558
|
+
label: "An approval process that locks the record on final approval or rejection leaves it read-only until unlocked",
|
|
55559
|
+
summary: 'An APPROVAL PROCESS that declares `finalApprovalRecordLock` (or `finalRejectionRecordLock`) as true LOCKS the record when the process reaches final approval (or final rejection): a locked record becomes READ-ONLY to everyone except administrators and users with the "Modify All Data" / "Modify All" permission (plus the approval process\'s own unlock step), so once the process completes, later user edits AND automation updates \u2014 field writes from a flow, workflow, trigger, or the API \u2014 FAIL with an entity-is-locked error unless the record is unlocked first. This matters for save-order and automation reasoning: a downstream flow or trigger that tries to update a just-approved (or just-rejected) record can silently fail on the lock. This is grounded from the approval process\'s own always-present `finalApprovalRecordLock` / `finalRejectionRecordLock` booleans; it names the DECLARED lock behavior, NOT whether any specific record is currently locked (which records have entered or completed the process is record-level runtime state the offline vault does not hold), NOT which specific users can still edit it (permission-holder membership is not evaluated here), and NOT whether any automation actually attempts a post-lock update. Only an approval process whose final-approval or final-rejection step locks the record contributes this freeze.',
|
|
55560
|
+
docs: [
|
|
55561
|
+
{ label: "Salesforce Help \u2014 Considerations for Approvals (record locking)", url: "https://help.salesforce.com/s/articleView?id=sf.approvals_considerations.htm" }
|
|
55562
|
+
]
|
|
55563
|
+
},
|
|
55564
|
+
"concept:record-type-inactive": {
|
|
55565
|
+
id: "concept:record-type-inactive",
|
|
55566
|
+
kind: "access-mechanism",
|
|
55567
|
+
label: "An inactive record type cannot be assigned to new records and is hidden from record-type selection",
|
|
55568
|
+
summary: "A RECORD TYPE whose `active` flag is FALSE is a DEAD routing mechanism: it cannot be assigned to new records and is hidden from users' record-type selection, so it routes NONE of its page layout, picklist value set, or business process to new work until an admin re-activates it. Only pre-existing records keep it. It must be EXCLUDED from \"which record type will new records get\", default-routing, and layout / picklist-scope reasoning about new work \u2014 treating a deactivated record type as a live routing option would misattribute a layout, restricted picklist, or business process that new records can never receive, while assuming it still governs selection would overstate the choices a user is offered. This is grounded from the record type's own always-present `active` boolean; it names the non-assignable STRUCTURAL fact, NOT whether any existing records still carry this record type (that is record-level data, not modeled offline), NOT which profiles or permission sets once defaulted to or were granted it (assignment is separate metadata), and NOT why it was deactivated. Only active record types belong in new-record routing surfaces.",
|
|
55569
|
+
docs: [
|
|
55570
|
+
{ label: "Salesforce Help \u2014 Create Record Types", url: "https://help.salesforce.com/s/articleView?id=sf.customize_recordtype.htm" }
|
|
55571
|
+
]
|
|
55572
|
+
},
|
|
55573
|
+
"concept:remote-site-setting-protocol-security-disabled": {
|
|
55574
|
+
id: "concept:remote-site-setting-protocol-security-disabled",
|
|
55575
|
+
kind: "external-api-surface",
|
|
55576
|
+
label: "A remote site setting that disables protocol security allows cleartext HTTP callouts to its allowlisted host",
|
|
55577
|
+
summary: "An ACTIVE remote site setting whose disableProtocolSecurity flag is TRUE drops the platform's HTTPS-only guard on outbound callouts to its allowlisted host: it permits cleartext HTTP requests to that endpoint, so request URLs, headers, and bodies \u2014 potentially including session ids, tokens, or credentials carried in the request \u2014 travel unencrypted and are exposed to network interception and tampering. This is grounded from the setting's own always-present disableProtocolSecurity and isActive booleans; it names the declared configuration POSTURE, NOT whether any Apex, Flow, or LWC actually issues an insecure callout to this host at runtime (the offline vault does not correlate outbound-callout code to allowlist entries), NOT a confirmed interception or breach, and NOT whether a plaintext endpoint is a deliberate, accepted design choice. The modern replacement is a Named Credential over HTTPS; re-enabling protocol security restores the encrypted-only guard unless a cleartext endpoint is genuinely required.",
|
|
55578
|
+
severity: "high",
|
|
55579
|
+
docs: [
|
|
55580
|
+
{ label: "Salesforce Help \u2014 Configure Remote Site Settings", url: "https://help.salesforce.com/s/articleView?id=sf.configuring_remoteproxy.htm" },
|
|
55581
|
+
{ label: "Apex Developer Guide \u2014 Invoking Callouts Using Apex", url: "https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_callouts.htm" }
|
|
55582
|
+
]
|
|
55583
|
+
},
|
|
55584
|
+
"concept:apex-intentional-system-mode-dml": {
|
|
55585
|
+
id: "concept:apex-intentional-system-mode-dml",
|
|
55586
|
+
kind: "access-mechanism",
|
|
55587
|
+
label: "An Apex class runs DML with an explicit AccessLevel.SYSTEM_MODE argument \u2014 a deliberate object-CRUD / field-level-security bypass for that write",
|
|
55588
|
+
summary: "An Apex class runs a DML operation (a Database.insert / update / upsert / delete and its siblings) with an EXPLICIT AccessLevel.SYSTEM_MODE argument. Apex runs in system context and does NOT automatically enforce the running user's object CRUD or field-level security on its DML; passing AccessLevel.SYSTEM_MODE makes that non-enforcement DELIBERATE and explicit for this write \u2014 the developer consciously chose to run the write in system context, so object- and field-level security are intentionally NOT applied and the write can create or change objects and fields regardless of whether the running user is permitted to. This is the CONSCIOUS counterpart to an accidental missing CRUD/FLS check: the recognizer surfaces it as a REVIEW finding rather than a defect, because a deliberate SYSTEM_MODE bypass is often exactly correct (a trusted service that must write fields the running user cannot edit), and adding an isUpdateable()-style guard the write deliberately bypasses would be the wrong fix. The remediation, IF the running user's permissions SHOULD apply to this write, is to switch the argument to AccessLevel.USER_MODE. HONEST BOUNDARIES: this is a HEURISTIC recognition from TOKENIZED Apex source \u2014 NOT a compiler AST \u2014 bound to the DML call site where the SYSTEM_MODE token appears; it names the DECLARED system-context bypass, NOT a proof that the bypass is unsafe or unintended (a deliberate SYSTEM_MODE write may be entirely right), and record-level SHARING is a SEPARATE access plane this does not read. It marks a write to REVIEW, not a proven authorization defect.",
|
|
55589
|
+
docs: [
|
|
55590
|
+
{ label: "Apex Developer Guide \u2014 Enforce User-Mode Database Operations (AccessLevel)", url: "https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_perms_enforcing.htm" }
|
|
55591
|
+
]
|
|
55592
|
+
},
|
|
55593
|
+
"concept:dataraptor-field-security-unenforced": {
|
|
55594
|
+
id: "concept:dataraptor-field-security-unenforced",
|
|
55595
|
+
kind: "access-mechanism",
|
|
55596
|
+
label: "A DataRaptor with Check Field Level Security off reads or writes SObject fields without enforcing the running user's FLS",
|
|
55597
|
+
summary: "A DataRaptor (an OmniStudio OmniDataTransform) whose 'Check Field Level Security' toggle is OFF reads and writes SObject fields WITHOUT enforcing the running user's field-level security: the transform can load a field the user has no Read access to into an output payload, or overwrite a field the user has no Edit access to, because FLS is not consulted on the fields it touches. This is an OVER-PERMISSIVE data-access surface \u2014 an FLS-bypass shape that widens what data can flow through the transform beyond what the invoking user could reach through a normal UI or FLS-respecting API. HONEST BOUNDARY \u2014 this is a DECLARED configuration shape read from the transform's own toggle, NOT a proven exploit: it does NOT establish that any specific field is actually over-exposed (that depends on which fields the transform maps and each running user's actual FLS), NOT who invokes the transform or in what user context, and NOT whether a compensating guard (a wrapping Apex class enforcing security, a restricted entry point, or a guest-user profile with no access) neutralizes the gap at runtime. It names the field-security-unenforced structural signal, not a confirmed data leak.",
|
|
55598
|
+
severity: "high",
|
|
55599
|
+
docs: [
|
|
55600
|
+
{ label: "Salesforce Help \u2014 DataRaptor Loads and Field-Level Security", url: "https://help.salesforce.com/s/articleView?id=sf.os_dataraptor_loads.htm" },
|
|
55601
|
+
{ label: "Salesforce Help \u2014 Enforce Field-Level Security in DataRaptors", url: "https://help.salesforce.com/s/articleView?id=sf.os_secure_dataraptors.htm" }
|
|
55602
|
+
]
|
|
55603
|
+
},
|
|
55604
|
+
"concept:field-classic-encrypted-text": {
|
|
55605
|
+
id: "concept:field-classic-encrypted-text",
|
|
55606
|
+
kind: "field-provenance",
|
|
55607
|
+
label: "A classic Encrypted Text field is masked and cannot be filtered, sorted, or used as an external id",
|
|
55608
|
+
summary: `A CLASSIC ENCRYPTED TEXT field stores its value encrypted at rest and MASKS it in the UI, API, and reports for any user who lacks the "View Encrypted Data" permission \u2014 most users see only asterisks. Its type class is NOT filterable, sortable, or groupable: it cannot appear in a SOQL WHERE / ORDER BY / GROUP BY, a list-view or report filter, and it cannot be an external id, a unique field, a default-value source, or a formula input. This is the DISTINCT LEGACY protection (a per-field type), NOT Shield Platform Encryption (a separate field-level encryption strategy not observable from offline metadata). Grounded from the field's own declared data type; it names the masking and restriction POSTURE that follow from the type, NOT which specific users can currently view the value (a permission-assignment question) and NOT whether the field actually holds sensitive data.`,
|
|
55609
|
+
docs: [
|
|
55610
|
+
{ label: "Salesforce Help \u2014 Encrypted Custom Fields (Classic Encryption)", url: "https://help.salesforce.com/s/articleView?id=sf.fields_about_encrypted_fields.htm" }
|
|
55611
|
+
]
|
|
55612
|
+
},
|
|
55613
|
+
"concept:field-autonumber-system-assigned-readonly": {
|
|
55614
|
+
id: "concept:field-autonumber-system-assigned-readonly",
|
|
55615
|
+
kind: "field-provenance",
|
|
55616
|
+
label: "An Auto Number field is system-assigned and read-only on every write path",
|
|
55617
|
+
summary: "An AUTO NUMBER field is SYSTEM-ASSIGNED: Salesforce generates its value from a display format and a sequence when the record is inserted, so it is READ-ONLY on every write path \u2014 the UI, API, Apex, Flow, and data imports cannot set or change it (attempts are ignored). Because it is assigned DURING insert, it is null / unavailable in a before-save context (a before-insert trigger or before-save flow cannot read the final value). It is stored and displayed as a formatted STRING, not a number, so it cannot be used in arithmetic; and changing the display format renumbers only NEW records \u2014 existing values are not rewritten, so sequence gaps from failed inserts or rollbacks persist. Grounded from the field's own declared data type; it names the system-assigned, read-only provenance, NOT the current sequence value or next number (record data) and NOT whether any specific integration attempts to write it.",
|
|
55618
|
+
docs: [
|
|
55619
|
+
{ label: "Salesforce Help \u2014 Auto-Number Fields", url: "https://help.salesforce.com/s/articleView?id=sf.custom_field_types.htm" }
|
|
55620
|
+
]
|
|
55621
|
+
},
|
|
55622
|
+
"concept:field-multiselect-picklist-storage-semantics": {
|
|
55623
|
+
id: "concept:field-multiselect-picklist-storage-semantics",
|
|
55624
|
+
kind: "field-provenance",
|
|
55625
|
+
label: "A multi-select picklist stores selections as one delimited string with special query semantics",
|
|
55626
|
+
summary: "A MULTI-SELECT PICKLIST stores every selected value in a SINGLE semicolon-delimited string, not as separate rows \u2014 so it behaves unlike a normal picklist. In SOQL and reports it must be filtered with INCLUDES / EXCLUDES rather than = / != / IN (an equality filter matches only the exact full delimited combination), and formulas must test membership with INCLUDES(); sorting or grouping orders by the raw delimited string, not by individual values. It CANNOT serve as the controlling field of a dependent picklist, and it cannot be an external id or unique field. Grounded from the field's own declared data type; it names the storage and query SEMANTICS that follow from the type, NOT which values a given record holds and NOT whether any specific query currently filters it incorrectly.",
|
|
55627
|
+
docs: [
|
|
55628
|
+
{ label: "Salesforce Help \u2014 Multi-Select Picklists", url: "https://help.salesforce.com/s/articleView?id=sf.fields_about_multiselect_picklists.htm" }
|
|
55629
|
+
]
|
|
55630
|
+
},
|
|
55631
|
+
"concept:permission-set-license-scoped": {
|
|
55632
|
+
id: "concept:permission-set-license-scoped",
|
|
55633
|
+
kind: "access-mechanism",
|
|
55634
|
+
label: "A license-scoped permission set can only be assigned to users who hold that user license",
|
|
55635
|
+
summary: "A PERMISSION SET whose `license` element is SET is bound to a specific USER LICENSE, and Salesforce only lets it be assigned to users who ALREADY HOLD that license \u2014 so every grant it carries (object CRUD, field-level security, Apex class access, system permissions) is UNREACHABLE by any user lacking the license, narrowing the ELIGIBLE POPULATION before any individual grant even applies. A license-scoped permission set therefore cannot widen access for a user on the wrong license no matter how strong its grants look, whereas an UNSCOPED permission set (no `license` element) carries no such assignability constraint and can be assigned to any user. This is grounded from the permission set's own declared `license` binding; it names the ASSIGNABILITY CONSTRAINT of the container, NOT whether any specific user holds that license or is actually assigned this permission set (an assignment question the offline vault cannot answer \u2014 the live plane resolves who holds a license or a permission set), and NOT the strength or correctness of the grants inside it. Only users on the bound license can ever receive its grants.",
|
|
55636
|
+
docs: [
|
|
55637
|
+
{ label: "Salesforce Help \u2014 Permission Set Licenses", url: "https://help.salesforce.com/s/articleView?id=sf.users_permissionset_licenses.htm" },
|
|
55638
|
+
{ label: "Salesforce Help \u2014 Permission Sets", url: "https://help.salesforce.com/s/articleView?id=sf.perm_sets_overview.htm" }
|
|
55639
|
+
]
|
|
55640
|
+
},
|
|
55641
|
+
"concept:session-based-permission-set-dormant": {
|
|
55642
|
+
id: "concept:session-based-permission-set-dormant",
|
|
55643
|
+
kind: "access-mechanism",
|
|
55644
|
+
label: "A session-based permission set grants nothing passively \u2014 every grant is dormant until session activation",
|
|
55645
|
+
summary: "A SESSION-BASED permission set \u2014 one whose activation-required flag is TRUE \u2014 grants NONE of its permissions passively. Every grant it confers (object CRUD, field-level security, View All / Modify All, Apex-class access, and custom-permission grants) stays DORMANT until the permission set is ACTIVATED for the current session, via Auth.SessionManagement or a launching flow, so all of them are conditional-on-activation rather than standing. When reasoning about what a holder of this set can do at rest, its grants must be treated as INACTIVE by default: assignment alone does not confer the access. This is grounded from the set's own always-present activation-required boolean; it names the activation-gate STRUCTURAL fact, NOT whether any given session actually activates the set (session activation is a runtime event the offline vault cannot observe), NOT which users hold the set, and NOT what the individual grants are when it IS active. Only the activation-gate posture is asserted here.",
|
|
55646
|
+
docs: [
|
|
55647
|
+
{ label: "Salesforce Help \u2014 Session-based Permission Sets", url: "https://help.salesforce.com/s/articleView?id=sf.perm_sets_session_map.htm" },
|
|
55648
|
+
{ label: "Apex Developer Guide \u2014 Auth.SessionManagement Class", url: "https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_class_Auth_SessionManagement.htm" }
|
|
55649
|
+
]
|
|
55650
|
+
},
|
|
55651
|
+
"concept:field-restricted-global-value-set": {
|
|
55652
|
+
id: "concept:field-restricted-global-value-set",
|
|
55653
|
+
kind: "field-provenance",
|
|
55654
|
+
label: "Picklist bound to a restricted global value set",
|
|
55655
|
+
summary: "A picklist field can draw its values from a shared global value set instead of an inline list. When that global value set is marked restricted, the field becomes a closed vocabulary: only the values defined in the shared set are valid, admins cannot add ad-hoc values on the field, and an integration or API write of a value outside the set is rejected. Changing the field's allowed values means editing the shared set, which ripples to every other field bound to it. The offline snapshot grounds this from the field's declared usesValueSet edge to a global value set whose metadata carries restricted=true. It does NOT prove runtime enforcement, does NOT assert that no existing record already holds an out-of-set value (a live, record-level question), and when the restricted flag is absent it does NOT fire \u2014 a global-value-set-backed picklist may still constrain values without the flag being declared in metadata.",
|
|
55656
|
+
docs: [
|
|
55657
|
+
{ label: "Salesforce Help \u2014 Create Global Picklist Value Sets", url: "https://help.salesforce.com/s/articleView?id=sf.fields_creating_global_picklist.htm" }
|
|
55658
|
+
]
|
|
55659
|
+
},
|
|
55660
|
+
"concept:field-picklist-has-retired-values": {
|
|
55661
|
+
id: "concept:field-picklist-has-retired-values",
|
|
55662
|
+
kind: "field-provenance",
|
|
55663
|
+
label: "A picklist retaining an inactive value keeps old data readable but no longer selectable",
|
|
55664
|
+
summary: "A PICKLIST field retains INACTIVE (retired) values in its OWN local value set: when an admin deactivates a value, Salesforce does NOT delete it \u2014 it stays in the field definition, so existing records that already hold it keep displaying and reporting it (the value remains readable), while the value is removed from the picker and can NO LONGER be newly selected in the UI. A retired value is therefore a data-hygiene and migration signal \u2014 it usually means old data still carries a value the org has moved away from. This is grounded from the field's OWN declared value-set entries (each value's active flag); it names the DECLARED presence of a retired value, NOT whether any record currently holds it (a record-level count the offline vault cannot answer), NOT GlobalValueSet-backed picklists (whose values live on the shared value set, not the field, and are not evaluated here), and NOT whether any report, formula, default value, or automation still references the retired value.",
|
|
55665
|
+
docs: [
|
|
55666
|
+
{ label: "Salesforce Help \u2014 Manage Picklist Values", url: "https://help.salesforce.com/s/articleView?id=sf.fields_managing_picklists.htm" }
|
|
55667
|
+
]
|
|
55668
|
+
},
|
|
55669
|
+
"concept:approval-process-inactive-dead": {
|
|
55670
|
+
id: "concept:approval-process-inactive-dead",
|
|
55671
|
+
kind: "firing-condition",
|
|
55672
|
+
label: "An inactive approval process never routes a record for approval and is dead automation",
|
|
55673
|
+
summary: 'An APPROVAL PROCESS whose `active` flag is FALSE is DEAD approval automation: Salesforce lets NO record be submitted into it for approval, never evaluates its entry criteria, and never runs any of its initial-submission actions, per-step approver routing, final-approval / final-rejection actions, or record locks until an admin re-activates it. It must be EXCLUDED from "what happens when this record is submitted for approval" reasoning, from record-lock and read-only-freeze analysis (its finalApprovalRecordLock / finalRejectionRecordLock never take effect while inactive), and from automation-impact counts: counting a deactivated process overstates the automation load, while assuming its field-update actions or locks still run would misattribute a value change or a read-only freeze. This is grounded from the process\'s own always-present `active` boolean; it names the non-running STRUCTURAL fact, NOT whether a Flow-based (record-triggered) approval has replaced it (migration lineage is org-specific) and NOT whether the process WOULD admit a given record if activated (entry criteria remain unevaluated offline). Only active approval processes belong in submit-for-approval and automation-impact surfaces.',
|
|
55674
|
+
docs: [
|
|
55675
|
+
{ label: "Salesforce Help \u2014 Considerations for Approvals", url: "https://help.salesforce.com/s/articleView?id=sf.approvals_considerations.htm" }
|
|
55676
|
+
]
|
|
55677
|
+
},
|
|
55678
|
+
"concept:escalation-rule-time-deferred": {
|
|
55679
|
+
id: "concept:escalation-rule-time-deferred",
|
|
55680
|
+
kind: "async-boundary",
|
|
55681
|
+
label: "An active escalation rule's actions are queued and fire later in a separate context",
|
|
55682
|
+
summary: "An ACTIVE escalation rule does NOT run its escalation actions during the record save. When a record (typically a Case) has aged past the rule entry's declared minute offset (`minutesToEscalation`) without meeting the rule's exit criteria, Salesforce's background escalation process fires the queued actions \u2014 reassigning ownership to a queue or user and/or sending a notification email \u2014 LATER, in a SEPARATE context decoupled from the save that first matched the record. So the effect is DEFERRED: the reassignment/notification lands minutes to hours after the triggering edit, its writes are not part of that save and cannot roll it back, and Salesforce re-checks the record at escalation time and silently drops the queued escalation if the record no longer qualifies (for example it was closed or edited to stop matching). Configured business hours on the entry can shift the fire time further. This names the deferred-action STRUCTURE from the rule's own active state; it does NOT evaluate the `minutesToEscalation` offset (which lives on the rule's per-action reference/notification edges, not on the rule node), assert WHEN the escalation fires, whether the record still qualifies when the timer elapses, or whether the action succeeds.",
|
|
55683
|
+
docs: [
|
|
55684
|
+
{ label: "Salesforce Help \u2014 Set Up Escalation Rules", url: "https://help.salesforce.com/s/articleView?id=sf.customize_escrules.htm" }
|
|
55685
|
+
]
|
|
55686
|
+
},
|
|
55687
|
+
"concept:auto-response-rule-first-match-starvation": {
|
|
55688
|
+
id: "concept:auto-response-rule-first-match-starvation",
|
|
55689
|
+
kind: "automation-collision",
|
|
55690
|
+
label: "Auto-response rule catch-all entry starves later specific entries",
|
|
55691
|
+
summary: 'Auto-response rules evaluate their rule entries top-down in XML order \u2014 the first entry whose criteria match wins and sends its email template, and later entries are never considered. A catch-all entry with NO criteria and NO formula filter (zero criteria items, no formula) matches EVERY record, so if it appears before more specific entries those later entries are structurally unreachable \u2014 a common cause of "why did this record get the wrong auto-response email?" confusion. The offline claim is grounded from the AutoResponseRule `sendsEmail` edges carrying `entryIndex` (evaluation order), `criteriaItemCount`, and `hasFormula`: a broad entry is one with `criteriaItemCount === 0` and `hasFormula === false` that precedes at least one later entry with criteria or a formula. HONEST BOUNDARIES: this names the STRUCTURAL ordering risk from metadata, NOT whether a specific record would match a specific entry at runtime (live criteria evaluation is out of scope). Only ONE auto-response rule per object is active at a time, so this reasons about entry ordering WITHIN a rule, not across rules. A `sendsEmail` edge whose target email template was not retrieved does not resolve in the slice, and the rule fails closed \u2014 yielding nothing rather than guessing \u2014 when `entryIndex` or the criteria metadata a counted edge needs is absent.',
|
|
55692
|
+
severity: "medium"
|
|
55693
|
+
},
|
|
55694
|
+
"concept:record-type-business-process-binding": {
|
|
55695
|
+
id: "concept:record-type-business-process-binding",
|
|
55696
|
+
kind: "access-mechanism",
|
|
55697
|
+
label: "A record type bound to a business process scopes the master status picklist to that process''s stages",
|
|
55698
|
+
summary: "A RECORD TYPE that declares a BUSINESS PROCESS binds records of that type to a specific ordered subset of the object's master status picklist \u2014 the Stage, Status, or Solution-status values that process defines \u2014 so records created with this record type are scoped to the stages the bound process exposes, NOT the object's full set of master-picklist values. This scopes what a user or an automation may set the status / stage field to on such a record: a Flow, an Apex assignment, an API create, or a data import that sets a stage value the bound process does not include can be rejected. This is grounded from the record type's own declared businessProcess reference; it names the DECLARED binding (that this record type IS scoped to a business process), NOT the specific stage values that process exposes (those live on the BusinessProcess metadata and are org-specific), NOT which records currently carry this record type or their current stage (record-level runtime state the offline vault does not hold), and NOT whether the bound business process is itself active. A record type WITHOUT a business process uses the object's full master picklist and has no such scoping. Only a record type that declares a business process contributes this constraint.",
|
|
55699
|
+
docs: [
|
|
55700
|
+
{ label: "Salesforce Help \u2014 Create Business Processes", url: "https://help.salesforce.com/s/articleView?id=sf.customize_busprocess.htm" }
|
|
55701
|
+
]
|
|
55702
|
+
},
|
|
55703
|
+
"concept:apex-dynamic-reflective-surface": {
|
|
55704
|
+
id: "concept:apex-dynamic-reflective-surface",
|
|
55705
|
+
kind: "code-quality-defect",
|
|
55706
|
+
label: "A dynamic or reflective Apex construct that static dependency analysis cannot see",
|
|
55707
|
+
summary: "A component uses DYNAMIC or REFLECTIVE Apex \u2014 object, field, or type references assembled at RUNTIME rather than written as static literals: a dynamic query built as a string (the dynamic-query API, Database.query), a runtime schema describe (Schema.getGlobalDescribe), reflective type instantiation by name (Type.forName), or untyped deserialization (JSON.deserializeUntyped). These constructs are INVISIBLE to static dependency analysis: the scanner resolves reads, writes, calls, and references from tokens it can see in the source, so a query, field, or class named by a runtime-built string is never captured as an edge. The honest consequence is a COMPLETENESS gap, not a proven defect \u2014 impact analysis, usage / where-used results, and dead-code findings for this class MAY BE INCOMPLETE, because a real dependency can be hidden behind the runtime construction. HONEST BOUNDARIES: this is a HEURISTIC token recognition, NOT a compiler AST \u2014 it can FLAG a dynamic construct whose reference is actually a safe constant, and can MISS one assembled in a way the tokenizer does not match. It does NOT prove the class is buggy, does NOT identify WHICH objects or fields the dynamic code touches, and does NOT assert any specific hidden dependency exists; it flags the class as one whose static analysis is blind in spots and warrants reading the source to confirm.",
|
|
55708
|
+
docs: [
|
|
55709
|
+
{ label: "Apex Developer Guide \u2014 Dynamic SOQL", url: "https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_dynamic_soql.htm" }
|
|
55710
|
+
]
|
|
55711
|
+
},
|
|
55712
|
+
"concept:named-credential-merge-fields-injectable": {
|
|
55713
|
+
id: "concept:named-credential-merge-fields-injectable",
|
|
55714
|
+
kind: "external-api-surface",
|
|
55715
|
+
label: "A named credential that allows merge fields in its HTTP header or body is an outbound injection surface",
|
|
55716
|
+
summary: "By DEFAULT Salesforce BLOCKS merge-field syntax in the HTTP header and body of a callout that authenticates through a named credential \u2014 a deliberate guard against injecting caller-influenced values into an authenticated outbound request. Setting `allowMergeFieldsInHeader` or `allowMergeFieldsInBody` to true LIFTS that guard for this credential: Apex may then substitute merge fields (including values drawn from record or user data) into the outbound HTTP header or body of any callout that uses it. That makes the credential an outbound INJECTION SURFACE \u2014 if a substituted value is attacker-influenced it can alter the request's headers or payload (header injection, request smuggling, or forging fields the upstream API trusts). This is grounded from the credential's own declared `allowMergeFieldsInHeader` / `allowMergeFieldsInBody` metadata; it names the DECLARED configuration that ENABLES substitution, not a proven exploit. HONEST BOUNDARIES \u2014 it does NOT prove: (a) that any Apex callout actually uses this credential (callers are a separate code-level question the offline vault may not resolve); (b) that any merge field carries UNTRUSTED input \u2014 the substituted values may all be static or trusted, in which case the setting is harmless and often intentional; or (c) that an injection actually occurs at runtime. It names the surface ENABLED by configuration, never a vulnerability. The header flag and the body flag are read independently, so a claim fires per flag that is set.",
|
|
55717
|
+
docs: [
|
|
55718
|
+
{ label: "Metadata API Developer Guide \u2014 NamedCredential (allowMergeFieldsInHeader / allowMergeFieldsInBody)", url: "https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_namedcredential.htm" }
|
|
55719
|
+
]
|
|
55720
|
+
},
|
|
55721
|
+
"concept:connected-app-saml-sso-federation": {
|
|
55722
|
+
id: "concept:connected-app-saml-sso-federation",
|
|
55723
|
+
kind: "access-mechanism",
|
|
55724
|
+
label: "A connected app carrying a SAML config is a SAML SSO federation target with Salesforce as the identity provider",
|
|
55725
|
+
summary: "A connected app that carries a `<samlConfig>` block is a SAML SSO federation target: it declares Salesforce as the SAML Identity Provider (IdP) and the app as an external Service Provider (SP) that Salesforce will mint SIGNED SAML assertions for, asserting an authenticated user's identity so they can single-sign-on into that external relying party. The app's `authProtocol` reads `saml` (SAML only) or `both` (SAML alongside an OAuth client), and the surfaced trust boundary \u2014 the Assertion Consumer Service (ACS) URL the assertion is posted to, the SP entity/audience it is scoped to, the expected issuer, and the subject / NameID format \u2014 defines WHO Salesforce federates identities out to. So it is an identity and trust surface worth reviewing: an outbound authentication relationship that hands a user's asserted identity to a third party. This is grounded from the app's own DECLARED SAML metadata; it names the DECLARED federation configuration, NOT a proven active login flow. HONEST BOUNDARIES: the presence of the config is a STATIC shape, not evidence that anyone authenticates through it, that the signing certificate / trust is currently valid (the key material is deliberately never vaulted), or that the relying party is live; WHO may launch or use the app is a separate access layer (profile / permission-set assignment) the config does not encode; and a SAML federation may be entirely intentional for a trusted downstream app.",
|
|
55726
|
+
docs: [
|
|
55727
|
+
{ label: "Salesforce Help \u2014 Enable SAML SSO for Connected Apps (Salesforce as Identity Provider)", url: "https://help.salesforce.com/s/articleView?id=sf.connected_app_create_web_app_sso.htm" }
|
|
55728
|
+
]
|
|
55729
|
+
},
|
|
55730
|
+
"concept:apex-fake-assertion-test": {
|
|
55731
|
+
id: "concept:apex-fake-assertion-test",
|
|
55732
|
+
kind: "test-quality",
|
|
55733
|
+
label: "A test class asserts a tautology that passes regardless of behavior, so it verifies nothing",
|
|
55734
|
+
summary: "An Apex class annotated @IsTest contains a TAUTOLOGICAL or self-referential assertion \u2014 a System.assert(true, ...), a System.assertEquals(x, x) on the same expression, or a System.assertEquals(literal, sameLiteral) \u2014 an assertion whose two operands are identical (or always true) so it PASSES no matter how the code under test behaves. Such an assertion verifies nothing: it can never fail because a computed value was wrong, only if the code under test throws an uncaught exception, yet it still EXECUTES the code under test and so counts toward the org's Apex code-coverage percentage. It therefore inflates the coverage number while providing no real regression protection, and it can mask a genuine defect behind a green run. HONEST BOUNDARY: this is HEURISTIC recognition from TOKENIZED Apex source \u2014 NOT a compiler AST. It flags the tautological call-site itself; it does NOT prove the whole class is worthless, because the same class may carry other, meaningful assertions alongside the fake one, and it can MISS a value-free assertion assembled through a variable or a shared helper. It names a test-quality review candidate, not proven coverage fraud. Read the test before concluding it verifies nothing.",
|
|
55735
|
+
docs: [
|
|
55736
|
+
{ label: "Apex Developer Guide \u2014 Testing Best Practices", url: "https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_best_practices.htm" }
|
|
55737
|
+
]
|
|
55738
|
+
},
|
|
55739
|
+
"concept:entitlement-process-inactive": {
|
|
55740
|
+
id: "concept:entitlement-process-inactive",
|
|
55741
|
+
kind: "firing-condition",
|
|
55742
|
+
label: "An inactive entitlement process never starts its milestone SLA timers and is dead SLA automation",
|
|
55743
|
+
summary: 'An ENTITLEMENT PROCESS whose `active` flag is FALSE is DEAD SLA automation: Salesforce never applies it to a case and never starts any of its milestone timers \u2014 no SLA countdown begins, no business-hours clock runs, and no milestone-driven escalation can fire from this version until an admin re-activates it. It must be EXCLUDED from SLA / entitlement reasoning and from "what milestones apply on save" impact counts; treating a deactivated process as a live SLA guard would cry wolf about timers that cannot start, while assuming its milestones still run would falsely imply cases are being tracked. This is grounded from the process\'s own `active` flag; it names the non-running STRUCTURAL fact, NOT whether any specific case is currently on-track or breached (that is live per-record timer data this offline vault does not hold), NOT whether this version WOULD apply if activated (entry criteria remain unevaluated offline), and NOT whether another active version of the same process exists (version lineage is org-specific). Only active entitlement processes belong in SLA and entitlement-impact surfaces.',
|
|
55744
|
+
docs: [
|
|
55745
|
+
{ label: "Metadata API Developer Guide \u2014 EntitlementProcess", url: "https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_entitlementprocess.htm" }
|
|
55746
|
+
]
|
|
55747
|
+
},
|
|
55748
|
+
"concept:omnistudio-inactive-component-version": {
|
|
55749
|
+
id: "concept:omnistudio-inactive-component-version",
|
|
55750
|
+
kind: "firing-condition",
|
|
55751
|
+
label: "An inactive OmniStudio component version does not execute at runtime and must be excluded from what-actually-runs analysis",
|
|
55752
|
+
summary: "An OmniStudio component version \u2014 an OmniScript, Integration Procedure, or FlexCard \u2014 whose `isActive` flag is FALSE is a SAVED-BUT-DORMANT version: Salesforce serves and dispatches only the ACTIVE version of an OmniStudio component, so an inactive version does not execute at runtime \u2014 it is not rendered, invoked as an action, or embedded on a page until an admin activates it. It must be EXCLUDED from runtime-reachability, invocation-impact, and 'what actually runs' reasoning about OmniStudio; treating a deactivated version as live would overstate the runtime surface, while assuming it still runs would misattribute behavior to a dormant draft. This is grounded from the component's own always-present `isActive` boolean; it names the non-running STRUCTURAL fact, NOT whether ANOTHER version of the same bundle is active and serving in its place (version lineage is org-specific and not resolved offline), NOT whether anything still references this version by name, NOT what the version WOULD do if activated, and NOT why it was deactivated. Only active OmniStudio component versions belong in runtime-execution surfaces.",
|
|
55753
|
+
docs: [
|
|
55754
|
+
{ label: "Salesforce Help \u2014 Activate an OmniScript", url: "https://help.salesforce.com/s/articleView?id=sf.os_activate_an_omniscript.htm" }
|
|
55755
|
+
]
|
|
55756
|
+
},
|
|
55757
|
+
"concept:required-field-absent-from-all-layouts": {
|
|
55758
|
+
id: "concept:required-field-absent-from-all-layouts",
|
|
55759
|
+
kind: "field-provenance",
|
|
55760
|
+
label: "A universally required field placed on no page layout has no declared UI data-entry surface",
|
|
55761
|
+
summary: "A field that is UNIVERSALLY REQUIRED at the field-definition level (every record must carry a value) but is placed on NO page layout has no declared UI data-entry surface: a user creating or editing a record through a layout that omits the field sees no input for it, so its required value must be supplied some other way \u2014 a default value, a before-save automation, an Apex / API / data-import insert that sets it, or the platform's own runtime rendering of universally-required fields on the create / edit form. This is grounded from the field's own declared required flag together with the ABSENCE of any layout that places the field in a field-bearing region (the detail body, the Highlights Panel, or the mini layout); it is an ABSENCE claim, so under incomplete Layout coverage the on-no-layout conclusion is NOT asserted (downgraded to not-checked). HONEST BOUNDARIES: it does NOT prove any specific save fails \u2014 a default, automation, or API path may supply the value, and the platform itself forces universally-required fields onto edit forms \u2014 and it does NOT see Lightning DYNAMIC FORM (FlexiPage) field placement, which lives OUTSIDE classic page-layout metadata, so a field surfaced only through a Dynamic Form still matches this shape. It names the DECLARED layout-placement gap, not a proven runtime data-entry failure.",
|
|
55762
|
+
docs: [
|
|
55763
|
+
{ label: "Metadata API Developer Guide \u2014 Layout", url: "https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_layouts.htm" }
|
|
55764
|
+
]
|
|
55765
|
+
},
|
|
55766
|
+
"concept:dataraptor-errors-ignored": {
|
|
55767
|
+
id: "concept:dataraptor-errors-ignored",
|
|
55768
|
+
kind: "code-quality-defect",
|
|
55769
|
+
label: "A DataRaptor with 'Ignore Error' on swallows per-record failures and continues instead of surfacing them",
|
|
55770
|
+
summary: "A DataRaptor (an OmniStudio OmniDataTransform) whose 'Ignore Error' toggle is ON does NOT halt or raise when an individual record operation inside the transform fails: the failing item is skipped and the transform CONTINUES, returning a success-shaped result to its caller even though some reads or writes did not complete. This is an ERROR-SWALLOWING reliability shape \u2014 a failure that would normally abort the operation is suppressed, so a partial or silent data-integrity gap (records not written, values not loaded) can pass undetected unless the caller explicitly inspects the returned error collection. It is DISTINCT from the 'Rollback on Error' toggle (a separate setting that controls whether already-completed writes are undone on failure); ignoring errors while not rolling back can leave partially applied data. It is also DISTINCT from an Apex swallowed-exception pattern \u2014 this is a DECLARED OmniStudio configuration flag, not a heuristic read of catch-block source. HONEST BOUNDARY \u2014 this is a declared configuration shape read from the transform's own toggle, NOT a proven failure: it does NOT establish that any record actually fails at runtime, NOT that data was actually lost or left partial, and NOT whether the invoking OmniScript, Integration Procedure, or Apex caller checks the error output and compensates. It names the error-suppression structural signal, not a confirmed data-loss incident.",
|
|
55771
|
+
docs: [
|
|
55772
|
+
{ label: "Salesforce Help \u2014 DataRaptor Loads", url: "https://help.salesforce.com/s/articleView?id=sf.os_dataraptor_loads.htm" },
|
|
55773
|
+
{ label: "Salesforce Help \u2014 Design DataRaptor Loads", url: "https://help.salesforce.com/s/articleView?id=sf.os_design_dataraptor_loads.htm" }
|
|
55774
|
+
]
|
|
55775
|
+
},
|
|
55776
|
+
"concept:object-deployment-status-in-development": {
|
|
55777
|
+
id: "concept:object-deployment-status-in-development",
|
|
55778
|
+
kind: "access-mechanism",
|
|
55779
|
+
label: "An In Development object is hidden from every user who lacks Customize Application",
|
|
55780
|
+
summary: `A CUSTOM OBJECT whose deployment status is IN DEVELOPMENT (not Deployed) is hidden from every user who lacks the "Customize Application" administrative permission: its tab, list views, and fields do not appear in the app for ordinary users, and it is effectively unusable in production until an admin flips it to Deployed. It must be EXCLUDED from "which users can work with this object" reasoning about non-admin users, because assuming an In Development object is generally reachable would overstate who can see or edit its records. This is grounded from the object's own declared deployment-status value; it names the DECLARED visibility posture, NOT whether any specific user holds Customize Application (an assignment question the offline vault cannot answer), NOT whether the object was intentionally left in development, and NOT record-level access once it IS deployed. Only Deployed objects belong in ordinary-user reachability surfaces.`,
|
|
55781
|
+
docs: [
|
|
55782
|
+
{ label: "Salesforce Help \u2014 Object Deployment Status (In Development vs Deployed)", url: "https://help.salesforce.com/s/articleView?id=sf.dev_object_deployment.htm" }
|
|
55783
|
+
]
|
|
55784
|
+
},
|
|
55785
|
+
"concept:object-autonumber-name-field": {
|
|
55786
|
+
id: "concept:object-autonumber-name-field",
|
|
55787
|
+
kind: "field-provenance",
|
|
55788
|
+
label: "A custom object with an Auto Number Name field has system-assigned, read-only record names",
|
|
55789
|
+
summary: "A CUSTOM OBJECT whose NAME field is an AUTO NUMBER gives every record a SYSTEM-ASSIGNED name generated from a display format and a sequence at insert \u2014 so the record Name is READ-ONLY on every write path (the UI, API, Apex, Flow, and data imports cannot set or change it) and is unavailable in a before-insert context (it is assigned during insert). The name is stored and displayed as a formatted STRING, not a number, so it cannot be used in arithmetic; changing the display format renumbers only NEW records, so existing names and any sequence gaps from failed inserts persist. This is grounded from the object's own declared name-field type; it names the record-name PROVENANCE (system-assigned, read-only), it is DISTINCT from a custom field of type Auto Number (here it is the record NAME itself that is auto-assigned), and it does NOT name the current or next sequence value (record-level data the offline vault cannot answer) or prove any integration attempts to set the name.",
|
|
55790
|
+
docs: [
|
|
55791
|
+
{ label: "Salesforce Help \u2014 Auto-Number Fields", url: "https://help.salesforce.com/s/articleView?id=sf.custom_field_types.htm" }
|
|
55792
|
+
]
|
|
55793
|
+
},
|
|
55794
|
+
"concept:global-value-set-has-inactive-value": {
|
|
55795
|
+
id: "concept:global-value-set-has-inactive-value",
|
|
55796
|
+
kind: "field-provenance",
|
|
55797
|
+
label: "A shared global value set retaining a deactivated value retires it across every bound field at once",
|
|
55798
|
+
summary: "A GLOBAL (shared) value set retains INACTIVE (deactivated) values in its own definition rather than deleting them. Because the set is SHARED, deactivating a value removes it from the picker on EVERY picklist field bound to the set at once \u2014 it is NO LONGER SELECTABLE for new records anywhere \u2014 while existing records that already hold it keep displaying and reporting it (the value stays readable). Reactivating or removing the value ripples to every field bound to the set, so a retired value here is an org-wide data-hygiene and migration signal, not a per-field one. This is grounded from the shared value set's OWN declared entries (each value's active flag); it names the DECLARED presence of a retired value, NOT whether any record currently holds it (a record-level count the offline vault cannot answer) and NOT which specific fields bind this set (that is the fields' own usesValueSet edges, resolved separately).",
|
|
55799
|
+
docs: [
|
|
55800
|
+
{ label: "Salesforce Help \u2014 Manage Global Picklist Value Sets", url: "https://help.salesforce.com/s/articleView?id=sf.fields_creating_global_picklist.htm" }
|
|
55801
|
+
]
|
|
55802
|
+
},
|
|
55803
|
+
"concept:standard-value-set-has-inactive-value": {
|
|
55804
|
+
id: "concept:standard-value-set-has-inactive-value",
|
|
55805
|
+
kind: "field-provenance",
|
|
55806
|
+
label: "A standard value set retaining a deactivated value retires it org-wide on the standard field that uses it",
|
|
55807
|
+
summary: "A STANDARD value set \u2014 the org-wide value list behind a standard picklist such as Industry, Lead Source, or Opportunity Stage \u2014 retains INACTIVE (deactivated) values rather than deleting them. A deactivated standard value is NO LONGER SELECTABLE for new records on the standard field(s) that draw from the set, yet existing records that already hold it keep displaying and reporting it (the value stays readable). This is grounded from the standard value set's OWN declared entries (each value's active flag); it names the DECLARED presence of a retired value. A standard field's binding to its value set is IMPLICIT \u2014 Salesforce wires it internally by the field's type, with no declared metadata pointer \u2014 so this does NOT name which specific fields are affected (there is no edge to follow), does NOT prove any record currently holds the value (a record-level count the offline vault cannot answer), and is DISTINCT from a custom field's own local retired value and from a custom shared global value set.",
|
|
55808
|
+
docs: [
|
|
55809
|
+
{ label: "Salesforce Help \u2014 Update Picklists with a Custom or Standard Value Set", url: "https://help.salesforce.com/s/articleView?id=sf.fields_managing_picklists.htm" }
|
|
55810
|
+
]
|
|
55811
|
+
},
|
|
55812
|
+
"concept:apex-test-hardcoded-sandbox-data": {
|
|
55813
|
+
id: "concept:apex-test-hardcoded-sandbox-data",
|
|
55814
|
+
kind: "test-quality",
|
|
55815
|
+
label: "A test class hardcodes sandbox-specific literals, so it will not run against production or another org",
|
|
55816
|
+
summary: "An Apex class annotated @IsTest contains a HARDCODED SANDBOX-SPECIFIC literal \u2014 a username or URL carrying a sandbox marker such as a `.sandbox` / `.dev` / `.uat` / `.fullcopy` suffix, a `--sandbox` My Domain segment, or a `sandbox.salesforce.com` host. Apex tests are expected to be SELF-CONTAINED and org-agnostic: they should build their own fixtures (a @TestSetup method or a test-data factory) and read environment-specific values from configuration, so the same test passes in every org it is deployed to. A test that embeds a value tied to one specific sandbox breaks that contract \u2014 it may pass in the sandbox it was written against and then FAIL, or silently exercise the wrong data, when the code is promoted to production or run in a different sandbox, and because it is a test the failure surfaces only at deploy or run time. Externalize the value into a Custom Metadata Type or Custom Setting record, or generate it in @TestSetup, instead. HONEST BOUNDARY: this is HEURISTIC recognition from TOKENIZED Apex source \u2014 NOT a compiler AST. It matches string literals that CARRY a sandbox marker, so it can FLAG a value that is deliberately inert or only descriptive, and can MISS a sandbox value assembled at runtime or held in a helper the recognizer cannot follow. It names a test-portability review candidate, not a proven test failure.",
|
|
55817
|
+
docs: [
|
|
55818
|
+
{ label: "Apex Developer Guide \u2014 Testing Best Practices", url: "https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_testing_best_practices.htm" }
|
|
55819
|
+
]
|
|
55820
|
+
},
|
|
55821
|
+
"concept:restriction-rule-inactive": {
|
|
55822
|
+
id: "concept:restriction-rule-inactive",
|
|
55823
|
+
kind: "firing-condition",
|
|
55824
|
+
label: "An inactive restriction rule enforces no narrowing and leaves records fully visible per normal sharing",
|
|
55825
|
+
summary: "A RESTRICTION RULE whose `active` flag is FALSE is DEAD access control: while inactive it filters NOTHING, so the records it would otherwise HIDE stay fully visible to the users it targets under the org-wide default, sharing rules, the role hierarchy, and manual / Apex shares. A restriction rule is the ONE declarative mechanism that NARROWS record access BELOW what every other sharing feature grants \u2014 every other mechanism only widens \u2014 so a deactivated one subtracts nothing until an admin re-activates it. It must be EXCLUDED from \"what can this user NOT see\" reasoning and from any conclusion that an object's records are narrowed on its account: treating a disabled rule as a live boundary would falsely imply records are hidden that are in fact exposed, while treating it as gone would miss that re-activation instantly narrows them again. This is grounded from the rule's own always-present `active` flag; it names the non-enforcing STRUCTURAL fact, NOT whether the rule WOULD narrow a specific record if activated (its recordFilter / userCriteria remain unevaluated offline) and NOT why it was deactivated. Only active restriction rules narrow record access.",
|
|
55826
|
+
docs: [
|
|
55827
|
+
{ label: "Salesforce Help \u2014 Restriction Rules", url: "https://help.salesforce.com/s/articleView?id=sf.security_restriction_rule.htm" }
|
|
55828
|
+
]
|
|
55829
|
+
},
|
|
55830
|
+
"concept:approval-process-pending-lock-editability": {
|
|
55831
|
+
id: "concept:approval-process-pending-lock-editability",
|
|
55832
|
+
kind: "access-mechanism",
|
|
55833
|
+
label: "An approval process can widen the pending record's lock so the assigned approver may edit it",
|
|
55834
|
+
summary: 'When a record is SUBMITTED into an approval process it is AUTOMATICALLY LOCKED while it is PENDING \u2014 read-only to everyone except administrators and "Modify All"/"Modify All Data" holders. The process\'s `recordEditability` setting decides whether that pending lock is WIDENED: `AdminOrCurrentApprover` additionally lets the CURRENTLY-ASSIGNED APPROVER edit the very record awaiting their decision, whereas the default `AdminOnly` bars even the approver from editing it until the process completes. This is an access and audit surface \u2014 under the widened posture the person evaluating the request can also modify the record they are approving, and any field the approver changes while it is pending is a real edit path a save-order or data-integrity analysis must account for. This is grounded from the approval process\'s own declared `recordEditability` value; it names the DECLARED pending-lock editability, NOT whether any specific record is currently pending or locked (record-level runtime state the offline vault does not hold), NOT WHO the assigned approver is on a given record (approver routing is per-record and per-step), and NOT the separate final-approval / final-rejection lock behavior. An approval process set to `AdminOnly` (or that declares no recordEditability) contributes no approver-edit widening.',
|
|
55835
|
+
docs: [
|
|
55836
|
+
{ label: "Salesforce Help \u2014 Considerations for Approvals (record locking)", url: "https://help.salesforce.com/s/articleView?id=sf.approvals_considerations.htm" }
|
|
55837
|
+
]
|
|
55838
|
+
},
|
|
55839
|
+
"concept:approval-process-recall-unlocks-record": {
|
|
55840
|
+
id: "concept:approval-process-recall-unlocks-record",
|
|
55841
|
+
kind: "firing-condition",
|
|
55842
|
+
label: "An approval process that allows recall lets the submitter withdraw a request, unlocking the record and firing recall actions",
|
|
55843
|
+
summary: "An APPROVAL PROCESS whose `allowRecall` flag is true lets the ORIGINAL SUBMITTER RECALL (withdraw) a still-pending approval request. A recall UNLOCKS the record \u2014 it leaves the locked/pending state without any approver's decision \u2014 and FIRES the process's recall actions: the field updates, email alerts, tasks, or outbound messages configured on the recall hook. So the record can exit approval purely by submitter action, and that exit runs its own automation, which matters for \"why did this record unlock, or why did this field change, while it was in approval?\" reasoning and for automation-impact counts. This is grounded from the process's own always-present `allowRecall` boolean; it names the DECLARED recall CAPABILITY, NOT whether any specific record was ever recalled (record-level runtime state the offline vault does not hold), WHO may submit or recall (submitter membership is per-record / per-config), or whether the recall actions succeed. An approval process with `allowRecall` false permits no submitter recall \u2014 a pending record moves forward only by an approver's action (or an admin), so no submitter-driven unlock or recall-action firing applies.",
|
|
55844
|
+
docs: [
|
|
55845
|
+
{ label: "Salesforce Help \u2014 Considerations for Approvals", url: "https://help.salesforce.com/s/articleView?id=sf.approvals_considerations.htm" }
|
|
55846
|
+
]
|
|
55847
|
+
},
|
|
55848
|
+
"concept:auth-provider-registration-handler-apex-hook": {
|
|
55849
|
+
id: "concept:auth-provider-registration-handler-apex-hook",
|
|
55850
|
+
kind: "access-mechanism",
|
|
55851
|
+
label: "An auth provider's registration handler runs Apex in system context during SSO just-in-time provisioning",
|
|
55852
|
+
summary: "An AUTH PROVIDER whose `registrationHandler` names an Apex class binds a hidden identity entry point: on every social-sign-on / SSO login through this provider, Salesforce invokes that class (an implementation of `Auth.RegistrationHandler`) in SYSTEM context to CREATE or UPDATE the User record for the authenticating identity \u2014 just-in-time (JIT) user provisioning. The handler runs OUTSIDE the normal UI / permission path and under the provider's declared `executionUser` identity, so it can insert or modify Users, assign profiles, and set fields with the platform's trust rather than the logging-in person's. This is grounded from the provider's own declared `registrationHandler` binding; it names the STRUCTURAL entry-point fact, NOT whether any user has actually logged in through this provider, NOT what the handler code does (its logic is a separate ApexClass the offline vault does not execute), and NOT whether the class still exists or compiles. Review the handler as a privileged provisioning surface.",
|
|
55853
|
+
severity: "high",
|
|
55854
|
+
docs: [
|
|
55855
|
+
{ label: "Salesforce Help \u2014 Add an Apex Registration Handler to an Auth. Provider", url: "https://help.salesforce.com/s/articleView?id=sf.sso_provider_addl_apex.htm" }
|
|
55856
|
+
]
|
|
55857
|
+
},
|
|
55858
|
+
"concept:platform-event-channel-member-filtered-stream": {
|
|
55859
|
+
id: "concept:platform-event-channel-member-filtered-stream",
|
|
55860
|
+
kind: "firing-condition",
|
|
55861
|
+
label: "A channel member's filter expression narrows which events publish to the platform event or CDC channel",
|
|
55862
|
+
summary: "A PLATFORM EVENT CHANNEL MEMBER that declares a `filterExpression` binds its entity onto the channel with a FILTER: only the change events (or platform events) whose fields satisfy that declared expression are published to the channel and delivered to its subscribers \u2014 every other change is silently withheld from this stream. So a subscriber reading this channel sees a NARROWED subset, not the object's full change feed; automation or integrations that assume every change arrives can miss records that fail the filter. This is grounded from the member's own declared `filterExpression`; it names the STRUCTURAL filtered-stream fact, NOT runtime EVALUATION of which specific records pass the filter (that needs record-level data the offline vault does not have) and NOT the delivery guarantees of the channel itself (retention, replay, and ordering are separate async limits covered elsewhere).",
|
|
55863
|
+
docs: [
|
|
55864
|
+
{ label: "Salesforce Help \u2014 Filter Your Stream of Change Events", url: "https://help.salesforce.com/s/articleView?id=sf.cdc_filter_change_events.htm" }
|
|
55865
|
+
]
|
|
55866
|
+
},
|
|
55867
|
+
"concept:external-service-registration-incomplete": {
|
|
55868
|
+
id: "concept:external-service-registration-incomplete",
|
|
55869
|
+
kind: "status-code",
|
|
55870
|
+
label: "An external service registration whose status is not Complete has unavailable generated actions",
|
|
55871
|
+
summary: "An EXTERNAL SERVICE REGISTRATION whose `status` is anything other than `Complete` (for example `InProgress` or `NotComplete`) did not finish importing its OpenAPI schema into invocable operations: its generated actions are UNAVAILABLE, so any Flow, Apex, or OmniStudio step that invokes an operation from this registration cannot resolve it and fails at build or run time. A non-Complete registration is a half-built integration binding, not a live one. This is grounded from the registration's own always-present `status` scalar; it names the STRUCTURAL availability fact, NOT why the import stalled (schema fetch, auth, or parse errors are not captured offline) and NOT whether any component actually calls an operation from this service (that is a separate usage question). Only a Complete registration exposes callable operations.",
|
|
55872
|
+
docs: [
|
|
55873
|
+
{ label: "Salesforce Help \u2014 Generate an External Service", url: "https://help.salesforce.com/s/articleView?id=sf.external_services.htm" }
|
|
55874
|
+
]
|
|
55875
|
+
},
|
|
55876
|
+
"concept:named-credential-per-user-principal": {
|
|
55877
|
+
id: "concept:named-credential-per-user-principal",
|
|
55878
|
+
kind: "access-mechanism",
|
|
55879
|
+
label: "A per-user named credential authenticates each callout under the running user's own external credential",
|
|
55880
|
+
summary: "A NAMED CREDENTIAL whose `principalType` is `PerUser` does NOT carry one shared org-wide identity: each callout that authenticates through it uses the RUNNING USER's own per-user external credential, which every user must configure individually before their callouts can succeed. So the same Apex or flow callout behaves differently per user \u2014 it authenticates as that user against the external system, and it FAILS for any user who has not set up their personal credential \u2014 and the external system's audit log attributes each call to a distinct per-user identity rather than a single service account. This is grounded from the credential's own declared `principalType`; it names the STRUCTURAL per-user authentication posture, NOT which users have configured their credential (that is per-user runtime state the offline vault does not hold) and NOT whether any Apex actually issues a callout through this credential.",
|
|
55881
|
+
docs: [
|
|
55882
|
+
{ label: "Salesforce Help \u2014 Define a Named Credential", url: "https://help.salesforce.com/s/articleView?id=sf.named_credentials_define.htm" }
|
|
55883
|
+
]
|
|
55884
|
+
},
|
|
55885
|
+
"concept:omnistudio-test-procedure-scope": {
|
|
55886
|
+
id: "concept:omnistudio-test-procedure-scope",
|
|
55887
|
+
kind: "firing-condition",
|
|
55888
|
+
label: "An OmniStudio component flagged as a test procedure is a development test harness, not production runtime, and must be excluded from what-actually-runs analysis",
|
|
55889
|
+
summary: "An OmniStudio component \u2014 an OmniScript or Integration Procedure \u2014 whose `isTestProcedure` flag is TRUE is a DEVELOPMENT TEST HARNESS: its declared purpose is to exercise and validate ANOTHER OmniScript or Integration Procedure during development, NOT to serve end users as a production flow. It is not part of the normal production runtime surface \u2014 it is invoked to test a target component, not rendered to users, embedded on a page, or dispatched as production automation. It must therefore be EXCLUDED from 'what actually runs in production', runtime-reachability, and invocation-impact reasoning about OmniStudio, and it is a likely cleanup candidate when found in a production org. This is grounded from the component's own always-present `isTestProcedure` boolean; it names the declared test-harness scope, NOT whether the test currently passes, NOT which component it targets, NOT whether it has ever been run, and NOT whether it is also active (liveness is the separate `isActive` axis). Test procedures do not belong in production runtime-execution surfaces.",
|
|
55890
|
+
docs: [
|
|
55891
|
+
{ label: "Salesforce Help \u2014 Test OmniScripts and Integration Procedures", url: "https://help.salesforce.com/s/articleView?id=sf.os_test_omniscripts.htm" }
|
|
55892
|
+
]
|
|
55893
|
+
},
|
|
55894
|
+
"concept:dataraptor-load-fires-assignment-rules": {
|
|
55895
|
+
id: "concept:dataraptor-load-fires-assignment-rules",
|
|
55896
|
+
kind: "firing-condition",
|
|
55897
|
+
label: "A DataRaptor with 'Assignment Rules Used' on fires the object's assignment rules as a side effect of the records it writes",
|
|
55898
|
+
summary: "A DataRaptor (an OmniStudio OmniDataTransform) whose 'Assignment Rules Used' toggle is ON writes its Lead or Case records with the assignment-rule header set, so when it inserts or updates those records the object's ACTIVE assignment rules EVALUATE as a side effect of the transform's save: record ownership can be reassigned and assignment email notifications can be sent, even though nothing in the DataRaptor's own field mappings says so. A reader tracing what this transform does must account for that downstream assignment automation, not just the mapped field writes \u2014 the write path fans out into the object's routing rules. This is grounded from the transform's own declared `assignmentRulesUsed` toggle; it names the declared intent to run assignment rules on write, NOT a proof of any outcome: it does NOT establish that the target object has any ACTIVE assignment rule, that any specific record is actually reassigned or notified, or that the transform writes Lead / Case at all (only Lead and Case support assignment rules \u2014 the toggle is inert on any other object). It names the save-time side-effect surface, not a confirmed reassignment.",
|
|
55899
|
+
docs: [
|
|
55900
|
+
{ label: "Salesforce Help \u2014 DataRaptor Load Options", url: "https://help.salesforce.com/s/articleView?id=sf.os_design_dataraptor_loads.htm" }
|
|
55901
|
+
]
|
|
55902
|
+
},
|
|
55903
|
+
"concept:omnistudio-metadata-cache-disabled": {
|
|
55904
|
+
id: "concept:omnistudio-metadata-cache-disabled",
|
|
55905
|
+
kind: "code-quality-defect",
|
|
55906
|
+
label: "An OmniStudio component with metadata caching disabled recompiles its definition on every invocation, adding per-request latency",
|
|
55907
|
+
summary: "An OmniStudio component \u2014 an OmniScript or Integration Procedure \u2014 whose `isMetadataCacheDisabled` flag is TRUE runs WITHOUT metadata caching: the OmniStudio runtime does not cache the component's compiled definition, so it re-reads and recompiles the definition metadata on EVERY load or invocation instead of serving a cached copy. That adds per-request latency, and for an Integration Procedure invoked at volume it repeats that compile work on each call, adding CPU and metadata-query pressure to every transaction that touches the component. Disabling the metadata cache is a documented DEVELOPMENT / debugging aid (so a designer sees definition edits immediately) that is not meant to ship to a production org, where it becomes a standing performance drag. This is grounded from the component's own always-present `isMetadataCacheDisabled` boolean; it names the declared cache-disabled configuration posture, NOT a measured regression: it does NOT prove any specific slowdown, timeout, page-load delay, or governor-limit breach at runtime \u2014 those depend on invocation volume and org load the offline vault does not hold. It names the disabled-cache structural signal, not a confirmed performance incident.",
|
|
55908
|
+
docs: [
|
|
55909
|
+
{ label: "Salesforce Help \u2014 OmniStudio Metadata Caching", url: "https://help.salesforce.com/s/articleView?id=sf.os_omnistudio_metadata_caching.htm" }
|
|
55910
|
+
]
|
|
55911
|
+
},
|
|
55912
|
+
"concept:static-resource-public-cache-control-exposure": {
|
|
55913
|
+
id: "concept:static-resource-public-cache-control-exposure",
|
|
55914
|
+
kind: "access-mechanism",
|
|
55915
|
+
label: "A static resource with Public cache-control is shared-cached and reachable by unauthenticated guest users",
|
|
55916
|
+
summary: "A STATIC RESOURCE whose cacheControl is set to Public is cached in a SHARED, cross-user cache (the browser and the Salesforce CDN keep one copy served to all users) and is eligible to be delivered to UNAUTHENTICATED guest users through a Salesforce Site or Experience Cloud resource URL \u2014 so its bytes are effectively world-readable to anyone who can reach that URL and must never hold secrets such as API keys, tokens, or credentials. The alternative, Private, scopes caching to the requesting user own session and is not shared across users. This is grounded from the resource own always-present cacheControl scalar; it names the DECLARED cache-control posture and the shared-cache / guest-exposure it enables, NOT proof that the resource actually contains sensitive data, NOT whether any public page currently references it, and NOT whether its URL has in fact been shared. Only the Public posture is asserted, never a proven leak of a specific secret.",
|
|
55917
|
+
docs: [
|
|
55918
|
+
{ label: "Metadata API Developer Guide \u2014 StaticResource", url: "https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_staticresource.htm" }
|
|
55919
|
+
]
|
|
55920
|
+
},
|
|
55921
|
+
"concept:custom-metadata-record-protected-namespace-scoped": {
|
|
55922
|
+
id: "concept:custom-metadata-record-protected-namespace-scoped",
|
|
55923
|
+
kind: "access-mechanism",
|
|
55924
|
+
label: "A protected custom metadata record is accessible only to code in its own namespace",
|
|
55925
|
+
summary: "A PROTECTED custom metadata record is accessible ONLY to Apex, Flow, and formula code that runs in the SAME namespace that owns the record. When the owning type is packaged and installed into a subscriber org, the subscriber own Apex and SOQL CANNOT read the record, and its protected field values are returned masked (the three-asterisk literal) rather than as real content \u2014 which is exactly why protected custom metadata is the standard place to store package secrets. An UNPROTECTED record, by contrast, is readable by any code in the org. This is grounded from the record own required, declared protected flag; it names a PACKAGING-SCOPED access boundary only. It does NOT assert the record actual field values (which may be masked and unreadable from this offline snapshot), NOT whether this org is the owning namespace or a downstream subscriber, and NOT that any specific query is currently blocked \u2014 those depend on install context the offline vault does not hold.",
|
|
55926
|
+
docs: [
|
|
55927
|
+
{ label: "Metadata API Developer Guide \u2014 CustomMetadata", url: "https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_custommetadata.htm" }
|
|
55928
|
+
]
|
|
55929
|
+
},
|
|
55930
|
+
"concept:email-template-unavailable-hidden": {
|
|
55931
|
+
id: "concept:email-template-unavailable-hidden",
|
|
55932
|
+
kind: "status-code",
|
|
55933
|
+
label: "An email template marked not Available For Use is hidden from the template picker",
|
|
55934
|
+
summary: "An EMAIL TEMPLATE whose Available For Use flag is false is NOT offered to users when they compose or send an email through the UI \u2014 it is hidden from the email-template picker and cannot be selected for a manual send, so it is effectively dormant for interactive use and should be EXCLUDED from any which-templates-can-a-user-choose surface. This is grounded from the template own required, declared available flag; it names the DECLARED availability status only. It does NOT prove the template is unused \u2014 automation, workflow / flow email alerts, or Apex that reference the template DIRECTLY by id or developer name can still send it regardless of this flag \u2014 and it says nothing about the template body, subject, or merge fields. Only the not-offered-in-the-picker status is asserted, never a proven absence of every sender.",
|
|
55935
|
+
docs: [
|
|
55936
|
+
{ label: "Metadata API Developer Guide \u2014 EmailTemplate", url: "https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_emailtemplate.htm" }
|
|
55937
|
+
]
|
|
55938
|
+
},
|
|
55939
|
+
"concept:group-role-subordinates-transitive-membership": {
|
|
55940
|
+
id: "concept:group-role-subordinates-transitive-membership",
|
|
55941
|
+
kind: "access-mechanism",
|
|
55942
|
+
label: "A public group whose member is a role-and-subordinates transitively contains the whole role subtree",
|
|
55943
|
+
summary: "A PUBLIC GROUP whose declared membership includes a role AND its SUBORDINATES transitively contains the named role plus EVERY role beneath it in the role hierarchy \u2014 the whole subtree is a member of the group. Because groups are the reusable principal that many access mechanisms grant to, ANY access conferred on this group \u2014 an owner-based or criteria-based sharing rule shared to the group, queue ownership, report / dashboard / document folder access, or list-view sharing \u2014 therefore reaches the entire role subtree, not just a single role. This is grounded from the group own declared member row (the role-and-subordinates membership marker); it names the DECLARED membership cascade \u2014 the ROLES the group pulls in \u2014 NOT the individual users occupying those roles (an assignment question the offline vault does not answer) and NOT any specific record grant, which additionally depends on each object org-wide default and record-level state the offline snapshot does not hold.",
|
|
55944
|
+
docs: [
|
|
55945
|
+
{ label: "Metadata API Developer Guide \u2014 Group", url: "https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_group.htm" }
|
|
55946
|
+
]
|
|
55509
55947
|
}
|
|
55510
55948
|
});
|
|
55511
55949
|
CONCEPT_RULES = Object.freeze([
|
|
@@ -56824,6 +57262,456 @@ var init_concept_model = __esm({
|
|
|
56824
57262
|
maxConfidence: "declared",
|
|
56825
57263
|
absenceShaped: false,
|
|
56826
57264
|
dependsOnCoverage: ["AssignmentRule", "Queue", "Role"]
|
|
57265
|
+
},
|
|
57266
|
+
{
|
|
57267
|
+
id: "rule:validation-rule/inactive-dead",
|
|
57268
|
+
concept: "concept:validation-rule-inactive",
|
|
57269
|
+
bind: { componentTypes: ["ValidationRule"], whereProperty: { key: "active", equals: false } },
|
|
57270
|
+
interpretation: `{ids} is INACTIVE \u2014 Salesforce never evaluates its error-condition formula on insert or update, so it can neither block a save nor surface its error message until an admin re-activates it. It must be EXCLUDED from save-order-of-execution analysis, from "what could reject this write" reasoning, and from required-field / collision gate counts: treating a deactivated rule as a live guard would cry wolf about a constraint that cannot fire, while treating it as protection would falsely assure that bad data is blocked. This names the non-enforcing structural fact from the rule's own active flag, NOT whether it WOULD reject a specific record if activated (the formula is not evaluated offline).`,
|
|
57271
|
+
maxConfidence: "declared",
|
|
57272
|
+
absenceShaped: false,
|
|
57273
|
+
dependsOnCoverage: ["ValidationRule"]
|
|
57274
|
+
},
|
|
57275
|
+
{
|
|
57276
|
+
id: "rule:workflow/inactive-dead",
|
|
57277
|
+
concept: "concept:workflow-rule-inactive-dead",
|
|
57278
|
+
bind: { componentTypes: ["WorkflowRule"], whereProperty: { key: "active", equals: false } },
|
|
57279
|
+
interpretation: `{ids} is INACTIVE \u2014 DEAD legacy automation that Salesforce never evaluates, whose actions (field updates, email alerts, outbound messages, time-dependent actions) never run until it is re-activated. It must be EXCLUDED from save-order-of-execution analysis, from field-writer-collision reasoning, and from "what fires on save" impact counts: counting a deactivated rule overstates the automation load, while assuming its field updates still run would misattribute a value change. This names the non-running structural fact from the rule's own active flag, NOT whether a Flow has replaced it and NOT whether it WOULD match a given record if activated (criteria remain unevaluated offline).`,
|
|
57280
|
+
maxConfidence: "declared",
|
|
57281
|
+
absenceShaped: false,
|
|
57282
|
+
dependsOnCoverage: ["WorkflowRule"]
|
|
57283
|
+
},
|
|
57284
|
+
{
|
|
57285
|
+
id: "rule:field/longtext-richtext-not-filterable",
|
|
57286
|
+
concept: "concept:field-longtext-richtext-not-filterable",
|
|
57287
|
+
bind: { componentTypes: ["CustomField"], whereProperty: { key: "dataType", in: ["LongTextArea", "Html"] } },
|
|
57288
|
+
interpretation: "{ids} is a Long Text Area or Rich Text (Html) field \u2014 this data-type class is not filterable, sortable, groupable, or indexed, so it cannot appear in a SOQL WHERE / ORDER BY / GROUP BY, a list-view filter, or a report filter, and it cannot be marked as an external id or unique. Reference it only in SELECT clauses and body content. This is the platform restriction that follows from the field's type class; it does NOT assert that any specific query, list view, or report currently references the field (a usage question), only that such a filter, sort, or group-by would be rejected.",
|
|
57289
|
+
maxConfidence: "declared",
|
|
57290
|
+
absenceShaped: false,
|
|
57291
|
+
dependsOnCoverage: ["CustomField"]
|
|
57292
|
+
},
|
|
57293
|
+
{
|
|
57294
|
+
id: "rule:duplicate-rule/bypass-sharing-match",
|
|
57295
|
+
concept: "concept:duplicate-rule-bypass-sharing-match",
|
|
57296
|
+
bind: { componentTypes: ["DuplicateRule"], whereProperty: { key: "securityOption", equals: "BypassSharingRules" } },
|
|
57297
|
+
interpretation: "{ids} sets securityOption to BypassSharingRules \u2014 its duplicate matching runs in SYSTEM CONTEXT, comparing an incoming record against records the running user cannot see under the sharing model. A save can therefore be blocked or alerted by a hidden duplicate the user has no visibility into and cannot open to resolve; the alternative, EnforceSharingRules, would limit matching to records the user can already access. This is the declared sharing-context posture only \u2014 not a proof that the rule is active, that matching records exist, or that a specific save would surface a hidden duplicate.",
|
|
57298
|
+
maxConfidence: "declared",
|
|
57299
|
+
absenceShaped: false,
|
|
57300
|
+
dependsOnCoverage: ["DuplicateRule"]
|
|
57301
|
+
},
|
|
57302
|
+
{
|
|
57303
|
+
id: "rule:duplicate-rule/references-inactive-matching-rule",
|
|
57304
|
+
concept: "concept:duplicate-rule-references-inactive-matching-rule",
|
|
57305
|
+
bind: { edgeType: "references", componentTypes: ["MatchingRule"], whereProperty: { key: "isActive", equals: true }, aggregate: { edgeSource: "root-outgoing", endpointWhereProperty: { key: "ruleStatus", notIn: ["Active"] }, countDistinctEndpoint: "to", op: "gte", threshold: 1 } },
|
|
57306
|
+
interpretation: "{object} is an ACTIVE duplicate rule that references {count} matching rule(s) ({ids}) whose ruleStatus is NOT Active \u2014 an inactive matching rule performs NO duplicate detection, so on that matcher duplicate records save SILENTLY with no alert and no block, even though the duplicate rule itself is enabled. Reactivate the matching rule, or repoint the duplicate rule at a live matcher, to restore protection. This asserts the declared active flag and the matcher's declared ruleStatus from metadata only \u2014 it does NOT prove duplicate records exist, that a specific save would have been caught, or that another active matcher on the same rule still covers the object.",
|
|
57307
|
+
maxConfidence: "declared",
|
|
57308
|
+
absenceShaped: false,
|
|
57309
|
+
dependsOnCoverage: ["DuplicateRule", "MatchingRule"]
|
|
57310
|
+
},
|
|
57311
|
+
{
|
|
57312
|
+
id: "rule:approval-process/final-approval-lock",
|
|
57313
|
+
concept: "concept:approval-process-final-lock-record-readonly",
|
|
57314
|
+
bind: { componentTypes: ["ApprovalProcess"], whereProperty: { key: "finalApprovalRecordLock", equals: true } },
|
|
57315
|
+
interpretation: '{ids} declares `finalApprovalRecordLock` = true \u2192 when this approval process reaches FINAL APPROVAL it LOCKS the record, making it READ-ONLY to everyone except administrators and "Modify All"/"Modify All Data" holders (plus the process\'s own unlock step). After final approval, later user edits AND automation updates \u2014 flow, workflow, trigger, or API field writes \u2014 FAIL with an entity-is-locked error unless the record is unlocked first, so a downstream automation that updates a just-approved record can silently fail on the lock. This is the DECLARED lock behavior from the process\'s own final-approval-lock flag; it does NOT assert whether any specific record is currently locked (record-level runtime state the offline vault does not hold), which specific users can still edit it, or whether any automation actually attempts a post-lock update.',
|
|
57316
|
+
maxConfidence: "declared",
|
|
57317
|
+
absenceShaped: false,
|
|
57318
|
+
dependsOnCoverage: ["ApprovalProcess"]
|
|
57319
|
+
},
|
|
57320
|
+
{
|
|
57321
|
+
id: "rule:approval-process/final-rejection-lock",
|
|
57322
|
+
concept: "concept:approval-process-final-lock-record-readonly",
|
|
57323
|
+
bind: { componentTypes: ["ApprovalProcess"], whereProperty: { key: "finalRejectionRecordLock", equals: true } },
|
|
57324
|
+
interpretation: '{ids} declares `finalRejectionRecordLock` = true \u2192 when this approval process reaches FINAL REJECTION it LOCKS the record, making it READ-ONLY to everyone except administrators and "Modify All"/"Modify All Data" holders (plus the process\'s own unlock step). After final rejection, later user edits AND automation updates \u2014 flow, workflow, trigger, or API field writes \u2014 FAIL with an entity-is-locked error unless the record is unlocked first, so a downstream automation that updates a just-rejected record can silently fail on the lock. This is the DECLARED lock behavior from the process\'s own final-rejection-lock flag; it does NOT assert whether any specific record is currently locked (record-level runtime state the offline vault does not hold), which specific users can still edit it, or whether any automation actually attempts a post-lock update.',
|
|
57325
|
+
maxConfidence: "declared",
|
|
57326
|
+
absenceShaped: false,
|
|
57327
|
+
dependsOnCoverage: ["ApprovalProcess"]
|
|
57328
|
+
},
|
|
57329
|
+
{
|
|
57330
|
+
id: "rule:record-type/inactive",
|
|
57331
|
+
concept: "concept:record-type-inactive",
|
|
57332
|
+
bind: { componentTypes: ["RecordType"], whereProperty: { key: "active", equals: false } },
|
|
57333
|
+
interpretation: `{ids} is INACTIVE \u2014 it cannot be assigned to new records and is hidden from users' record-type selection, so it routes NONE of its page layout, picklist value set, or business process to new work until an admin re-activates it; only pre-existing records keep it. It must be EXCLUDED from "which record type will new records get", default-routing, and layout / picklist-scope reasoning about new work: treating a deactivated record type as a live routing option would misattribute a layout, restricted picklist, or business process that new records can never receive. This names the non-assignable structural fact from the record type's own active flag, NOT whether any existing records still carry it (record-level, not modeled offline), NOT which profiles once defaulted to or were granted it, and NOT why it was deactivated.`,
|
|
57334
|
+
maxConfidence: "declared",
|
|
57335
|
+
absenceShaped: false,
|
|
57336
|
+
dependsOnCoverage: ["RecordType"]
|
|
57337
|
+
},
|
|
57338
|
+
{
|
|
57339
|
+
id: "rule:integration/remote-site-protocol-security-disabled",
|
|
57340
|
+
concept: "concept:remote-site-setting-protocol-security-disabled",
|
|
57341
|
+
bind: { componentTypes: ["RemoteSiteSetting"], whereProperty: [{ key: "disableProtocolSecurity", equals: true }, { key: "isActive", equals: true }] },
|
|
57342
|
+
interpretation: "{ids} is an ACTIVE remote site setting with protocol security DISABLED, so the platform's HTTPS-only guard is dropped for outbound callouts to its allowlisted host: it permits cleartext http callouts to that endpoint, and request URLs, headers, and bodies \u2014 potentially including session ids, tokens, or credentials in the request \u2014 can travel unencrypted, exposing them to network interception and tampering. This names the declared configuration posture from the setting's own flags, NOT whether any Apex, Flow, or LWC actually issues an insecure callout to this host at runtime (the offline vault does not correlate outbound-callout code to allowlist entries) and NOT a confirmed interception. Prefer a Named Credential over HTTPS; re-enable protocol security unless a cleartext endpoint is deliberately required.",
|
|
57343
|
+
maxConfidence: "declared",
|
|
57344
|
+
absenceShaped: false,
|
|
57345
|
+
dependsOnCoverage: ["RemoteSiteSetting"]
|
|
57346
|
+
},
|
|
57347
|
+
{
|
|
57348
|
+
id: "rule:code-quality/intentional-system-mode-dml",
|
|
57349
|
+
concept: "concept:apex-intentional-system-mode-dml",
|
|
57350
|
+
bind: { componentTypes: ["ApexClass"], whereProperty: { key: "qualityIssues", anyElement: { key: "rule", equals: "intentional-system-mode-dml" } } },
|
|
57351
|
+
interpretation: "{ids} runs a DML operation with an EXPLICIT AccessLevel.SYSTEM_MODE argument (an intentional-system-mode-dml pattern) \u2014 so for that write it DELIBERATELY opts OUT of the running user's object CRUD and field-level security. Apex runs in system context and does NOT auto-enforce object CRUD or FLS on its DML; the AccessLevel.SYSTEM_MODE argument makes that non-enforcement a CONSCIOUS choice, so the write can create or change objects and fields regardless of the running user's object and field permissions. This is the DELIBERATE counterpart to an accidental missing-crud-check / missing-fls-check omission \u2014 the recognizer surfaces it for REVIEW, not as a defect, because a system-context write is often correct (a trusted service writing fields the running user cannot edit); if the running user's permissions SHOULD apply to this write, switch the argument to AccessLevel.USER_MODE. Record-level sharing is a SEPARATE access plane this does not read. This is HEURISTIC recognition from TOKENIZED Apex source \u2014 NOT a compiler AST \u2014 bound to the DML call site where the token appears; it names the DECLARED system-context bypass, not a proven authorization defect.",
|
|
57352
|
+
maxConfidence: "heuristic",
|
|
57353
|
+
absenceShaped: false,
|
|
57354
|
+
dependsOnCoverage: ["ApexClass"]
|
|
57355
|
+
},
|
|
57356
|
+
{
|
|
57357
|
+
id: "rule:omnistudio/dataraptor-field-security-unenforced",
|
|
57358
|
+
concept: "concept:dataraptor-field-security-unenforced",
|
|
57359
|
+
bind: { componentTypes: ["OmniDataTransform"], whereProperty: { key: "fieldLevelSecurityEnabled", equals: false } },
|
|
57360
|
+
interpretation: "{ids} has 'Check Field Level Security' turned OFF \u2014 it reads and writes SObject fields WITHOUT enforcing the running user's field-level security, so it can load a field the user cannot Read into its output or overwrite a field the user cannot Edit. This is an over-permissive data-access surface (an FLS-bypass shape) that must be treated as a review candidate for data-exposure, NOT as an FLS-respecting transform. This names the declared configuration shape from the transform's own field-security toggle, NOT a proven leak: it does NOT establish which specific fields are over-exposed (depends on the field mappings and each user's actual FLS), who invokes it, or whether a wrapping Apex guard or restricted entry point neutralizes the gap at runtime.",
|
|
57361
|
+
maxConfidence: "declared",
|
|
57362
|
+
absenceShaped: false,
|
|
57363
|
+
dependsOnCoverage: ["OmniDataTransform"]
|
|
57364
|
+
},
|
|
57365
|
+
{
|
|
57366
|
+
id: "rule:field/classic-encrypted-text",
|
|
57367
|
+
concept: "concept:field-classic-encrypted-text",
|
|
57368
|
+
bind: { componentTypes: ["CustomField"], whereProperty: { key: "dataType", equals: "EncryptedText" } },
|
|
57369
|
+
interpretation: `{ids} is a CLASSIC ENCRYPTED TEXT field \u2014 stored encrypted and MASKED in the UI, API, and reports for any user without the "View Encrypted Data" permission (most users see asterisks). Its type class is not filterable, sortable, or groupable, so it cannot appear in a SOQL WHERE / ORDER BY / GROUP BY, a list-view or report filter, and it cannot be an external id, a unique field, a default-value source, or a formula input. This is the LEGACY per-field protection, distinct from Shield Platform Encryption (not observable offline). Grounded from the field's declared data type; it names the masking and restriction posture, NOT which users can currently view the value and NOT whether the field holds sensitive data.`,
|
|
57370
|
+
maxConfidence: "declared",
|
|
57371
|
+
absenceShaped: false,
|
|
57372
|
+
dependsOnCoverage: ["CustomField"]
|
|
57373
|
+
},
|
|
57374
|
+
{
|
|
57375
|
+
id: "rule:field/autonumber-system-assigned-readonly",
|
|
57376
|
+
concept: "concept:field-autonumber-system-assigned-readonly",
|
|
57377
|
+
bind: { componentTypes: ["CustomField"], whereProperty: { key: "dataType", equals: "AutoNumber" } },
|
|
57378
|
+
interpretation: "{ids} is an AUTO NUMBER field \u2014 system-assigned from a display format and sequence at insert, so it is READ-ONLY on every write path (UI, API, Apex, Flow, and data import cannot set it). It is null / unavailable in a before-save context (assigned during insert), is stored as a formatted STRING rather than a number, and changing its format renumbers only new records \u2014 existing values and any sequence gaps from failed inserts persist. Grounded from the field's declared data type; it names the system-assigned read-only provenance, NOT the current or next sequence value and NOT whether an integration tries to write it.",
|
|
57379
|
+
maxConfidence: "declared",
|
|
57380
|
+
absenceShaped: false,
|
|
57381
|
+
dependsOnCoverage: ["CustomField"]
|
|
57382
|
+
},
|
|
57383
|
+
{
|
|
57384
|
+
id: "rule:field/multiselect-picklist-storage",
|
|
57385
|
+
concept: "concept:field-multiselect-picklist-storage-semantics",
|
|
57386
|
+
bind: { componentTypes: ["CustomField"], whereProperty: { key: "dataType", equals: "MultiselectPicklist" } },
|
|
57387
|
+
interpretation: "{ids} is a MULTI-SELECT PICKLIST \u2014 every selected value is stored in a SINGLE semicolon-delimited string, not as separate rows. In SOQL and reports it must be filtered with INCLUDES / EXCLUDES rather than = / != / IN (an equality filter matches only the exact full delimited combination), and formulas must use INCLUDES() to test membership; sorting or grouping orders by the raw delimited string. It cannot be the controlling field of a dependent picklist, nor an external id or unique field. Grounded from the field's declared data type; it names the storage and query semantics that follow from the type, NOT which values a record holds and NOT whether a specific query filters it incorrectly.",
|
|
57388
|
+
maxConfidence: "declared",
|
|
57389
|
+
absenceShaped: false,
|
|
57390
|
+
dependsOnCoverage: ["CustomField"]
|
|
57391
|
+
},
|
|
57392
|
+
{
|
|
57393
|
+
id: "rule:access/permission-set-license-scoped",
|
|
57394
|
+
concept: "concept:permission-set-license-scoped",
|
|
57395
|
+
bind: { componentTypes: ["PermissionSet"], whereProperty: { key: "license", isNull: false } },
|
|
57396
|
+
interpretation: "{ids} is a LICENSE-SCOPED permission set \u2014 its `license` element binds it to a specific user license, so Salesforce only lets it be assigned to users who ALREADY hold that license. Every grant it carries (object CRUD, field-level security, Apex access, system permissions) is therefore UNREACHABLE by any user lacking the license, which NARROWS the eligible population before any individual grant even applies: no matter how strong its grants look, it cannot widen access for a user on the wrong license. This names the DECLARED assignability constraint of the container from the permission set's own `license` binding, NOT whether any specific user holds that license or is assigned this permission set (a live-plane assignment question the offline vault cannot answer), and NOT the strength or correctness of the grants inside it.",
|
|
57397
|
+
maxConfidence: "declared",
|
|
57398
|
+
absenceShaped: false,
|
|
57399
|
+
dependsOnCoverage: ["PermissionSet"]
|
|
57400
|
+
},
|
|
57401
|
+
{
|
|
57402
|
+
id: "rule:permission-set/session-based-dormant",
|
|
57403
|
+
concept: "concept:session-based-permission-set-dormant",
|
|
57404
|
+
bind: { componentTypes: ["PermissionSet"], whereProperty: { key: "hasActivationRequired", equals: true } },
|
|
57405
|
+
interpretation: "{ids} is a SESSION-BASED permission set \u2014 its activation-required flag is TRUE \u2014 so it grants NONE of its permissions passively. Every grant it confers (object CRUD, field-level security, View All / Modify All, Apex-class access, custom-permission grants) stays DORMANT until the permission set is ACTIVATED for the current session, via Auth.SessionManagement or a launching flow, making all of them conditional-on-activation rather than standing. When reasoning about what a holder can do at rest, treat these grants as INACTIVE by default: assignment alone does not confer the access until a session activation occurs. This names the activation-gate structural fact from the set's own activation-required flag, NOT whether any given session actually activates it (session activation is a runtime event not observable offline) and NOT which users hold the set.",
|
|
57406
|
+
maxConfidence: "declared",
|
|
57407
|
+
absenceShaped: false,
|
|
57408
|
+
dependsOnCoverage: ["PermissionSet"]
|
|
57409
|
+
},
|
|
57410
|
+
{
|
|
57411
|
+
id: "rule:field/restricted-global-value-set",
|
|
57412
|
+
concept: "concept:field-restricted-global-value-set",
|
|
57413
|
+
bind: { edgeType: "usesValueSet", componentTypes: ["CustomField", "GlobalValueSet"], toWhereProperty: { key: "restricted", equals: true } },
|
|
57414
|
+
interpretation: "{0} draws its values from restricted global value set {1} \u2014 a closed vocabulary. Only values defined in the shared set are valid, so admins cannot add ad-hoc values on this field and an integration or API write of an out-of-set value is rejected; changing the allowed values means editing the shared set, which ripples to every other field bound to it. This is the metadata-declared restriction, not proof of runtime enforcement or that no existing record already holds an out-of-set value.",
|
|
57415
|
+
maxConfidence: "declared",
|
|
57416
|
+
absenceShaped: false,
|
|
57417
|
+
dependsOnCoverage: ["CustomField", "GlobalValueSet"]
|
|
57418
|
+
},
|
|
57419
|
+
{
|
|
57420
|
+
id: "rule:field/picklist-has-retired-values",
|
|
57421
|
+
concept: "concept:field-picklist-has-retired-values",
|
|
57422
|
+
bind: { componentTypes: ["CustomField"], whereProperty: { key: "picklistValues", anyElement: { key: "isActive", equals: false } } },
|
|
57423
|
+
interpretation: "{ids} is a picklist whose OWN local value set retains at least one INACTIVE (retired) value \u2014 a value kept in the field definition after an admin deactivated it. Existing records that already hold a retired value keep displaying and reporting it (the value stays readable), but it is NO LONGER offered in the picker and cannot be newly selected in the UI, so a retired value is a data-hygiene and migration signal, not a live option. This names the DECLARED presence of a retired value in the field's own value-set entries from metadata; it does NOT prove any record currently holds that value (a record-level count the offline vault cannot answer), does NOT cover GlobalValueSet-backed picklists (whose values live on the shared value set, not the field, and fail closed here because picklistValues is null), and does NOT prove any report, formula, default value, or automation still references the retired value.",
|
|
57424
|
+
maxConfidence: "declared",
|
|
57425
|
+
absenceShaped: false,
|
|
57426
|
+
dependsOnCoverage: ["CustomField"]
|
|
57427
|
+
},
|
|
57428
|
+
{
|
|
57429
|
+
id: "rule:approval-process/inactive-dead",
|
|
57430
|
+
concept: "concept:approval-process-inactive-dead",
|
|
57431
|
+
bind: { componentTypes: ["ApprovalProcess"], whereProperty: { key: "active", equals: false } },
|
|
57432
|
+
interpretation: `{ids} is INACTIVE \u2014 DEAD approval automation that Salesforce never runs: no record can be submitted into it for approval, its entry criteria are never evaluated, and none of its initial-submission actions, per-step approver routing, final-approval / final-rejection actions, or record locks ever fire until an admin re-activates it. It must be EXCLUDED from "what happens when this record is submitted for approval" reasoning, from record-lock analysis (its finalApprovalRecordLock / finalRejectionRecordLock never take effect while inactive), and from automation-impact counts: counting a deactivated process overstates the automation load, while assuming its field-update actions or locks still run would misattribute a value change or a read-only freeze. This names the non-running structural fact from the process's own active flag, NOT whether a Flow-based approval has replaced it and NOT whether it WOULD admit a given record if activated (entry criteria remain unevaluated offline).`,
|
|
57433
|
+
maxConfidence: "declared",
|
|
57434
|
+
absenceShaped: false,
|
|
57435
|
+
dependsOnCoverage: ["ApprovalProcess"]
|
|
57436
|
+
},
|
|
57437
|
+
{
|
|
57438
|
+
id: "rule:escalation/time-deferred",
|
|
57439
|
+
concept: "concept:escalation-rule-time-deferred",
|
|
57440
|
+
bind: { componentTypes: ["EscalationRule"], whereProperty: { key: "active", equals: true } },
|
|
57441
|
+
interpretation: "{ids} is an ACTIVE escalation rule \u2192 its escalation actions (reassign the record to a queue or user, and/or send a notification email) are NOT run during the record save. They are QUEUED to Salesforce's background escalation process and fire later, in a separate context, once the record has aged past the entry's declared minute offset without meeting the rule's exit criteria. The effect is DEFERRED and decoupled from the triggering edit: the reassignment/notification is not part of that save and cannot roll it back, and Salesforce silently drops the queued escalation if the record stops qualifying before the timer elapses. This names the deferred-action structure from the rule's active state; it does NOT evaluate the `minutesToEscalation` offset (carried on the rule's per-action edges, not the node), assert WHEN the escalation fires, whether the record still qualifies, or whether it succeeds.",
|
|
57442
|
+
maxConfidence: "declared",
|
|
57443
|
+
absenceShaped: false,
|
|
57444
|
+
dependsOnCoverage: ["EscalationRule"]
|
|
57445
|
+
},
|
|
57446
|
+
{
|
|
57447
|
+
id: "rule:automation/auto-response-rule-first-match-starvation",
|
|
57448
|
+
concept: "concept:auto-response-rule-first-match-starvation",
|
|
57449
|
+
bind: { edgeType: "sendsEmail", componentTypes: ["EmailTemplate"], aggregate: { edgeSource: "root-outgoing", countDistinctEndpoint: "to", firstMatchOrdinal: { ordinalEdgeProperty: "entryIndex", broadEntryWhere: [{ key: "criteriaItemCount", equals: 0 }, { key: "hasFormula", equals: false }] } } },
|
|
57450
|
+
interpretation: "{0} is an auto-response rule evaluated top-down by entry order: entry {broadOrdinal} is a catch-all with no criteria or formula filter, so it matches every record and its auto-response email {1} is sent before any later, more specific entry is considered \u2014 {starvedCount} later entries are structurally unreachable because the first matching entry wins. This names the metadata ordering risk only; it does NOT prove which email a specific record would trigger at runtime, and only one auto-response rule per object is active at a time.",
|
|
57451
|
+
maxConfidence: "declared",
|
|
57452
|
+
absenceShaped: false,
|
|
57453
|
+
dependsOnCoverage: ["AutoResponseRule", "EmailTemplate"]
|
|
57454
|
+
},
|
|
57455
|
+
{
|
|
57456
|
+
id: "rule:record-type/business-process-binding",
|
|
57457
|
+
concept: "concept:record-type-business-process-binding",
|
|
57458
|
+
bind: { componentTypes: ["RecordType"], whereProperty: { key: "businessProcess", isNull: false } },
|
|
57459
|
+
interpretation: "{ids} declares a BUSINESS PROCESS binding, so records created with this record type are scoped to that process's ordered subset of the master status picklist \u2014 it constrains the available stage picklist values to those the bound business process exposes (the Stage / Status / Solution-status values), NOT the object's full master picklist. On any write path \u2014 a Flow, an Apex assignment, an API create, or a data import \u2014 setting the stage / status field to a value the bound process does not include can be rejected. This names the DECLARED binding from the record type's own businessProcess reference, NOT the specific stage values the process exposes (those live on the BusinessProcess metadata and are org-specific), NOT which records currently carry this record type or their current stage (record-level, not modeled offline), and NOT whether the bound business process is itself active. A record type without a business process uses the object's full master picklist and has no such scoping.",
|
|
57460
|
+
maxConfidence: "declared",
|
|
57461
|
+
absenceShaped: false,
|
|
57462
|
+
dependsOnCoverage: ["RecordType"]
|
|
57463
|
+
},
|
|
57464
|
+
{
|
|
57465
|
+
id: "rule:code-quality/dynamic-reflective-surface",
|
|
57466
|
+
concept: "concept:apex-dynamic-reflective-surface",
|
|
57467
|
+
bind: { componentTypes: ["ApexClass"], whereProperty: { key: "qualityIssues", anyElement: { key: "rule", equals: "dynamic-apex" } } },
|
|
57468
|
+
interpretation: "{ids} uses DYNAMIC or REFLECTIVE Apex \u2014 object, field, or type references built at RUNTIME (a dynamic-query string, a runtime schema describe, reflective type instantiation by name, or untyped deserialization) rather than as static literals. Such runtime-built references are INVISIBLE to static dependency analysis, so impact, usage / where-used, and dead-code results for this class MAY BE INCOMPLETE \u2014 a real dependency can be hidden behind the runtime construction. This is HEURISTIC token recognition, NOT a compiler AST: it can FLAG a dynamic construct whose reference is actually a safe constant, and can MISS one the tokenizer does not match. It does NOT prove the class is buggy, does NOT name WHICH objects or fields the dynamic code touches, and does NOT assert any specific hidden dependency \u2014 it flags the class as one whose static analysis is blind in spots; read the source to confirm.",
|
|
57469
|
+
maxConfidence: "heuristic",
|
|
57470
|
+
absenceShaped: false,
|
|
57471
|
+
dependsOnCoverage: ["ApexClass"]
|
|
57472
|
+
},
|
|
57473
|
+
{
|
|
57474
|
+
id: "rule:named-credential-merge-fields-injectable/header",
|
|
57475
|
+
concept: "concept:named-credential-merge-fields-injectable",
|
|
57476
|
+
bind: { componentTypes: ["NamedCredential"], whereProperty: [{ key: "allowMergeFieldsInHeader", equals: true }] },
|
|
57477
|
+
interpretation: "{ids} is a named credential with `allowMergeFieldsInHeader` = true \u2014 the default guard against merge-field substitution in the outbound HTTP HEADER is LIFTED, so Apex callouts authenticating through this credential may substitute merge fields (including record- or user-derived values) into request headers. That makes it an outbound injection surface: if a substituted value is attacker-influenced it can alter or forge headers the upstream API trusts (header injection). This names the DECLARED configuration that ENABLES substitution; it does NOT prove that any Apex actually uses this credential, that any merge field carries UNTRUSTED input (the values may be static/trusted and the setting intentional), or that an injection occurs at runtime.",
|
|
57478
|
+
maxConfidence: "declared",
|
|
57479
|
+
absenceShaped: false,
|
|
57480
|
+
dependsOnCoverage: ["NamedCredential"]
|
|
57481
|
+
},
|
|
57482
|
+
{
|
|
57483
|
+
id: "rule:named-credential-merge-fields-injectable/body",
|
|
57484
|
+
concept: "concept:named-credential-merge-fields-injectable",
|
|
57485
|
+
bind: { componentTypes: ["NamedCredential"], whereProperty: [{ key: "allowMergeFieldsInBody", equals: true }] },
|
|
57486
|
+
interpretation: "{ids} is a named credential with `allowMergeFieldsInBody` = true \u2014 the default guard against merge-field substitution in the outbound HTTP BODY is LIFTED, so Apex callouts authenticating through this credential may substitute merge fields (including record- or user-derived values) into the request payload. That makes it an outbound injection surface: if a substituted value is attacker-influenced it can forge or tamper with body fields the upstream API trusts (payload injection). This names the DECLARED configuration that ENABLES substitution; it does NOT prove that any Apex actually uses this credential, that any merge field carries UNTRUSTED input (the values may be static/trusted and the setting intentional), or that an injection occurs at runtime.",
|
|
57487
|
+
maxConfidence: "declared",
|
|
57488
|
+
absenceShaped: false,
|
|
57489
|
+
dependsOnCoverage: ["NamedCredential"]
|
|
57490
|
+
},
|
|
57491
|
+
{
|
|
57492
|
+
id: "rule:access-mechanism/connected-app-saml-sso-federation",
|
|
57493
|
+
concept: "concept:connected-app-saml-sso-federation",
|
|
57494
|
+
bind: { componentTypes: ["ConnectedApp"], whereProperty: { key: "authProtocol", in: ["saml", "both"] } },
|
|
57495
|
+
interpretation: "{ids} is a connected app carrying a SAML config \u2014 a SAML SSO federation target that declares Salesforce as the SAML identity provider (IdP) and the app as an external service provider (SP) Salesforce will mint signed SAML assertions for, federating an authenticated user's identity into that third party for single sign-on. Its authProtocol is saml (SAML only) or both (SAML alongside an OAuth client), and the declared trust boundary \u2014 the Assertion Consumer Service (ACS) URL, the SP entity / audience, the expected issuer, and the NameID / subject format \u2014 defines who Salesforce federates identities out to. So it is an identity and trust surface worth reviewing. This names the DECLARED SAML SSO federation configuration, not a proven active login: the config is a static shape, not evidence that anyone authenticates through it or that the signing certificate is valid (the key material is never vaulted), WHO may use the app is a separate profile / permission-set access layer the config does not encode, and the federation may be intentional for a trusted downstream app.",
|
|
57496
|
+
maxConfidence: "declared",
|
|
57497
|
+
absenceShaped: false,
|
|
57498
|
+
dependsOnCoverage: ["ConnectedApp"]
|
|
57499
|
+
},
|
|
57500
|
+
{
|
|
57501
|
+
id: "rule:apex-fake-assertion/tautology-assertion",
|
|
57502
|
+
concept: "concept:apex-fake-assertion-test",
|
|
57503
|
+
bind: { componentTypes: ["ApexClass"], whereProperty: { key: "qualityIssues", anyElement: { key: "rule", equals: "fake-assertion" } } },
|
|
57504
|
+
interpretation: "{ids} is an @IsTest class that contains a TAUTOLOGICAL or self-referential assertion \u2014 a System.assert(true, ...), a System.assertEquals(x, x), or a System.assertEquals(literal, sameLiteral) \u2014 whose operands are identical or always true, so it passes no matter how the code under test behaves. That assertion verifies nothing: it cannot fail on a wrong computed value, only on an uncaught exception, yet it still executes the code under test and so inflates the org code-coverage number while providing no real regression protection, and it can mask a genuine defect behind a green run. Assert on real field values, record counts, or thrown exceptions instead. This is HEURISTIC recognition from TOKENIZED Apex source \u2014 NOT a compiler AST: it flags the tautological call-site itself and does NOT prove the whole class is worthless (the class may carry other, meaningful assertions alongside the fake one). It names a test-quality review candidate, not proven coverage fraud.",
|
|
57505
|
+
maxConfidence: "heuristic",
|
|
57506
|
+
absenceShaped: false,
|
|
57507
|
+
dependsOnCoverage: ["ApexClass"]
|
|
57508
|
+
},
|
|
57509
|
+
{
|
|
57510
|
+
id: "rule:entitlement-process/inactive",
|
|
57511
|
+
concept: "concept:entitlement-process-inactive",
|
|
57512
|
+
bind: { componentTypes: ["EntitlementProcess"], whereProperty: { key: "active", equals: "false" } },
|
|
57513
|
+
interpretation: '{ids} is an INACTIVE entitlement process \u2014 its `active` flag is FALSE, so Salesforce never applies it to a case and never starts any of its milestone timers until an admin re-activates it. It is DEAD SLA automation: no milestone clock runs, no business-hours SLA countdown begins, and no entitlement-driven escalation can fire from this version while it is inactive. It must be EXCLUDED from SLA / entitlement reasoning and from "what milestones apply on save" impact counts \u2014 treating a deactivated process as a live SLA guard would cry wolf about timers that cannot start, while assuming its milestones still run would falsely imply cases are being tracked. This is the DECLARED non-running fact read from the process\'s own active flag; it does NOT prove whether any specific case is currently on-track or breached (that is live per-record timer data the offline vault does not hold), NOT whether this version WOULD apply if activated (entry criteria remain unevaluated offline), and NOT whether another active version of the same process exists (version lineage is org-specific).',
|
|
57514
|
+
maxConfidence: "declared",
|
|
57515
|
+
absenceShaped: false,
|
|
57516
|
+
dependsOnCoverage: ["EntitlementProcess"]
|
|
57517
|
+
},
|
|
57518
|
+
{
|
|
57519
|
+
id: "rule:omnistudio/inactive-component-version",
|
|
57520
|
+
concept: "concept:omnistudio-inactive-component-version",
|
|
57521
|
+
bind: { componentTypes: ["OmniScript", "OmniIntegrationProcedure", "OmniUiCard"], whereProperty: { key: "isActive", equals: false } },
|
|
57522
|
+
interpretation: "{ids} is an INACTIVE OmniStudio component version (an OmniScript, Integration Procedure, or FlexCard whose isActive flag is FALSE). Salesforce serves and dispatches only the ACTIVE version of an OmniStudio component, so this saved version does not execute at runtime: it is not rendered, invoked as an action, or embedded on a page until an admin activates it. It must be EXCLUDED from runtime-reachability, invocation-impact, and 'what actually runs' reasoning about OmniStudio \u2014 treating a deactivated version as live would overstate the runtime surface. This names the non-running structural fact from the component's own isActive flag, NOT whether another version of the same bundle is active and serving in its place (version lineage is org-specific), NOT whether anything still references this version by name, NOT what it would do if activated, and NOT why it was deactivated.",
|
|
57523
|
+
maxConfidence: "declared",
|
|
57524
|
+
absenceShaped: false,
|
|
57525
|
+
dependsOnCoverage: ["OmniScript", "OmniIntegrationProcedure", "OmniUiCard"]
|
|
57526
|
+
},
|
|
57527
|
+
{
|
|
57528
|
+
id: "rule:field/required-absent-from-all-layouts",
|
|
57529
|
+
concept: "concept:required-field-absent-from-all-layouts",
|
|
57530
|
+
bind: { componentTypes: ["CustomField"], whereProperty: [{ key: "required", equals: true }], antiJoin: { absentEdgeType: "usedInLayout", correlate: "sameTo", absentFromTypes: ["Layout"] } },
|
|
57531
|
+
interpretation: "{ids} is UNIVERSALLY REQUIRED yet NO extracted page layout places it in any field-bearing region (the detail body, the Highlights Panel, or the mini layout) \u2014 so a user creating or editing a record through those layouts has no declared input for its value, which must instead come from a default value, a before-save automation, an Apex / API / data-import insert, or the platform's own runtime rendering of required fields on the create / edit form. Grounded from the field's declared required flag plus the ABSENCE of any usedInLayout edge from a Layout; under incomplete Layout coverage this absence is NOT asserted. This does NOT prove any save fails, and it does NOT see Lightning Dynamic Form (FlexiPage) placement \u2014 a field surfaced only through a Dynamic Form still matches here.",
|
|
57532
|
+
maxConfidence: "declared",
|
|
57533
|
+
absenceShaped: true,
|
|
57534
|
+
dependsOnCoverage: ["CustomField", "Layout"]
|
|
57535
|
+
},
|
|
57536
|
+
{
|
|
57537
|
+
id: "rule:omnistudio/dataraptor-errors-ignored",
|
|
57538
|
+
concept: "concept:dataraptor-errors-ignored",
|
|
57539
|
+
bind: { componentTypes: ["OmniDataTransform"], whereProperty: { key: "errorIgnored", equals: true } },
|
|
57540
|
+
interpretation: "{ids} has 'Ignore Error' turned ON \u2014 when an individual record operation inside the transform fails, the failing item is skipped and the transform CONTINUES, returning a success-shaped result even though some reads or writes did not complete. This is an error-swallowing reliability shape: a partial or silent data-integrity gap can pass undetected unless the caller explicitly inspects the returned error collection. Treat it as a review candidate for silent data loss, NOT as a transform that surfaces its failures. It is distinct from the 'Rollback on Error' toggle \u2014 ignoring errors while not rolling back can leave partially applied data. This names the declared configuration shape from the transform's own toggle, NOT a proven failure: it does NOT establish that any record actually fails at runtime, that data was actually lost or left partial, or whether the invoking OmniScript, Integration Procedure, or Apex caller checks the error output and compensates.",
|
|
57541
|
+
maxConfidence: "declared",
|
|
57542
|
+
absenceShaped: false,
|
|
57543
|
+
dependsOnCoverage: ["OmniDataTransform"]
|
|
57544
|
+
},
|
|
57545
|
+
{
|
|
57546
|
+
id: "rule:object/deployment-status-in-development",
|
|
57547
|
+
concept: "concept:object-deployment-status-in-development",
|
|
57548
|
+
bind: { componentTypes: ["CustomObject"], whereProperty: { key: "deploymentStatus", equals: "InDevelopment" } },
|
|
57549
|
+
interpretation: `{ids} has deployment status IN DEVELOPMENT (not Deployed) \u2014 so the object, its tab, its list views, and its fields are HIDDEN from every user who lacks the "Customize Application" administrative permission (in practice, all non-admin users), and the object is effectively unusable in production until an admin sets it to Deployed. It must be EXCLUDED from reasoning about which ordinary users can see or work with this object and its records. This names the DECLARED deployment-status posture from the object's own metadata; it does NOT prove whether any specific user holds Customize Application (an assignment question the offline vault cannot answer) and does NOT establish whether the object was intentionally left in development. Only Deployed objects belong in ordinary-user reachability surfaces.`,
|
|
57550
|
+
maxConfidence: "declared",
|
|
57551
|
+
absenceShaped: false,
|
|
57552
|
+
dependsOnCoverage: ["CustomObject"]
|
|
57553
|
+
},
|
|
57554
|
+
{
|
|
57555
|
+
id: "rule:object/autonumber-name-field",
|
|
57556
|
+
concept: "concept:object-autonumber-name-field",
|
|
57557
|
+
bind: { componentTypes: ["CustomObject"], whereProperty: { key: "nameFieldType", equals: "AutoNumber" } },
|
|
57558
|
+
interpretation: "{ids} is a custom object whose NAME field is an AUTO NUMBER \u2014 every record's Name is SYSTEM-ASSIGNED from a display format and a sequence at insert, so the record name is READ-ONLY on every write path (UI, API, Apex, Flow, and data import cannot set it), is unavailable in a before-insert context (assigned during insert), and is stored and displayed as a formatted STRING rather than a number. Changing the display format renumbers only new records; existing names and any sequence gaps from failed inserts persist. This is grounded from the object's own declared name-field type; it names the system-assigned read-only provenance of the record NAME (DISTINCT from a custom field of type Auto Number), NOT the current or next sequence value (record-level data the offline vault cannot answer) and NOT whether any integration tries to set the name.",
|
|
57559
|
+
maxConfidence: "declared",
|
|
57560
|
+
absenceShaped: false,
|
|
57561
|
+
dependsOnCoverage: ["CustomObject"]
|
|
57562
|
+
},
|
|
57563
|
+
{
|
|
57564
|
+
id: "rule:global-value-set/has-inactive-value",
|
|
57565
|
+
concept: "concept:global-value-set-has-inactive-value",
|
|
57566
|
+
bind: { componentTypes: ["GlobalValueSet"], whereProperty: { key: "values", anyElement: { key: "isActive", equals: false } } },
|
|
57567
|
+
interpretation: "{ids} is a GLOBAL (shared) value set that retains at least one INACTIVE (deactivated) value. Because this value set is SHARED, the retired value is removed from the picker on EVERY picklist field bound to the set at once \u2014 it is NO LONGER SELECTABLE for new records anywhere \u2014 yet existing records that already hold it keep displaying and reporting it (the value stays readable). Reactivating or removing the value ripples to every field bound to the set. This names the DECLARED presence of a deactivated entry in the shared value set's own metadata; it does NOT prove any record currently holds the value (a record-level count the offline vault cannot answer) and does NOT enumerate which fields bind this set (that is the fields' own usesValueSet edges).",
|
|
57568
|
+
maxConfidence: "declared",
|
|
57569
|
+
absenceShaped: false,
|
|
57570
|
+
dependsOnCoverage: ["GlobalValueSet"]
|
|
57571
|
+
},
|
|
57572
|
+
{
|
|
57573
|
+
id: "rule:standard-value-set/has-inactive-value",
|
|
57574
|
+
concept: "concept:standard-value-set-has-inactive-value",
|
|
57575
|
+
bind: { componentTypes: ["StandardValueSet"], whereProperty: { key: "values", anyElement: { key: "active", equals: false } } },
|
|
57576
|
+
interpretation: "{ids} is a STANDARD value set (the org-wide value list behind a standard picklist such as Industry, Lead Source, or Opportunity Stage) that retains at least one INACTIVE (deactivated) value. The retired value is NO LONGER SELECTABLE for new records on the standard field(s) that draw from this set, yet existing records that already hold it keep displaying and reporting it (the value stays readable). This names the DECLARED presence of a deactivated entry in the standard value set's own metadata; a standard field's binding to its value set is IMPLICIT (Salesforce wires it internally, so there is no edge and this does NOT name which fields are affected), it does NOT prove any record currently holds the value (record-level data the offline vault cannot answer), and it is DISTINCT from a custom field's own local retired value and from a shared global value set.",
|
|
57577
|
+
maxConfidence: "declared",
|
|
57578
|
+
absenceShaped: false,
|
|
57579
|
+
dependsOnCoverage: ["StandardValueSet"]
|
|
57580
|
+
},
|
|
57581
|
+
{
|
|
57582
|
+
id: "rule:apex-test-quality/hardcoded-sandbox-data",
|
|
57583
|
+
concept: "concept:apex-test-hardcoded-sandbox-data",
|
|
57584
|
+
bind: { componentTypes: ["ApexClass"], whereProperty: { key: "qualityIssues", anyElement: { key: "rule", equals: "hardcoded-sandbox-test-data" } } },
|
|
57585
|
+
interpretation: "{ids} is an @IsTest class that hardcodes a SANDBOX-SPECIFIC literal \u2014 a username or URL carrying a sandbox marker (a `.sandbox` / `.dev` / `.uat` / `.fullcopy` suffix, a `--sandbox` My Domain segment, or a `sandbox.salesforce.com` host). An Apex test is expected to be org-agnostic and self-contained, building its own fixtures in @TestSetup or a test-data factory; a sandbox-specific literal breaks that, so the test may pass in the sandbox it was written against and then FAIL, or exercise the wrong data, when the code is promoted to production or run in another org \u2014 and because it is a test that failure surfaces only at deploy or run time. Move the value into a Custom Metadata Type or Custom Setting record, or generate it in @TestSetup. This is HEURISTIC recognition from TOKENIZED Apex source \u2014 NOT a compiler AST: it flags the sandbox-marked literal itself and can FLAG a deliberately inert string or MISS a value assembled at runtime. It names a test-portability review candidate, not a proven test failure.",
|
|
57586
|
+
maxConfidence: "heuristic",
|
|
57587
|
+
absenceShaped: false,
|
|
57588
|
+
dependsOnCoverage: ["ApexClass"]
|
|
57589
|
+
},
|
|
57590
|
+
{
|
|
57591
|
+
id: "rule:restriction-rule/inactive",
|
|
57592
|
+
concept: "concept:restriction-rule-inactive",
|
|
57593
|
+
bind: { componentTypes: ["RestrictionRule"], whereProperty: { key: "active", equals: "false" } },
|
|
57594
|
+
interpretation: '{ids} is an INACTIVE restriction rule (its `active` flag is false) \u2014 while inactive it enforces NO narrowing, so the records it would otherwise HIDE stay fully visible to the users it targets under the org-wide default, sharing rules, the role hierarchy, and manual / Apex shares. It must be EXCLUDED from "what can this user NOT see" reasoning and from any conclusion that an object is narrowed on its account: a restriction rule is the sole subtractive sharing mechanism, and a deactivated one subtracts nothing until an admin re-activates it. This is grounded from the rule\'s own `active` flag; it names the non-enforcing STRUCTURAL fact, NOT whether the rule WOULD narrow a specific record if activated (its recordFilter / userCriteria remain unevaluated offline) and NOT why it was deactivated. Only active restriction rules narrow record access.',
|
|
57595
|
+
maxConfidence: "declared",
|
|
57596
|
+
absenceShaped: false,
|
|
57597
|
+
dependsOnCoverage: ["RestrictionRule"]
|
|
57598
|
+
},
|
|
57599
|
+
{
|
|
57600
|
+
id: "rule:approval-process/pending-lock-editable-by-approver",
|
|
57601
|
+
concept: "concept:approval-process-pending-lock-editability",
|
|
57602
|
+
bind: { componentTypes: ["ApprovalProcess"], whereProperty: { key: "recordEditability", equals: "AdminOrCurrentApprover" } },
|
|
57603
|
+
interpretation: '{ids} declares `recordEditability` = AdminOrCurrentApprover \u2014 while a record is PENDING in this approval process it is AUTOMATICALLY LOCKED, and this setting WIDENS who may edit that locked record to include the CURRENTLY-ASSIGNED APPROVER, not only administrators and "Modify All"/"Modify All Data" holders. So the approver evaluating the request can also modify the very record awaiting their decision (an access and audit surface), whereas the default AdminOnly posture bars even the approver from editing while it is pending. This is the DECLARED pending-lock editability from the process\'s own recordEditability flag; it does NOT assert whether any specific record is currently pending or locked (record-level runtime state the offline vault does not hold), WHO the assigned approver is on a given record, or the separate final-approval / final-rejection lock behavior. An approval process set to AdminOnly, or that declares no recordEditability, contributes no approver-edit widening.',
|
|
57604
|
+
maxConfidence: "declared",
|
|
57605
|
+
absenceShaped: false,
|
|
57606
|
+
dependsOnCoverage: ["ApprovalProcess"]
|
|
57607
|
+
},
|
|
57608
|
+
{
|
|
57609
|
+
id: "rule:approval-process/recall-enabled",
|
|
57610
|
+
concept: "concept:approval-process-recall-unlocks-record",
|
|
57611
|
+
bind: { componentTypes: ["ApprovalProcess"], whereProperty: { key: "allowRecall", equals: true } },
|
|
57612
|
+
interpretation: "{ids} declares `allowRecall` = true \u2014 this approval process lets the ORIGINAL SUBMITTER RECALL (withdraw) a still-pending approval request. A recall UNLOCKS the record (it leaves the locked/pending state) and fires the process's recall actions \u2014 the field updates, email alerts, tasks, or outbound messages configured on the recall hook \u2014 so a record can exit the pending approval WITHOUT any approver's decision, purely by submitter action, and that exit runs its own automation. This matters for \"why did this record unlock, or why did this field change while it was in approval?\" reasoning. This names the DECLARED recall capability from the process's own allowRecall flag; it does NOT assert that any specific record was recalled, WHO may submit or recall it, or whether the recall actions succeed. An approval process with allowRecall false permits no submitter recall \u2014 only an approver's action moves a pending record forward.",
|
|
57613
|
+
maxConfidence: "declared",
|
|
57614
|
+
absenceShaped: false,
|
|
57615
|
+
dependsOnCoverage: ["ApprovalProcess"]
|
|
57616
|
+
},
|
|
57617
|
+
{
|
|
57618
|
+
id: "rule:integration/auth-provider-registration-handler",
|
|
57619
|
+
concept: "concept:auth-provider-registration-handler-apex-hook",
|
|
57620
|
+
bind: { componentTypes: ["AuthProvider"], whereProperty: { key: "registrationHandler", isNull: false } },
|
|
57621
|
+
interpretation: "{ids} is an auth provider with a REGISTRATION HANDLER \u2014 an Apex class Salesforce invokes in SYSTEM context on every SSO / social login through this provider to CREATE or UPDATE the authenticating user's User record (just-in-time provisioning), running under the declared executionUser identity rather than the logging-in person. It is a privileged, hidden entry point that can insert Users, assign profiles, and set fields outside the normal permission path. This names the DECLARED handler binding only \u2014 NOT proof that anyone has logged in through this provider, NOT what the handler code does (a separate ApexClass the offline vault does not execute), and NOT that the class still compiles.",
|
|
57622
|
+
maxConfidence: "declared",
|
|
57623
|
+
absenceShaped: false,
|
|
57624
|
+
dependsOnCoverage: ["AuthProvider"]
|
|
57625
|
+
},
|
|
57626
|
+
{
|
|
57627
|
+
id: "rule:integration/platform-event-channel-member-filter",
|
|
57628
|
+
concept: "concept:platform-event-channel-member-filtered-stream",
|
|
57629
|
+
bind: { componentTypes: ["PlatformEventChannelMember"], whereProperty: { key: "filterExpression", isNull: false } },
|
|
57630
|
+
interpretation: "{ids} is a platform event / CDC channel member with a declared FILTER EXPRESSION \u2014 it narrows the channel to only the change events whose fields satisfy that expression, so subscribers see a NARROWED subset of the object's changes and every non-matching change is withheld from this stream. Integrations that assume the full change feed arrives can miss filtered-out records. This is the DECLARED filter text only \u2014 NOT runtime evaluation of which records actually pass (that needs record-level data the offline vault lacks), and NOT the channel's retention / replay / ordering guarantees, which are a separate async concern.",
|
|
57631
|
+
maxConfidence: "declared",
|
|
57632
|
+
absenceShaped: false,
|
|
57633
|
+
dependsOnCoverage: ["PlatformEventChannelMember"]
|
|
57634
|
+
},
|
|
57635
|
+
{
|
|
57636
|
+
id: "rule:integration/external-service-registration-incomplete",
|
|
57637
|
+
concept: "concept:external-service-registration-incomplete",
|
|
57638
|
+
bind: { componentTypes: ["ExternalService"], whereProperty: { key: "status", notIn: ["Complete"] } },
|
|
57639
|
+
interpretation: "{ids} is an external service registration whose status is NOT Complete \u2014 its OpenAPI schema did not finish importing into invocable operations, so its generated actions are UNAVAILABLE and any Flow, Apex, or OmniStudio step that invokes an operation from this registration cannot resolve it and fails. This names the DECLARED status only \u2014 NOT why the import stalled (fetch / auth / parse errors are not captured offline) and NOT whether any component actually calls an operation from this service. Only a Complete registration exposes callable operations.",
|
|
57640
|
+
maxConfidence: "declared",
|
|
57641
|
+
absenceShaped: false,
|
|
57642
|
+
dependsOnCoverage: ["ExternalService"]
|
|
57643
|
+
},
|
|
57644
|
+
{
|
|
57645
|
+
id: "rule:integration/named-credential-per-user-principal",
|
|
57646
|
+
concept: "concept:named-credential-per-user-principal",
|
|
57647
|
+
bind: { componentTypes: ["NamedCredential"], whereProperty: { key: "principalType", equals: "PerUser" } },
|
|
57648
|
+
interpretation: "{ids} is a named credential with a PER-USER principal type \u2014 it carries no shared org-wide identity; each callout authenticates under the running user's own per-user external credential, which every user must configure individually. The same callout authenticates as a different identity per user and FAILS for any user who has not set up their personal credential, and the external system attributes calls to distinct per-user identities rather than one service account. This names the DECLARED per-user posture only \u2014 NOT which users have configured their credential (per-user runtime state the offline vault does not hold) and NOT whether any Apex actually calls through this credential.",
|
|
57649
|
+
maxConfidence: "declared",
|
|
57650
|
+
absenceShaped: false,
|
|
57651
|
+
dependsOnCoverage: ["NamedCredential"]
|
|
57652
|
+
},
|
|
57653
|
+
{
|
|
57654
|
+
id: "rule:omnistudio/test-procedure-scope",
|
|
57655
|
+
concept: "concept:omnistudio-test-procedure-scope",
|
|
57656
|
+
bind: { componentTypes: ["OmniScript", "OmniIntegrationProcedure"], whereProperty: { key: "isTestProcedure", equals: true } },
|
|
57657
|
+
interpretation: "{ids} is flagged as an OmniStudio TEST PROCEDURE (isTestProcedure = true) \u2014 a development test harness whose purpose is to exercise and validate another OmniScript or Integration Procedure, NOT a production user-facing flow. It is not part of the normal production runtime surface: it is invoked to test a target component, not served to end users or dispatched as production automation. EXCLUDE it from 'what actually runs in production', runtime-reachability, and invocation-impact reasoning, and treat it as a likely cleanup candidate in a production org. This names the declared test-procedure flag from the component's own metadata, NOT whether the test currently passes, which component it targets, whether it has ever been run, or whether it is also active (liveness is the separate isActive axis).",
|
|
57658
|
+
maxConfidence: "declared",
|
|
57659
|
+
absenceShaped: false,
|
|
57660
|
+
dependsOnCoverage: ["OmniScript", "OmniIntegrationProcedure"]
|
|
57661
|
+
},
|
|
57662
|
+
{
|
|
57663
|
+
id: "rule:omnistudio/dataraptor-load-fires-assignment-rules",
|
|
57664
|
+
concept: "concept:dataraptor-load-fires-assignment-rules",
|
|
57665
|
+
bind: { componentTypes: ["OmniDataTransform"], whereProperty: { key: "assignmentRulesUsed", equals: true } },
|
|
57666
|
+
interpretation: "{ids} is a DataRaptor with 'Assignment Rules Used' turned ON \u2014 when it writes Lead or Case records (a DataRaptor Load), the insert or update runs with the assignment-rule header set, so the object's ACTIVE assignment rules evaluate on the written records and can reassign record ownership and send assignment email notifications as a SIDE EFFECT of the transform's save. A reader tracing what this transform does must account for that downstream assignment automation, not just the mapped field writes. This names the declared assignment-rules toggle from the transform's own metadata; it does NOT prove the target object has any active assignment rule, that any record is actually reassigned or notified, or that the transform writes Lead / Case at all (only Lead and Case support assignment rules) \u2014 the runtime outcome depends on org data the offline vault does not hold.",
|
|
57667
|
+
maxConfidence: "declared",
|
|
57668
|
+
absenceShaped: false,
|
|
57669
|
+
dependsOnCoverage: ["OmniDataTransform"]
|
|
57670
|
+
},
|
|
57671
|
+
{
|
|
57672
|
+
id: "rule:omnistudio/metadata-cache-disabled",
|
|
57673
|
+
concept: "concept:omnistudio-metadata-cache-disabled",
|
|
57674
|
+
bind: { componentTypes: ["OmniScript", "OmniIntegrationProcedure"], whereProperty: { key: "isMetadataCacheDisabled", equals: true } },
|
|
57675
|
+
interpretation: "{ids} has metadata caching DISABLED (isMetadataCacheDisabled = true) \u2014 the OmniStudio runtime does not cache this component's compiled definition, so it re-reads and recompiles the definition metadata on every load or invocation instead of serving a cached copy. That adds per-request latency, and for an Integration Procedure invoked at volume it repeats that compile work on each call, increasing CPU and metadata-query pressure. Disabling the metadata cache is a documented development / debugging aid that is not meant to ship to a production org. This names the declared cache-disabled configuration flag from the component's own metadata, NOT a measured regression: it does NOT prove any specific slowdown, timeout, or limit breach at runtime, only the disabled-cache posture.",
|
|
57676
|
+
maxConfidence: "declared",
|
|
57677
|
+
absenceShaped: false,
|
|
57678
|
+
dependsOnCoverage: ["OmniScript", "OmniIntegrationProcedure"]
|
|
57679
|
+
},
|
|
57680
|
+
{
|
|
57681
|
+
id: "rule:static-resource/public-cache-control",
|
|
57682
|
+
concept: "concept:static-resource-public-cache-control-exposure",
|
|
57683
|
+
bind: { componentTypes: ["StaticResource"], whereProperty: { key: "cacheControl", equals: "Public" } },
|
|
57684
|
+
interpretation: "{ids} is a static resource whose cacheControl is Public \u2014 the platform caches it in a SHARED, cross-user cache and it can be served to UNAUTHENTICATED guest users through a Site or Experience Cloud resource URL, so its bytes are effectively world-readable to anyone who can reach that URL and must never hold secrets (API keys, tokens, credentials). A Private cacheControl instead scopes caching to the requesting user own session. This names the DECLARED cache-control posture from the resource own metadata; it does NOT prove the resource actually contains sensitive data, that any public page currently references it, or that its URL has been shared \u2014 only that the Public setting makes shared caching and guest exposure possible.",
|
|
57685
|
+
maxConfidence: "declared",
|
|
57686
|
+
absenceShaped: false,
|
|
57687
|
+
dependsOnCoverage: ["StaticResource"]
|
|
57688
|
+
},
|
|
57689
|
+
{
|
|
57690
|
+
id: "rule:custom-metadata-record/protected-namespace-scoped",
|
|
57691
|
+
concept: "concept:custom-metadata-record-protected-namespace-scoped",
|
|
57692
|
+
bind: { componentTypes: ["CustomMetadataRecord"], whereProperty: { key: "protected", equals: true } },
|
|
57693
|
+
interpretation: "{ids} is a PROTECTED custom metadata record \u2014 protected metadata is accessible ONLY to Apex, Flow, and formula code that runs in the SAME namespace that owns it. When this type is packaged and installed in a subscriber org, the subscriber own Apex and SOQL CANNOT read the record, and its protected field values come back masked rather than as real content (which is why protected records are the standard home for package secrets); an unprotected record is readable by any code in the org. This names the DECLARED protection flag from the record own metadata \u2014 a packaging-scoped ACCESS boundary \u2014 NOT the record actual field values (which may be masked and unreadable offline) and NOT whether this org is the owning namespace or a subscriber.",
|
|
57694
|
+
maxConfidence: "declared",
|
|
57695
|
+
absenceShaped: false,
|
|
57696
|
+
dependsOnCoverage: ["CustomMetadataRecord"]
|
|
57697
|
+
},
|
|
57698
|
+
{
|
|
57699
|
+
id: "rule:email-template/unavailable-hidden",
|
|
57700
|
+
concept: "concept:email-template-unavailable-hidden",
|
|
57701
|
+
bind: { componentTypes: ["EmailTemplate"], whereProperty: { key: "available", equals: false } },
|
|
57702
|
+
interpretation: "{ids} has its Available For Use flag set to false \u2014 the template is NOT offered in the email-template picker, so users cannot select it when composing or sending an email through the UI. It is effectively hidden and dormant for manual use and should be EXCLUDED from which-templates-can-a-user-choose surfaces. This names the DECLARED availability flag from the template own metadata; it does NOT prove the template is unused \u2014 automation, email alerts, or Apex that reference it directly by id can still send it \u2014 and it says nothing about the template body or merge fields.",
|
|
57703
|
+
maxConfidence: "declared",
|
|
57704
|
+
absenceShaped: false,
|
|
57705
|
+
dependsOnCoverage: ["EmailTemplate"]
|
|
57706
|
+
},
|
|
57707
|
+
{
|
|
57708
|
+
id: "rule:group/role-subordinates-transitive-membership",
|
|
57709
|
+
concept: "concept:group-role-subordinates-transitive-membership",
|
|
57710
|
+
bind: { edgeType: "hasMember", componentTypes: ["Group", "Role"], edgeWhereProperty: { key: "inheritance", equals: "subordinates" } },
|
|
57711
|
+
interpretation: "Transitive group membership among {ids}: this public group membership includes a role AND its SUBORDINATES, so the group transitively contains the named role plus EVERY role beneath it in the role hierarchy \u2014 the whole subtree is a member. Any access granted to this group \u2014 an owner- or criteria-based sharing rule shared to it, queue ownership, folder access, or list-view sharing \u2014 therefore reaches the entire role subtree, not just a single role. This is the DECLARED membership cascade on the group own member row; it names the ROLES the group pulls in, NOT the individual users occupying them (an assignment question the offline vault does not answer) and NOT any specific record grant.",
|
|
57712
|
+
maxConfidence: "declared",
|
|
57713
|
+
absenceShaped: false,
|
|
57714
|
+
dependsOnCoverage: ["Group", "Role"]
|
|
56827
57715
|
}
|
|
56828
57716
|
]);
|
|
56829
57717
|
}
|
|
@@ -83723,7 +84611,7 @@ var init_refusal_gates = __esm({
|
|
|
83723
84611
|
});
|
|
83724
84612
|
|
|
83725
84613
|
// ../mcp/dist/src/funnel-utterances.js
|
|
83726
|
-
var FUNNEL_UTTERANCES;
|
|
84614
|
+
var FUNNEL_UTTERANCES, INTERPRET_CONCEPT_CARDS;
|
|
83727
84615
|
var init_funnel_utterances = __esm({
|
|
83728
84616
|
"../mcp/dist/src/funnel-utterances.js"() {
|
|
83729
84617
|
"use strict";
|
|
@@ -86031,7 +86919,21 @@ var init_funnel_utterances = __esm({
|
|
|
86031
86919
|
"does a broad assignment rule entry with no criteria appear before more specific queue routing entries?",
|
|
86032
86920
|
"assignment rule first-match ordering \u2014 can an early catch-all entry make later entries unreachable?",
|
|
86033
86921
|
"when an assignment rule has a catch-all entry first, are later specific entries structurally starved by first-match evaluation?",
|
|
86034
|
-
"does entry order on this assignment rule mean a no-criteria row wins before targeted queue rules below it?"
|
|
86922
|
+
"does entry order on this assignment rule mean a no-criteria row wins before targeted queue rules below it?",
|
|
86923
|
+
// ARC-2 concept-expansion — validation-rule-inactive. A deactivated validation
|
|
86924
|
+
// rule never enforces its constraint and must be excluded from save-failure
|
|
86925
|
+
// reasoning. Anchored on the rule-type noun so it does not misbind to
|
|
86926
|
+
// inactive-USER tools. Generic placeholders / standard objects only.
|
|
86927
|
+
"is this validation rule inactive, so it never blocks a save or shows its error message?",
|
|
86928
|
+
"this validation rule is deactivated \u2014 does it still enforce its constraint or is it dead?",
|
|
86929
|
+
"does an inactive validation rule still run in the save order, or can it never fire?",
|
|
86930
|
+
"which validation rules are turned off and therefore never enforce their error condition?",
|
|
86931
|
+
// ARC-2 concept-expansion — workflow-rule-inactive-dead. An inactive workflow
|
|
86932
|
+
// rule never runs its field updates / alerts — dead legacy automation.
|
|
86933
|
+
"is this workflow rule inactive, so its field updates and email alerts never fire?",
|
|
86934
|
+
"this workflow rule is deactivated \u2014 is it dead legacy automation that no longer runs on save?",
|
|
86935
|
+
"does an inactive workflow rule still perform field updates, or has it stopped firing entirely?",
|
|
86936
|
+
"which workflow rules are inactive and therefore never run their actions?"
|
|
86035
86937
|
],
|
|
86036
86938
|
"sfi.find_field_anywhere": [
|
|
86037
86939
|
"find all objects that have a field called External_Id__c",
|
|
@@ -86367,6 +87269,349 @@ var init_funnel_utterances = __esm({
|
|
|
86367
87269
|
"interpret this CODE_UNIT_STARTED / LIMIT_USAGE debug log"
|
|
86368
87270
|
]
|
|
86369
87271
|
};
|
|
87272
|
+
INTERPRET_CONCEPT_CARDS = {
|
|
87273
|
+
"concept:field-longtext-richtext-not-filterable": [
|
|
87274
|
+
"Can I filter a report on the long text area field on Account?",
|
|
87275
|
+
"Why can't I sort a list view by a rich text field?",
|
|
87276
|
+
"Is this long text area field usable in a SOQL WHERE clause?",
|
|
87277
|
+
"Can I make a long text area field an external id or unique?",
|
|
87278
|
+
"Why won't Salesforce let me group by a description field?"
|
|
87279
|
+
],
|
|
87280
|
+
"concept:duplicate-rule-bypass-sharing-match": [
|
|
87281
|
+
"Do any of our duplicate rules match against records the running user can't see?",
|
|
87282
|
+
"Which duplicate rules bypass sharing when they check for duplicates?",
|
|
87283
|
+
"Is there a duplicate rule that runs its duplicate matching in system context?",
|
|
87284
|
+
"Could a duplicate rule block my save because of a duplicate I don't have access to?",
|
|
87285
|
+
"What does bypass sharing rules mean for duplicate matching on Account?",
|
|
87286
|
+
"Show me duplicate rules that ignore the sharing model during matching"
|
|
87287
|
+
],
|
|
87288
|
+
"concept:duplicate-rule-references-inactive-matching-rule": [
|
|
87289
|
+
"Why is my duplicate rule not catching duplicates on Account?",
|
|
87290
|
+
"Why do duplicate records still save even though I have a duplicate rule enabled?",
|
|
87291
|
+
"Is my duplicate rule actually doing anything if its matching rule is inactive?",
|
|
87292
|
+
"What happens when a duplicate rule points at a matching rule that isn't active?",
|
|
87293
|
+
"Does deactivating a matching rule silently break duplicate detection?",
|
|
87294
|
+
"My duplicate rule looks active but duplicates keep getting created \u2014 why?"
|
|
87295
|
+
],
|
|
87296
|
+
"concept:approval-process-final-lock-record-readonly": [
|
|
87297
|
+
"Which approval processes lock the record after final approval?",
|
|
87298
|
+
"Does getting this record approved make it read-only?",
|
|
87299
|
+
"Why does automation fail to update a record after it's been approved?",
|
|
87300
|
+
"What leaves a record locked once an approval process finishes?",
|
|
87301
|
+
"Will a rejected record stay locked from further edits until someone unlocks it?",
|
|
87302
|
+
"Does this approval process leave the record read-only after it completes?"
|
|
87303
|
+
],
|
|
87304
|
+
"concept:record-type-inactive": [
|
|
87305
|
+
"What does it mean that this record type is inactive?",
|
|
87306
|
+
"If a record type is deactivated, can new records still be assigned to it?",
|
|
87307
|
+
"Does an inactive record type still route a page layout or business process to new records?",
|
|
87308
|
+
"This record type has its active flag set to false \u2014 what are the implications?",
|
|
87309
|
+
"Can users pick a deactivated record type when creating a record?",
|
|
87310
|
+
"What happens to a business process when its record type is inactive?"
|
|
87311
|
+
],
|
|
87312
|
+
"concept:remote-site-setting-protocol-security-disabled": [
|
|
87313
|
+
"does this remote site setting allow insecure http callouts?",
|
|
87314
|
+
"which remote site settings have protocol security disabled?",
|
|
87315
|
+
"is this remote site setting insecure?",
|
|
87316
|
+
"can this org make cleartext http callouts to an allowlisted host?",
|
|
87317
|
+
"why would a remote site setting drop the https-only guard on outbound callouts?",
|
|
87318
|
+
"are any of our outbound allowlist entries not requiring https?"
|
|
87319
|
+
],
|
|
87320
|
+
"concept:apex-intentional-system-mode-dml": [
|
|
87321
|
+
"Which Apex classes deliberately run DML in system mode and skip the running user's CRUD and field-level security?",
|
|
87322
|
+
"What does it imply when a class writes records with an explicit AccessLevel.SYSTEM_MODE argument?",
|
|
87323
|
+
"Is there Apex that intentionally opts out of object and field security for a write?",
|
|
87324
|
+
"Which classes do a conscious system-context DML bypass rather than an accidental missing check?",
|
|
87325
|
+
"Does running DML in SYSTEM_MODE mean field-level security is not enforced for that write?"
|
|
87326
|
+
],
|
|
87327
|
+
"concept:dataraptor-field-security-unenforced": [
|
|
87328
|
+
"Does this DataRaptor bypass field-level security when it reads Account fields?",
|
|
87329
|
+
"Which DataRaptors have Check Field Level Security turned off?",
|
|
87330
|
+
"Is this OmniStudio data transform a data-exposure risk for fields the user cannot see?",
|
|
87331
|
+
"Can this DataRaptor overwrite fields the running user has no edit access to?",
|
|
87332
|
+
"Show me DataRaptors that read or write SObject fields without enforcing FLS",
|
|
87333
|
+
"Does turning off field-level security on this DataRaptor over-expose Contact data?"
|
|
87334
|
+
],
|
|
87335
|
+
"concept:field-classic-encrypted-text": [
|
|
87336
|
+
"Is this an encrypted text field, and who can actually see its value?",
|
|
87337
|
+
"why is this field showing asterisks to most users?",
|
|
87338
|
+
"can I filter or report on a classic encrypted text field?",
|
|
87339
|
+
"is this encrypted field usable as an external id or in a formula?",
|
|
87340
|
+
"does this masked field hide its value unless you have View Encrypted Data?"
|
|
87341
|
+
],
|
|
87342
|
+
"concept:field-autonumber-system-assigned-readonly": [
|
|
87343
|
+
"Can I set this auto number field from the API or Apex?",
|
|
87344
|
+
"why can't my integration write to this auto-number field?",
|
|
87345
|
+
"is this auto number field available in a before-save trigger?",
|
|
87346
|
+
"what does it mean that this field is an Auto Number?",
|
|
87347
|
+
"does reformatting an auto number field renumber existing records?"
|
|
87348
|
+
],
|
|
87349
|
+
"concept:field-multiselect-picklist-storage-semantics": [
|
|
87350
|
+
"how is a multi-select picklist stored, and how do I query it?",
|
|
87351
|
+
"why does my equals filter not match this multi-select picklist?",
|
|
87352
|
+
"can a multi-select picklist be the controlling field of a dependent picklist?",
|
|
87353
|
+
"do I need INCLUDES to filter a multiselect picklist in SOQL?",
|
|
87354
|
+
"what are the reporting limitations of a multi-select picklist field?"
|
|
87355
|
+
],
|
|
87356
|
+
"concept:permission-set-license-scoped": [
|
|
87357
|
+
"Which permission sets are bound to a specific user license?",
|
|
87358
|
+
"Is this permission set restricted to users who hold a particular license?",
|
|
87359
|
+
"What does it mean that a permission set has a license set on it?",
|
|
87360
|
+
"Can a permission set that is tied to a license be assigned to any user?",
|
|
87361
|
+
"Which permission sets can only be assigned to users on a matching license?",
|
|
87362
|
+
"Does binding a permission set to a user license limit who can receive its grants?"
|
|
87363
|
+
],
|
|
87364
|
+
"concept:session-based-permission-set-dormant": [
|
|
87365
|
+
"Which permission sets require session activation before their grants apply?",
|
|
87366
|
+
"Is this permission set session-based, so its access stays dormant until activated?",
|
|
87367
|
+
"Does this permission set grant its object and field access passively or only after session activation?",
|
|
87368
|
+
"What permission sets confer no standing access because they are activation-gated?",
|
|
87369
|
+
"Are the CRUD and Apex-class grants on this permission set conditional on session activation?"
|
|
87370
|
+
],
|
|
87371
|
+
"concept:field-restricted-global-value-set": [
|
|
87372
|
+
"Is this picklist field restricted to a fixed set of values?",
|
|
87373
|
+
"Can an admin add new values to this picklist directly on the field?",
|
|
87374
|
+
"Does the Status picklist on Case use a locked-down global value set?",
|
|
87375
|
+
"Will an API write be rejected if it sends a value not in this picklist?",
|
|
87376
|
+
"Which fields share this global value set and can their values drift?",
|
|
87377
|
+
"Is this picklist a closed vocabulary or can users enter free-form values?"
|
|
87378
|
+
],
|
|
87379
|
+
"concept:field-picklist-has-retired-values": [
|
|
87380
|
+
"Which picklist fields still have inactive values?",
|
|
87381
|
+
"Does the Account Industry picklist have any retired values?",
|
|
87382
|
+
"Show me picklists with old values that are no longer selectable",
|
|
87383
|
+
"Are there deactivated picklist values left on Opportunity fields?",
|
|
87384
|
+
"Find fields that kept legacy picklist entries after cleanup",
|
|
87385
|
+
"List picklists carrying retired values from a past migration"
|
|
87386
|
+
],
|
|
87387
|
+
"concept:approval-process-inactive-dead": [
|
|
87388
|
+
"Is this approval process still active?",
|
|
87389
|
+
"Which approval processes on Account are inactive?",
|
|
87390
|
+
"If this approval process is deactivated, does submitting a record for approval do anything?",
|
|
87391
|
+
"Show me the dead approval processes in this org",
|
|
87392
|
+
"Does this inactive approval process still lock records on approval?",
|
|
87393
|
+
"Will its final-approval field update run while the process is off?"
|
|
87394
|
+
],
|
|
87395
|
+
"concept:escalation-rule-time-deferred": [
|
|
87396
|
+
"Do my escalation rules run during the save or later?",
|
|
87397
|
+
"When does a case escalation actually fire?",
|
|
87398
|
+
"Are escalation actions synchronous with the record update?",
|
|
87399
|
+
"Does this escalation rule reassign the case immediately or on a timer?",
|
|
87400
|
+
"Is case escalation part of the save transaction?",
|
|
87401
|
+
"What happens after a record ages past its escalation threshold?"
|
|
87402
|
+
],
|
|
87403
|
+
"concept:auto-response-rule-first-match-starvation": [
|
|
87404
|
+
"Show me the auto-response rules for Lead",
|
|
87405
|
+
"Why did this case get the wrong auto-response email?",
|
|
87406
|
+
"Do any auto-response rule entries never fire?",
|
|
87407
|
+
"Is there a catch-all auto-response entry starving later ones?",
|
|
87408
|
+
"Which auto-response rule entries are unreachable on Case?",
|
|
87409
|
+
"Are my auto-response rule entries in the right order?"
|
|
87410
|
+
],
|
|
87411
|
+
"concept:record-type-business-process-binding": [
|
|
87412
|
+
"Which record types are tied to a specific sales process?",
|
|
87413
|
+
"Does this record type limit which stages are available on an opportunity?",
|
|
87414
|
+
"What business process is bound to the Enterprise record type?",
|
|
87415
|
+
"Why can't I pick this status value on a case with this record type?",
|
|
87416
|
+
"Show me record types that restrict the status picklist to a business process",
|
|
87417
|
+
"Which record types scope the stage picklist to a subset of values?"
|
|
87418
|
+
],
|
|
87419
|
+
"concept:apex-dynamic-reflective-surface": [
|
|
87420
|
+
"Does this Apex class use dynamic SOQL or reflection that static analysis can't see?",
|
|
87421
|
+
"Which classes build queries or field references at runtime?",
|
|
87422
|
+
"Is the impact analysis for this class complete, or are there reflective blind spots?",
|
|
87423
|
+
"Show me Apex that uses dynamic queries, describes, or type reflection",
|
|
87424
|
+
"What classes could have hidden dependencies my usage results miss?",
|
|
87425
|
+
"Are there dynamic-Apex constructs that make dead-code findings unreliable here?"
|
|
87426
|
+
],
|
|
87427
|
+
"concept:named-credential-merge-fields-injectable": [
|
|
87428
|
+
"which named credentials allow merge fields in the HTTP header or body",
|
|
87429
|
+
"are any of our named credentials an injection surface for outbound callouts",
|
|
87430
|
+
"show me named credentials that lifted the default merge-field guard",
|
|
87431
|
+
"list named credentials configured with allowMergeFieldsInHeader or allowMergeFieldsInBody",
|
|
87432
|
+
"which outbound credentials let Apex substitute merge fields into the request"
|
|
87433
|
+
],
|
|
87434
|
+
"concept:connected-app-saml-sso-federation": [
|
|
87435
|
+
"Which connected apps are set up as SAML single sign-on service providers?",
|
|
87436
|
+
"Is this connected app a SAML SSO federation target with Salesforce as the identity provider?",
|
|
87437
|
+
"Which connected apps will Salesforce mint SAML assertions for?",
|
|
87438
|
+
"Does this connected app federate a user's identity out to a third party over SAML?",
|
|
87439
|
+
"What connected apps declare a SAML config instead of, or alongside, OAuth?",
|
|
87440
|
+
"Which connected apps act as SAML service providers we should review as an identity surface?"
|
|
87441
|
+
],
|
|
87442
|
+
"concept:apex-fake-assertion-test": [
|
|
87443
|
+
"Which test classes have fake or tautological assertions?",
|
|
87444
|
+
"Show me tests that assert true or assert a value against itself",
|
|
87445
|
+
"Find Apex tests that pass no matter what the code does",
|
|
87446
|
+
"Are any of my test classes inflating coverage without verifying anything?",
|
|
87447
|
+
"Which tests use System.assertEquals with identical operands?",
|
|
87448
|
+
"List test classes flagged for fake-assertion smells"
|
|
87449
|
+
],
|
|
87450
|
+
"concept:entitlement-process-inactive": [
|
|
87451
|
+
"Which entitlement processes are inactive?",
|
|
87452
|
+
"Is this SLA / entitlement process actually live or disabled?",
|
|
87453
|
+
"Does this entitlement process still start its milestone timers?",
|
|
87454
|
+
"Are any of our SLA processes dead or deactivated?",
|
|
87455
|
+
"Should I count this entitlement process when reasoning about milestones on Cases?",
|
|
87456
|
+
"Why aren't milestones tracking on my Cases?"
|
|
87457
|
+
],
|
|
87458
|
+
"concept:omnistudio-inactive-component-version": [
|
|
87459
|
+
"Which OmniScripts are inactive?",
|
|
87460
|
+
"Do we have any FlexCards that aren't active?",
|
|
87461
|
+
"Is this Integration Procedure live or just a saved draft?",
|
|
87462
|
+
"Which OmniStudio components won't run at runtime?",
|
|
87463
|
+
"Show me the dormant OmniScript versions in this org",
|
|
87464
|
+
"Are any of our OmniStudio components deactivated?"
|
|
87465
|
+
],
|
|
87466
|
+
"concept:required-field-absent-from-all-layouts": [
|
|
87467
|
+
"Which required fields aren't on any page layout?",
|
|
87468
|
+
"Is this required field missing from every layout?",
|
|
87469
|
+
"Do we have required fields with no UI data-entry surface?",
|
|
87470
|
+
"Which required Account fields can't be entered through the UI?",
|
|
87471
|
+
"Show me required fields absent from all page layouts",
|
|
87472
|
+
"Are there any universally required fields not placed on a layout?"
|
|
87473
|
+
],
|
|
87474
|
+
"concept:dataraptor-errors-ignored": [
|
|
87475
|
+
"Which DataRaptors ignore errors instead of failing?",
|
|
87476
|
+
"Are any of our DataRaptor loads swallowing record failures silently?",
|
|
87477
|
+
"Show me OmniStudio data transforms configured to continue on error",
|
|
87478
|
+
"Which DataRaptors could be losing data without reporting it?",
|
|
87479
|
+
"Do any DataRaptors have 'Ignore Error' turned on?",
|
|
87480
|
+
"Find data transforms that don't surface their write failures"
|
|
87481
|
+
],
|
|
87482
|
+
"concept:object-deployment-status-in-development": [
|
|
87483
|
+
"Which custom objects are still In Development instead of Deployed?",
|
|
87484
|
+
"Is this object's deployment status hiding it from users without Customize Application?",
|
|
87485
|
+
"What does an In Development deployment status mean for who can use the object?",
|
|
87486
|
+
"Show me objects whose deployment status is not Deployed yet."
|
|
87487
|
+
],
|
|
87488
|
+
"concept:object-autonumber-name-field": [
|
|
87489
|
+
"Which custom objects use an Auto Number for their Name field?",
|
|
87490
|
+
"Is this object's record Name auto-generated or entered by users?",
|
|
87491
|
+
"Can I set the Name on insert for this object, or is it auto-numbered?",
|
|
87492
|
+
"Does this object's name field auto-assign a formatted sequence?",
|
|
87493
|
+
"What objects have a system-assigned Auto Number record name?"
|
|
87494
|
+
],
|
|
87495
|
+
"concept:global-value-set-has-inactive-value": [
|
|
87496
|
+
"Does this global value set have any deactivated values?",
|
|
87497
|
+
"Which shared value sets retain retired values across every field that uses them?",
|
|
87498
|
+
"Is there an inactive value in this global picklist value set?",
|
|
87499
|
+
"What global value sets carry values that are no longer selectable?",
|
|
87500
|
+
"Are any entries in this shared value set deactivated but still on records?"
|
|
87501
|
+
],
|
|
87502
|
+
"concept:standard-value-set-has-inactive-value": [
|
|
87503
|
+
"Does the Lead Source standard value set have retired values?",
|
|
87504
|
+
"Which standard picklists have deactivated values org-wide?",
|
|
87505
|
+
"Are any Opportunity Stage standard values inactive but still on records?",
|
|
87506
|
+
"Show me standard value sets that retain deactivated entries.",
|
|
87507
|
+
"Is there an inactive value in this standard picklist value set?"
|
|
87508
|
+
],
|
|
87509
|
+
"concept:apex-test-hardcoded-sandbox-data": [
|
|
87510
|
+
"Which test classes have sandbox-specific data baked into them?",
|
|
87511
|
+
"Do any of my Apex tests hardcode a sandbox URL or org suffix?",
|
|
87512
|
+
"Show me tests that won't run in production because of hardcoded sandbox values",
|
|
87513
|
+
"Are there test classes coupled to a specific sandbox environment?",
|
|
87514
|
+
"Which tests reference .sandbox or --sandbox literals instead of using @TestSetup?"
|
|
87515
|
+
],
|
|
87516
|
+
"concept:restriction-rule-inactive": [
|
|
87517
|
+
"Is this restriction rule inactive \u2014 does it still hide any records or is its narrowing switched off?",
|
|
87518
|
+
"does a deactivated restriction rule leave records fully visible under normal sharing?",
|
|
87519
|
+
"this restriction rule has active false \u2014 does it enforce any narrowing until it is reactivated?",
|
|
87520
|
+
"should an inactive restriction rule be excluded from what a user cannot see on Case?",
|
|
87521
|
+
"if a restriction rule is turned off, do the records it would hide become visible again?"
|
|
87522
|
+
],
|
|
87523
|
+
"concept:approval-process-pending-lock-editability": [
|
|
87524
|
+
"Can the approver edit a record while it's pending their approval?",
|
|
87525
|
+
"Which approval processes let the assigned approver modify the locked record during approval?",
|
|
87526
|
+
"Is a submitted record editable by the current approver, or admin-only, while it awaits approval?",
|
|
87527
|
+
"Does this approval process widen pending-record editability to the approver?",
|
|
87528
|
+
"Who can change a record that's locked in an approval process before a decision is made?"
|
|
87529
|
+
],
|
|
87530
|
+
"concept:approval-process-recall-unlocks-record": [
|
|
87531
|
+
"Can a submitter recall a pending approval request on this process?",
|
|
87532
|
+
"Which approval processes allow recall, and what actions fire when a request is recalled?",
|
|
87533
|
+
"What happens when someone recalls an approval \u2014 does the record unlock?",
|
|
87534
|
+
"Does recalling an approval trigger field updates or email alerts?",
|
|
87535
|
+
"Can a record leave an approval process without an approver's decision?"
|
|
87536
|
+
],
|
|
87537
|
+
"concept:auth-provider-registration-handler-apex-hook": [
|
|
87538
|
+
"Which auth providers run a registration handler during SSO login?",
|
|
87539
|
+
"Does the Corporate SSO auth provider provision users just-in-time?",
|
|
87540
|
+
"What Apex runs when someone signs in through our SAML provider?",
|
|
87541
|
+
"Which SSO providers can create User records automatically?",
|
|
87542
|
+
"Show me auth providers with a JIT user-provisioning handler."
|
|
87543
|
+
],
|
|
87544
|
+
"concept:platform-event-channel-member-filtered-stream": [
|
|
87545
|
+
"Which platform event channel members have a filter expression?",
|
|
87546
|
+
"Is the Account CDC channel filtered or does it publish every change?",
|
|
87547
|
+
"What filter narrows the change events on this channel member?",
|
|
87548
|
+
"Do any change data capture subscribers only get a subset of records?",
|
|
87549
|
+
"Which channel members withhold non-matching changes from subscribers?"
|
|
87550
|
+
],
|
|
87551
|
+
"concept:external-service-registration-incomplete": [
|
|
87552
|
+
"Which external service registrations are not fully imported?",
|
|
87553
|
+
"Is the Weather API external service registration complete?",
|
|
87554
|
+
"Which registered external services have unavailable generated actions?",
|
|
87555
|
+
"Do any external service registrations have a broken OpenAPI schema import?",
|
|
87556
|
+
"Show me external services whose status isn't Complete."
|
|
87557
|
+
],
|
|
87558
|
+
"concept:named-credential-per-user-principal": [
|
|
87559
|
+
"Which named credentials use per-user authentication?",
|
|
87560
|
+
"Does the ERP named credential require each user to set up their own login?",
|
|
87561
|
+
"Which callouts authenticate as the running user instead of a service account?",
|
|
87562
|
+
"Are any named credentials per-user rather than a shared named principal?",
|
|
87563
|
+
"Which named credentials will fail for users who haven't configured credentials?"
|
|
87564
|
+
],
|
|
87565
|
+
"concept:omnistudio-test-procedure-scope": [
|
|
87566
|
+
"Which OmniScripts are flagged as test procedures?",
|
|
87567
|
+
"Do we have any Integration Procedure test harnesses left in production?",
|
|
87568
|
+
"Is this OmniScript a test procedure or a real user-facing flow?",
|
|
87569
|
+
"List the OmniStudio components marked isTestProcedure.",
|
|
87570
|
+
"Which OmniStudio test procedures are cleanup candidates in this org?"
|
|
87571
|
+
],
|
|
87572
|
+
"concept:dataraptor-load-fires-assignment-rules": [
|
|
87573
|
+
"Which DataRaptors run assignment rules when they write?",
|
|
87574
|
+
"Does this DataRaptor Load trigger Case assignment rules?",
|
|
87575
|
+
"What OmniStudio transforms reassign record owners on save?",
|
|
87576
|
+
"Which DataRaptors have 'Assignment Rules Used' turned on?",
|
|
87577
|
+
"Will loading Leads through this DataRaptor fire assignment rules?"
|
|
87578
|
+
],
|
|
87579
|
+
"concept:omnistudio-metadata-cache-disabled": [
|
|
87580
|
+
"Which OmniScripts have metadata caching disabled?",
|
|
87581
|
+
"Are any Integration Procedures running with the metadata cache turned off?",
|
|
87582
|
+
"Does this OmniScript recompile its definition on every load?",
|
|
87583
|
+
"List the OmniStudio components with isMetadataCacheDisabled set.",
|
|
87584
|
+
"Which Integration Procedures skip metadata caching in production?"
|
|
87585
|
+
],
|
|
87586
|
+
"concept:static-resource-public-cache-control-exposure": [
|
|
87587
|
+
"Is this static resource safe to store an API key in?",
|
|
87588
|
+
"Which static resources are cached publicly and reachable by guest users?",
|
|
87589
|
+
"Does a Public cache-control static resource leak to unauthenticated Site visitors?",
|
|
87590
|
+
"What is the difference between Private and Public cache-control on my static resources?",
|
|
87591
|
+
"Can a guest user download this static resource without logging in?"
|
|
87592
|
+
],
|
|
87593
|
+
"concept:custom-metadata-record-protected-namespace-scoped": [
|
|
87594
|
+
"Can subscriber code read this protected custom metadata record?",
|
|
87595
|
+
"Why are the values on this custom metadata record masked?",
|
|
87596
|
+
"Is this protected custom metadata type readable outside its managed package?",
|
|
87597
|
+
"Which custom metadata records are namespace-locked to the owning package?",
|
|
87598
|
+
"Does marking a custom metadata record protected hide it from other Apex?"
|
|
87599
|
+
],
|
|
87600
|
+
"concept:email-template-unavailable-hidden": [
|
|
87601
|
+
"Why can't agents pick this email template when composing?",
|
|
87602
|
+
"Which email templates are marked not Available For Use?",
|
|
87603
|
+
"Is this email template hidden from the template picker?",
|
|
87604
|
+
"Does an unavailable email template still get sent by automation?",
|
|
87605
|
+
"What does the Available For Use flag on an email template do?"
|
|
87606
|
+
],
|
|
87607
|
+
"concept:group-role-subordinates-transitive-membership": [
|
|
87608
|
+
"Which public groups pull in an entire role subtree?",
|
|
87609
|
+
"Does this group membership cascade down the role hierarchy?",
|
|
87610
|
+
"If I share to this group, does the whole role-and-subordinates tree get access?",
|
|
87611
|
+
"What roles does this public group transitively include?",
|
|
87612
|
+
"Does a role-and-subordinates group member reach every role beneath it?"
|
|
87613
|
+
]
|
|
87614
|
+
};
|
|
86370
87615
|
}
|
|
86371
87616
|
});
|
|
86372
87617
|
|
|
@@ -86613,7 +87858,7 @@ var init_static_embed = __esm({
|
|
|
86613
87858
|
});
|
|
86614
87859
|
|
|
86615
87860
|
// ../mcp/dist/src/semantic-funnel.js
|
|
86616
|
-
var STOPWORDS, SYNONYMS, PHRASE_SYNONYMS3, applyPhraseSynonyms3, tokenize6, TOOL_KEYWORDS, PLANE_OVERRIDES, planeForTool, EXCLUDED_FROM_CANDIDATES, liveRequiredForPlane, buildPlaneByTool, cachedPlanes, getPlaneByTool, resolveCandidatePlane, EXPANSION_WEIGHT, expandWeighted, CORPUS_EXCLUDED, buildToolDocs, cached, buildIndex, getFunnelIndex, CONF_HIGH_TOP1, CONF_HIGH_MARGIN, CONF_HIGH_COVERAGE, CONF_FLOOR_TOP1, CONF_MIN_COVERAGE, CONF_LOW_MARGIN, CONF_RESCUE_TOP1, CONF_RESCUE_COVERAGE, CONF_LOW_COVERAGE, funnelConfidence, staticEmbedEnabled, fuseStaticEmbeddings, semanticCandidates;
|
|
87861
|
+
var STOPWORDS, SYNONYMS, PHRASE_SYNONYMS3, applyPhraseSynonyms3, tokenize6, TOOL_KEYWORDS, PLANE_OVERRIDES, planeForTool, EXCLUDED_FROM_CANDIDATES, liveRequiredForPlane, buildPlaneByTool, cachedPlanes, getPlaneByTool, resolveCandidatePlane, EXPANSION_WEIGHT, expandWeighted, CORPUS_EXCLUDED, buildToolDocs, TOOL_CONCEPT_CARDS, buildVector, cached, buildIndex, getFunnelIndex, CONF_HIGH_TOP1, CONF_HIGH_MARGIN, CONF_HIGH_COVERAGE, CONF_FLOOR_TOP1, CONF_MIN_COVERAGE, CONF_LOW_MARGIN, CONF_RESCUE_TOP1, CONF_RESCUE_COVERAGE, CONF_LOW_COVERAGE, funnelConfidence, staticEmbedEnabled, fuseStaticEmbeddings, semanticCandidates;
|
|
86617
87862
|
var init_semantic_funnel = __esm({
|
|
86618
87863
|
"../mcp/dist/src/semantic-funnel.js"() {
|
|
86619
87864
|
"use strict";
|
|
@@ -87059,6 +88304,27 @@ var init_semantic_funnel = __esm({
|
|
|
87059
88304
|
}
|
|
87060
88305
|
return docs;
|
|
87061
88306
|
};
|
|
88307
|
+
TOOL_CONCEPT_CARDS = {
|
|
88308
|
+
"sfi.interpret": INTERPRET_CONCEPT_CARDS
|
|
88309
|
+
};
|
|
88310
|
+
buildVector = (toks, idf, idfFallback) => {
|
|
88311
|
+
const vec = /* @__PURE__ */ new Map();
|
|
88312
|
+
if (toks.length === 0)
|
|
88313
|
+
return vec;
|
|
88314
|
+
const tf = /* @__PURE__ */ new Map();
|
|
88315
|
+
for (const t of toks)
|
|
88316
|
+
tf.set(t, (tf.get(t) ?? 0) + 1);
|
|
88317
|
+
let norm = 0;
|
|
88318
|
+
for (const [term, f] of tf) {
|
|
88319
|
+
const w = f / toks.length * (idf.get(term) ?? idfFallback);
|
|
88320
|
+
vec.set(term, w);
|
|
88321
|
+
norm += w * w;
|
|
88322
|
+
}
|
|
88323
|
+
norm = Math.sqrt(norm) || 1;
|
|
88324
|
+
for (const [term, w] of vec)
|
|
88325
|
+
vec.set(term, w / norm);
|
|
88326
|
+
return vec;
|
|
88327
|
+
};
|
|
87062
88328
|
cached = null;
|
|
87063
88329
|
buildIndex = () => {
|
|
87064
88330
|
const docs = buildToolDocs();
|
|
@@ -87081,27 +88347,23 @@ var init_semantic_funnel = __esm({
|
|
|
87081
88347
|
for (const [term, d] of df)
|
|
87082
88348
|
idf.set(term, Math.log((n + 1) / (d + 1)) + 1);
|
|
87083
88349
|
const vectors = /* @__PURE__ */ new Map();
|
|
87084
|
-
for (const [tool, toks] of docTokens)
|
|
87085
|
-
|
|
87086
|
-
|
|
88350
|
+
for (const [tool, toks] of docTokens)
|
|
88351
|
+
vectors.set(tool, buildVector(toks, idf, 0));
|
|
88352
|
+
const idfDefault = Math.log((n + 1) / (1 + 1)) + 1;
|
|
88353
|
+
const conceptCardVectors = /* @__PURE__ */ new Map();
|
|
88354
|
+
for (const [tool, cards] of Object.entries(TOOL_CONCEPT_CARDS)) {
|
|
88355
|
+
if (!vectors.has(tool))
|
|
87087
88356
|
continue;
|
|
88357
|
+
const vecs = [];
|
|
88358
|
+
for (const utterances of Object.values(cards)) {
|
|
88359
|
+
const vec = buildVector(tokenize6(utterances.join(" ")), idf, idfDefault);
|
|
88360
|
+
if (vec.size > 0)
|
|
88361
|
+
vecs.push(vec);
|
|
87088
88362
|
}
|
|
87089
|
-
|
|
87090
|
-
|
|
87091
|
-
tf.set(t, (tf.get(t) ?? 0) + 1);
|
|
87092
|
-
const vec = /* @__PURE__ */ new Map();
|
|
87093
|
-
let norm = 0;
|
|
87094
|
-
for (const [term, f] of tf) {
|
|
87095
|
-
const w = f / toks.length * (idf.get(term) ?? 0);
|
|
87096
|
-
vec.set(term, w);
|
|
87097
|
-
norm += w * w;
|
|
87098
|
-
}
|
|
87099
|
-
norm = Math.sqrt(norm) || 1;
|
|
87100
|
-
for (const [term, w] of vec)
|
|
87101
|
-
vec.set(term, w / norm);
|
|
87102
|
-
vectors.set(tool, vec);
|
|
88363
|
+
if (vecs.length > 0)
|
|
88364
|
+
conceptCardVectors.set(tool, vecs);
|
|
87103
88365
|
}
|
|
87104
|
-
return { vectors, idf, toolCategory };
|
|
88366
|
+
return { vectors, idf, toolCategory, conceptCardVectors };
|
|
87105
88367
|
};
|
|
87106
88368
|
getFunnelIndex = () => cached ??= buildIndex();
|
|
87107
88369
|
CONF_HIGH_TOP1 = 0.27;
|
|
@@ -87200,8 +88462,7 @@ var init_semantic_funnel = __esm({
|
|
|
87200
88462
|
qnorm = Math.sqrt(qnorm) || 1;
|
|
87201
88463
|
if (qvec.size === 0)
|
|
87202
88464
|
return [];
|
|
87203
|
-
const
|
|
87204
|
-
for (const [tool, vec] of idx.vectors) {
|
|
88465
|
+
const dotWith = (vec) => {
|
|
87205
88466
|
let dot = 0;
|
|
87206
88467
|
const [small, large] = qvec.size <= vec.size ? [qvec, vec] : [vec, qvec];
|
|
87207
88468
|
for (const [term, w] of small) {
|
|
@@ -87209,6 +88470,19 @@ var init_semantic_funnel = __esm({
|
|
|
87209
88470
|
if (o !== void 0)
|
|
87210
88471
|
dot += w * o;
|
|
87211
88472
|
}
|
|
88473
|
+
return dot;
|
|
88474
|
+
};
|
|
88475
|
+
const scored = [];
|
|
88476
|
+
for (const [tool, vec] of idx.vectors) {
|
|
88477
|
+
let dot = dotWith(vec);
|
|
88478
|
+
const cards = idx.conceptCardVectors.get(tool);
|
|
88479
|
+
if (cards !== void 0) {
|
|
88480
|
+
for (const cardVec of cards) {
|
|
88481
|
+
const d = dotWith(cardVec);
|
|
88482
|
+
if (d > dot)
|
|
88483
|
+
dot = d;
|
|
88484
|
+
}
|
|
88485
|
+
}
|
|
87212
88486
|
if (dot <= 0)
|
|
87213
88487
|
continue;
|
|
87214
88488
|
const score = dot / qnorm;
|
|
@@ -99681,8 +100955,8 @@ var init_server = __esm({
|
|
|
99681
100955
|
init_tools();
|
|
99682
100956
|
SERVER_NAME = "sf-intelligence";
|
|
99683
100957
|
resolveServerVersion = () => {
|
|
99684
|
-
if ("0.2.
|
|
99685
|
-
return "0.2.
|
|
100958
|
+
if ("0.2.2") {
|
|
100959
|
+
return "0.2.2";
|
|
99686
100960
|
}
|
|
99687
100961
|
for (const rel of ["../package.json", "../../package.json"]) {
|
|
99688
100962
|
try {
|
|
@@ -100548,7 +101822,7 @@ var init_package_version = __esm({
|
|
|
100548
101822
|
"use strict";
|
|
100549
101823
|
readCliPackageVersion = () => {
|
|
100550
101824
|
if (true)
|
|
100551
|
-
return "0.2.
|
|
101825
|
+
return "0.2.2";
|
|
100552
101826
|
for (const rel of ["../package.json", "../../package.json"]) {
|
|
100553
101827
|
try {
|
|
100554
101828
|
const raw = readFileSync6(fileURLToPath4(new URL(rel, import.meta.url)), "utf8");
|
|
@@ -106205,7 +107479,7 @@ var makeShutdownOnce = (ctx) => {
|
|
|
106205
107479
|
|
|
106206
107480
|
// dist/src/commands/demo.js
|
|
106207
107481
|
init_refresh();
|
|
106208
|
-
var buildVersion = () => true ? "0.2.
|
|
107482
|
+
var buildVersion = () => true ? "0.2.2" : "dev";
|
|
106209
107483
|
var SHUTDOWN_SIGNALS2 = ["SIGINT", "SIGTERM"];
|
|
106210
107484
|
var resolveDemoSource = () => {
|
|
106211
107485
|
let dir = dirname25(fileURLToPath5(import.meta.url));
|
|
@@ -107660,7 +108934,7 @@ init_vault_git();
|
|
|
107660
108934
|
init_watch();
|
|
107661
108935
|
var readVersion = () => {
|
|
107662
108936
|
if (true)
|
|
107663
|
-
return "0.2.
|
|
108937
|
+
return "0.2.2";
|
|
107664
108938
|
const pkgUrl = new URL("../../package.json", import.meta.url);
|
|
107665
108939
|
const raw = readFileSync10(fileURLToPath6(pkgUrl), "utf8");
|
|
107666
108940
|
const parsed = JSON.parse(raw);
|