The binding

generated from the accepted mappings 105 of 936 fields bound

binding.yaml

binding: nordbank-ag revision: 3 model: ict-assurance@2026-07-15 generated: 2026-09-08T14:20:00+02:00 sources: warehouse: kind: aws-rds-postgresql endpoint: nb-grc-ro.eu-central-1.rds.amazonaws.com auth: secretsmanager://dl-reader access: select-only documents: kind: extracted retained: page, sheet and cell of every value entities: ict_asset_inventory: from: warehouse:itsm_prod.SYS_INVENTAR grain: [SYS_ID] fields: asset_id: SYS_ID asset_name: BEZEICHNUNG owner: transform: split_part(VERANTW, ' / ', 2) runs: pushdown coverage: 0.870 # 1,623 rows produce no owner location: transform: parse(STANDORT, 'DC-{site}-{rack}' | 'AWS {region}') runs: pushdown coverage: 0.970 asset_type: TYP status: STATUS owner: VERANTW # team and person in one column location: STANDORT network_segment: NETZ_ZONE last_review_date: LETZTE_PRUEF vendor_support_end_date: SUPPORT_ENDE criticality_classification: column: KRITIKALITAET map: {KRITISCH: CRITICAL, HOCH: HIGH, MITTEL: MEDIUM, NIEDRIG: LOW} unbound: # no source at this tenant - dependencies # required - interfaces # required - redundancy_configuration # required - supporting_function_ids critical_function_register: from: documents:Kritische_Geschaeftsprozesse_2026.xlsx at: "Prozesse 2026!A2:I215" grain: [Prozess-ID] fields: function_id: Prozess-ID function_name: Bezeichnung function_owner: Verantwortlich criticality_tier: Kritikalitätsstufe # 3 tiers, model has 4 recovery_time_objective: transform: to_minutes(Wiederanlaufzeit) runs: platform # the value came from a spreadsheet coverage: 0.930 # 15 rows refused, incl. 4 "sofort" supporting_asset_ids: transform: resolve(split(Betroffene Systeme, ','), against: SYS_INVENTAR.BEZEICHNUNG) runs: platform coverage: 0.610 # 190 of 487 names do not resolve unbound: - business_impact_rating # required derived: # produced, not recorded. Not a binding. ict_asset_inventory.dependencies: from: co-occurrence in STOER_MELD within 15 minutes, 3+ times coverage: 0.147 # 1,840 of 12,481 assets have evidence marked: derived # every answer using it says so relationships: - from: ict_incident_register.affected_asset to: ict_asset_inventory via: STOER_MELD.BETROFF_SYS = SYS_INVENTAR.SYS_ID resolves: 0.992 approved_by: m.bauer@nordbank.de approved_at: 2026-09-08T14:11:00+02:00 - from: critical_function_register.supporting_asset_ids to: ict_asset_inventory via: "text match on SYS_INVENTAR.BEZEICHNUNG" resolves: 0.610 coverage_warning: 83 of 214 rows do not resolve approved_by: pending writes: # the layer describes it, the application does it ict_incident_register.status: to: warehouse:itsm_prod.STOER_MELD.STATUS map: {OPEN: OFFEN, INVESTIGATING: IN_BEARBEITUNG, CLOSED: GESCHLOSSEN} requires: [root_cause_description] # refuse to close without one grant: dl_writer # a second role, never dl_reader audit: [actor, reason, before, after] ict_incident_register.closure_date: to: warehouse:itsm_prod.STOER_MELD.ABGESCHL_AM set: when status becomes CLOSED grant: dl_writer audit: [actor, reason, before, after] ict_asset_inventory.*: to: none reason: > Read-only source. The CMDB is authoritative and owned by IT Infrastructure; an application that wants to change an asset raises a change request instead. remediation_action.*: to: none reason: > Nothing at this tenant stores remediation actions. An application that wants to create one has nowhere to put it, and is told so rather than writing into a free text field.

What is in it, and what is deliberately not

Is in it
Which canonical field reads which physical column, the value maps, the grain, the join paths, and who approved each one and when.
Is in it
unbound. Every required field with no source is named, so a consumer knows what it cannot ask for before it asks.
Is in it
coverage_warning where a join does not fully resolve, so an answer built on it can say so.
Is not in it
Any customer data. The binding is a description of where things are, not a copy of them.
Is in it
transform and its coverage, so a consumer knows a field was reshaped and how many rows the reshaping refused. derived is kept separate from bound fields on purpose.
Is in it
writes. Which canonical fields can be written back, onto which column, through which value map, under which precondition, with which grant. And which ones cannot, with the reason.
Is not in it
Credentials. The source carries a reference to a secret, never the secret.
Is not in it
The writing itself. The layer never holds a write grant; it says what a write would have to look like.
Why this file is the product Bind once and every application below reads the same thing. Without it each one re-derives what KRITIKALITAET means, and they disagree, which is how two dashboards end up giving a board two different numbers for the same KPI.

How the data reaches them

Federated

Queries are resolved against the source when they are asked. Nothing is copied and nothing goes stale.

Materialised

Bound entities are imported on a schedule into a store the platform owns. Fast, and as old as the last run.

Both

The entities that are read constantly are materialised; the rest are federated. One binding drives both.

 FreshnessLoad on the source Data leaves the clientSuits

What snaps onto it

Same binding, six consumers
The Ask assistant
Answers questions in entities, not tables. Reads unbound so it can decline rather than guess, and coverage_warning so it can state its own limits.
POST /v1/semantic/query
Authorization: tenant token
Live
Control assurance engine
Every deterministic control declares the entities it needs. Binding one source makes every control referencing it executable, and the unbound list is exactly the set of controls that cannot run yet.
binding.yaml
GET /v1/entities/{name}
Live
Applications that write back
An assistant closing a finding, or a workflow setting a status, reads writes and acts through its own runtime with its own dl_writer grant. Two applications closing the same finding therefore close it the same way, which is the whole reason the read side is defined once.
writes: from binding.yaml
grant assumed by the application, not the layer
Contract only
BI and dashboards
Generated views over the source, one per bound entity, with the value maps already applied. Power BI and Tableau point at these rather than at SYS_INVENTAR.
CREATE VIEW dl.ict_asset_inventory
18 views, refreshed with the binding
Live
dbt project
Sources and staging models emitted from the same file, so the transformation layer inherits the definitions instead of restating them in SQL.
models/staging/dl_*.sql
sources.yml
On request
Any application, through the SDK
The agentic runtime already used for the other AI use cases resolves entities, fields and relationships through the binding, so a new application is a new prompt rather than a new data project.
pip install revolution
engine.bind("nordbank-ag@3")
Live
Draft, not published Publishing makes this binding the one all five consumers read. Revision 2 stays available, so a consumer that breaks can be pinned back to it.

Revisions of this binding

RevisionChangedFields bound By
3Critical functions bound from the spreadsheet; two document relationships approved 105m.bauer@nordbank.de Draft
2Access reviews and employees bound 88m.bauer@nordbank.de Published
1First binding, assets and incidents only 25s.krause@nordbank.de Superseded