Tenants Guide
jinflow is multi-tenant. Each tenant is an independent analytical workspace with its own data, AFS, and KLS.
Tenant Layout
Section titled “Tenant Layout”live_root/ millesime/ rmc/ afs/ ← analytical framework (copy of pack + tenant-specific additions) raw/ ← immutable source CSVs (from DLZ) build/ ← intermediaries (compiled SQL, enriched CSVs) store/ ← KLS + OPS + logs + snapshotsPack-Qualified IDs
Section titled “Pack-Qualified IDs”All commands use pack.tenant notation:
jin make --tenant hrcentral.vaijin desk --tenant hrcentral.vaijin afs update --tenant hrcentral.vaiCreating a Tenant
Section titled “Creating a Tenant”# From a pack name (resolved via pack_root)jin init --pack hrcentral --tenant new_hospital --source-system opale
# From a pack pathjin init --pack /path/to/jinflow-pack-hrcentral --tenant new_hospital --source-system opaleThis creates live_root/numetrix/new_hospital/ with:
afs/— copy of the packraw/,build/,store/— empty, ready for data
Syncing Pack → Tenant
Section titled “Syncing Pack → Tenant”When the pack is updated (new signals, theses, etc.):
# Dry-run (see what would change)jin afs update --tenant hrcentral.vai
# Apply changesjin afs update --tenant hrcentral.vai --do-it
# All tenants across all packsjin afs update --all --do-it
# Force pack version on conflictsjin afs update --tenant hrcentral.vai --do-it --forceThree-way sync: pack base manifest tracks what was synced last. If both pack and tenant changed the same file → conflict (not overwritten unless --force).
Building
Section titled “Building”jin make --tenant hrcentral.vai # build one tenantjin make --pack hrcentral # all tenants in packjin make --all # all tenants, all packsjin make --tenant hrcentral.vai --skip-extract # skip Phase 0 when DLZ hasn't changedjin make --tenant hrcentral.vai --extract-only # run Phase 0 only, then stopjin make --tenant hrcentral.vai --clean # clear intermediaries, full rebuildThe Extraction Contract (pipeline.yml)
Section titled “The Extraction Contract (pipeline.yml)”Every tenant has a pipeline.yml at afs/scripts/pipeline.yml that declares every folder crossing the extraction layer: folder path, source type, sheet conventions, expected columns, minimum rows. The configuration IS the contract, and the contract is the audit trail. Reading it tells you the complete universe of what jin make will ever touch on the way in.
generate: generate_synthetic_data.pycanonicalise: canonicalise_csvs.pyenrich: enrich_csvs.py
extract_entries: - id: e1_material_master # = DLZ folder name purpose: "Material master — articles, prices, quantities" source: type: system_export path: "opale/xlsx/e1_material_master/" all_sheets: true header_row: 3 expected: min_rows: 1000 # per dated member
- id: e00_ou_structure purpose: "ABT department structure with priority flags and ABT→KST mapping" source: type: expert_curation path: "opale/xlsx/e00_ou_structure/" sheet: "Tabelle1" header_row: 6 expected: required_columns: ["ABT Code", "ABT Name", "ABT Kat.", "Prio"] min_rows: 100One entry per source folder, not per file. Inside each folder, every YYYY-MM-DD*.xlsx file is a dated member of the series — the extractor discovers them on every run, hashes them into afs/state/extract_log.jsonl, and skips unchanged members.
The file is tenant-specific and fully self-contained — there is no pack-level inheritance. Two tenants in the same pack using the same source system still have different pipeline.yml files because deliveries, auxiliary files, and file versions differ.
See the Extraction Guide for the seven source types, the zero-transform rule, and the jin inspect CLI, and DLZ Layout and the Three Generations for how folders feed Gen 00 → Gen 01 → Gen 02.
Data Flow
Section titled “Data Flow”make gathers its inputs on the way in (Phase 0 extract from the DLZ) and then builds the KLS from the complete AFS.
Cloning a Tenant
Section titled “Cloning a Tenant”jin clone --source hrcentral.vai --name experiment# Creates: hrcentral.vai_experiment (shares DLZ with source)Snapshots
Section titled “Snapshots”jin make --snapshot # auto-tag: YYYYMMDD-HHMMjin make --snapshot post-audit # named tagSnapshots are immutable — make refuses to overwrite them.
Configuration
Section titled “Configuration”# Set default tenantjin us --tenant hrcentral.vai
# Show current configjin usOutput:
Live root: /path/to/jinflow-live Pack root: /path/to/jinflow-packhub (4 packs) DLZ: /path/to/jinflow-datalandingzone (ok) Current tenant: hrcentral.vaiMulti-Pack
Section titled “Multi-Pack”Each pack is an independent analytical domain. Tenants belong to one pack:
live_root/ millesime/ ← winemaking analytics rmc/ inspire/ alptrack/ ← ski resort analytics inspire/ rmc/Packs are developed independently (separate git repos) and synced to tenants via jin afs update.