ANVIL Tenant Architecture — Phase D 2026-05-07

Organizational tenant restructure: multi-tenant home tree, personal/business/client isolation, agent personas relocated, BasicConsulting clarified, ucenje extracted. Follow-on to mechanical sweep (ADR-022). Defines canonical tree structure going forward.

ADR-023 — Tenant Restructure Decision

Status: Accepted 2026-05-07
Cross-reference: This follows the ANVIL Filesystem Sweep (Mechanical) — ADR-022. Phase D addresses organizational/tenant concerns.

Context

ADR-022 documented the mechanical filesystem sweep — orphans, broken refs, PHANTOM daemons. After completion CEO observed that the home tree, while mechanically clean, remained semantically misorganized:

"Zelim da sam ponosan file strukture, a ne da sam zabrinut."
"alai.no/ucenje" — Alem's personal Quran-19 scholarly site lives inside the ALAI commercial brand tree.

A 6-agent multi-perspective audit (Petter / Brad / Parisa / Lexicon / Kelsey / Skybound) produced ~84 findings, ~22 convergent across 3+ angles. The unanimous top finding: personal scholarly content under commercial brand surface = brand contamination + GDPR exposure + blocks divestment.

Beyond ucenje, the audit surfaced:

Decision

Implement multi-tenant home tree with strict isolation per legal entity / personal scope / client scope:

Backward compatibility:

Sub-decisions

#DecisionRationale
D-1~/ALAI/ renamed to ~/business/ALAI-Holding-AS/Tenant isolation, name reflects legal entity
D-2Symlink ~/ALAI → canonical preserved158 daemons hardcode old path; rewrite is non-urgent TD
D-3~/companies/ removed entirelyWas anti-pattern; entities → ~/business/, personas → ~/system/agents/personas/, brand-only domains → not a tree
D-4ALAI-Tech-DOO promoted to peer entityReal legal subsidiary per company.json
D-5BasicConsulting NOT a treeCEO clarified: domain only (basicconsulting.no), no firma. Domain assets → ~/business/ALAI-Holding-AS/brand-surfaces/basicconsulting.no/
D-6~/personal/ createdSeparation of CEO personal scope from business; GDPR purpose limitation
D-7~/clients-external/ createdTenant isolation per client; ends ~/projects/ sprawl
D-8ucenje extractedPersonal scholarly project moved to own repo (johnatbasicas/ucenje) + own subdomain (ucenje.alai.no); 301 redirect from alai.no/ucenje/*
D-9Agent personas relocated12 personas (CodeCraft / Vizu / etc.) → ~/system/agents/personas/; symlink ~/companies → here for tool/daemon backward compat
D-10KenanHot reclassified product → clientKenan Hot is a person (soccer player, knyhot.pro), not an ALAI product
D-11FreeMyEV stub merged into clientWas duplicate (stub in products/, active in clients-external)
D-12ufs/ renamed unified-form-service/Opaque acronym → descriptive; placed under products/ (deployed at forms.alai.no)
D-13architecture/ and services/ renamed in ALAI-Holding-ASDisambiguate from ~/system/architecture/ and ~/system/services/ (operational vs commercial) — architectureproduct-architecture, servicesservice-catalog

Consequences

Positive

Negative

Neutral

Alternatives Considered

AlternativeWhy rejected
Status quo (semantic chaos accepted)CEO explicit "zelim da sam ponosan, ne zabrinut" + Lexicon legal exposure findings
Storage-only deeper sweep (no rename)ucenje brand contamination is structural, not storage
~/tenants/ umbrella with per-tenant subdirEquivalent to chosen ~/business/ + ~/personal/ + ~/clients-external/, but less natural-language for CEO solo founder
Hard rewrite of all LaunchAgent paths in same operationHigh risk; symlink grace period is industry-standard
Move ucenje to broj19.com (own domain, $12/year)Subdomain ucenje.alai.no is sufficient (CEO Decision #1B); domain purchase deferred
Keep BasicConsulting as separate entity treeCEO clarified there is no separate firma; would create maintenance burden for non-existent legal entity

Implementation

WaveScopeResult
W1-A (BLOCKER)Unload 3 PHANTOM daemons (mlx-router, db-ttl-sweep, distillation-scorer)DONE — boot failure resolved, 56 → 53 com.alai daemons
W1-B (bulk cleanup)Archive + delete 35 paths; settings.bak retention; ~/~ cleanup; ~/projects/ALAI collisionDONE — 30 valid tar archives in ~/backups/_archive/anvil-fs-sweep-2026-05-07/, ~9GB freed
W1-C (split-brain)6 active pairs merged/renamed; ~/ALAI/CLAUDE.md surgical updateDONE — agents merged, architecture/services renamed for disambiguation
W2 (docs)canonical-registry.md, ADR-022, drift-detection-design.mdDONE — MC #99701
W3 (validation + publish)Proveo E2E, BookStack publishDONE — Proveo 9/10 PASS, BookStack shelf 2845
Phase A (org-audit quick wins)chmod planka, gitignore tfstate, PII quarantine, ollama.tar.gz deleteDONE
Phase B (ucenje extract)New repo + CF Pages + 301 redirectDONE — ucenje.alai.no live, 301 verified
Phase D.1 (personal + clients-external)Skeleton + AlemPersonal + client repo migrationDONE
Phase D.2 (~/ALAI rename)Symlink-based canonical renameDONE
Phase D.3 (agent personas)12 personas → ~/system/agents/personas/DONE
Phase D.4 (BasicConsulting unwind + companies removal)Tenant cleanup + symlink for daemon backward compatDONE
Phase D push-through_multi-client-hub split, virtual-serbia classification, _legacy-bc reconciliation, futureProjects removal, ufs rename, KenanHot reclassification, FreeMyEV stub merge, nav-bc-residual mergeDONE

References

Tree Blueprint — Where to Put Things

⚠️ READ FIRST when deciding any new path
Purpose: Single answer to "where does this go?" — read FIRST before any new path creation, repo clone, or directory move.

One rule: every file has exactly one canonical home determined by what it is + whose it is, not by who created it or when.

1. Top-level decision tree

For any new content, answer 4 questions in order:

Q1: Is it CODE / file content / data?  No → it's a process artefact, not a tree concern.
Q2: Whose data is it? (CEO personal / ALAI Holding AS / ALAI Tech DOO / a specific client / regenerable)
Q3: What kind? (product, client deliverable, internal tool, scholarly, financial record, brand asset, …)
Q4: What stage? (active draft, in-flight, completed deliverable, archive)

2. Routing matrix

Whose?What kind?Canonical home
CEO personalCV, NAV records, ID docs~/personal/{cv,nav,legal-personal}/
CEO personalScholarly research (Quran-19, etc.)~/personal/scholarly/<topic>/ (or own repo + own domain — see ucenje precedent)
CEO personalPersonal coding (games, hobby projects)~/personal/code/<project>/
CEO personalReal estate, family property~/personal/real-estate/<property>/
CEO personalPersonal accounting (NOT ALAI Holding)~/personal/finance-personal/
ALAI Holding ASA product (own SaaS, own brand within ALAI)~/business/ALAI-Holding-AS/products/<product-name>/
ALAI Holding ASClient deliverable / engagement~/business/ALAI-Holding-AS/clients/<CLIENT-NAME>/
ALAI Holding ASBrand surface (alai.no, basicconsulting.no, forms.alai.no)~/business/ALAI-Holding-AS/brand-surfaces/<domain>/ OR ~/business/ALAI-Holding-AS/web/ if alai.no main
ALAI Holding ASBrand assets (logo, palette, typography)~/business/ALAI-Holding-AS/brand/ (single source of truth)
ALAI Holding ASFinance (accounting, grants, invoices, timesheets)~/business/ALAI-Holding-AS/finance/
ALAI Holding ASLegal (contracts, ROPA, vedtekter, certificates)~/business/ALAI-Holding-AS/legal/
ALAI Holding ASInternal libraries / shared packages~/business/ALAI-Holding-AS/internal/packages/
ALAI Holding ASSales pipeline, partners, comms, marketing~/business/ALAI-Holding-AS/{sales,partners,comms,content}/
ALAI Holding ASInternal product architecture decisions~/business/ALAI-Holding-AS/product-architecture/ (NOT system architecture)
ALAI Holding ASService catalog / commercial offerings~/business/ALAI-Holding-AS/service-catalog/ (NOT system services)
ALAI Tech DOORS subsidiary content (Bilko/Tok/Drop distribution)~/business/ALAI-Tech-DOO/{products,deliverables,legal,ops}/
External clientClient-owned repo (we work IN their repo)~/clients-external/<client-name>/ (matches their org name when possible)
External clientEngagement records, contracts with that client~/business/ALAI-Holding-AS/clients/<CLIENT>/engagement-docs/
External clientClient's brand assets we use~/clients-external/<client-name>/branding/
System runtimeDaemons, schedulers, hooks~/system/{daemons,tools,hooks}/
System runtimeArchitecture decisions (system-level)~/system/architecture/decisions/ADR-XXX.md
System runtimeOperational services (authentik, planka, vault)~/system/services/<service>/
System runtimeAgent persona definitions~/system/agents/personas/<PersonaName>/
System runtimeSpecs, plans, runbooks~/system/specs/, ~/system/runbooks/
System runtimeActive databases (Mission Control, HiveMind, …)~/system/databases/ (symlinked) or ~/Library/Application Support/ALAI/db/
ALAI engineering toolsInternal CLI / SDK / library used across ALAI~/projects/<repo-name>/ (must have GitHub remote, must be tracked, must NOT mix client work)
ALAI infra deploy workspaceCF/DNS/Tailscale/Vault/BookStack systemic configs~/aisystem/ (Mehanik gate reads BUILD-BLUEPRINT.md here)
Regenerablenode_modules, .gradle, .next, target, venv, build outputsINSIDE the repo, gitignored, never outside
BackupsTar archives, snapshot dumps~/backups/_archive/<sweep-name-date>/
OS-managedLibrary data (apps), Caches~/Library/ (DO NOT TOUCH)

3. Anti-patterns — explicitly forbidden

Anti-patternCorrect alternative
Putting personal scholarly content under commercial brand siteOwn repo + own domain (see ucenje → johnatbasicas/ucenje + ucenje.alai.no)
Client deliverable in ~/projects/~/clients-external/<client>/
Agent persona in ~/companies/<Name>/~/system/agents/personas/<Name>/
Pretending a domain is a separate firma (vedtekter for it, etc.)Domain → brand-surfaces/<domain>/ under owning entity
Mixing two clients in one treeOne tenant per top-level subdir under ~/clients-external/
Creating new top-level home dir without entry in ~/system/specs/canonical-registry.mdUpdate registry first, then create dir
Writing CEO PII (CV, NAV, ID) anywhere outside ~/personal/~/personal/legal-personal/, ~/personal/cv/, ~/personal/nav/
Auto-generated _pii-staging-* quarantine pattern (one-time fix)Process docs/forms BEFORE landing them in tree
~/Public for sensitive content (it is local-network readable)Never. Move to private tree.
Build artefacts (node_modules, target) outside their repoAlways inside repo with .gitignore entry
.env files committed to git.env* in .gitignore; secrets in Bitwarden / Keychain
Terraform state on local diskRemote state (S3/Azure/CF KV); *.tfstate* in .gitignore

4. References

Git Structure Rules

Purpose: Standard git hygiene for the multi-tenant tree. Read BEFORE git init, gh repo create, or any commit decision.

1. Repo placement matrix

Repo typeCanonical homeGitHub org/ownerVisibility default
ALAI product (Bilko, Drop, Tok)~/business/ALAI-Holding-AS/products/<product>/johnatbasicas/<product>private until launch
ALAI internal CLI / SDK / library~/projects/<repo-name>/johnatbasicas/<repo>public if open-source
ALAI infra workspace~/aisystem/n/an/a
ALAI Tech DOO (RS subsidiary)~/business/ALAI-Tech-DOO/alai-tech-doo/<repo>private
Client-owned repo~/clients-external/<client>/client's GitHub orgclient's choice
Personal scholarly project~/personal/scholarly/<topic>/johnatbasicas/<topic>public (transparency)
System orchestration~/system/johnatbasicas/alai-systemprivate

2. Required files per repo type

FileWhen required
README.mdAlways
CLAUDE.mdEvery repo where agents will be dispatched
BUILD-BLUEPRINT.mdRepos that build/deploy (per ZAKON PI2)
DEPLOY-MAP.mdRepos with live deploys (CF Pages, Cloud Run, App Runner, etc.)
.gitignoreAlways — see Section 4
.github/workflows/deploy*.ymlRepos with CI/CD
LICENSEPublic repos (default MIT for ALAI products)

3. Commit conventions — Conventional Commits (mandatory)

<type>(<scope>): <subject> (MC #<id>)

<body — what changed and why>

Co-Authored-By: <persona-name> <noreply@alai.no>

typefeat | fix | chore | docs | style | refactor | perf | test | ci | build

4. .gitignore standards

Universal (every repo)

# OS
.DS_Store
Thumbs.db

# Editor / IDE
.vscode/
.idea/
*.swp
.aider*
.claude-scratch/

# Secrets — NEVER COMMIT
.env
.env.*
!.env.example
*.pem
*.key
id_rsa*
*.p12
.bw-session

# Logs
*.log
logs/

# Build outputs
dist/
build/
out/
target/
.next/
.nuxt/
.output/
.turbo/

Node-specific

node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

Terraform / IaC (CRITICAL after Parisa finding)

*.tfstate
*.tfstate.*
*.tfplan
.terraform/
.terraform.lock.hcl
crash.log

5. Anti-patterns — explicitly forbidden

Anti-patternWhy it's badCorrect alternative
git add . without reviewing diffCommits unwanted files (.env, tfstate, secrets, IDE configs)git add -p or explicit paths
Committing .env "for now"Secrets in git history foreverBitwarden / .env.example pattern
Force-push to shared/masterDestroys teammates' workPRs only; force-push only on private feat branches
Cross-tenant reposTenant contamination, IP confusionSplit into 2 repos, separate orgs ideally
Tags pushed before work is verified liveTag points to broken stateTag AFTER curl 200 + Playwright pass

6. References

Canonical Registry (Phase D Updated)

Note: This is a live snapshot of the canonical paths registry. Manual sync from ~/system/specs/canonical-registry.md. Last updated: 2026-05-07 (ANVIL Phase D)
Purpose: Industry-standard ITIL CMDB / Spotify Backstage pattern. Catalog of canonical paths, their owners, scope, and anti-drift rules. This is the authoritative source for "where does X belong" questions.

Tree Ownership Table

One row per major tree. These are the canonical locations — creating parallel structures elsewhere violates the registry.

TreePurposeOwner
~/system/Orchestration runtime, daemons, tools, agents, specs, rules, hooks (git), schemasJohn (orchestrator)
~/business/ALAI-Holding-AS/Company state — clients, brand, products, sales, legal, org, processes, pipelines, web-worktreesALAI (CEO)
~/business/ALAI-Tech-DOO/RS d.o.o. legal subsidiary (Bilko/Tok/Drop distribution)ALAI Tech DOO
~/personal/CEO Alem Basic personal scope (NOT business)CEO (personal capacity)
~/clients-external/Client-owned content + state, one tenant per subdirPer client
~/projects/Code repositories (libraries, internal tools, experiments) — ALAI internal engineering onlyPer repo
~/.claude/Claude Code harness (settings.json, hooks, agents, projects, memory, skills)Anthropic Claude Code
~/Library/macOS system and vendor-managed application stateOS / app vendors
~/aisystem/Canonical infra deploy workspace (Cloudflare Pages/DNS, BookStack, Vault, fleet configs)John, Mehanik gate reads this path
~/backups/Tar archives + offsite backup source (7-day + 30-day retention)John

Phase D Additions (2026-05-07) — Final Tenant-Isolated Structure

~/business/
  ├── ALAI-Holding-AS/   (was ~/ALAI; symlink kept for 158 daemons grace)
  └── ALAI-Tech-DOO/     (RS d.o.o. subsidiary, real legal entity)

~/personal/              (NEW — CEO scope, 9 typed dirs)
~/clients-external/      (NEW — 13 named clients + 1 variants umbrella)
~/companies              SYMLINK → ~/system/agents/personas/  (10+ daemon backward compat)
~/system/agents/personas/  (12 personas)
~/projects/              (8 ALAI eng repos only)

Renamed for Disambiguation (Phase D)

4-Way CLAUDE.md Scope Rules

CLAUDE.md files exist at 4 different scope levels. Each loads based on current working directory (CWD).

FileScopeLoads WhenPurpose
~/.claude/CLAUDE.mdUser-globalAlways loaded (all Claude Code sessions)John's identity, ZAKONs, specialist routing, hard constraints
~/CLAUDE.mdHome directory projectCWD = /Users/makinjaOrchestration mode guardrails, session boot protocol, routing one-liners
~/system/CLAUDE.mdSystem tree projectCWD inside ~/system/System-specific build/deploy rules, tool usage
~/business/ALAI-Holding-AS/CLAUDE.mdALAI tree projectCWD inside ~/business/ALAI-Holding-AS/ALAI brand guidelines, client-facing constraints

What MUST NOT Recreate

These paths were archived during ANVIL FS Sweep. Recreating them silently reintroduces filesystem chaos and split-brain drift.

From ~/system/ (archived):

Post-D additions (MUST NOT recreate):

Live Deployments (post-D)

References