# Observable Checks — detection map Each `[observable]` criterion from `well-architected-rubric.md`, mapped to **how to detect it** (preferred skill/MCP tool first, grep fallback) and **the anti-pattern it flags**. Delegate to the named skill when available; use the grep/Bash pattern for lightweight structural signals or when the skill/tool is unavailable. Conventions below: `` = a package directory from `sfdx-project.json` (usually `force-app`). --- ## 🛡️ Trusted ### Secure | Criterion | Detection | Anti-pattern flagged | |---|---|---| | Sharing keyword on every class | `grep -rLE 'with(out)? sharing\|inherited sharing' --include='*.cls' ` (lists files with NO sharing keyword) | `ApexSharingViolations` — class omits sharing declaration | | FLS/CRUD enforced | `dx-code-analyzer-run` (rule `ApexCRUDViolation`); grep `grep -rn 'WITH USER_MODE\|WITH SECURITY_ENFORCED\|stripInaccessible\|AccessLevel.USER_MODE' --include='*.cls' ` to confirm enforcement present | SOQL/DML with no FLS check | | No SOQL injection | `dx-code-analyzer-run` (rule `ApexSOQLInjection`); grep dynamic SOQL: `grep -rn 'Database.query\|Database.getQueryLocator' --include='*.cls' ` then inspect for string concat vs `:bind` | User input concatenated into SOQL | | No hard-coded secrets | `grep -rnE "(password\|secret\|api[_-]?key\|token)\s*=\s*'[^']+'" --include='*.cls' ` ; check for inline endpoint URLs | Credentials in code instead of Named Credentials | | HTTPS callouts / safe crypto | `dx-code-analyzer-run` (`ApexInsecureEndpoint`, `ApexBadCrypto`); grep `grep -rn "'http://" --include='*.cls' ` | `http://` endpoints; hard-coded IV/key | | Internal OWD not Public R/W | `platform-metadata-retrieve` + `sf org` inspection (org-connected) — inspect `` in object metadata: `grep -rn '' ` | OWD ReadWrite without justification | ### Compliant *(mostly manual — weak file signals only)* | Criterion | Detection | Anti-pattern flagged | |---|---|---| | Accessibility practice in LWC | grep LWC templates for inputs without `label`/`aria-`: `grep -rn ' --include='*.html'` (inspect) | Inputs lacking labels; color-only cues | | Translatable strings | grep for hard-coded user-facing text vs `$Label`: `grep -rn '{!\$Label\|@salesforce/label' ` (presence is a positive signal) | Hard-coded text instead of Custom Labels | > Most Compliant criteria are governance — push to the manual checklist. ### Reliable | Criterion | Detection | Anti-pattern flagged | |---|---|---| | Bulkified DML/SOQL | `dx-code-analyzer-run` (`OperationWithLimitsInLoop`) — primary | SOQL or DML inside a loop | | Selective SOQL | `platform-lsp-integrate` → `check_soql_selectivity`; grep `grep -rniE 'LIKE .%|ALL ROWS' --include='*.cls' ` | Leading-wildcard `LIKE`, `ALL ROWS`, non-selective filters | | No expensive ops in loops | `dx-code-analyzer-run` (`OperationWithHighCostInLoop`) | `Schema.describe*` / callouts in loops | | Async for heavy work | grep `grep -rln 'implements Queueable\|implements Database.Batchable\|@future' --include='*.cls' ` (presence is positive; all-sync heavy logic is the smell) | Heavy/after-commit work forced synchronous | --- ## ⚡ Easy ### Intentional | Criterion | Detection | Anti-pattern flagged | |---|---|---| | No legacy automation | `find -name '*.workflow-meta.xml' -o -name '*.flowDefinition-meta.xml'` ; for Process Builder, grep flow files for `Workflow` | Workflow Rules / Process Builder still active | | No `@future` (prefer Queueable) | `grep -rln '@future' --include='*.cls' ` | `@future` instead of Queueable | | Modern API version | `grep -rn '' --include='*.xml' \| awk -F'[<>]' '$3 < 30'` ; check `sourceApiVersion` in `sfdx-project.json` | API version < 30.0 | | No duplicated standard objects | `find -path '*objects*' -name '*__c.object-meta.xml'` then compare base names to standard objects (Account, Contact, Case, Order, …) | `Account__c`, `Case__c` duplicating standard objects | | Readable naming | Inspect class/object/field names for `Test1`, `tmp`, `asdf`, single letters | Throwaway/cryptic names in committed metadata | | Documentation present | `grep -rL '/\*\*\|//' --include='*.cls' ` (files with no comments at all) | Undocumented classes | ### Automated | Criterion | Detection | Anti-pattern flagged | |---|---|---| | Single-purpose Flows | Inspect Flow metadata count of distinct triggers/objects per flow | One flow doing many unrelated jobs | | Try-catch around DML/SOQL/callouts | `grep -rLn 'try' --include='*.cls' ` cross-referenced with files doing DML/callouts | Unhandled DML/SOQL/callout | | No debug in prod | `dx-code-analyzer-run` (`AvoidDebugStatements`); `grep -rn 'System.debug' --include='*.cls' ` | `System.debug` left in production paths | | Sync-before / async-after | Inspect trigger handlers: DML in `after` contexts vs queued | DML in after-context blocking the transaction | ### Engaging *(manual — UX)* | Criterion | Detection | Anti-pattern flagged | |---|---|---| | LDS over custom Apex for simple CRUD | grep LWC for `lightning/uiRecordApi` vs `@salesforce/apex`: `grep -rln 'lightning/uiRecordApi' ` | Hand-rolled Apex controllers for simple record CRUD | --- ## 🔁 Adaptable ### Resilient | Criterion | Detection | Anti-pattern flagged | |---|---|---| | Source-tracked + CI | `test -d .git` ; `ls .github/workflows/*.yml 2>/dev/null` | No CI; not under source control | | Source/package deploys (not change sets) | `ls manifest/package.xml` (past PoC = smell); confirm `packageDirectories` in `sfdx-project.json` | `package.xml`-driven deployment as the model | | Meaningful tests | `find -name '*Test.cls'` count vs class count; `grep -rln 'SeeAllData=true' --include='*.cls' ` ; check `System.assert` presence | No tests; `SeeAllData=true`; coverage-padding with no assertions | ### Composable | Criterion | Detection | Anti-pattern flagged | |---|---|---| | Thin triggers → handlers | `grep -rEn 'SELECT\|insert \|update \|delete \|for *\(' --include='*.trigger' ` (logic/SOQL/DML/loops inside `.trigger` = smell) | Business logic in trigger body | | CMT over Custom Settings | `find -name '*.md-meta.xml'` (CMT, positive) vs custom settings: `grep -rln '' ` | Custom Settings / custom objects holding runtime config | | Eventing for decoupling | `find -name '*__e.object-meta.xml'` ; `grep -rln 'EventBus.publish' --include='*.cls' ` (presence positive where hand-offs exist) | Tight synchronous coupling for cross-domain hand-offs | | Packageable + `LATEST` aliasing | `grep -n 'LATEST\|"versionNumber"' sfdx-project.json` ; check `packageDirectories` structure | Explicit pinned deps; no package strategy | | No unmanaged packages committed | `grep -rln 'installedPackages' ` ; look for `*.installedPackage-meta.xml` | Unmanaged package artifacts in prod source | | No duplicated metadata across pkg dirs | Compare component names across multiple `packageDirectories` paths | Same metadata in two package dirs | --- ## Mapping `dx-code-analyzer-run` severities → pillars When `dx-code-analyzer-run` returns findings, map by rule: | Rule | Pillar / Sub-pillar | Severity → review verdict | |---|---|---| | `ApexSOQLInjection` | Trusted / Secure | Critical → ❌ | | `ApexCRUDViolation` | Trusted / Secure | High → ❌/⚠️ | | `ApexInsecureEndpoint`, `ApexBadCrypto`, `ApexOpenRedirect` | Trusted / Secure | High → ⚠️ | | `ApexSharingViolations` | Trusted / Secure + Adaptable / Composable | Moderate → ⚠️ | | `OperationWithLimitsInLoop` | Trusted / Reliable + Easy / Automated | Moderate → ⚠️ (❌ if widespread) | | `OperationWithHighCostInLoop` | Trusted / Reliable | Moderate → ⚠️ | | `AvoidDebugStatements` | Easy / Automated | Low → note | | `AvoidNonRestrictiveQueries` | Trusted / Reliable | Low → ⚠️ | ## Notes - Prefer the skill/MCP tool over grep — `dx-code-analyzer-run` understands Apex structure; grep finds string patterns and over/under-reports. Use grep for structural/file-type signals (sharing keyword presence, legacy file types, deploy strategy) where a string match is reliable. - Quote glob patterns passed to tools to stop the shell expanding them. - A grep "hit count" is a signal, not a verdict — open the file and confirm before scoring a finding. - Org-connected checks (OWD, permission sets) require `sf org display` to succeed; otherwise mark them manual.