|
| 1 | +--- |
| 2 | +'@objectstack/spec': minor |
| 3 | +--- |
| 4 | + |
| 5 | +feat(spec)!: retire `rowLevelSecurity[].tags` — no mainstream platform tags a row-level policy, and nothing here ever read one (#20321) |
| 6 | + |
| 7 | +Clause-②: no (narrowing) |
| 8 | + |
| 9 | +**BREAKING** — shipped as `minor` under the launch-window convention |
| 10 | +(`check-changeset-no-major` refuses `major` until GA; breaking-ness is carried by |
| 11 | +this banner, the `(narrowing)` arm above and the ADR-0087 disposition below). |
| 12 | + |
| 13 | +`tags` is removed from the row-level security policy (`RowLevelSecurityPolicySchema`, |
| 14 | +the entries of a permission set's `rowLevelSecurity`). ADR-0049 |
| 15 | +enforce-or-remove, graded RETIRE by the maintainer's criterion for |
| 16 | +declared-but-unenforced families — does a mainstream platform have the |
| 17 | +capability? None does: Salesforce sharing rules, Dataverse security roles and |
| 18 | +PostgreSQL RLS policies carry no tag attribute, and compliance reporting there |
| 19 | +keys on the rule itself. |
| 20 | + |
| 21 | +The key promised "categorization and reporting" for governance and compliance. |
| 22 | +Nothing ever read it. Measured before removal, each against a lit control: the |
| 23 | +RLS compiler reads a policy's `name`, `object`, `operation`, `positions`, |
| 24 | +`enabled` and predicates, never `tags`; objectui's permission preview renders |
| 25 | +the policy COUNT and its policy editor neither seeds nor reads the key; cloud |
| 26 | +has no reader. No example, default permission set or cloud source wrote it. |
| 27 | + |
| 28 | +### FROM → TO |
| 29 | + |
| 30 | +| removed | what to write instead | |
| 31 | +| --- | --- | |
| 32 | +| `rowLevelSecurity[].tags` | delete the key. To limit whom a policy applies to, list the positions in `positions` — a tag never did that. To say why a policy exists, use `description`. | |
| 33 | + |
| 34 | +**The one-line fix: delete `tags:` from every row-level security policy.** |
| 35 | +`os migrate meta --from 17` lists the mechanical edits for existing sources; |
| 36 | +apply them by hand. |
| 37 | + |
| 38 | +⚠️ Runtime behaviour is deliberately **unchanged**. No access decision ever |
| 39 | +depended on a tag, so removing the key removes no behaviour. What changes is the |
| 40 | +answer an author gets: a policy carrying `tags` is now refused at parse, with the |
| 41 | +prescription, instead of being stored with no effect. An author who wrote a tag |
| 42 | +such as `managers_only` believing it scoped the policy now learns that only |
| 43 | +`positions` does. |
| 44 | + |
| 45 | +### The retirement kit |
| 46 | + |
| 47 | +- **A `retiredKey()` tombstone** on `RowLevelSecurityPolicySchema` (the |
| 48 | + `priority` posture one key over): `tsc` types the key `never`, and every parse |
| 49 | + raises the prescription rather than a bare unknown-key verdict. The shape's |
| 50 | + did-you-mean never offers it: a near-miss `tag` is refused as unknown. |
| 51 | +- **D2 conversion `permission-rls-tags-removed`** (step 18, retired from the load |
| 52 | + path): a lossless delete over `permissions[].rowLevelSecurity[]`, so a stored |
| 53 | + permission row that still carries the key replays clean through the |
| 54 | + rehydration seam, while a live author is refused rather than rewritten. |
| 55 | +- **`RETIRED_KEYS_BY_MAJOR[18]`**: `security/RowLevelSecurityPolicy:tags`, and |
| 56 | + the family's D3 entry `permission-rls-tags-retired`, which states what the |
| 57 | + strip cannot decide — any report, audit filter or review process built on the |
| 58 | + belief that policy tags were read needs another path. |
| 59 | +- **The liveness row stays**, `dead`, under its tombstone (the key is still in |
| 60 | + the walked shape); `authorable-surface/security.json` carries it as |
| 61 | + `security/RowLevelSecurityPolicy:tags [RETIRED]`, and the generated reference |
| 62 | + pages print the prescription in place of the old describe. |
| 63 | +- **No deprecation window**, per the project's startup-stage posture. |
| 64 | + |
| 65 | +⚠️ **The out-of-repo consumer population is NOT MEASURED.** `@objectstack/spec` |
| 66 | +is published, so this is breaking for consumers no telemetry was consulted for. |
| 67 | + |
| 68 | +<!-- adr-0087: registered permission-rls-tags-removed, permission-rls-tags-retired --> |
0 commit comments