fix(acl): close the #808 review findings — reference variables, owner folder chain, NUL keys, unknown ids (#808)

Review of af5c9744:
1. UNS reference variables (s=Area/Line/Equip/Eff) of a moved or renamed
   equipment stayed readable/writable under the OLD names' grants: they now
   resolve as ReferenceVariable and are authorized at their split path only
   while it equals their live equipment folder's placement (live chain ==
   generation chain) + one name; otherwise denied (Read and Write).
2. TryPlaceScriptedCondition now also requires the owner folder's live chain
   to match the generation (AuthorizeScriptedCondition gains ownerFolderChain),
   so a moved equipment's alarm/children/commands follow its folder.
3. Identifiers containing NUL are denied before the decision cache, keeping
   client ids disjoint from the NUL-prefixed resolved-scope keys (a client
   could otherwise poison a real folder's cached verdict for its key shard).
4. An id no live node holds is Unknown: placed at [\0unknown] so only
   Cluster / Namespace-uns grants decide it (a removed opaque id can no longer
   split onto a same-named narrow grant; narrow grantees get no NodeDeleted for
   removed UNS folders/vtags/conditions — documented); 4-segment
   reference-shaped ids keep their split.
5. A wire test drives placements from DeploymentArtifact.ParseDataPlaneAuthority.

Baseline updates: #797 owner tests (unit + wire) and Sdk2RepeatedAlarmAuthority
now install folder scopes; Sdk2HistoryAuthority's UNS alias used the RAW path
as its UNS id (never minted in production) and now carries EqA/HistoryAlias.
Each new guard was falsified (reverting it fails its test).
This commit is contained in:
Joseph Doherty
2026-11-10 23:44:11 -05:00
parent af5c9744b7
commit e39a125069
11 changed files with 557 additions and 64 deletions
+9 -2
View File
@@ -592,8 +592,15 @@ deploys** (a moved equipment is denied under its old and new line's grants until
virtual tag / its sub-folder at its equipment's path plus a reserved segment; a scripted condition and its children
at the owning equipment's path plus that reserved segment, through exactly the #797 owner rule. The reserved segment
means only grants on the equipment or an ancestor confer them — a `Tag` grant beneath the equipment never does, and
its Browse transit does not expose the equipment's alarms or virtual tags. UNS reference variables
(`s=Area/Line/Equipment/Name`) are unchanged: their id IS their path. Server-object (`i=2253`) delivery of a
its Browse transit does not expose the equipment's alarms or virtual tags. A scripted condition additionally requires
its owner folder's live ancestry to match the generation's (the folder rule). UNS reference variables
(`s=Area/Line/Equipment/Name`) keep their id as their path — but only while it equals their live equipment folder's
placement plus one name, so a moved or renamed equipment's variables (still on the old-name id) are denied for Read
and Write under old and new names until the address space re-points them. An id that no live node holds (a removed
folder / virtual tag / condition, a probe, a NodeDeleted model change) is decided only by a `Cluster` or `uns`
`Namespace` grant — so narrow grantees do not receive NodeDeleted for removed opaque-id nodes, and a removed id can
never match an unrelated narrow grant that shares its name; a four-segment (reference-shaped) id keeps its split.
Identifiers containing NUL are refused. Server-object (`i=2253`) delivery of a
**scripted** condition is now decided on the condition alone (its folders add nothing in steady state and would
leak a moved alarm to its old owner). So a key holding only an `Equipment` grant can navigate to its equipment,
read its alarm children, receive its scripted alarm events through the Server object and Acknowledge / Confirm /