A lightweight capability-based framework for implementing TEKSI workflows.
See https://teksi.github.io/teksi_hooks/index.html
teksi_hooks provides reusable building blocks for rights evaluation, validation,
configuration parsing, hook execution and capability-based dependency injection.
The framework is intentionally domain-agnostic and does not depend on QGIS, PostgreSQL, INTERLIS, wastewater models or any specific application.
Applications compose the framework by providing capabilities and concrete implementations for deployment-specific concerns.
- Dynamic hook loading and execution
- Capability-based dependency injection
- Rights and permission modelling
- Validation framework with findings and severity levels
- Configuration-driven workflows
- Parser and resolver infrastructure
- Extensible identifier types (
Oid) - Domain-independent architecture
- No dependency on QGIS
- No dependency on PostgreSQL
- No dependency on specific TEKSI business models
Hooks implement workflows and extension points.
from teksi_hooks.hook import (
HookBase,
HookContext,
HookMetadata,
)
class Hook(HookBase):
required_capabilities = frozenset()
@property
def metadata(
self,
) -> HookMetadata:
return HookMetadata(
name="Example Hook",
description="Example hook implementation.",
)
def run_hook(
self,
context: HookContext,
) -> None:
context.logger.info(
"Hello from a hook.",
)Capabilities provide application-specific services.
The framework depends on contracts rather than implementations.
context = HookContext(
parameters={},
logger=logger,
capabilities={
SqlCapability: SqlCapability(
connection,
),
},
)Access inside a hook:
sql = context.capability(
SqlCapability,
)Rights, privileges and validation rules can be defined declaratively.
privileges:
DBW_WI:
labels:
de: Datenbewirtschafter Werkinformation
classes:
- id: wastewater_structure
create_rules:
- privileges:
- DBW_WIThe parser produces typed model definitions which are subsequently resolved and evaluated by framework services.
Validation and evaluation produce structured findings.
Finding(
severity=Severity.ERROR,
message="Invalid transition.",
)Findings can be aggregated and raised through framework exceptions.
from teksi_hooks.hook import (
HookContext,
HookHandler,
)
context = HookContext(
parameters={},
logger=logger,
capabilities={},
)
HookHandler(
file="example_hook.py",
).run(
context,
)Application
│
▼
Capabilities
│
▼
Services / Evaluators
│
▼
Resolvers
│
▼
Models
│
▼
Hooks
teksi_hooks/
├── capabilities/
├── evaluators/
├── models/
├── parser/
├── resolver/
├── services/
├── exceptions.py
└── hook.py
Typed domain contracts and value objects.
Examples:
- Oid
- RightsDefinition
- ClassDefinition
- Finding
- Validation rules
Convert external configuration formats into typed model definitions.
Examples:
- RightsParser
- ProviderRightsParser
- WildcardRightsParser
Resolve inheritance, defaults and cross-references.
Apply runtime evaluation logic.
Examples:
- Rights evaluation
- Validation evaluation
- Transition evaluation
Provide reusable orchestration and application services.
Define extension points supplied by the hosting application.
- Explicit over implicit
- Configuration over hard-coding
- No global state
- Capability-based dependency injection
- Strongly typed contracts
- Separation of parsing, resolution and evaluation
- Domain-independent framework core
- Application-defined integrations
GPL-3.0-or-later