bcquality/microsoft/knowledge/privacy/ship-a-default-retention-policy-setup.md
Jeremy Vyska 02e7ab15b0
Some checks are pending
Validate knowledge index / validate-index (push) Waiting to run
Validate AL review fixtures / validate-review-fixtures (push) Waiting to run
Validate skill index and report schemas / validate-contract (push) Waiting to run
Validate frontmatter and structure / validate (push) Waiting to run
Add retention policy knowledge to the privacy domain (#177)
* Add retention policy knowledge to the privacy domain

Two articles covering retention policies for extension-owned tables,
the gap that lets high-volume log tables grow unbounded:

- register-owned-log-tables-for-retention-policies: an extension's own
  log tables must be added to the allowed-tables list from install AND
  upgrade code, guarded by IsAllowedTable plus an upgrade tag, with a
  mandatory minimum retention where audit needs one.
- ship-a-default-retention-policy-setup: registration only makes a table
  selectable; nothing is deleted until a Retention Policy Setup record
  exists, so ship one (disabled by default) as the platform's own
  Retention Policy Installer does.

Each ships good/bad AL samples. Claims verified against the BC admin
docs and the Retention Policy module in microsoft/BCApps.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gvTjm746MtJEVWeRTbG46

* Address review feedback on retention policy knowledge

- Scope both articles to bc-version [17..] (retention policies shipped in v17).
- Allowed-tables sample: add OnRefreshAllowedTables subscriber with a
  ForceUpdate path; the upgrade tag now gates one-time setup only.
- Default-policy sample: use Retention Policy Setup.FindOrCreateRetentionPeriod
  instead of a hand-rolled lookup-then-insert that can collide on code.
- Anti-pattern now keys on append-only tables rather than table names.
- al-privacy-review: add retention-policy tokens and deterministic routing
  for both articles, with a bounded per-table text search for delete and
  registration paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Address second review round on retention policy knowledge

- Scope both articles to bc-version [22..]: FindOrCreateRetentionPeriod
  first appears in the 21.1 System Application and OnRefreshAllowedTables
  in 22.
- Reframe the default-setup article as optional guidance; registration
  without a setup is valid. The anti-pattern and review routing now cover
  only false claims that registration alone cleans up data.
- Make all four samples self-contained: declare Contoso Activity Log in
  each, add the Retention Policy Setup permission, and guard the default
  setup on IsAllowedTable.
- Let evaluation overrides list additionalArticles and register both
  retention pairs as extra privacy cases (38 cases, existing IDs unchanged).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Revert evaluation harness change for multiple articles per domain

The harness intentionally evaluates one paired article per domain. Keep it
as designed; how the retention pairs join privacy evaluation is left to the
maintainers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Register retention policy pairs in the privacy evaluation override

Use main's articles override so both retention article pairs get positive
and clean cases alongside no-pii-in-telemetry-message-string.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Jeremy Vyska <jeremy@sparebrained.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-05 15:02:04 +02:00

3.7 KiB

bc-version domain keywords technologies countries application-area
22..
privacy
retention-policy
retention-policy-setup
addallowedtable
findorcreateretentionperiod
retention-period
default-policy
unbounded-table-growth
opt-in-deletion
upgrade-tag
al
w1
all

Registering a table does not delete anything — consider shipping a default setup

Description

AddAllowedTable only makes a table selectable on the Retention Policies page. Nothing is deleted until a Retention Policy Setup record exists for that table, names a Retention Period, and is enabled. Registration alone is a valid pattern — several Microsoft apps register tables and leave the policy entirely to the administrator — but it means the table keeps growing until someone discovers the page, works out which of the extension's tables are safe to trim, and picks a period. Shipping a default setup is optional; where the extension's author knows a sensible period, it removes that discovery step. Microsoft's Codeunit 3907 "Retention Policy Installer" shows the shape — it registers Retention Policy Log Entry, then creates a setup record with a six-month period on first install, inserted disabled, guarded by an upgrade tag so a policy the administrator later deleted is not recreated on the next upgrade.

Best Practice

When you ship a default, do it in the same install and upgrade routine that registers the table (see register-owned-log-tables-for-retention-policies.md), and create the Retention Policy Setup record: get the period code from Codeunit "Retention Policy Setup".FindOrCreateRetentionPeriod, which reuses an existing Retention Period with the requested enum value and otherwise creates one without colliding on an existing code (a hand-written lookup-then-insert fails when a period with the chosen code already exists for a different value), then Validate "Table Id", "Apply to all records" and "Retention Period" before inserting. The codeunit that inserts the record needs tabledata "Retention Policy Setup" = ri. Gate the creation on an upgrade tag so it happens once per company rather than on every upgrade. Default to inserting with Enabled set to false: pre-creating the line puts a reviewed, sensible period in front of the administrator while leaving the decision to delete tenant data with them. Shipping the policy enabled is defensible for rows that are purely diagnostic and documented as transient — state that choice, and the default period, in the app's onboarding material either way.

See sample: ship-a-default-retention-policy-setup.good.al.

Anti Pattern

Registering a table and then claiming, in a message, notification, label, teaching tip, or setup text, that its data is now cleaned up automatically. Registration only makes the table selectable; without an enabled Retention Policy Setup nothing is deleted, so the administrator is told a cleanup is running when none is, and the table grows unnoticed. Registration without a default setup is not itself a defect.

See sample: ship-a-default-retention-policy-setup.bad.al.

References