ADR-023 — Tenant Restructure Decision
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:
- BasicConsulting AS treated as separate legal entity in tree (vedtekter, share register expectations) when in fact it is a domain only owned by ALAI Holding AS (CEO clarified post-audit)
- ALAI-Tech-DOO is a real legal subsidiary (RS d.o.o., Bosnia/Serbia distribution of Bilko/Tok/Drop) but lived under
~/companies/mixed with agent personas - 12 agent personas (CodeCraft, Vizu, FlowForge, etc.) mislabeled as "companies" in
~/companies/ - Client work scattered across
~/projects/mixed with ALAI internal engineering - CEO personal data (CV 19×, NAV records, employment-verification PII) scattered across business trees
~/Public/containing CEO PII (employment-verification, ownership cert, firmaattest) — local-network readable- Lumiscare client
.envfiles committed to git history (auth bypass flags) - Planka
.envat 644 perms; Snowit terraform.tfstate one accidentalgit add .from leak
Decision
Implement multi-tenant home tree with strict isolation per legal entity / personal scope / client scope:
~/business/ # legal entities (ALAI corporate group)
├── ALAI-Holding-AS/ # commercial parent (renamed from ~/ALAI/)
└── ALAI-Tech-DOO/ # RS d.o.o. subsidiary
~/personal/ # CEO natural-person scope (NEW)
~/clients-external/ # one canonical subdir per client (NEW)
~/system/ # orchestration runtime
└── agents/personas/ # agent persona definitions (12)
~/projects/ # ALAI internal engineering repos ONLY (8 entries, was 23)
Backward compatibility:
~/ALAIsymlinked to~/business/ALAI-Holding-AS/for 158 LaunchAgent paths grace period~/companiessymlinked to~/system/agents/personas/for 10+ daemon/tool refs grace period
Sub-decisions
| # | Decision | Rationale |
|---|---|---|
| D-1 | ~/ALAI/ renamed to ~/business/ALAI-Holding-AS/ | Tenant isolation, name reflects legal entity |
| D-2 | Symlink ~/ALAI → canonical preserved | 158 daemons hardcode old path; rewrite is non-urgent TD |
| D-3 | ~/companies/ removed entirely | Was anti-pattern; entities → ~/business/, personas → ~/system/agents/personas/, brand-only domains → not a tree |
| D-4 | ALAI-Tech-DOO promoted to peer entity | Real legal subsidiary per company.json |
| D-5 | BasicConsulting NOT a tree | CEO clarified: domain only (basicconsulting.no), no firma. Domain assets → ~/business/ALAI-Holding-AS/brand-surfaces/basicconsulting.no/ |
| D-6 | ~/personal/ created | Separation of CEO personal scope from business; GDPR purpose limitation |
| D-7 | ~/clients-external/ created | Tenant isolation per client; ends ~/projects/ sprawl |
| D-8 | ucenje extracted | Personal scholarly project moved to own repo (johnatbasicas/ucenje) + own subdomain (ucenje.alai.no); 301 redirect from alai.no/ucenje/* |
| D-9 | Agent personas relocated | 12 personas (CodeCraft / Vizu / etc.) → ~/system/agents/personas/; symlink ~/companies → here for tool/daemon backward compat |
| D-10 | KenanHot reclassified product → client | Kenan Hot is a person (soccer player, knyhot.pro), not an ALAI product |
| D-11 | FreeMyEV stub merged into client | Was duplicate (stub in products/, active in clients-external) |
| D-12 | ufs/ renamed unified-form-service/ | Opaque acronym → descriptive; placed under products/ (deployed at forms.alai.no) |
| D-13 | architecture/ and services/ renamed in ALAI-Holding-AS | Disambiguate from ~/system/architecture/ and ~/system/services/ (operational vs commercial) — architecture → product-architecture, services → service-catalog |
Consequences
Positive
- 13 named clients in
~/clients-external/(one tenant per subdir, no cross-contamination) - 9 ALAI products in
~/business/ALAI-Holding-AS/products/(no client-as-product misclassifications) - 12 agent personas in
~/system/agents/personas/(correct semantic home; no longer "companies") - 2 legal entities under
~/business/(Holding AS + Tech DOO; no third entity confusion) - CEO personal scope isolated under
~/personal/(cv, nav, scholarly, code, real-estate, legal-personal) ~/projects/narrowed from 23 → 8 entries (ALAI internal engineering only)- ucenje brand contamination resolved (ucenje.alai.no separate, alai.no/ucenje 301)
- 26 GB freed (ollama.tar.gz cleanup) + 16 GB freed (test scaffolds + companies archive)
- ~/Public PII quarantined to ~/personal/legal-personal/ (5 sensitive PDFs no longer local-network readable)
~/companies/completely removed (anti-pattern eliminated)
Negative
- 158 LaunchAgent paths still resolve via
~/ALAIsymlink (TD: rewrite to canonical, ≥30d grace) - 10+ tool/daemon refs to
~/companies/resolve via symlink (TD: same grace, lower priority) _legacy-bc-2026-05-07/content from BasicConsulting unwind required manual reconciliation intoclients/Entur/andclients/RPG/(DONE, but added one-time manual step)- 19 CV references across grant submissions remain in place (each is a submission artifact, not a duplicate to dedup)
- Some opaque-name decisions deferred (
internal/left as-is — well-organized but generic name)
Neutral
- Boot health unchanged (29/29 daemons loaded, 0 failing, before and after)
- Git histories preserved (used
git mvfor in-repo moves, plainmvfor cross-repo) - ALAI-Tech-DOO retains its own git repo and
.alai/orchestration metadata
Alternatives Considered
| Alternative | Why 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 subdir | Equivalent to chosen ~/business/ + ~/personal/ + ~/clients-external/, but less natural-language for CEO solo founder |
| Hard rewrite of all LaunchAgent paths in same operation | High 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 tree | CEO clarified there is no separate firma; would create maintenance burden for non-existent legal entity |
Implementation
| Wave | Scope | Result |
|---|---|---|
| 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 collision | DONE — 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 update | DONE — agents merged, architecture/services renamed for disambiguation |
| W2 (docs) | canonical-registry.md, ADR-022, drift-detection-design.md | DONE — MC #99701 |
| W3 (validation + publish) | Proveo E2E, BookStack publish | DONE — Proveo 9/10 PASS, BookStack shelf 2845 |
| Phase A (org-audit quick wins) | chmod planka, gitignore tfstate, PII quarantine, ollama.tar.gz delete | DONE |
| Phase B (ucenje extract) | New repo + CF Pages + 301 redirect | DONE — ucenje.alai.no live, 301 verified |
| Phase D.1 (personal + clients-external) | Skeleton + AlemPersonal + client repo migration | DONE |
| Phase D.2 (~/ALAI rename) | Symlink-based canonical rename | DONE |
| Phase D.3 (agent personas) | 12 personas → ~/system/agents/personas/ | DONE |
| Phase D.4 (BasicConsulting unwind + companies removal) | Tenant cleanup + symlink for daemon backward compat | DONE |
| 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 merge | DONE |
References
- Multi-perspective audit:
~/system/specs/anvil-organizational-audit-2026-05-07.md - Sub-agent reports:
/tmp/anvil-org-audit/01-petter*.md…06-skybound*.md - Mechanical sweep ADR:
~/system/architecture/decisions/ADR-022-anvil-fs-sweep-2026-05-07.md - Canonical registry:
~/system/specs/canonical-registry.md(post-D updates) - Tree blueprint (NEW):
~/system/specs/anvil-tree-blueprint-2026-05-07.md - Git structure rules (NEW):
~/system/specs/anvil-git-structure-2026-05-07.md - Memory entries:
project_alai_entity_identity_clarified_2026-05-07.md,project_anvil_phase_d_done_2026-05-07.md - MC chain: #99710 (org audit parent), #99742 (Phase B.1), #99744 (Phase B.2), #99722 (Brønnøysund — closed), #99723 (BC clarification — pending close), #99724 (Lumiscare notification), #99725 (Telegram revoke)
- Live deployment: https://ucenje.alai.no, https://github.com/johnatbasicas/ucenje
No comments to display
No comments to display