Validation¶
etcion.validation.permissions
¶
ArchiMate 3.2 Appendix B relationship permission table.
Encodes the normative relationship permission matrix and exposes a lookup function: given a relationship type, source element type, and target element type, returns whether the relationship is permitted by the specification.
Reference: ADR-028; ArchiMate 3.2 Specification, Appendix B.
PermissionRule
¶
Bases: NamedTuple
A single entry in the declarative permission table.
source_type and target_type may be abstract base classes (ABCs)
as well as concrete types; the table intentionally encodes rules at the
ABC level for hierarchical matching. type[Any] is used so mypy does
not raise type-abstract on ABC entries.
warm_cache()
¶
Eagerly build the permission lookup cache.
By default the cache is built lazily on the first is_permitted()
call. Call this function during application startup to pay the cost
upfront and ensure deterministic latency on the first permission check.
This is a no-op if the cache is already built.
Source code in src/etcion/validation/permissions.py
369 370 371 372 373 374 375 376 377 378 379 380 | |
is_permitted(rel_type, source_type, target_type)
¶
Check whether a relationship is permitted per Appendix B.
Universal rules are checked first (ADR-017 ss7):
Composition,Aggregation: permitted between same-type elements.Specialization: permitted between same concrete type only.Association: always permitted between any two concepts.
The Realization(WorkPackage, Deliverable) deprecation special case
(ADR-028 Decision 8) is evaluated after universal short-circuits and
before the cache lookup.
All other rules are resolved via the _PERMISSION_TABLE expanded into
the concrete-type cache.
:param rel_type: The concrete relationship type to check.
:param source_type: The type of the source element.
:param target_type: The type of the target element.
:returns: True if the relationship is permitted; False otherwise.
Source code in src/etcion/validation/permissions.py
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 | |
register_permission_rule(rule)
¶
Append a custom permission rule to the permission table.
.. warning:: Custom permission rules are not portable. Models validated with custom rules may not conform to the ArchiMate 3.2 spec.
The rule is appended to the end of _PERMISSION_TABLE.
Ordering matters: prohibitions (permitted=False) should precede
permissions (permitted=True) within each rel_type group for
correct first-match-wins semantics during cache build.
:param rule: A :class:PermissionRule namedtuple.
:raises TypeError: If rule is not a PermissionRule.
Source code in src/etcion/validation/permissions.py
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 475 476 477 | |
etcion.validation.rules
¶
Custom validation rule protocol.
Reference: ADR-038.
ValidationRule
¶
Bases: Protocol
Protocol for user-defined model validation rules.
Implement this protocol and register instances via
:meth:Model.add_validation_rule.
Example::
class NoEmptyDocs:
def validate(self, model: Model) -> list[ValidationError]:
from etcion.exceptions import ValidationError
return [
ValidationError(f"Element '{e.id}' has no documentation")
for e in model.elements
if not e.description
]
model.add_validation_rule(NoEmptyDocs())
validate(model)
¶
Return a list of validation errors found in model.
Return an empty list if the model passes this rule.
Source code in src/etcion/validation/rules.py
36 37 38 39 40 41 | |