The previous LLM-generated knowledge files contained factual
hallucinations. The most visible was the claim that `FindFirst` /
`FindLast` "forces a full-table scan" on an unfiltered record - it does
not; those APIs return a single row via the current key.
Other inaccuracies the audit found and fixed:
* `FindSet(true)` was described as "taking a LockTable". The correct
upstream phrasing is that `FindSet(true)` sets
`ReadIsolation::UpdLock` on the read. UpdLock and LockTable are
related but distinct mechanisms.
* The list of production-scale tables had been invented beyond the
upstream source (e.g. "Detailed Cust. Ledg. Entry") without a
citation. The regenerated list matches the ten tables upstream lists
with their P95 row counts.
* `SetLoadFields` guidance had been augmented with an extra mechanism
claim ("the database resolves the filter using the index without
hydrating the value") not present in upstream.
Approach: full regeneration of `microsoft/knowledge/` from the six
upstream BCApps Code Review instruction files, with Microsoft Learn /
the AL language reference as a secondary source. Every claim in every
regenerated file is anchored to a verbatim upstream quote (or a Learn
URL); the audit trail lives in artifacts/trace-<domain>.json on the
session workspace.
The PR #11 transaction/error-handling cluster is preserved verbatim:
* performance/understand-implicit-transaction-boundary.md
* performance/codeunit-run-as-atomic-sub-operation.{md,good.al,bad.al}
* performance/codeunit-run-requires-prior-commit-inside-transaction.{md,good.al,bad.al}
* performance/use-tryfunction-for-error-catching-not-rollback.{md,good.al,bad.al}
* performance/avoid-commit-inside-loops.{md,good.al,bad.al}
* security/commitbehavior-attribute-scopes-explicit-commits.{md,good.al,bad.al}
* testing/transactionmodel-attribute-governs-test-transactions.{md,good.al,bad.al}
These articles already cite Microsoft Learn and were carefully
cross-referenced; the regeneration skips their topics rather than
duplicating them.
File counts after regeneration:
performance 35 .md (5 preserved + 30 new)
privacy 17 .md
security 18 .md (1 preserved + 17 new)
style 33 .md
testing 1 .md (preserved)
ui 19 .md
upgrade 18 .md
Total 141 atomic knowledge files, each strictly one rule. All pass
.github/scripts/validate_frontmatter.py with 0 errors and 0 warnings.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1.6 KiB
| bc-version | domain | keywords | technologies | countries | application-area | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
security |
|
|
|
|
Use SecretStrSubstNo to compose strings that contain secrets
Description
SecretStrSubstNo is the secret-preserving counterpart of StrSubstNo. It accepts a format string and arguments (any of which may be SecretText) and returns a SecretText — the substitution happens without ever materializing the result as plain Text. It is the right tool whenever a secret needs to be embedded in a larger string: an Authorization: Bearer <token> header value, a URI that includes an API key as a query parameter, or any other interpolation that combines a SecretText with surrounding context.
Best Practice
Compose every secret-bearing string through SecretStrSubstNo and keep the result as SecretText end-to-end. Pass the result to the SecretText overload of the consumer — HttpClient.SetSecretRequestUri, HttpHeaders.Add, or HttpContent.WriteFrom. See sample: secretstrsubstno-for-composing-secrets.good.al.
Anti Pattern
Calling StrSubstNo('Bearer %1', Token.Unwrap()) to build the header value, or concatenating 'Bearer ' + Token.Unwrap(). Both produce a plain Text containing the secret, which is then visible in the debugger and in any subsequent log or trace. Reviewers should flag any Unwrap() whose result is fed into StrSubstNo or used in + concatenation — SecretStrSubstNo removes the need for either. See sample: secretstrsubstno-for-composing-secrets.bad.al.