Skip to main content
Jira progress: loading…

ZRR

ZAYAZ Ruleset Registry

1. Purpose and Positioning

The ZAYAZ Ruleset Registry (ZRR) formalizes every enforceable logic construct within the ZAYAZ platform into a first-class, versioned, auditable governance object.

ZRR transforms rules from implicit code fragments into explicit, declarative, traceable artifacts governed under the ZAR (ZAYAZ Artifact Registry) framework.

ZRR ensures that:

  • Every validation rule is addressable.
  • Every compliance rule is traceable to framework obligations.
  • Every computation rule is version-controlled.
  • Every enforcement action is auditable.
  • Every rule lifecycle event is logged.
  • Every rule is compatible with CMCB schema governance.
  • Every rule execution can be explained to verifiers, regulators, and stakeholders.

ZRR is the enforcement abstraction layer between:

  • Signals (SSSR)
  • Ontology (USO)
  • Engines (MICE)
  • Dispatcher (ZSSR)
  • Validation Layer (DICE / DaVE / VTE)
  • Audit Layer (ALTD / DAL)
  • AI Governance Systems

ZRR enables ZAYAZ to operate as a declarative ESG logic platform — not merely a SaaS interface.


2. Canonical Rule Identifier (CRID) Architecture

Every rule registered in ZRR must possess a Canonical Rule Identifier (CRID).

CRID Format

<crid_prefix>.<rule_type>.<domain>.<framework>.<topic>.<profile>.<SEVERITY>.<X_Y_Z>
^ruleset\.(validation|computation|transformation|aggregation|classification|tagging|governance|risk_mapping|ai_assisted)\.[a-z0-9][a-z0-9_-]{0,39}\.[a-z0-9][a-z0-9_-]{0,39}\.[a-z0-9][a-z0-9_-]{0,79}\.[a-z0-9][a-z0-9_-]{0,79}\.(INFO|WARNING|CRITICAL|BLOCKING)\.(0|[1-9][0-9]*)_(0|[1-9][0-9]*)_(0|[1-9][0-9]*)$

Examples

ruleset.validation.ghg.esrs.e1-6.standard.CRITICAL.1_0_0
ruleset.computation.ghg.global.scope3-category4.standard.BLOCKING.2_1_0
ruleset.governance.gov.csrd.g1-4.policy-required.CRITICAL.1_0_0
ruleset.transformation.meta.global.unit-conversion.standard.INFO.3_0_2

CRID Components

ComponentDescription
crid_prefixFixed prefix identifying CRID namespace. Must be ruleset for ruleset artifacts.
rule_typeOne of: validation, computation, transformation, aggregation, classification, tagging, governance, risk_mapping, ai_assisted. Must match zrr.rule_type.
domainDomain code (lowercase) such as ghg, finance, gov, meta, waste, etc.
frameworkFramework namespace such as esrs, csrd, gri, global, iso14001.
topicThe subject identifier: a clause, metric family, or logical object like e1-6, scope3-category4, g1-4, unit-conversion.
profileVariant/profile of the ruleset logic (e.g., standard, policy-required, strict, tenant-acme, sector-mining).
SEVERITYEnforcement severity enum: INFO, WARNING, CRITICAL, BLOCKING (UPPERCASE).
X_Y_ZRuleset semantic version encoded as major_minor_patch (e.g., 1_0_0).

CRIDs are immutable.
A new version always generates a new CRID.


3. Rule Classification Model

Every rule must be classified into one of the following categories:

Ruleset TypeDescription
ValidationRange checks, completeness checks, structural validation
ComputationMathematical transformations, derived metrics
TransformationUnit conversion, structural normalization
AggregationMulti-signal summarization
GovernancePolicy requirement enforcement
Risk MappingRisk categorization and threshold enforcement
AI-AssistedAI-based inference or extrapolation rules

Each ruleset must define:

  • Enforcement Mode
  • Severity Level
  • Execution Engine Binding
  • Fallback Logic
  • Audit Requirements

4. ZRR Core Schema (Logical Model)

ZRR is implemented as a formal registry object under ZAR.

ruleset_registry

ColumnTypeDescription
zar_ruleset_reftext (PK)ZAR:ruleset:<artifact_name>@sha256:<hash> immutable id
rule_idtextCRID (canonical rule identifier), from zrr.crid
rule_nametextHuman title; recommend adding zrr.title
scopetext`global
tenant_idtext nulltenant scope id
entity_idtext nullentity scope id
domaintextfrom zrr.domain
ruleset_kindtexte.g. `tag_detection
rule_typetextfrom zrr.rule_type (Validation/Computation/…)
linked_signal_idsjsonbarray of signal ids
linked_frameworksjsonbarray of frameworks
severity_leveltextINFO/WARNING/CRITICAL/BLOCKING
enforcement_modetextadvisory/soft/hard/blocking/audit_only
execution_enginetextMEID that executes it (zrr.execution_engine)
fallback_logictextnone/manual_escalation/…
ontology_bindingtext nullreference (USO etc.)
schema_min_reftext nullfrom compatibility.min_schema_ref
schema_max_reftext nullfrom compatibility.max_schema_ref
versiontextsemver (explicit), or derived from CRID tail
lifecycle_statustextdraft/approved/frozen/superseded/deprecated
audit_requiredbooleanfrom policy/constraints
zar_content_hashtextsha256 hash (redundant but useful)
created_bytextsystem/governance/admin
created_attimestamptzartifact lifecycle created time
updated_attimestamptzregistry update timestamp

ZRR is part of the ZAR Artifact Layer and inherits:

  • Version lineage tracking
  • DAL registration
  • Federation readiness
  • Assurance cloud propagation

Field mapping: YAML → ruleset_registry

ruleset_registry fieldSource
rule_idzrr.crid (ruleset.…__)
rule_namezar.artifact_name or add zrr.title (recommended)
domainzrr.domain
rule_typezrr.rule_type (validation/computation/classification/tagging…)
linked_signal_idszrr.linked_signal_ids
linked_frameworkszrr.linked_frameworks
severity_levelzrr.severity
execution_enginezrr.execution_engine
schema_version_bindingcompatibility.min_schema_ref + compatibility.max_schema_ref (store both)
versionderived from CRID tail X_Y_Z (or store explicitly as zrr.version if preferred)
active_statuslifecycle.status mapped: approved→active, draft→experimental, deprecated→deprecated
created_atlifecycle.created_at
updated_atset by registry service on ingest/update

5. Rule Binding Architecture

Every rule must bind to at least one of the following:

  • Signal (signal_id)
  • Framework obligation
  • Ontology node (USO)
  • Micro Engine (MEID)
  • Validation engine (DICE / DaVE)
  • Agent profile (optional)
  • AI risk tier (if applicable)

This creates full traceability across:

Signal → Rule → Engine → Enforcement → Audit Log → Assurance Ledger

No rule may execute outside this binding model.


6. Rule Execution Logging

All rule executions must generate a Rule Execution Event.

rule_execution_log (event table)

ColumnTypeDescription
execution_iduuid (PK)unique execution event
zar_ruleset_reftextexact artifact executed
rule_idtextCRID
meidtextengine id that executed
signal_idtext nullif single-signal event
signal_idsjsonb nullif multi-signal event
execution_timestamptimestamptzUTC
execution_resulttextpass/fail/warn
enforcement_action_takentextnone/notify/block/escalate
confidence_scoredouble precision null0–1 for AI-assisted
override_flagbooleanwhether an override applied
overridden_bytext nullidentity
audit_hashtext nullintegrity anchor

Execution logs are stored in:

Rule logs are immutable.


7. Integrity Governance Model

7.1. Scope and Object of Status

Integrity status applies at three levels (all three can exist):

  1. Job Integrity (job_integrity_status)
  2. Dataset Integrity (dataset_integrity_status) — e.g., canonical GL set for a period/entity
  3. Artifact Integrity (artifact_integrity_status) — e.g., transition_project_cost_profile

Normative Rule:
Only dataset_integrity_status controls regulatory reporting eligibility.
Artifact-level integrity may be stricter but cannot override dataset eligibility.


7.2. Canonical Status Enum

7.2.1. Primary states (normative)

StateMeaningReporting eligible?
PENDINGJob started; integrity not assessed yet
IN_PROGRESSCanonicalization or checks running
PASSEDAll blocking and hard checks satisfied
PASSED_WITH_WARNINGSPassed but has warnings (soft/hard warnings below thresholds)✅ (flagged)
FAILEDIntegrity checks failed beyond tolerance / blocking rules triggered
PASSED_WITH_EXCEPTIONFailed originally, but a governed exception is approved and attached✅ (flagged + exception)
REVOKEDPreviously passed/exceptioned status invalidated (ruleset change, exception expiry, data change)

7.2.2. Optional operational states (if useful)

  • CANCELLED (job cancelled)
  • ERROR (system/runtime error; not a data-integrity conclusion)

7.3. Deterministic Inputs to State Transitions

Integrity status is computed from a set of check results produced by rulesets:

  • Tag detection checks (MEID_ACCT_CRAWLER tag ruleset)
  • Classification checks (MEID_ACCT_CRAWLER classification ruleset)
  • Reconciliation checks (MEID_ACCT_CRAWLER reconciliation ruleset)

Each check yields:

  • result: PASS | WARN | FAIL
  • enforcement_mode: advisory | soft | hard | blocking
  • metrics: diffs, counts, ratios
  • crid
  • ruleset_ref
  • timestamp

7.4. Transition Rules

7.4.1. Start / execution

  1. PENDING → IN_PROGRESS Trigger: JobStarted
  2. IN_PROGRESS → FAILED Trigger: any blocking check FAIL and no valid exception exists.
  3. IN_PROGRESS → PASSED_WITH_WARNINGS Trigger: no blocking FAILs, but one or more soft/hard warnings exist.
  4. IN_PROGRESS → PASSED Trigger: all checks PASS (or only advisory warnings).

7.4.2. Exception handling (governed override)

  1. FAILED → PASSED_WITH_EXCEPTION Trigger: IntegrityExceptionApproved event with:
  • matching job_id
  • matching failed_rule_crid
  • matching ruleset_ref (or compatible lineage rule)
  • exception not expired
  1. PASSED_WITH_WARNINGS → PASSED_WITH_EXCEPTION (rare)

Trigger: exception applied to a warning that is treated as blocking for reporting in a specific context (e.g., EU filing requires strict mode). Optional, only if if/when we support “strict compliance mode.”

7.4.3. Revocation (critical for replay + audit)

  1. PASSED → REVOKED Triggers (any):
  • dataset content hash changed (re-ingest, re-canonicalize)
  • ruleset_ref changed for integrity-critical rulesets (reconciliation/classification)
  • schema compatibility boundary violated
  • manual tamper detection / DAL violation

Revocation does not mutate historical artifacts. It creates a new integrity evaluation event referencing the same dataset with updated governance context.

  1. PASSED_WITH_WARNINGS → REVOKED Same triggers as above.

  2. PASSED_WITH_EXCEPTION → REVOKED Triggers (any):

  • exception expired
  • exception deprecated/revoked
  • job/dataset hash changed
  • referenced ruleset_ref changed
  • exception evidence invalidated (optional governance action)

7.4.4. Re-run / recomputation

  1. REVOKED → IN_PROGRESS Trigger: job replay/recompute requested using a specific ruleset_ref set.

7.5. enforcement_mode

7.5.1. What “enforcement_mode” Actually Controls:

It defines:

What happens when the ruleset determines a failure condition. So the key is: what exactly gets blocked?

There are three different “layers” where blocking can apply:

LayerWhat gets blocked
Engine layerThe microservice job execution
Artifact layerPublication of output artifacts
Integrity layer“Integrity = PASSED” status

These are very different in terms of operational impact.

The Four Modes — Operational Meaning

🟢 advisory

  • Rule failure logged
  • No flags
  • No status change
  • No UI impact

Use when:

  • Low-risk signals
  • Informational rules

🟡 soft

  • Rule failure logged
  • Integrity flag attached
  • Warning surfaced in UI/API
  • Artifacts still published

Use when:

  • Data quality issue
  • Not materially misleading
  • CFO review recommended

🟠 hard

  • Rule failure logged
  • Integrity status downgraded
  • Must acknowledge or override
  • Artifacts published but marked non-compliant

Use when:

  • Financial classification uncertainty
  • High unknown ratio
  • Partial reconciliation

This is typically the sweet spot for most finance policy rules.


🔴 blocking

  • Rule failure logged
  • Artifact cannot be marked “valid”
  • Either:
    • Prevent publishing entirely
    • OR publish but status = INVALID and not eligible for downstream reporting
  • Requires manual resolution before progressing workflow

Use when:

  • Ledger integrity failure
  • Double counting risk
  • Currency mismatch without FX policy
  • Schema incompatibility
  • Reconciliation beyond tolerance
Rulesetenforcement_modeInterpretation
Tag detectionsoftFlag if tagging weak
ClassificationhardMust review if unknown high
ReconciliationblockingBlock integrity_passed status

Blocking in the ZRR means:

“Prevents dataset from achieving integrity_passed status and from being used in compliance-critical outputs until resolved or formally overridden.”

7.5.2. Integrity Exception Framework

We treat overrides as Governance Events. An override must:

  • Never delete the original failure
  • Never change the ruleset
  • Never mutate the underlying data
  • Create a separate, immutable governance artifact

Override = “accept deviation with documented justification”

An override does not convert a FAIL into PASS. It produces a distinct state: PASSED_WITH_EXCEPTION.

The following artifact is a first-class governance object.

ZAR:integrity_exception:<entity>:<job_id>@sha256:<hash>

YAML name:

integrity-exception--<job_id>--<ruleset_family>--1_0_0.yaml

Artifact Index Table: zar_artifact_index

zar_artifact_index.sqlGitHub ↗
-- ZAR Artifact Index (minimal)
-- Purpose: fast lookup of ANY ZAR artifact by ref, and filtering by tenant/entity/job/type.

CREATE TABLE zar_artifact_index (
zar_ref TEXT PRIMARY KEY, -- e.g. ZAR:ruleset:acct_crawler_tag_detection@sha256:...
artifact_type TEXT NOT NULL, -- ruleset | schema | integrity_check_report | integrity_exception | dataset | event | ...
artifact_name TEXT NOT NULL, -- human/stable name, not necessarily unique globally
content_hash TEXT NOT NULL, -- sha256:<64hex>
schema_ref TEXT NOT NULL, -- e.g. ZAR:schema:integrity_check_report@v1

tenant_id TEXT NULL, -- null => global artifact
entity_id TEXT NULL, -- null => not entity-scoped
job_id TEXT NULL, -- populated for execution artifacts
run_id TEXT NULL, -- retry/attempt id if applicable

created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
created_by TEXT NULL, -- system|governance|admin|user OR user id/email
lifecycle_status TEXT NULL, -- draft|approved|deprecated (mainly for rulesets/schemas); null for immutable outputs

storage_uri TEXT NOT NULL, -- canonical storage location (S3/GCS/file/DB blob ref)
size_bytes BIGINT NULL,
mime_type TEXT NULL, -- application/yaml, application/json, etc.

metadata JSONB NOT NULL DEFAULT '{}'::jsonb -- optional indexing hints, non-authoritative
);

-- Useful indexes
CREATE INDEX idx_zar_artifact_type ON zar_artifact_index (artifact_type);
CREATE INDEX idx_zar_tenant_entity ON zar_artifact_index (tenant_id, entity_id);
CREATE INDEX idx_zar_job_run ON zar_artifact_index (job_id, run_id);
CREATE INDEX idx_zar_hash ON zar_artifact_index (content_hash);

7.5.3. Minimum required fields for an override:

integrity-exception--JOB-XYZ-123--acct-crawler-reconciliation--1_0_0.yamlGitHub ↗
zar:
artifact_type: integrity_exception
artifact_name: integrity_exception_JOB-XYZ-123
applies_to_meid: MEID_ACCT_CRAWLER

zrr:
crid: ruleset.validation.finance.global.reconciliation.override.standard.critical.1_0_0
rule_type: governance
domain: finance
severity: critical
execution_engine: MEID_ACCT_CRAWLER
enforcement_mode: blocking
audit_required: true

lifecycle:
status: approved
created_by: governance
owners:
- finance.controller@client.com
approved_by:
- finance.controller@client.com
created_at: 2026-03-02T12:34:00Z
supersedes: null
deprecated_by: null
changelog: "Approved reconciliation exception for timing difference."

exception_scope:
level: job
reporting_eligibility_restored: true

context:
exception_id: INT-EXC-2026-0001
job_id: JOB-XYZ-123
ruleset_ref: ZAR:ruleset:acct_crawler_reconciliation_policy@sha256:abc
failed_rule_crid: ruleset.validation.finance.global.reconciliation.standard.critical.1_0_0

failure_snapshot:
entity_diff_abs: 12.45
entity_diff_rel: 0.0008
failed_accounts:
- "6100"
- "6200"

justification: >
Timing difference due to late journal posting.
Verified against closing Trial Balance extract.

supporting_evidence_refs:
- ledger_export_2026_01_v2.pdf
- tb_reconciliation_workpaper.xlsx

risk_assessment: immaterial

expiry_policy:
scope: reporting_year
valid_for: 2026

This ensures:

  • Full traceability
  • Snapshot of failure context
  • Evidence attachment
  • Role-based approval
  • Time-bound validity

7.5.4. Runtime Logic After Override

If exception exists and is valid:

  • integrity_status = PASSED_WITH_EXCEPTION
  • reporting_eligible = true
  • audit_flag = true
  • override_flag = true

Downstream artifacts must include:

"integrity_status": "PASSED_WITH_EXCEPTION",
"exception_ref": "ZAR:integrity_exception:entity@sha256:xyz"

Auditor can then inspect the exception object.


7.5.5. Auditor-Safe Design Principles

To satisfy assurance requirements:

  1. Override Must Be Additive

Original failure event remains immutable.

  1. Override Must Be Linked to Specific Job + Ruleset

If ruleset changes → override invalid.

  1. Override Must Expire

Cannot carry forward silently into next year.

  1. Override Must Be Role-Restricted

Only:

  • Controller
  • CFO
  • Designated governance role
  1. Override Must Be Logged in DAL

Every override creates:

  • RuleExecutionEvent (override=true)
  • DAL hash entry
  • Governance event log

7.5.6. Safe “Fix” vs “Override”

There are two types of resolution:

A. Data Fix (Preferred)

  • Correct connector config
  • Re-run extraction
  • Re-run reconciliation
  • Pass legitimately

No override needed.


B. Accepted Deviation (Controlled Exception)

Used only when:

  • Timing differences
  • FX rounding immaterial
  • Known ERP quirks
  • Minor TB extraction limitations

This is where exception artifact applies.


7.5.7. UX Design (Important)

When reconciliation fails, UI must show:

Integrity Panel

  • Difference amount
  • Threshold
  • Failed accounts
  • Root cause category suggestion

Options:

  1. Fix data and re-run
  2. Adjust ruleset (requires governance approval)
  3. Create exception (requires controller approval)

This ensures:

✔ Structured workflow ✔ No shadow overrides ✔ No hidden toggles


7.5.8. Strategically Powerful

With this system, ZAYAZ can say:

“All integrity deviations are explicitly governed, time-bound, evidence-backed, and auditable.”

  • That is exactly what auditors want.
  • We are not suppressing issues.
  • We are documenting them formally.

7.5.9. Should Overrides Modify Tolerances?

No.

Never mutate ruleset automatically.

If tolerance is wrong:

  • Create new ruleset version
  • Activate new version
  • Re-run job

That maintains replay safety.


7.6. State Machine Diagram (textual)

PENDING
└──(JobStarted)──> IN_PROGRESS
├──(IntegrityEvaluated: Blocking FAIL, no exception)──> FAILED
│ └──(IntegrityExceptionApproved & valid)──> PASSED_WITH_EXCEPTION
├──(IntegrityEvaluated: No blocking FAIL, warnings exist)──> PASSED_WITH_WARNINGS
└──(IntegrityEvaluated: All PASS)──> PASSED

PASSED ──(dataset_hash change OR bundle_ref/ruleset_ref change OR schema_ref incompatibility)──> REVOKED
PASSED_WITH_WARNINGS ──(dataset_hash change OR bundle_ref/ruleset_ref change OR schema_ref incompatibility)──> REVOKED
PASSED_WITH_EXCEPTION ──(exception expiry OR exception revoked OR dataset_hash/bundle_ref change)──> REVOKED
REVOKED ──(Replay/Recompute requested)──> IN_PROGRESS

Pipeline alignment:

JobStarted

Canonicalized

Reconciled

IntegrityEvaluated

Published (publish_allowed may be true even if FAILED)
> Key: we don’t “block artifact generation”; we block **reporting eligibility** (integrity_passed/reporting_eligible).

7.7. Integrity “Blocking” Semantics

Blocking prevents a dataset from reaching PASSED status and from being marked reporting_eligible = true. Blocking does not prevent artifact generation unless a system-level ERROR occurs.

The formal rule is:

  • Artifact generation: always allowed (unless system error)
  • Reporting eligibility: depends on integrity status

Reporting eligibility mapping

Integrity statusreporting_eligiblepublish_allowed
PASSEDtruetrue
PASSED_WITH_WARNINGStrue (flagged)true
PASSED_WITH_EXCEPTIONtrue (flagged + exception_ref required)true
FAILEDfalsetrue
REVOKEDfalsefalse
PENDING/IN_PROGRESSfalsefalse

7.8. Required Metadata Fields (for audit + replay)

Every dataset/artifact must include:

  • integrity_status
  • integrity_ruleset_bundle_refs (all ruleset refs used)
  • integrity_check_results_ref (pointer to check report artifact)
  • exception_ref (nullable; required if PASSED_WITH_EXCEPTION)
  • input_dataset_hash
  • job_id
  • timestamp

7.9. Events (align with the pipeline)

You already have: JobStarted, Canonicalized, Reconciled, Published. Add two governance events:

  • IntegrityEvaluated (emits computed status + check summary ref)
  • IntegrityExceptionApproved (links exception artifact ref)

Optional:

  • IntegrityRevoked (when status becomes REVOKED)

7.10. Practical guardrails for auditors

To make overrides “safe and sound”:

  • PASSED_WITH_EXCEPTION must always carry:
    • exception_ref
    • failed_rule_crid
    • ruleset_ref
    • expiry_policy
    • evidence refs
  • Any change to dataset hash or ruleset ref forces REVOKED
  • Recompute with original refs reproduces original status

7.11. Implementation notes

  • Model as a pure function:

integrity_status = f(check_results, exception?, hashes, ruleset_refs, schema_refs, now)

So it’s deterministic and replayable.

  • Store “check results” as a separate artifact:

ZAR:integrity_check_report:<job_id>@sha256:<hash>

This makes the evaluation explainable.


7.12. ZAR Integrity Check Report Artifact

7.12.1. Artifact definition

Artifact type

integrity_check_report

Normative invariants

  • Must be content-addressable and stored in ZAR:
  • ZAR:integrity_check_report:<job_id>@sha256:<hash>
  • Must include:
    • job_id
    • applies_to_meid
    • dataset_hash (hash of the canonicalized dataset being assessed)
    • all ruleset refs used
    • all check results (including PASS/WARN/FAIL)
    • computed integrity_status (one of the canonical states)
  • Must be replay-safe:
    • same inputs + same rulesets + same dataset_hash ⇒ identical report content (except timestamps if you choose to exclude them from hash; see §4)

7.13. Schemas

7.13.1. Schema & Report Example

Integrity Check Report — JSON Schema (v1)GitHub ↗
[SchemaSnippet] Loading schema "zar/integrity_check_report.v1.schema.json" on client...

Notes:

  • zar_ref is the canonical ID. Everything else is query convenience.
  • metadata is non-authoritative (the artifact file is authoritative). It’s for search/filter performance and UI summaries.

Example integrity_check_report instance

integrity_check_report.jsonGitHub ↗
{
"zar": {
"artifact_type": "integrity_check_report",
"artifact_name": "integrity_check_report_JOB-XYZ-123",
"applies_to_meid": "MEID_ACCT_CRAWLER",
"content_hash": "sha256:1111111111111111111111111111111111111111111111111111111111111111",
"schema_ref": "ZAR:schema:integrity_check_report@v1"
},
"scope": {
"level": "dataset",
"object_ref": "<ZAR:dataset:...@sha256:...>"
},
"context": {
"job_id": "JOB-XYZ-123",
"run_id": "RUN-XYZ-123-1",
"tenant_id": "TENANT-ACME",
"entity_id": "ENTITY-ACME-DE",
"generated_at": "2026-02-17T10:12:00Z",
"initiated_by": "system",
"mode": "standard"
},
"dataset": {
"dataset_type": "canonical_trial_balance",
"dataset_hash": "sha256:2222222222222222222222222222222222222222222222222222222222222222",
"schema_ref": "ZAR:schema:canonical_trial_balance@v1",
"period": { "start": "2026-01-01", "end": "2026-01-31", "reporting_year": 2026 },
"source_systems": ["netsuite"],
"record_counts": { "lines_total": 12045, "accounts_total": 412, "projects_total": 18 }
},
"rulesets": {
"bundle_ref": "ZAR:ruleset_bundle:acct_crawler_default@sha256:3333333333333333333333333333333333333333333333333333333333333333",
"resolved": [
{
"ruleset_ref": "ZAR:ruleset:acct_crawler_tag_detection@sha256:aaaa",
"artifact_name": "acct_crawler_tag_detection",
"crid": "ruleset.tag_detection.finance.global.transition.standard.warning.1_0_0",
"enforcement_mode": "soft"
},
{
"ruleset_ref": "ZAR:ruleset:acct_crawler_classification@sha256:bbbb",
"artifact_name": "acct_crawler_classification",
"crid": "ruleset.classification.finance.global.capex-opex.standard.warning.1_0_0",
"enforcement_mode": "hard"
},
{
"ruleset_ref": "ZAR:ruleset:acct_crawler_reconciliation_policy@sha256:cccc",
"artifact_name": "acct_crawler_reconciliation_policy",
"crid": "ruleset.validation.finance.global.reconciliation.standard.critical.1_0_0",
"enforcement_mode": "blocking"
}
]
},
"checks": [
{
"check_id": "TB_ENTITY_DIFF",
"crid": "ruleset.validation.finance.global.reconciliation.standard.critical.1_0_0",
"ruleset_ref": "ZAR:ruleset:acct_crawler_reconciliation_policy@sha256:cccc",
"category": "reconciliation",
"result": "FAIL",
"severity": "BLOCKING",
"enforcement_layer": "integrity",
"message": "Entity-level TB reconciliation diff exceeds absolute tolerance.",
"metrics": { "entity_diff_abs": 12.45, "entity_diff_rel": 0.0008, "abs_tol": 5.0, "rel_tol": 0.0001 }
},
{
"check_id": "UNKNOWN_CLASSIFICATION_RATIO",
"crid": "ruleset.classification.finance.global.capex-opex.standard.warning.1_0_0",
"ruleset_ref": "ZAR:ruleset:acct_crawler_classification@sha256:bbbb",
"category": "classification",
"result": "WARN",
"severity": "WARNING",
"message": "Unknown classification ratio exceeds preferred threshold but below hard fail threshold.",
"metrics": { "unknown_ratio": 0.012, "warn_threshold": 0.01, "fail_threshold": 0.02 }
}
],
"summary": {
"integrity_status": "FAILED",
"reporting_eligible": false,
"publish_allowed": true,
"exception_ref": null,
"counts": { "pass": 0, "warn": 1, "fail": 1 },
"failed_rule_crids": [
"ruleset.validation.finance.global.reconciliation.standard.critical.1_0_0"
],
"warnings": [
"Classification unknown ratio above preferred threshold."
]
}
}

Tie to IntegrityEvaluated event

When IntegrityEvaluated is emitted, include:

  • integrity_check_report_ref (ZAR ref)
  • integrity_status
  • failed_rule_crids
  • dataset_hash
  • ruleset_bundle_ref

This makes the event log minimal but fully traceable.


7.13.2. Canonicalization + hashing rules (so ZAR refs are stable)

To ensure deterministic content_hash:

  1. Canonicalize JSON before hashing:
  • UTF-8
  • sorted object keys recursively
  • arrays preserve order
  • remove insignificant whitespace
  1. Either:
  • include generated_at in hash (strict immutability), OR
  • move timestamps into a separate non-hashed envelope and hash only a hash_basis object.

Recommendation: For audit trails, keep timestamp in the artifact, but compute hash over everything except generated_at if you want stable reproduction across replays. If you want strict immutability per run, keep it included.

Given the replay goal (“same inputs, same outputs”), we'll do:

  • generated_at included in artifact
  • content_hash_basis excludes it

7.13.3. integrity_report_registry (SSSR table spec)

Purpose

A query-optimized registry of integrity outcomes produced by integrity evaluation runs. Each row represents the integrity conclusion for a specific (scope, tenant, entity, period, dataset_hash, ruleset_bundle_ref) and links to the authoritative ZAR artifacts:

  • integrity_check_report_ref (full check details)
  • optional exception_ref (governed override)
  • optional revocation_ref (revocation event/artifact)

Table

Postgres SQL DDL — integrity_report_registry

integrity_report_registry.sqlGitHub ↗
DO $$ BEGIN
CREATE TYPE integrity_mode AS ENUM ('standard', 'strict_compliance');
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

DO $$ BEGIN
CREATE TYPE integrity_scope_level AS ENUM ('job','dataset','artifact');
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

DO $$ BEGIN
CREATE TYPE integrity_status_enum AS ENUM (
'PENDING','IN_PROGRESS','PASSED','PASSED_WITH_WARNINGS','FAILED','PASSED_WITH_EXCEPTION','REVOKED'
);
EXCEPTION WHEN duplicate_object THEN NULL; END $$;

CREATE TABLE IF NOT EXISTS integrity_report_registry (
integrity_id TEXT PRIMARY KEY,

-- ZAR binding (if you have the ZAR ref at write-time)
artifact_ref TEXT UNIQUE NULL, -- recommended to populate; can be backfilled from zar_artifact_index
artifact_name TEXT NOT NULL,
artifact_type TEXT NOT NULL DEFAULT 'integrity_check_report',
applies_to_meid TEXT NOT NULL,
content_hash TEXT NOT NULL,
schema_ref TEXT NOT NULL,

-- scope
scope_level integrity_scope_level NOT NULL DEFAULT 'dataset',
scope_object_ref TEXT NOT NULL,
scope_hash TEXT NOT NULL,

-- context
job_id TEXT NOT NULL,
run_id TEXT NULL,
tenant_id TEXT NOT NULL,
entity_id TEXT NOT NULL,
generated_at TIMESTAMPTZ NOT NULL,
initiated_by TEXT NOT NULL DEFAULT 'system',
mode integrity_mode NOT NULL DEFAULT 'standard',

-- dataset
dataset_type TEXT NOT NULL,
dataset_hash TEXT NOT NULL,
dataset_schema_ref TEXT NOT NULL,
period_start DATE NOT NULL,
period_end DATE NOT NULL,
reporting_year INT NOT NULL,
source_systems JSONB NOT NULL DEFAULT '[]'::jsonb,
record_counts JSONB NOT NULL DEFAULT '{}'::jsonb,

-- rulesets
ruleset_bundle_ref TEXT NOT NULL,
ruleset_resolved JSONB NOT NULL DEFAULT '[]'::jsonb,
ruleset_refs JSONB NOT NULL DEFAULT '[]'::jsonb,
ruleset_crids JSONB NOT NULL DEFAULT '[]'::jsonb,

-- summary
integrity_status integrity_status_enum NOT NULL,
reporting_eligible BOOLEAN NOT NULL DEFAULT FALSE,
publish_allowed BOOLEAN NOT NULL DEFAULT FALSE,
integrity_passed BOOLEAN NOT NULL DEFAULT FALSE,
exception_ref TEXT NULL,
counts_pass INT NOT NULL DEFAULT 0,
counts_warn INT NOT NULL DEFAULT 0,
counts_fail INT NOT NULL DEFAULT 0,
failed_rule_crids JSONB NOT NULL DEFAULT '[]'::jsonb,
warnings JSONB NOT NULL DEFAULT '[]'::jsonb,

-- checks (optional denormalized cache)
check_results JSONB NOT NULL DEFAULT '[]'::jsonb,
check_ids_failed JSONB NOT NULL DEFAULT '[]'::jsonb,
check_ids_warn JSONB NOT NULL DEFAULT '[]'::jsonb,
top_failure_category TEXT NULL,
flags JSONB NOT NULL DEFAULT '[]'::jsonb,

created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

-- constraints
ALTER TABLE integrity_report_registry
ADD CONSTRAINT chk_dataset_hash_format
CHECK (dataset_hash ~ '^sha256:[0-9a-f]{64}$');

ALTER TABLE integrity_report_registry
ADD CONSTRAINT chk_content_hash_format
CHECK (content_hash ~ '^sha256:[0-9a-f]{64}$');

ALTER TABLE integrity_report_registry
ADD CONSTRAINT chk_exception_ref_required
CHECK (
(integrity_status <> 'PASSED_WITH_EXCEPTION')
OR (exception_ref IS NOT NULL)
);

-- indexes
CREATE INDEX IF NOT EXISTS idx_ir_tenant_entity_year
ON integrity_report_registry (tenant_id, entity_id, reporting_year);

CREATE INDEX IF NOT EXISTS idx_ir_status_eligible
ON integrity_report_registry (integrity_status, reporting_eligible);

CREATE INDEX IF NOT EXISTS idx_ir_dataset_hash
ON integrity_report_registry (dataset_hash);

CREATE INDEX IF NOT EXISTS idx_ir_job
ON integrity_report_registry (job_id);

CREATE INDEX IF NOT EXISTS idx_ir_ruleset_bundle
ON integrity_report_registry (ruleset_bundle_ref);

CREATE INDEX IF NOT EXISTS gin_ir_failed_rule_crids
ON integrity_report_registry USING GIN (failed_rule_crids);

CREATE INDEX IF NOT EXISTS gin_ir_ruleset_refs
ON integrity_report_registry USING GIN (ruleset_refs);

CREATE INDEX IF NOT EXISTS gin_ir_flags
ON integrity_report_registry USING GIN (flags);

CREATE INDEX idx_integrity_scope_hash
ON integrity_report_registry(scope_hash);

Note: the “revocation_ref required on REVOKED” constraint is strict. If we want to allow REVOKED without an explicit artifact, remove that constraint and treat it as recommended.


7.13.3. Projection mapping — integrity_check_reportintegrity_report_registry

This assumes the integrity_check_report JSON schema includes these (or similar) top-level structures:

  • meta (job_id, tenant_id, entity_id, meid, timestamps)
  • scope (level + object ref)
  • dataset (type, hash, schema_ref, period)
  • rulesets (bundle ref + array refs + mode)
  • summary (integrity_status, reporting_eligible, publish_allowed, counts)
  • checks (array of check objects with result, crid, enforcement_mode, category, flags)

If the actual report differs, keep the same mapping approach—just adjust paths.


Deterministic derivations (normative)

A) integrity_id (deterministic)

Recommended formula (stable, unique enough, replay-safe):

integrity_id =
"INT-" + tenant_id + "-" + entity_id + "-" + scope_level + "-" +
reporting_year + "-" + period_label + "-" +
substring(dataset_hash, 8, 12) + "-" +
substring(sha256(ruleset_bundle_ref), 1, 8) + "-" +
mode
  • Use dataset_hash + ruleset_bundle_ref + period as anchor inputs.
  • It is also possible to store supersedes_integrity_id if lineage chains is needed/wanted.

B) integrity_passed (canonical)

integrity_passed = integrity_status IN (
'PASSED', 'PASSED_WITH_WARNINGS', 'PASSED_WITH_EXCEPTION'
)

C) reporting_eligible and publish_allowed (canonical)

From the governance model:

integrity_statusreporting_eligiblepublish_allowed
PASSEDtruetrue
PASSED_WITH_WARNINGStruetrue
PASSED_WITH_EXCEPTIONtruetrue
FAILEDfalsetrue
REVOKEDfalsefalse
PENDING/IN_PROGRESSfalsefalse

So:

  • If report contains these booleans in summary, trust them.
  • Otherwise compute them deterministically from integrity_status.

Field-by-field mapping table

Registry ColumnSource in integrity_check_reportRule
artifact_typezar.artifact_typeMust equal integrity_check_report.
artifact_namezar.artifact_nameRequired.
applies_to_meidzar.applies_to_meidRequired.
content_hashzar.content_hashRequired, format sha256:<hash>.
schema_refzar.schema_refRequired.
scope_levelscope.levelMust be one of job / dataset / artifact.
scope_object_refscope.object_refPreferred: ZAR ref for the scoped object (e.g., ZAR:dataset:...@sha256:...). Required for deterministic identity.
job_idcontext.job_idRequired.
run_idcontext.run_idOptional.
tenant_idcontext.tenant_idRequired.
entity_idcontext.entity_idRequired.
generated_at±Required.
initiated_bycontext.initiated_byOptional; default system.
modecontext.modeDefault standard.
dataset_typedataset.dataset_typeRequired.
dataset_hashdataset.dataset_hashRequired, format sha256:<hash>.
dataset_schema_refdataset.schema_refRequired.
period_startdataset.period.startRequired.
period_enddataset.period.endRequired.
reporting_yeardataset.period.reporting_yearRequired.
source_systemsdataset.source_systemsOptional array.
record_countsdataset.record_countsOptional object.
ruleset_bundle_refrulesets.bundle_refRequired.
ruleset_resolvedrulesets.resolvedFull resolved ruleset list (good to store).
ruleset_refsderived from rulesets.resolved[].ruleset_refNormalize + unique.
ruleset_cridsderived from rulesets.resolved[].cridNormalize + unique.
integrity_statussummary.integrity_statusRequired enum.
reporting_eligiblesummary.reporting_eligibleIf missing, compute from status mapping.
publish_allowedsummary.publish_allowedIf missing, compute from status mapping.
integrity_passedderived from summary.integrity_statustrue if status in {PASSED, PASSED_WITH_WARNINGS, PASSED_WITH_EXCEPTION}.
exception_refsummary.exception_refNullable. Can later be updated via IntegrityExceptionApproved.
counts_passsummary.counts.passIf missing, count checks where result=PASS.
counts_warnsummary.counts.warnIf missing, count checks where result=WARN.
counts_failsummary.counts.failIf missing, count checks where result=FAIL.
failed_rule_cridssummary.failed_rule_crids OR derive from checks[]Prefer summary; else all FAIL checks[].crid.
warning_rule_cridsderive from checks[]All WARN checks[].crid (this is currently not stored this in summary).
warningssummary.warningsOptional list of warning strings.
top_failure_categoryderive from checks[]First FAIL’s category (or null).
check_resultschecksStore full checks[] if you want fast UI.
check_ids_failedderive from checks[]FAIL checks[].check_id.
check_ids_warnderive from checks[]WARN checks[].check_id.
flagsderive (future)If you later add checks[].flags or summary.flags, normalize + unique.
artifact_refknown at persistence OR from ZAR indexNot present in JSON; comes from ZAR when stored (recommended).
integrity_idderivedDeterministic ID based on (tenant_id, entity_id, mode, dataset_hash, period) (see below).
revocation_reffrom revocation eventNot present in report; updated on IntegrityRevoked.
exception_statusderived from exception artifactNot present in report; projection field from exception lifecycle.
created_bycontext.initiated_byYour report uses initiated_by not created_by; map it here.
supersedes_integrity_idoptional (registry-only)Not in report; used when we explicitly supersede an old record.
notesoptional (registry-only)Not in report.

Exact mapping from the JSON → table columns

Given the payload:

Direct mappings

  • artifact_namezar.artifact_name
  • applies_to_meidzar.applies_to_meid
  • content_hashzar.content_hash
  • schema_refzar.schema_ref
  • job_idcontext.job_id
  • run_idcontext.run_id
  • tenant_idcontext.tenant_id
  • entity_idcontext.entity_id
  • generated_atcontext.generated_at
  • initiated_bycontext.initiated_by
  • modecontext.mode
  • dataset_typedataset.dataset_type
  • dataset_hashdataset.dataset_hash
  • dataset_schema_refdataset.schema_ref
  • period_startdataset.period.start
  • period_enddataset.period.end
  • reporting_yeardataset.period.reporting_year
  • source_systemsdataset.source_systems
  • record_countsdataset.record_counts
  • ruleset_bundle_refrulesets.bundle_ref
  • ruleset_resolvedrulesets.resolved
  • integrity_statussummary.integrity_status
  • reporting_eligiblesummary.reporting_eligible
  • publish_allowedsummary.publish_allowed
  • exception_refsummary.exception_ref
  • counts_passsummary.counts.pass
  • counts_warnsummary.counts.warn
  • counts_failsummary.counts.fail
  • failed_rule_cridssummary.failed_rule_crids
  • warningssummary.warnings
  • check_resultschecks (full array)

Derived mappings (deterministic)

  • artifact_type ← constant integrity_check_report
  • scope_level ← default dataset (until we explicitly add scope to the report schema)
  • scope_object_refdataset.dataset_hash (or dataset artifact ref if you have it)
  • ruleset_refsrulesets.resolved[].ruleset_ref
  • ruleset_cridsrulesets.resolved[].crid
  • check_ids_failedchecks[].check_id where result == "FAIL"
  • check_ids_warnchecks[].check_id where result == "WARN"
  • top_failure_category ← first check where result == "FAIL" then category else null
  • integrity_passedintegrity_status IN ("PASSED","PASSED_WITH_WARNINGS","PASSED_WITH_EXCEPTION")
  • flagsempty [] for now (unless/ until we add flags per check or summary)

integrity_id formula

Use a deterministic stable ID:

integrity_id =
"INT-" + tenant_id + "-" + entity_id + "-" +
scope_level + "-" +
slug(scope_object_ref) + "-" +
mode

Where slug(scope_object_ref) is a deterministic shortening function, e.g.:

  • extract the sha256 tail if present and take first 12 chars (...@sha256:abcdef... → abcdef123456)
  • else fallback to md5(scope_object_ref) first 12 chars

Practical example

If:

  • tenant_id = TENANT-ACME
  • entity_id = ENTITY-ACME-DE
  • scope.level = dataset
  • scope.object_ref = ZAR:dataset:canonical_trial_balance:ENTITY-ACME-DE:2026M01@sha256:2222...
  • mode = standard

Then:

INT-TENANT-ACME-ENTITY-ACME-DE-dataset-222222222222-standard


This is:

  • stable across replays
  • changes if dataset_hash or bundle_ref changes (correct)
  • human-readable enough to debug

Update semantics (what changes a row)

Insert

On IntegrityEvaluated:

  • insert new row (preferred), OR upsert by unique anchor

Update

On IntegrityExceptionApproved:

  • set exception_ref, exception_status='active'
  • set integrity_status='PASSED_WITH_EXCEPTION'
  • set reporting_eligible=true, publish_allowed=true, integrity_passed=true
  • bump updated_at

On IntegrityRevoked:

  • set integrity_status='REVOKED'
  • set reporting_eligible=false, publish_allowed=false, integrity_passed=false
  • set revocation_ref
  • bump updated_at

Implementation hint for the team (very practical)

Treat integrity_report_registry as a projection written by an event consumer that listens to:

  • IntegrityEvaluated
  • IntegrityExceptionApproved
  • IntegrityRevoked

This keeps it consistent with ZSSR and avoids ad hoc writes.


8. Rule Lifecycle Management (CMCB Integration)

ZRR integrates directly with the Change Management & Compatibility (CMCB) Framework.

Change Types

Change TypeDescription
PATCHMetadata adjustment (non-breaking)
MINORThreshold adjustment
MAJORStructural logic change
DEPRECATIONRule replacement required
MIGRATIONAutomatic remapping to new CRID

MAJOR changes require:

  • Deprecation window
  • Canary execution simulation
  • ZSSR impact classification
  • AI risk re-evaluation (if applicable)
  • Governance sign-off

All lifecycle changes must be logged in:

  • rule_change_log
  • DAL
  • AI Governance Register (if high risk)

9. Formal CRID semantic versioning policy (PATCH/MINOR/MAJOR)

9.1. CRID Version Format

CRID ends with X_Y_Z where:

  • X = MAJOR
  • Y = MINOR
  • Z = PATCH

Example: ruleset.validation.finance.global.reconciliation.standard.critical.1_2_3

Definitions

  • CRID version = governance-visible semantic version of the ruleset’s behavior
  • ZAR hash = execution-identity of the exact ruleset content
  • A given CRID version may map to multiple historical hashes (draft iterations), but only one approved + active hash per scope (global/tenant/entity) at a time.

9.2. Change Classifications

PATCH (Z increment)

Intent: Non-behavioral or behavior-neutral changes. Compatibility: Must remain fully backward compatible in output meaning.

Typical PATCH changes:

  • Metadata-only changes:
    • owners, approved_by, created_at, changelog text edits (if not altering meaning)
  • Documentation / comments updates
  • Reordering rules without changing precedence or results
  • Tightening validations that only improve error messaging (no new rejects)
  • Expanding explicit allowlists in a way that does not change classification of existing inputs (rare; see below)

PATCH must NOT:

  • Change any computed numeric result given identical inputs
  • Change pass/warn/fail outcomes for previously valid inputs
  • Change precedence rules
  • Change default assumptions used in computations

Required tests for PATCH:

  • Schema validation
  • Static lint checks
  • “Golden replay” on canonical sample set: outputs must be identical byte-for-byte (except metadata timestamps)

MINOR (Y increment)

Intent: Backward-compatible behavior extension. Compatibility: Existing consumers remain valid; outputs may expand but not break contracts.

Typical MINOR changes:

  • Adding new optional rule branches that apply only when new fields exist
  • Expanding mappings to cover new accounts/dimensions without reclassifying existing mapped values
  • Introducing new flags/warnings (non-blocking) for edge cases
  • Adding new optional output fields (must be additive and documented)
  • Increasing granularity in rollups (new grouping keys allowed) while keeping defaults unchanged
  • New thresholds that only affect previously “unknown/unclassified” items (doesn’t change already-classified items)

MINOR must NOT:

  • Change meaning of existing output fields
  • Change default calculation assumptions (unless gated behind an explicit input param defaulted off)
  • Change reject/blocking behavior for requests that previously passed validation

Required tests for MINOR:

  • Schema validation + contract tests
  • Golden replay:
    • For baseline input set: existing outputs unchanged
    • New scenarios: new behavior demonstrated
    • Compatibility check: min_schema_ref/max_schema_ref must remain compatible

MAJOR (X increment)

Intent: Breaking behavioral change. Compatibility: May change outputs, validations, or semantics; requires controlled migration.

Typical MAJOR changes:

  • Any change that can alter numeric outputs for the same inputs
    • e.g., PV discounting default changes (t0 vs spread)
    • abatement cost formula changes
  • Precedence changes
    • tag detection precedence order changes
    • classification precedence changes (attribute vs account)
  • Threshold changes that flip pass/warn/fail outcomes
  • Changing default inclusion rules (e.g., include R=0 projects in ratio rollups)
  • Changing field semantics or units
  • Removing fields or renaming outputs
  • Changing interpretation of “reconciliation passed_with_warnings” behavior
  • Any change requiring downstream migration work or re-baselining

Required tests for MAJOR:

  • Schema validation + full contract suite
  • Golden replay with documented diffs (expected deltas)
  • Canary execution on representative tenant extracts (if available)
  • Governance sign-off (CMCB approval)
  • Migration notes required in changelog with:
    • “what changed”
    • “why”
    • “what breaks”
    • “how to migrate”
    • “recommended rollout plan”

9.3. Decision Matrix

ChangePatchMinorMajor
Metadata changes only
Doc/comment changes
Add new optional output field
Add new flag/warning only
New mapping for previously UNKNOWN items only
Change precedence order
Change tolerance thresholds affecting pass/fail
Change formula or default assumption
Remove/rename output fields
Tighten validation to reject previously accepted inputs

9.4. CRID ↔ Ruleset Artifact Governance Rules

  1. CRID version must increment according to the change class above.
  2. A CRID version is immutable once any approved hash exists for it.
  3. Draft iterations may update the hash under the same CRID version until approval.
  4. Once approved, further changes require:
  • PATCH/MINOR/MAJOR bump (new CRID), and
  • supersedes linking.

Required lifecycle linkage fields

  • supersedes: prior CRID or prior ZAR ruleset ref
  • deprecated_by: next CRID once retired

9.5. Activation & Rollout Policy (CMCB-aligned)

Default rollout sequence

  1. Create draft ruleset (new hash)
  2. Validate (unit tests + replay)
  3. Approve
  4. Activate as tenant default (or entity override)
  5. Monitor via rule execution logs
  6. Deprecate prior CRID after defined window

Compatibility enforcement

ZAR must block activation if:

  • applies_to_meid mismatch
  • current engine schema outside [min_schema_ref, max_schema_ref]
  • rule status not approved (unless sandbox mode)

B.5 Practical examples (so engineers don’t argue later)


Example 1 — Patch

“Fix typo in changelog and reorder tag_sources keys.” → ...1_0_0 → ...1_0_1


Example 2 — Minor

“Add new accepted project code pattern for a new client program; does not affect existing matches.” → ...1_0_0 → ...1_1_0


Example 3 — Major

“Change PV assumption from t0 to spread_evenly_over_year when timeline missing.” → ...1_1_0 → ...2_0_0


10. AI Governance Integration

If a rule:

  • Uses AI inference,
  • Impacts compliance decisions,
  • Alters financial or regulatory outputs,

It must:

  • Be registered in the AI Risk Register.
  • Define trust threshold.
  • Require human oversight if below threshold.
  • Log model version used.
  • Log dataset version used.
  • Record explainability metadata.

ZRR ensures AI rules remain compliant with:

  • EU AI Act
  • CSRD traceability
  • ESG audit requirements

11. Federation & Cross-ECO Interoperability

Rules may be:

  • Federated
  • Shared
  • Version-mapped
  • Trust-scored across ecosystems

ZRR supports:

  • Rule lineage exchange
  • CRID translation across partners
  • Federation compatibility scoring
  • Cross-ECO validation transparency

No federated rule may execute without CRID validation.


12. Governance Mandates

The following are mandatory:

  1. No validation logic may exist outside ZRR registration.
  2. No compliance rule may execute without CRID.
  3. No rule may bypass execution logging.
  4. No rule may be altered without lifecycle tracking.
  5. No AI-assisted rule may operate without trust metadata.

ZRR is a compliance-critical subsystem.


13. Strategic Outcome

ZRR establishes:

  • Declarative ESG enforcement
  • Versioned compliance logic
  • Audit-ready validation chains
  • Explainable AI integration
  • Trust amplification across the ecosystem
  • Future-proof regulatory adaptation

ZRR is not a feature.

It is the enforcement spine of ZAYAZ.

Precision Before Automation.
Integrity Above Velocity.


14. Ruleset Bundles as First-Class ZAR Artifacts

Rulesets define individual executable logic. Ruleset bundles define the deterministic composition of rulesets used by a job.

A bundle is a first-class, content-addressed ZAR artifact:

ZAR:ruleset_bundle:<bundle_name>@sha256:<hash>

Bundles are immutable and replay-safe. Any change to membership or ordering produces a new bundle hash.


14.1. Storage Model (Defaults and Overrides)

Bundle resolution is an orchestration responsibility (dispatcher/orchestrator), not a MICE responsibility.

ZAYAZ stores bundle pointers at three governance levels:

  1. Platform default (global) Stored in zar_platform_meid_defaults:
  • one default bundle per MEID
  1. Tenant override (optional, approved) Stored in zar_tenant_meid_bundle_overrides:
  • allows tenant-level policy customization per MEID
  1. Entity override (optional, approved) Stored in zar_entity_meid_bundle_overrides:
  • highest priority override per entity per MEID

14.2. Orchestrator Resolution Algorithm (Normative)

At JobStarted, the orchestrator must resolve an effective bundle ref using:

Priority order (highest → lowest):

  1. entity_bundle_override_ref (if exists and status=active)
  2. tenant_bundle_override_ref (if exists and status=active)
  3. global_default_bundle_ref (from platform defaults)

The orchestrator MUST validate:

  • bundle lifecycle.status is approved or frozen
  • bundle.applies_to_meid == requested MEID
  • schema compatibility (compatibility.min_engine_schema_ref / max_engine_schema_ref)
  • (optional) bundle.allow_tenant_overrides if resolution attempts tenant/entity overrides

The resolved bundle ref must be written into:

  • JobStarted event payload
  • all downstream pipeline events
  • integrity_check_report.rulesets.bundle_ref
  • integrity_report_registry.ruleset_bundle_ref
  • all output artifacts as provenance metadata

This guarantees deterministic replay and auditability.


14.3. Deterministic Execution Order

A ruleset bundle defines:

  • the exact set of rulesets
  • the ordered execution sequence

Engines must execute rulesets strictly in bundle.execution_order to ensure deterministic results.


14.4. Governance Outcome

With bundle refs recorded in job events and artifacts, ZAYAZ can:

  • reproduce any historical run using the exact bundle hash
  • prove which governance logic was applied
  • prevent “silent configuration drift”

15 Ruleset Bundles

15.1. What Is a Ruleset Bundle (Formal Definition)

A Ruleset Bundle is a content-addressed ZAR artifact that defines:

The exact ordered set of rulesets to be used for a specific MEID and execution context.

It is not:

  • A ruleset
  • A rule
  • A config file

It is:

  • A deterministic composition object

15.2. ZAR Artifact Identity

ZAR Reference Format

ZAR:ruleset_bundle:<bundle_name>@sha256:<hash>

Example:

ZAR:ruleset_bundle:acct_crawler_default@sha256:3333...

This must be immutable.


15.3. Bundle YAML Structure (Canonical)

15.3.1. acct_crawler_default (Canonical example bundle YAMLs)

acct-crawler-default-bundle-1_0_0.yamlGitHub ↗
zar:
artifact_type: ruleset_bundle
artifact_name: acct_crawler_default
applies_to_meid: MEID_ACCT_CRAWLER
content_hash: null
schema_ref: "ZAR:schema:ruleset_bundle@v1"

lifecycle:
status: approved
owners: ["cto@viroway.com"]
approved_by: ["cto@viroway.com"]
created_at: 2026-02-19T00:00:00.000Z
supersedes: null
deprecated_by: null
changelog: "Initial approved default bundle for tagged accounting crawler."

compatibility:
min_engine_schema_ref: "ZAR:schema:canonical_trial_balance@v1"
max_engine_schema_ref: "ZAR:schema:canonical_trial_balance@v1"
allowed_modes: ["standard"]

bundle:
strict_mode: false
allow_tenant_overrides: true
labels: ["default", "finance", "acct_crawler"]

execution_order:
- acct_crawler_tag_detection
- acct_crawler_classification
- acct_crawler_reconciliation_policy

rulesets:
- name: acct_crawler_tag_detection
ref: "ZAR:ruleset:acct_crawler_tag_detection@sha256:aaaa"
required: true
notes: "Project tag detection (regex, segments, precedence)."

- name: acct_crawler_classification
ref: "ZAR:ruleset:acct_crawler_classification@sha256:bbbb"
required: true
notes: "CapEx/OpEx classification rules and UNKNOWN thresholds."

- name: acct_crawler_reconciliation_policy
ref: "ZAR:ruleset:acct_crawler_reconciliation_policy@sha256:cccc"
required: true
notes: "TB reconciliation tolerances and pass/warn/fail policy."

15.3.2. transition_roi_default bundle YAML

transition-roi-default-bundle-1_0_0.yamlGitHub ↗
zar:
artifact_type: ruleset_bundle
artifact_name: transition_roi_default
applies_to_meid: MEID_CALC_TRANSITION_ROI
content_hash: null
schema_ref: "ZAR:schema:ruleset_bundle@v1"

lifecycle:
status: approved
owners: ["cto@viroway.com"]
approved_by: ["cto@viroway.com"]
created_at: 2026-02-19T00:00:00.000Z
supersedes: null
deprecated_by: null
changelog: "Initial approved default bundle for Transition ROI Calculator."

compatibility:
min_engine_schema_ref: "ZAR:schema:transition_roi_request@v1"
max_engine_schema_ref: "ZAR:schema:transition_roi_request@v1"
allowed_modes: ["standard"]

bundle:
strict_mode: false
allow_tenant_overrides: true
labels: ["default", "finance", "transition_roi"]

execution_order:
- transition_roi_calculation_policy
- transition_roi_rollup_policy
- transition_roi_validation_policy
- transition_roi_abatement_cost_policy

rulesets:
- name: transition_roi_calculation_policy
ref: "ZAR:ruleset:transition_roi_calculation_policy@sha256:1111"
required: true
notes: "PV timing assumption, discounting behavior, rounding policy."

- name: transition_roi_rollup_policy
ref: "ZAR:ruleset:transition_roi_rollup_policy@sha256:2222"
required: true
notes: "Allowed group_by keys, weighting, inclusion/exclusion rules."

- name: transition_roi_validation_policy
ref: "ZAR:ruleset:transition_roi_validation_policy@sha256:3333"
required: true
notes: "Reject vs warn mapping and standardized flags."

- name: transition_roi_abatement_cost_policy
ref: "ZAR:ruleset:transition_roi_abatement_cost_policy@sha256:4444"
required: false
notes: "Defines which benefits count and when abatement cost is computed."

15.4. Why Bundles Must Be Content-Addressed

Because:

If someone changes only one ruleset reference inside the bundle, the bundle hash changes.

That gives:

✔ Deterministic replay ✔ Immutable compliance configuration ✔ Clear governance delta ✔ No “hidden rule changes”


15.5. Activation Model Update

Modify orchestrator resolution:

Current:

global_default_ruleset_ref
tenant_ruleset_override_ref
entity_ruleset_override_ref

New:

global_default_bundle_ref
tenant_bundle_override_ref
entity_bundle_override_ref

Then:

  1. Resolve bundle
  2. Load ruleset refs from bundle
  3. Execute in defined order
  4. Persist bundle_ref in:
  • JobStarted
  • IntegrityEvaluated
  • integrity_check_report
  • integrity_report_registry
  • all downstream artifacts

15.7. Bundle Governance Model

Bundles follow same lifecycle rules as rulesets:

StateMeaning
drafteditable
approvedactivatable
deprecatedcannot be newly activated
frozencompliance-locked

Advanced state:

  • compliance_locked (for regulatory filing year)

15.8. Why Bundles Are Strategically Powerful

Because we you can support:

15.8.1. Strict Compliance Mode

Example:

acct_crawler_esrs_strict_bundle

Differences:

  • stricter reconciliation tolerance
  • stricter unknown classification thresholds
  • strict_mode: true

One click → compliance mode.


15.8.2. Sandbox Mode

acct_crawler_sandbox_bundle
  • enforcement downgraded to soft
  • no blocking rules

Perfect for ERP onboarding.


15.8.3. Filing-Year Locking

For CSRD 2026 filing:

acct_crawler_esrs_2026_locked_bundle

Immutable.

Auditor can verify exact hash used.


15.9. Table: ruleset_bundle_registry

ruleset_bundle_registry

FieldTypeDescription
bundle_idUUIDPK
bundle_nameTEXTHuman-readable name
bundle_refTEXTZAR reference
applies_to_meidTEXTEngine
bundle_hashTEXTsha256
strict_modeBOOLEANStrict mode flag
allow_tenant_overridesBOOLEANGovernance flag
execution_orderJSONBOrdered ruleset names
ruleset_refsJSONBArray of refs
statusTEXTdraft / approved / deprecated / frozen
created_atTIMESTAMPCreated
approved_atTIMESTAMPApproved
supersedes_bundle_idUUIDOptional lineage
notesTEXTGovernance notes

Postgres DDL

ruleset_bundle_registry.sqlGitHub ↗
CREATE TABLE IF NOT EXISTS ruleset_bundle_registry (

bundle_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),

bundle_name TEXT NOT NULL,
bundle_ref TEXT NOT NULL UNIQUE,

applies_to_meid TEXT NOT NULL,
schema_ref TEXT NOT NULL,

bundle_hash TEXT NOT NULL,

strict_mode BOOLEAN NOT NULL DEFAULT false,
allow_tenant_overrides BOOLEAN NOT NULL DEFAULT true,

execution_order JSONB NOT NULL,
ruleset_refs JSONB NOT NULL,

status TEXT NOT NULL CHECK (
status IN ('draft', 'approved', 'deprecated', 'frozen')
),

created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
approved_at TIMESTAMPTZ NULL,

supersedes_bundle_id UUID NULL,
notes TEXT NULL,

CONSTRAINT fk_supersedes_bundle
FOREIGN KEY (supersedes_bundle_id)
REFERENCES ruleset_bundle_registry(bundle_id)
ON DELETE SET NULL
);

ALTER TABLE ruleset_bundle_registry
ADD CONSTRAINT chk_bundle_hash_format
CHECK (bundle_hash ~ '^sha256:[0-9a-f]{64}$');

CREATE INDEX IF NOT EXISTS idx_rsb_meid_status
ON ruleset_bundle_registry (applies_to_meid, status);

CREATE INDEX IF NOT EXISTS idx_rsb_bundle_hash
ON ruleset_bundle_registry (bundle_hash);

CREATE INDEX IF NOT EXISTS idx_rsb_execution_order_gin
ON ruleset_bundle_registry USING GIN (execution_order);

CREATE INDEX IF NOT EXISTS idx_rsb_ruleset_refs_gin
ON ruleset_bundle_registry USING GIN (ruleset_refs);

15.10. ZRR Integration

Ruleset bundles are:

  • Not CRIDs
  • Not rules
  • Not signals

They are governance compositions.

ZRR references rulesets. Bundle registry references ZAR artifacts. Execution engine references bundle.

Clear separation.


15.11. Schema

Rulset Bundle — JSON Schema (v1)GitHub ↗
[SchemaSnippet] Loading schema "zar/ruleset_bundle.v1.schema.json" on client...

15.12. What This Unlocks Later

With bundles in place, we can later:

  • Add cross-engine compliance bundles
  • Create “Assurance Bundle”
  • Create “Limited Assurance Mode”
  • Create “ESRS Simplified Mode”
  • Create “Client-Specific Finance Policy Bundle”

Without touching MEID code.


15 Platform config table (global default bundles)

15.1. Table: zar_platform_meid_defaults (Global default per MEID)

NameTypeDescription
applies_to_meidTEXT (PK)MEID this policy applies to (e.g., MEID_ACCT_CRAWLER).
global_default_bundle_refTEXTZAR ref: ZAR:ruleset_bundle:<name>@sha256:<hash>
statusTEXTactive | deprecated (guardrail for emergency cutovers).
created_atTIMESTAMPTZInsert timestamp.
updated_atTIMESTAMPTZUpdate timestamp.
notesTEXT NULLOptional governance notes.

Postgres DDL

zar_platform_meid_defaults.sqlGitHub ↗
CREATE TABLE IF NOT EXISTS zar_platform_meid_defaults (
applies_to_meid TEXT PRIMARY KEY,
global_default_bundle_ref TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'active',
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
notes TEXT NULL
);

CREATE INDEX IF NOT EXISTS idx_zpmd_status
ON zar_platform_meid_defaults(status);

15.2. Formalized defaults + overrides + orchestrator resolution (Tenants)

NameTypeDescription
tenant_idTEXT (PK part)Tenant identifier
applies_to_meidTEXT (PK part)MEID
tenant_bundle_override_refTEXTApproved bundle ref
statusTEXTactive | paused | deprecated
approved_byTEXT NULLEmail/actor
approved_atTIMESTAMPTZ NULLApproval timestamp
created_atTIMESTAMPTZInsert timestamp
updated_atTIMESTAMPTZUpdate timestamp
notesTEXT NULLGovernance notes

Postgres DDL

zar_tenant_meid_bundle_overrides.sqlGitHub ↗
CREATE TABLE IF NOT EXISTS zar_tenant_meid_bundle_overrides (
tenant_id TEXT NOT NULL,
applies_to_meid TEXT NOT NULL,
tenant_bundle_override_ref TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'active',
approved_by TEXT NULL,
approved_at TIMESTAMPTZ NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
notes TEXT NULL,
PRIMARY KEY (tenant_id, applies_to_meid)
);

CREATE INDEX IF NOT EXISTS idx_ztmbo_status
ON zar_tenant_meid_bundle_overrides(status);

15.3. Formalized defaults + overrides + orchestrator resolution (Entities)

NameTypeDescription
tenant_idTEXT (PK part)Tenant identifier
entity_idTEXT (PK part)Entity identifier
applies_to_meidTEXT (PK part)MEID
entity_bundle_override_refTEXTApproved bundle ref
statusTEXTactive | paused | deprecated
approved_byTEXT NULLEmail/actor
approved_atTIMESTAMPTZ NULLApproval timestamp
created_atTIMESTAMPTZInsert timestamp
updated_atTIMESTAMPTZUpdate timestamp
notesTEXT NULLGovernance notes

Postgres DDL

zar_entity_meid_bundle_overrides.sqlGitHub ↗
CREATE TABLE IF NOT EXISTS zar_entity_meid_bundle_overrides (
tenant_id TEXT NOT NULL,
entity_id TEXT NOT NULL,
applies_to_meid TEXT NOT NULL,
entity_bundle_override_ref TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'active',
approved_by TEXT NULL,
approved_at TIMESTAMPTZ NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
notes TEXT NULL,
PRIMARY KEY (tenant_id, entity_id, applies_to_meid)
);

CREATE INDEX IF NOT EXISTS idx_zembo_status
ON zar_entity_meid_bundle_overrides(status);

15.4. Orchestrator: Resolve effective ruleset bundle for a job (deterministic + auditable)

orchestrator-resolution.tsGitHub ↗
/**
* Orchestrator: Resolve effective ruleset bundle for a job (deterministic + auditable).
*
* Priority (highest → lowest):
* 1) entity override
* 2) tenant override
* 3) platform default
*
* Output:
* - resolved_bundle_ref
* - resolved_bundle_hash
* - resolved_ruleset_refs[] in deterministic execution order
* - persisted into JobStarted + all downstream events/artifacts
*/

type BundleStatus = "draft" | "approved" | "deprecated" | "frozen";

type ResolveMode = "standard" | "strict_compliance";

type BundleRegistryRow = {
bundle_id: string;
bundle_name: string;
bundle_ref: string; // ZAR:ruleset_bundle:...@sha256:...
applies_to_meid: string; // MEID_...
schema_ref: string; // ZAR:schema:ruleset_bundle@v1
bundle_hash: string; // sha256:<hash>
strict_mode: boolean;
allow_tenant_overrides: boolean;
execution_order: string[]; // ordered ruleset names
ruleset_refs: string[]; // array of ZAR:ruleset:...@sha256:...
status: BundleStatus;
created_at: string;
approved_at: string | null;
supersedes_bundle_id: string | null;
notes: string | null;
};

type DefaultRow = {
applies_to_meid: string;
global_default_bundle_ref: string;
status: "active" | "deprecated";
};

type TenantOverrideRow = {
tenant_id: string;
applies_to_meid: string;
tenant_bundle_override_ref: string;
status: "active" | "paused" | "deprecated";
approved_by: string | null;
approved_at: string | null;
};

type EntityOverrideRow = {
tenant_id: string;
entity_id: string;
applies_to_meid: string;
entity_bundle_override_ref: string;
status: "active" | "paused" | "deprecated";
approved_by: string | null;
approved_at: string | null;
};

type ResolutionDecision = {
resolved_bundle_ref: string;
resolved_bundle_hash: string;
resolved_bundle_id: string;
resolved_ruleset_refs: string[]; // already ordered
resolved_execution_order: string[];
strict_mode_effective: boolean;
provenance: {
source: "entity_override" | "tenant_override" | "platform_default";
entity_override_ref?: string;
tenant_override_ref?: string;
platform_default_ref: string;
applied_override_allowed: boolean;
requested_mode: ResolveMode;
};
};

/**
* DB access helpers (pseudocode signatures)
*/
async function getEntityOverride(
tenant_id: string,
entity_id: string,
meid: string
): Promise<EntityOverrideRow | null> { /* ... */ return null; }

async function getTenantOverride(
tenant_id: string,
meid: string
): Promise<TenantOverrideRow | null> { /* ... */ return null; }

async function getPlatformDefault(meid: string): Promise<DefaultRow | null> {
/* ... */ return null;
}

async function getBundleByRef(bundle_ref: string): Promise<BundleRegistryRow | null> {
/* ... */ return null;
}

/**
* Optional: schema compatibility check (engine input schema vs bundle compatibility)
* In v1 you can keep this as a ZAR-side verification, but the orchestrator must enforce it.
*/
function assertBundleCompatibleOrThrow(args: {
bundle: BundleRegistryRow;
applies_to_meid: string;
requested_mode: ResolveMode;
}): void {
const { bundle, applies_to_meid, requested_mode } = args;

if (bundle.applies_to_meid !== applies_to_meid) {
throw new Error(
`BUNDLE_MEID_MISMATCH: bundle.applies_to_meid=${bundle.applies_to_meid} != ${applies_to_meid}`
);
}

// lifecycle gate
if (!(bundle.status === "approved" || bundle.status === "frozen")) {
throw new Error(`BUNDLE_NOT_ACTIVATABLE: status=${bundle.status}`);
}

// strict_compliance mode requires strict_mode bundle OR explicit policy
if (requested_mode === "strict_compliance" && bundle.strict_mode !== true) {
// You can choose: either allow (and just run "standard"), or require strict_mode.
// Recommended for determinism: require strict_mode for strict_compliance.
throw new Error(`BUNDLE_NOT_STRICT: requested strict_compliance but bundle.strict_mode=false`);
}

// sanity check ordering
const eo = bundle.execution_order || [];
const refs = bundle.ruleset_refs || [];
if (eo.length === 0 || refs.length === 0) {
throw new Error("BUNDLE_INVALID: missing execution_order or ruleset_refs");
}

// (Optional) deeper check: enforce a naming map in the YAML to ensure eo names exist.
// Since registry stores only refs, we assume bundle authoring validated this.
}

/**
* Primary resolution function
*/
export async function resolveRulesetBundleForJob(args: {
tenant_id: string;
entity_id: string;
applies_to_meid: string;
requested_mode: ResolveMode; // standard | strict_compliance
}): Promise<ResolutionDecision> {
const { tenant_id, entity_id, applies_to_meid, requested_mode } = args;

// 0) platform default is mandatory fallback
const platformDefault = await getPlatformDefault(applies_to_meid);
if (!platformDefault || platformDefault.status !== "active") {
throw new Error(`NO_PLATFORM_DEFAULT_BUNDLE: meid=${applies_to_meid}`);
}

// 1) load overrides (if any)
const [entityOverride, tenantOverride] = await Promise.all([
getEntityOverride(tenant_id, entity_id, applies_to_meid),
getTenantOverride(tenant_id, applies_to_meid),
]);

// 2) candidate selection (priority)
// NOTE: we only consider overrides that are active and approved (approved_at present).
const entityCandidateRef =
entityOverride &&
entityOverride.status === "active" &&
!!entityOverride.approved_at
? entityOverride.entity_bundle_override_ref
: null;

const tenantCandidateRef =
tenantOverride &&
tenantOverride.status === "active" &&
!!tenantOverride.approved_at
? tenantOverride.tenant_bundle_override_ref
: null;

const platformRef = platformDefault.global_default_bundle_ref;

const candidateChain: Array<{ source: ResolutionDecision["provenance"]["source"]; ref: string }> =
entityCandidateRef
? [{ source: "entity_override", ref: entityCandidateRef }, { source: "tenant_override", ref: tenantCandidateRef || "" }, { source: "platform_default", ref: platformRef }]
: tenantCandidateRef
? [{ source: "tenant_override", ref: tenantCandidateRef }, { source: "platform_default", ref: platformRef }]
: [{ source: "platform_default", ref: platformRef }];

// 3) attempt resolution in order, with governance constraints
// If an override is not allowed by the selected bundle, fall back.
// Key: allow_tenant_overrides belongs to the *base bundle* we would otherwise use.
// Policy:
// - entity override allowed only if the platform default bundle allows overrides
// - tenant override allowed only if the platform default bundle allows overrides
// - (optional) if tenant override bundle itself sets allow_tenant_overrides=false, that prevents *entity* override layering.
//
// Practical v1 approach:
// - Resolve platform default first (for override permission)
// - If platform default disallows overrides, ignore tenant/entity overrides
const platformBundle = await getBundleByRef(platformRef);
if (!platformBundle) throw new Error(`PLATFORM_BUNDLE_NOT_FOUND: ${platformRef}`);
assertBundleCompatibleOrThrow({ bundle: platformBundle, applies_to_meid, requested_mode: "standard" });

const overridesPermitted = platformBundle.allow_tenant_overrides === true;

// helper to resolve a candidate ref into a validated bundle
async function tryResolveBundle(ref: string): Promise<BundleRegistryRow | null> {
if (!ref) return null;
const b = await getBundleByRef(ref);
if (!b) return null;
// For strict_compliance: require strict_mode bundle (enforced by assert)
assertBundleCompatibleOrThrow({ bundle: b, applies_to_meid, requested_mode });
return b;
}

let chosenSource: ResolutionDecision["provenance"]["source"] = "platform_default";
let chosenBundle: BundleRegistryRow | null = null;

// If overrides not permitted, force platform default
if (!overridesPermitted) {
chosenBundle = platformBundle;
chosenSource = "platform_default";
} else {
// Try entity first, then tenant, else platform
if (entityCandidateRef) {
const b = await tryResolveBundle(entityCandidateRef);
if (b) {
// if chosen tenant bundle disallows further overrides, that only matters when entity sits above tenant.
// We are already at entity level, so ok.
chosenBundle = b;
chosenSource = "entity_override";
}
}

if (!chosenBundle && tenantCandidateRef) {
const b = await tryResolveBundle(tenantCandidateRef);
if (b) {
chosenBundle = b;
chosenSource = "tenant_override";
}
}

if (!chosenBundle) {
// default (already validated)
chosenBundle = platformBundle;
chosenSource = "platform_default";
}
}

// 4) deterministic ordering (registry stores execution_order + ruleset_refs)
// Engine expects ordered refs. We assume bundle authoring validated 1:1 mapping.
// If you store only refs without names, treat execution_order as authoritative and
// keep ruleset_refs already ordered in registry. (Best: store ordered refs in registry.)
const resolvedExecutionOrder = chosenBundle.execution_order;
const resolvedRulesetRefs = chosenBundle.ruleset_refs;

if (resolvedRulesetRefs.length === 0) throw new Error("BUNDLE_EMPTY_RULESET_REFS");

// 5) strict mode effective:
// if requested strict_compliance, it must already be strict bundle.
const strictModeEffective =
requested_mode === "strict_compliance" ? true : chosenBundle.strict_mode === true;

return {
resolved_bundle_ref: chosenBundle.bundle_ref,
resolved_bundle_hash: chosenBundle.bundle_hash,
resolved_bundle_id: chosenBundle.bundle_id,
resolved_ruleset_refs: resolvedRulesetRefs,
resolved_execution_order: resolvedExecutionOrder,
strict_mode_effective: strictModeEffective,
provenance: {
source: chosenSource,
entity_override_ref: entityCandidateRef || undefined,
tenant_override_ref: tenantCandidateRef || undefined,
platform_default_ref: platformRef,
applied_override_allowed: overridesPermitted,
requested_mode,
},
};
}

/**
* Persist into JobStarted event (pseudocode)
*/
export function buildJobStartedEvent(args: {
job_id: string;
tenant_id: string;
entity_id: string;
applies_to_meid: string;
resolution: ResolutionDecision;
}) {
const { job_id, tenant_id, entity_id, applies_to_meid, resolution } = args;

return {
event_type: "JobStarted",
job_id,
tenant_id,
entity_id,
applies_to_meid,
generated_at: new Date().toISOString(),
rulesets: {
bundle_ref: resolution.resolved_bundle_ref,
bundle_hash: resolution.resolved_bundle_hash,
resolved_ruleset_refs: resolution.resolved_ruleset_refs,
execution_order: resolution.resolved_execution_order,
strict_mode_effective: resolution.strict_mode_effective,
resolution_provenance: resolution.provenance
}
};
}
  • Approved gating: overrides should require approved_at IS NOT NULL + status='active'.
  • Bundle activatable: bundle must be approved or frozen.
  • Override permission: simplest v1 rule is: if platform default bundle has allow_tenant_overrides=false then ignore all overrides.
  • Strict compliance: if requested_mode='strict_compliance', require bundle.strict_mode=true (or explicitly downgrade to standard, but then the job must record that downgrade).

Production-grade Postgres queries for the orchestrator resolution flow (platform default → tenant override → entity override → bundle lookup)


Platform default bundle ref

platform-default-bundle-ref.sqlGitHub ↗
-- Q0: Get platform default bundle ref for a MEID
SELECT
applies_to_meid,
global_default_bundle_ref,
status
FROM zar_platform_meid_defaults
WHERE applies_to_meid = $1
AND status = 'active';

Param

  • $1 = MEID_ACCT_CRAWLER (or other MEID)

Entity override (highest priority; optional)

entity-override.sqlGitHub ↗
-- Q1: Get entity override bundle ref (only active + approved overrides should be considered)
SELECT
tenant_id,
entity_id,
applies_to_meid,
entity_bundle_override_ref,
status,
approved_by,
approved_at
FROM zar_entity_meid_bundle_overrides
WHERE tenant_id = $1
AND entity_id = $2
AND applies_to_meid = $3
AND status = 'active'
AND approved_at IS NOT NULL;

Params

  • $1 = tenant_id
  • $2 = entity_id
  • $3 = applies_to_meid (MEID)

Tenant override (highest priority; optional)

tenant-override.sqlGitHub ↗
-- Q2: Get tenant override bundle ref (only active + approved)
SELECT
tenant_id,
applies_to_meid,
tenant_bundle_override_ref,
status,
approved_by,
approved_at
FROM zar_tenant_meid_bundle_overrides
WHERE tenant_id = $1
AND applies_to_meid = $2
AND status = 'active'
AND approved_at IS NOT NULL;

Params

  • $1 = tenant_id
  • $2 = applies_to_meid (MEID)

Bundle lookup by ref (for any candidate ref)

bundle-lookup.sqlGitHub ↗
-- Q3: Resolve bundle registry row by bundle_ref
SELECT
bundle_id,
bundle_name,
bundle_ref,
applies_to_meid,
schema_ref,
bundle_hash,
strict_mode,
allow_tenant_overrides,
execution_order,
ruleset_refs,
status,
created_at,
approved_at,
supersedes_bundle_id,
notes
FROM ruleset_bundle_registry
WHERE bundle_ref = $1;

Param

  • $1 = candidate bundle_ref

Single-shot “best candidate ref” resolver (optional optimization)

This query returns one ref: entity override if present, else tenant override, else platform default.

best-candidate.sqlGitHub ↗
-- Q4: Resolve best candidate bundle ref for a job (ref only)
WITH platform AS (
SELECT global_default_bundle_ref AS ref
FROM zar_platform_meid_defaults
WHERE applies_to_meid = $3 AND status = 'active'
),
entity_override AS (
SELECT entity_bundle_override_ref AS ref
FROM zar_entity_meid_bundle_overrides
WHERE tenant_id = $1
AND entity_id = $2
AND applies_to_meid = $3
AND status = 'active'
AND approved_at IS NOT NULL
LIMIT 1
),
tenant_override AS (
SELECT tenant_bundle_override_ref AS ref
FROM zar_tenant_meid_bundle_overrides
WHERE tenant_id = $1
AND applies_to_meid = $3
AND status = 'active'
AND approved_at IS NOT NULL
LIMIT 1
)
SELECT ref FROM entity_override
UNION ALL
SELECT ref FROM tenant_override
UNION ALL
SELECT ref FROM platform
LIMIT 1;

Params

  • $1 tenant_id
  • $2 entity_id
  • $3 applies_to_meid

Enforce “platform default disallows overrides”

Because allow_tenant_overrides lives in the bundle, we need one extra step:

  1. Fetch platform default ref (Q0)
  2. Fetch platform bundle row (Q3)
  3. If allow_tenant_overrides = false → ignore Q1/Q2 entirely

A single SQL query that bakes this in:

resolve-bundle-ref.sqlGitHub ↗
-- Q5: Resolve effective bundle_ref with override permission enforced by platform default bundle
WITH platform_ref AS (
SELECT global_default_bundle_ref AS ref
FROM zar_platform_meid_defaults
WHERE applies_to_meid = $3 AND status = 'active'
),
platform_bundle AS (
SELECT
r.bundle_ref AS ref,
r.allow_tenant_overrides AS allow_overrides
FROM ruleset_bundle_registry r
JOIN platform_ref p ON p.ref = r.bundle_ref
WHERE r.status IN ('approved', 'frozen')
),
entity_override AS (
SELECT e.entity_bundle_override_ref AS ref
FROM zar_entity_meid_bundle_overrides e
JOIN platform_bundle pb ON pb.allow_overrides = true
WHERE e.tenant_id = $1
AND e.entity_id = $2
AND e.applies_to_meid = $3
AND e.status = 'active'
AND e.approved_at IS NOT NULL
LIMIT 1
),
tenant_override AS (
SELECT t.tenant_bundle_override_ref AS ref
FROM zar_tenant_meid_bundle_overrides t
JOIN platform_bundle pb ON pb.allow_overrides = true
WHERE t.tenant_id = $1
AND t.applies_to_meid = $3
AND t.status = 'active'
AND t.approved_at IS NOT NULL
LIMIT 1
)
SELECT ref FROM entity_override
UNION ALL
SELECT ref FROM tenant_override
UNION ALL
SELECT ref FROM platform_bundle
LIMIT 1;

This returns the correct effective ref while respecting “no overrides” policy.


Resolve full bundle row in one query (end-to-end)

Returns the bundle row directly (not just the ref):

resolve-full-bundle-row.sqlGitHub ↗
-- Q6: End-to-end resolution returning the selected bundle row
WITH platform_ref AS (
SELECT global_default_bundle_ref AS ref
FROM zar_platform_meid_defaults
WHERE applies_to_meid = $3 AND status = 'active'
),
platform_bundle AS (
SELECT r.*
FROM ruleset_bundle_registry r
JOIN platform_ref p ON p.ref = r.bundle_ref
WHERE r.status IN ('approved', 'frozen')
AND ($4 <> 'strict_compliance' OR r.strict_mode = true)
),
candidate_ref AS (
SELECT e.entity_bundle_override_ref AS ref, 1 AS prio
FROM zar_entity_meid_bundle_overrides e
JOIN platform_bundle pb ON pb.allow_tenant_overrides = true
WHERE e.tenant_id = $1
AND e.entity_id = $2
AND e.applies_to_meid = $3
AND e.status = 'active'
AND e.approved_at IS NOT NULL

UNION ALL

SELECT t.tenant_bundle_override_ref AS ref, 2 AS prio
FROM zar_tenant_meid_bundle_overrides t
JOIN platform_bundle pb ON pb.allow_tenant_overrides = true
WHERE t.tenant_id = $1
AND t.applies_to_meid = $3
AND t.status = 'active'
AND t.approved_at IS NOT NULL

UNION ALL

SELECT pb.bundle_ref AS ref, 3 AS prio
FROM platform_bundle pb
),
chosen AS (
SELECT ref
FROM candidate_ref
ORDER BY prio
LIMIT 1
)
SELECT
r.bundle_id,
r.bundle_name,
r.bundle_ref,
r.applies_to_meid,
r.schema_ref,
r.bundle_hash,
r.strict_mode,
r.allow_tenant_overrides,
r.execution_order,
r.ruleset_refs,
r.status,
r.created_at,
r.approved_at,
r.supersedes_bundle_id,
r.notes
FROM ruleset_bundle_registry r
JOIN chosen c ON c.ref = r.bundle_ref;
WHERE ($4 <> 'strict_compliance' OR r.strict_mode = true);

Param

  • $4 = requested_mode ('standard' | 'strict_compliance')

APPENDIX A - ZAR Validator Checklist — ruleset_bundle Registration (v1)

This ZAR ruleset_bundle validator function checklist written to be:

  1. Engineer-friendly (clear steps, return codes, inputs/outputs)
  2. CODEX App–ready (each step is an atomic “automation action” with deterministic success/fail + structured output). It can be used as the blueprint for a CODEX App workflow.

A.0. Function signature (contract)

Function validate_and_register_ruleset_bundle(bundle_doc, context) -> result

Inputs

  • bundle_doc: parsed YAML/JSON object (ruleset_bundle.v1)
  • context (object):
    • requested_meid (string) — MEID being registered for
    • requested_status (string|null) — draft/approved/frozen/deprecated (optional if in doc)
    • env (string) — dev|staging|prod
    • actor (string) — user/system identity
    • now (ISO datetime)
    • zar_lookup (function) — resolves refs to artifacts
    • zar_registry (function) — writes registry record
    • hash_fn (function) — canonical hash calculator

Outputs

  • result:
    • ok (boolean)
    • bundle_ref (string|null)
    • bundle_hash (string|null)
    • ordered_ruleset_refs (array)
    • warnings (array of objects)
    • errors (array of objects)
    • normalized_doc (object) — canonicalized payload used for hashing

Error object format

error-object-format.jsonGitHub ↗
{ "code": "BUNDLE_SCHEMA_INVALID", "path": "bundle.rulesets[0].ref", "message": "..." }

A.1. Parse + basic input checks

Step 1.1 — Parse input

  • Accept YAML or JSON.
  • Reject if parse fails.

Fail codes

  • BUNDLE_PARSE_ERROR

Step 1.2 — Enforce top-level shape exists

  • Must contain: zar, lifecycle, compatibility, bundle.

Fail codes

  • BUNDLE_MISSING_REQUIRED_FIELD

A.2. JSON Schema validation (hard gate)

Step 2.1 — Validate against JSON Schema

  • Validate bundle_doc against ZAR:schema:ruleset_bundle@v1.
  • Reject on any schema violation.

Fail codes

  • BUNDLE_SCHEMA_INVALID

Notes (CODEX)

  • Keep the schema validator output; map each issue to {code, path, message}.

A.3. Canonicalization (deterministic hashing)

Step 3.1 — Normalize string fields

  • Trim leading/trailing whitespace on all string fields (deep).
  • Normalize line endings in lifecycle.changelog (if present).

Warn codes

  • BUNDLE_NORMALIZED_WHITESPACE (optional warning)

Step 3.2 — Normalize arrays (order rules)

Sort lexicographically

  • lifecycle.owners
  • lifecycle.approved_by
  • bundle.labels

Do NOT reorder

  • bundle.execution_order (semantic)
  • bundle.rulesets (author order ok)

Step 3.3 — Remove non-hash fields

Exclude from hashing:

  • zar.content_hash (server assigned)
  • Any registry-only metadata (if present)

Fail codes

  • BUNDLE_CANONICALIZATION_FAILED (only if your canonicalizer errors)

Output

  • normalized_doc

A.4. MEID and identity checks

Step 4.1 — MEID match

  • Enforce: bundle_doc.zar.applies_to_meid == context.requested_meid

Fail codes

  • BUNDLE_MEID_MISMATCH

Step 4.2 — Artifact name constraints (semantic)

  • Enforce uniqueness of zar.artifact_name scoped to:
  • recommended: (artifact_type, applies_to_meid, artifact_name)
  • If collision exists and hash differs → reject.

Fail codes

  • BUNDLE_NAME_CONFLICT

A.5. Execution order integrity (critical)

Let:

  • EO = bundle.execution_order
  • RS = bundle.rulesets
  • RSN = set(rs.name for rs in RS)
  • REQ = set(rs.name for rs in RS if rs.required != false)

Step 5.1 — All execution_order names exist

  • Enforce: every name in EO must exist in RSN.

Fail codes

  • BUNDLE_EXECUTION_ORDER_UNKNOWN_NAME

Step 5.2 — All required rulesets are ordered

  • Enforce: every name in REQ must appear in EO.

Fail codes

  • BUNDLE_REQUIRED_RULESET_NOT_ORDERED

Step 5.3 — Compute ordered_ruleset_refs

Build:

  • ordered_ruleset_refs = [ ruleset.ref where ruleset.name == EO[i] ]

Fail codes

  • BUNDLE_EXECUTION_ORDER_RESOLUTION_FAILED (should not happen if steps above passed)

A.6. Reference resolution checks (rulesets exist + correct type)

Policy depends on lifecycle.status:

  • draft: allow unresolved refs only if required=false
  • approved|frozen: all refs must resolve

For each ruleset in bundle.rulesets[]:

Step 6.1 — Validate ref format

  • Must match ZAR:ruleset:<name>@sha256:<hash>
  • In prod: require 64 hex
  • In dev: may allow shorter (but warn)

Fail codes

  • BUNDLE_RULESET_REF_INVALID
  • BUNDLE_RULESET_REF_HASH_LENGTH_INVALID (prod)

Warn codes

  • BUNDLE_RULESET_REF_SHORT_HASH_DEV

Step 6.2 — Resolve ruleset ref in ZAR

  • artifact = zar_lookup(ref)
  • Must exist if required or status is approved/frozen.

Fail codes

  • BUNDLE_RULESET_REF_NOT_FOUND

Step 6.3 — Enforce resolved artifact type = ruleset

  • artifact.zar.artifact_type == "ruleset"

Fail codes

  • BUNDLE_RULESET_REF_WRONG_TYPE

Step 6.4 — Enforce MEID match

  • artifact.zar.applies_to_meid == bundle.zar.applies_to_meid

Fail codes

  • BUNDLE_RULESET_MEID_MISMATCH

Step 6.5 — Enforce ruleset lifecycle status

  • If bundle is approved|frozen:
  • ruleset must not be deprecated
  • ruleset must be approved or frozen (recommended)

Fail codes

  • BUNDLE_RULESET_DEPRECATED
  • BUNDLE_RULESET_NOT_APPROVED

A.7. Compatibility checks (approved/frozen hard gate)

Step 7.1 — Bundle compatibility range sanity

  • Ensure min_engine_schema_ref and max_engine_schema_ref are same schema family
  • Ensure min <= max (you’ll compare version numbers)

Fail codes

  • BUNDLE_COMPATIBILITY_RANGE_INVALID

Step 7.2 — Ruleset compatibility overlap

For each resolved ruleset:

  • Require overlap between:
  • bundle range: [min_bundle, max_bundle]
  • ruleset range: [min_ruleset, max_ruleset]

Overlap condition:

  • min_ruleset <= max_bundle AND max_ruleset >= min_bundle

Fail codes

  • BUNDLE_RULESET_COMPATIBILITY_VIOLATION

Step 7.3 — Strict mode consistency

If compatibility.allowed_modes contains strict_compliance:

  • Require bundle.bundle.strict_mode == true

Fail codes

  • BUNDLE_STRICT_MODE_INCONSISTENT

A.8. Lineage checks (supersedes/deprecated_by)

Step 8.1 — supersedes exists and matches MEID

If lifecycle.supersedes != null:

  • ref must resolve
  • must be a ruleset_bundle
  • must have same applies_to_meid

Fail codes

  • BUNDLE_LINEAGE_REF_NOT_FOUND
  • BUNDLE_LINEAGE_WRONG_TYPE
  • BUNDLE_LINEAGE_MEID_MISMATCH

Step 8.2 — cycle detection

  • Ensure no cycles in supersedes chain.

Fail codes

  • BUNDLE_LINEAGE_CYCLE_DETECTED

Step 8.3 — deprecated_by points to valid bundle

If lifecycle.deprecated_by != null:

  • must resolve, same MEID, and be approved/frozen

Fail codes

  • BUNDLE_DEPRECATED_BY_INVALID

A.9. Hashing + ref generation

Step 9.1 — Compute content hash

  • bundle_hash = sha256(canonical_json(normalized_doc))
  • Output as sha256:<64hex>

Fail codes

  • BUNDLE_HASH_COMPUTE_FAILED

Step 9.2 — Validate provided content_hash (if present)

If zar.content_hash provided:

  • must equal computed hash

Fail codes

  • BUNDLE_HASH_MISMATCH

Step 9.3 — Generate canonical ZAR ref

  • bundle_ref = "ZAR:ruleset_bundle:<artifact_name>@<bundle_hash>"

A.10. Registration decision rules

Step 10.1 — Status enforcement

  • If lifecycle.status is approved|frozen:
  • approved_by must be non-empty
  • approved_at must exist (if you store it here or at registry level)
  • all required refs must resolve

Fail codes

  • BUNDLE_APPROVAL_MISSING
  • BUNDLE_APPROVAL_INCOMPLETE

Step 10.2 — Registry uniqueness

  • If bundle_ref already exists → idempotent success
  • If (artifact_type, artifact_name, applies_to_meid) exists with different hash:
  • allow only if status is draft and old is deprecated (policy)
  • else reject

Fail codes

  • BUNDLE_REF_CONFLICT
  • BUNDLE_NAME_HASH_CONFLICT

A.11. Registry write (side effect)

Step 11.1 — Write to ruleset_bundle_registry

Persist:

  • bundle_id (uuid)
  • bundle_name (artifact_name)
  • bundle_ref
  • applies_to_meid
  • schema_ref
  • bundle_hash
  • strict_mode
  • allow_tenant_overrides
  • execution_order (JSONB)
  • ruleset_refs (JSONB) ← store ordered_ruleset_refs (recommended)
  • status
  • created_at / approved_at
  • supersedes_bundle_id
  • notes

Fail codes

  • BUNDLE_REGISTRY_WRITE_FAILED

''Step 11.2 — Return result''

Return:

  • ok=true
  • bundle_ref, bundle_hash
  • ordered_ruleset_refs
  • normalized_doc
  • warnings/errors arrays

A.12. CODEX App Automation Steps (suggested task graph)

This is the “automation-friendly” view (each step is a job node):

  1. ParseDocument
  2. ValidateJsonSchema
  3. CanonicalizePayload
  4. ValidateMeidAndName
  5. ValidateExecutionOrder
  6. ResolveRulesetRefs
  7. ValidateCompatibility
  8. ValidateLineage
  9. ComputeHashAndRef
  10. EnforceApprovalPolicy
  11. UpsertRegistryRow
  12. EmitRegistrationEvent (optional)
  • RulesetBundleRegistered(bundle_ref, hash, actor, time)

Each step outputs:

  • step_ok
  • step_errors[]
  • step_warnings[]
  • plus step-specific artifacts (normalized payload, ordered refs, resolved metadata)

Machine-readable YAML Recipe

Below is a machine-readable YAML recipe for the CODEX App that validates and registers a ruleset_bundle artifact in ZAR.

It is structured as:

  • deterministic steps
  • explicit inputs/outputs
  • formal error codes
  • clear side-effects
  • suitable for automation pipelines

This can be treated as:

codex_app: zar.ruleset_bundle.register.v1

ruleset-bundle-register-1_0_0.yamlGitHub ↗
codex_app:
id: zar.ruleset_bundle.register.v1
name: ZAR Ruleset Bundle Registration
version: 1.0.0
artifact_type: ruleset_bundle
description: >
Validates, canonicalizes, resolves, hashes, and registers a ruleset_bundle
artifact in ZAR. Enforces schema, compatibility, lineage, and governance rules.

inputs:
bundle_doc:
type: object
description: Parsed YAML/JSON ruleset_bundle document.
context:
type: object
required:
- requested_meid
- env
- actor
- now
properties:
requested_meid:
type: string
env:
type: string
enum: [dev, staging, prod]
actor:
type: string
now:
type: string
format: date-time

outputs:
ok:
type: boolean
bundle_ref:
type: string
nullable: true
bundle_hash:
type: string
nullable: true
ordered_ruleset_refs:
type: array
items: string
normalized_doc:
type: object
warnings:
type: array
errors:
type: array

steps:

- id: parse_document
action: validate_input_object
description: Ensure bundle_doc is present and structured.
fail_codes:
- BUNDLE_PARSE_ERROR
- BUNDLE_MISSING_REQUIRED_FIELD

- id: validate_schema
action: json_schema_validate
schema_ref: ZAR:schema:ruleset_bundle@v1
description: Validate bundle_doc against JSON schema.
fail_codes:
- BUNDLE_SCHEMA_INVALID

- id: canonicalize_payload
action: canonicalize_object
rules:
trim_all_strings: true
sort_arrays:
- lifecycle.owners
- lifecycle.approved_by
- bundle.labels
exclude_from_hash:
- zar.content_hash
outputs:
normalized_doc: canonical_object
fail_codes:
- BUNDLE_CANONICALIZATION_FAILED

- id: validate_meid
action: assert_equal
left: bundle_doc.zar.applies_to_meid
right: context.requested_meid
fail_codes:
- BUNDLE_MEID_MISMATCH

- id: validate_execution_order
action: validate_execution_mapping
inputs:
execution_order: bundle_doc.bundle.execution_order
rulesets: bundle_doc.bundle.rulesets
checks:
- all_execution_names_exist
- all_required_rulesets_in_execution_order
- no_duplicate_execution_entries
outputs:
ordered_ruleset_refs: resolved_refs_in_execution_order
fail_codes:
- BUNDLE_EXECUTION_ORDER_UNKNOWN_NAME
- BUNDLE_REQUIRED_RULESET_NOT_ORDERED
- BUNDLE_EXECUTION_ORDER_DUPLICATE

- id: validate_ruleset_refs
action: resolve_artifact_refs
for_each: bundle_doc.bundle.rulesets
checks:
- ref_format_valid
- resolve_exists_if_required_or_status_approved
- artifact_type_is_ruleset
- applies_to_meid_matches_bundle
- not_deprecated_if_bundle_approved
fail_codes:
- BUNDLE_RULESET_REF_INVALID
- BUNDLE_RULESET_REF_NOT_FOUND
- BUNDLE_RULESET_REF_WRONG_TYPE
- BUNDLE_RULESET_MEID_MISMATCH
- BUNDLE_RULESET_DEPRECATED

- id: validate_compatibility
condition: bundle_doc.lifecycle.status in [approved, frozen]
action: validate_compatibility_ranges
checks:
- bundle_range_valid
- ruleset_range_overlap
- strict_mode_consistency
fail_codes:
- BUNDLE_COMPATIBILITY_RANGE_INVALID
- BUNDLE_RULESET_COMPATIBILITY_VIOLATION
- BUNDLE_STRICT_MODE_INCONSISTENT

- id: validate_lineage
action: validate_lineage_references
checks:
- supersedes_exists_if_present
- supersedes_same_meid
- no_lineage_cycles
- deprecated_by_valid_if_present
fail_codes:
- BUNDLE_LINEAGE_REF_NOT_FOUND
- BUNDLE_LINEAGE_CYCLE_DETECTED
- BUNDLE_LINEAGE_MEID_MISMATCH

- id: compute_hash
action: compute_sha256
input: normalized_doc
output: bundle_hash
fail_codes:
- BUNDLE_HASH_COMPUTE_FAILED

- id: validate_hash_if_provided
condition: bundle_doc.zar.content_hash != null
action: assert_equal
left: bundle_doc.zar.content_hash
right: bundle_hash
fail_codes:
- BUNDLE_HASH_MISMATCH

- id: generate_bundle_ref
action: format_string
template: "ZAR:ruleset_bundle:{artifact_name}@{bundle_hash}"
inputs:
artifact_name: bundle_doc.zar.artifact_name
bundle_hash: bundle_hash
output: bundle_ref

- id: validate_approval_policy
condition: bundle_doc.lifecycle.status in [approved, frozen]
action: validate_approval_fields
required_fields:
- lifecycle.approved_by
fail_codes:
- BUNDLE_APPROVAL_MISSING

- id: check_registry_uniqueness
action: registry_lookup
checks:
- no_name_hash_conflict
fail_codes:
- BUNDLE_NAME_HASH_CONFLICT
- BUNDLE_REF_CONFLICT

- id: upsert_registry_row
action: registry_upsert
table: ruleset_bundle_registry
mapping:
bundle_name: bundle_doc.zar.artifact_name
bundle_ref: bundle_ref
applies_to_meid: bundle_doc.zar.applies_to_meid
schema_ref: bundle_doc.zar.schema_ref
bundle_hash: bundle_hash
strict_mode: bundle_doc.bundle.strict_mode
allow_tenant_overrides: bundle_doc.bundle.allow_tenant_overrides
execution_order: bundle_doc.bundle.execution_order
ruleset_refs: ordered_ruleset_refs
status: bundle_doc.lifecycle.status
created_at: context.now
fail_codes:
- BUNDLE_REGISTRY_WRITE_FAILED

- id: emit_event
action: emit_domain_event
event_type: RulesetBundleRegistered
payload:
bundle_ref: bundle_ref
bundle_hash: bundle_hash
actor: context.actor
timestamp: context.now

success_condition: no_errors_present

error_model:
structure:
code: string
path: string
message: string

warning_model:
structure:
code: string
message: string



GitHub RepoRequest for Change (RFC)