Commit 8fc941a
committed
fix(unified_bridge): authorize against canonical entity type, not bridge alias
Codex P2 review on PR #363 caught a real semantic bug: authorize_read /
authorize_write / authorize_act were passing the bridge-side `public_name`
to Policy::evaluate instead of the canonical OGIT entity type that
`bridge.entity()` had just resolved to.
Concrete failure mode (per Codex's example): WoaBridge maps public name
"WorkOrder" → canonical `ogit.WorkOrder:Order`. A policy granting access
to "Order" (canonical) was being evaluated against "WorkOrder" (alias)
and denying access. Conversely, alias-specific grants could diverge
from canonical policy in either direction.
Fix:
- Switch from `bridge.entity(public_name)` to `bridge.row(public_name)`
in all three authorize_* methods. `row()` returns a `MappingRow`
carrying the canonical OGIT URI in `row.ogit_uri`; the local-name
part (`OgitUri::name()`) is the canonical entity type.
- New `canonical_entity_type(row, public_name)` helper extracts the
canonical name; falls back to `public_name` if the URI somehow
lacks a name part (defensive — a malformed URI shouldn't break
authorization).
- EntityRef constructed directly from `row.schema_ptr` (same pointer
`bridge.entity()` would have returned).
Cost: `bridge.row()` calls `bridge.entity()` internally and then
enumerates the namespace to find the row — O(n) over rows in the
namespace, n ~50 typical. Acceptable on the auth-decision path; the
sub-microsecond hot path is the OwlIdentity bitmask predicate one
layer down (DataFusion plan-rewrite via PolicyRewriter), which this
function gates but does not run on every row.
Two new regression tests:
- `unified_bridge_evaluates_policy_against_canonical_entity_type` —
policy keyed on "Order" allows the call when caller uses alias
"WorkOrder"
- `unified_bridge_does_not_honor_alias_keyed_policy` — inverse: a
policy keyed on the alias "WorkOrder" does NOT grant access through
the canonical-name evaluation path (proves the decoupling)
Both tests use a real OntologyRegistry seeded with a single
MappingProposal where public_name ("WorkOrder") differs from
ogit_uri.name() ("Order"). 6/6 unified_bridge tests pass.
Architectural note: this means a Policy authored against canonical
OGIT entity types is honored regardless of which bridge / public alias
the caller used. Consumer-facing aliases stay decoupled from policy
authorship — Foundry-parity-style tenant policies write canonical OGIT
names once and any bridge that resolves to them honors the grant.
Module docs (//! header on authorize_read) call this out so future
readers don't re-introduce the bug.
Refs: PR #363 review by chatgpt-codex-connector1 parent be472bf commit 8fc941a
1 file changed
Lines changed: 133 additions & 9 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
| 41 | + | |
41 | 42 | | |
42 | 43 | | |
43 | 44 | | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
44 | 58 | | |
45 | 59 | | |
46 | 60 | | |
| |||
240 | 254 | | |
241 | 255 | | |
242 | 256 | | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
243 | 264 | | |
244 | 265 | | |
245 | 266 | | |
246 | 267 | | |
247 | 268 | | |
248 | | - | |
249 | | - | |
250 | | - | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
251 | 273 | | |
252 | 274 | | |
253 | 275 | | |
| 276 | + | |
| 277 | + | |
254 | 278 | | |
255 | 279 | | |
256 | 280 | | |
257 | 281 | | |
258 | 282 | | |
259 | | - | |
260 | | - | |
261 | | - | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
262 | 287 | | |
263 | 288 | | |
264 | 289 | | |
| 290 | + | |
| 291 | + | |
265 | 292 | | |
266 | 293 | | |
267 | 294 | | |
268 | 295 | | |
269 | 296 | | |
270 | | - | |
271 | | - | |
272 | | - | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
273 | 301 | | |
274 | 302 | | |
275 | 303 | | |
| |||
348 | 376 | | |
349 | 377 | | |
350 | 378 | | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | + | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
351 | 475 | | |
0 commit comments