Collaboration Guide
jinflow uses git for collaboration. Every tenant AFS is a git repository from birth. Teams share work through GitHub (or any git remote).
Two Ways to Start
Section titled “Two Ways to Start”1. New Tenant (First Analyst)
Section titled “1. New Tenant (First Analyst)”Create a tenant from a domain pack, connect to GitHub, push:
# Create from packjinflow init --pack hrcentral --tenant rmc
# Connect to GitHub (create the repo on GitHub first)jinflow afs remote https://github.com/org/afs-hrcentral-vai.git
# Push initial statejinflow afs push -m "initial setup"2. Join Existing Tenant (Second Analyst)
Section titled “2. Join Existing Tenant (Second Analyst)”Clone the AFS from GitHub — no pack needed:
# Clone from GitHubjinflow init --clone https://github.com/org/afs-hrcentral-vai.git
# Sync data and buildjinflow make --tenant hrcentral.vai --sync --cleanThis creates the full tenant layout (raw/, build/, store/) around the cloned AFS. The pack is not needed — the AFS IS the analytical framework.
Daily Workflow
Section titled “Daily Workflow”# Start of day: pull team changesjinflow afs pull
# Work: edit signals, theses, notes# Build and explorejinflow makejinflow desk
# End of day: push your changesjinflow afs push -m "added io_coefficient signal"Inviting People
Section titled “Inviting People”A principal is a person (or role, or group) recognised in a tenant. Each principal carries a stable slug (principal_id), a display name, and — for human users — an identity like owner, analyst, or viewer that determines what they can do.
Send an invitation
Section titled “Send an invitation”jinflow invite alice@example.com numetrix.rmc \ --identity analyst --principal-id aliceThis:
- Writes
afs/principals/user_alice.yamllocally - Fires a Clerk invitation email to
alice@example.com - Stamps the returned
clerk_invitation_idonto the YAML
Alice receives the email, clicks the magic link, signs up (or signs in if she already has a Clerk account), and lands on the tenant page.
After acceptance — materialise the binding
Section titled “After acceptance — materialise the binding”Once Alice has accepted, run:
jinflow sync-principals numetrix.rmcThis walks Clerk’s accepted invitations for the tenant, matches them to AFS principal YAMLs by clerk_invitation_id, and stamps clerk_user_id + accepted_at onto each one. Idempotent — safe to re-run; --dry-run previews changes without writing.
Propagate
Section titled “Propagate”jinflow ship numetrix.rmc --do-itRebuilds the KLS with Alice’s pinned binding, syncs to R2, refreshes Fly. Her badge now shows green in JinDesk with her identity.
Removing Someone
Section titled “Removing Someone”jinflow revoke alice numetrix.rmcThis:
- Calls Clerk to surgically remove
publicMetadata.jinflow.tenants["numetrix.rmc"]from Alice’s record — other tenant assignments she holds are preserved - Marks her YAML
status: archivedand stampsleft_at(the file stays — analytical authorship references continue to resolve) - Refuses self-revocation (you can’t lock yourself out)
After jinflow ship, Alice’s access to the tenant disappears. She keeps her Clerk account; she just no longer belongs to this tenant.
Re-inviting
Section titled “Re-inviting”If you revoke someone and later want them back, re-run jinflow invite with the same email and slug. The archived YAML gets resurrected with fresh active state; a new Clerk invitation is sent. Lifecycle history (previous clerk_user_id, accepted_at, left_at) survives in git.
AFS Commands
Section titled “AFS Commands”jinflow afs remote # show current remotejinflow afs remote <url> # set remote (add or update)jinflow afs status # show branch, tags, changesjinflow afs log # build logbook (git log)jinflow afs log -n 10 # last 10 entriesjinflow afs pull # pull from remote (fast-forward only)jinflow afs push # commit all changes + pushjinflow afs push -m "message" # with custom commit messageWhat Gets Versioned
Section titled “What Gets Versioned”The AFS (afs/) is the git repo. It contains:
| Content | Versioned | Notes |
|---|---|---|
| Signals, theses, verdicts | Yes | The analytical instruments |
| SMEbits, BitBundles | Yes | Expert knowledge |
| Notebooks | Yes | Investigation notes |
| Entities, lineage, contracts | Yes | Schema definitions |
| dbt macros, seeds, tests | Yes | Data transformation logic |
| Models (bronze, silver, gold) | Yes | SQL source models |
| jinflow.yml | Yes | Pack config |
| tenant/ (config, logo, seeds) | Yes | Tenant-specific content |
What is NOT in git (lives alongside the AFS):
| Content | Location | Notes |
|---|---|---|
| Raw CSVs | raw/ | Immutable source data from DLZ |
| Build artifacts | build/ | Compiled SQL, enriched CSVs (regenerable) |
| KLS + OPS | store/ | Built databases (regenerable via make) |
Auto-Commits
Section titled “Auto-Commits”jinflow make auto-commits a structured one-liner after each build:
jinflow make: ok | clean | 34/0/1 | v0.7.9 | darwin | mig | hrcentral.vai | 12.3sjinflow afs update --do-it auto-commits after syncing pack content.
These auto-commits create a build logbook visible via jinflow afs log.
Domain packs are independent git repos (e.g., jinflow-pack-hrcentral). They’re cloned manually:
git clone https://github.com/jinflow-io/jinflow-pack-hrcentral.gitConfigure the pack root so jinflow can find them:
jinflow us --pack-root ~/jinflow-packsPack changes flow into tenant AFS via jinflow afs update --do-it.
Conflict Resolution
Section titled “Conflict Resolution”jinflow afs update uses three-way merge (SHA-256 manifest):
- Only pack changed → safe update (auto-applied)
- Only tenant changed → preserved (your customization wins)
- Both changed → conflict (NOT overwritten, flagged for manual resolution)
- Force mode →
--forcemakes pack win on conflicts
jinflow afs pull uses fast-forward only. If local and remote diverge, it tells you to resolve manually with git pull --rebase.