# Org discovery queries

Status: DRAFT, NOT APPROVED. Written from the Salesforce object references and not yet run in every org edition. Run each once in a sandbox and fix what fails. Tested on: ____________ (date, org).

Replace `<alias>` with your sandbox alias. Queries marked "tooling" need `--use-tooling-api`. These return counts and names. They do not return record contents.

## 1. Active users by profile
```bash
sf data query --target-org <alias> \
  --query "SELECT Profile.Name, COUNT(Id) FROM User WHERE IsActive = true GROUP BY Profile.Name"
```
Does not tell you: which of these users actually log in. See query 11.

## 2. Custom objects (tooling)
```bash
sf data query --use-tooling-api --target-org <alias> \
  --query "SELECT COUNT() FROM CustomObject"
```
Does not tell you: which objects hold data. Counting records per object is a separate query per object.

## 3. Active Flows by type
```bash
sf data query --target-org <alias> \
  --query "SELECT ProcessType, TriggerType, COUNT(Id) FROM FlowDefinitionView WHERE IsActive = true GROUP BY ProcessType, TriggerType"
```
Does not tell you: what each Flow does or whether it runs often.

## 4. Apex classes in your own namespace
```bash
sf data query --target-org <alias> \
  --query "SELECT COUNT() FROM ApexClass WHERE NamespacePrefix = null"
```
Does not tell you: which classes are used. A class can exist and never be called.

## 5. Apex triggers by object
```bash
sf data query --target-org <alias> \
  --query "SELECT Name, TableEnumOrId, Status, ApiVersion FROM ApexTrigger WHERE NamespacePrefix = null ORDER BY TableEnumOrId"
```
Does not tell you: what the trigger does. Several triggers on one object may run in an order you cannot set.

## 6. Validation rules (tooling)
```bash
sf data query --use-tooling-api --target-org <alias> \
  --query "SELECT EntityDefinition.QualifiedApiName, ValidationName, Active FROM ValidationRule ORDER BY EntityDefinition.QualifiedApiName"
```
Does not tell you: the formula. Retrieve the object to read it.

## 7. Workflow Rules (tooling)
```bash
sf data query --use-tooling-api --target-org <alias> \
  --query "SELECT TableEnumOrId, Name FROM WorkflowRule ORDER BY TableEnumOrId"
```
Does not tell you: whether the rule is active or what actions it fires. Check in Setup or retrieve the rule.

## 8. Active Process Builder processes
```bash
sf data query --target-org <alias> \
  --query "SELECT ApiName, Label, LastModifiedDate FROM FlowDefinitionView WHERE IsActive = true AND ProcessType = 'Workflow'"
```
Does not tell you: which object the process runs on. Open the process or retrieve it.

## 9. Scheduled jobs
```bash
sf data query --target-org <alias> \
  --query "SELECT CronJobDetail.Name, CronExpression, State, NextFireTime FROM CronTrigger ORDER BY NextFireTime"
```
Does not tell you: scheduled Flows that are not Apex jobs. Check Setup, Scheduled Jobs, and the Flow list.

## 10. Permission sets (not profile-owned)
```bash
sf data query --target-org <alias> \
  --query "SELECT Name, Label, PermissionsModifyAllData, PermissionsViewAllData FROM PermissionSet WHERE IsOwnedByProfile = false ORDER BY Name"
```
Does not tell you: how many users hold each set. Query `PermissionSetAssignment` for that. Profiles are separate: query `Profile` and read the system permissions in Setup.

## 11. Who logged in, and when
```bash
sf data query --target-org <alias> \
  --query "SELECT Username, Profile.Name, LastLoginDate FROM User WHERE IsActive = true ORDER BY LastLoginDate ASC NULLS FIRST"
```
Does not tell you: what an integration user does. Match the usernames to the client's list of integrations.

## 12. Connected apps
```bash
sf data query --target-org <alias> \
  --query "SELECT Name, CreatedDate FROM ConnectedApplication ORDER BY CreatedDate"
```
Does not tell you: who uses each app today, or external client apps in newer orgs. Check Setup, Connected Apps OAuth Usage.

## Bonus: what depends on a field (tooling, two steps)
Validate both steps in a sandbox before you rely on them.

Step 1: resolve the field's ID, so two fields with the same name on different objects are not mixed up.
```bash
sf data query --use-tooling-api --target-org <alias> \
  --query "SELECT Id FROM CustomField WHERE TableEnumOrId = '<ObjectApiNameOrId>' AND DeveloperName = '<FieldWithout__c>'"
```
For a custom object, `TableEnumOrId` may need the object's ID. Custom fields only: check standard fields by hand.

Step 2: list what depends on that field.
```bash
sf data query --use-tooling-api --target-org <alias> \
  --query "SELECT MetadataComponentId, MetadataComponentName, MetadataComponentType, RefMetadataComponentId FROM MetadataComponentDependency WHERE RefMetadataComponentId = '<FieldIdFromStep1>'"
```
Needs the Tooling API. It does not cover every reference type and results can be capped, so a short list does not prove a short list of dependents. It shows that a dependency exists, not whether it reads or writes. It does not see dynamic strings, outside systems or field names stored as data.
