ECOSYSTEM.md
Rama main · réplica de lectura del repositorio original.
# janua — Ecosystem Context
> [!IMPORTANT]
> Janua owns ecosystem identity: users, tenants, OAuth/OIDC clients, sessions, token signing keys, MFA/passkeys, SAML/SCIM metadata, webhooks, and migration exports. Treat identity data and auth-provider operations as sensitive and side-effectful; keep examples placeholder-only. This is the identity-data side-effect doctrine for ecosystem context.
> [!IMPORTANT]
> MADFAM-ENCLII-FIRST-LEGACY-RAW v1: This document contains legacy raw infrastructure command examples.
> Routine production operations must use Enclii web, API, or CLI. Treat raw
> `kubectl`, `helm`, SSH, provider CLI/API, `docker exec`, and direct container
> access as platform bootstrap or documented break-glass only, and record any
> missing Enclii adapter gap.
> **Self-hosted OIDC/OAuth2 provider — the identity backbone for every MADFAM service.**
This file is self-contained: a Claude session on a fresh machine can operate
this service by reading only this one document. No external links are
load-bearing — the MADFAM ecosystem map and the full enclii CLI reference are
embedded below.
---
## 1. What this repo is
Janua is MADFAM's Auth0 replacement: OIDC/OAuth 2.0 with RS256 JWTs, multi-tenant orgs, GitHub OAuth, and a JWKS endpoint every other service verifies tokens against. It's hard-wired into Enclii (switchyard-api auth), and every ecosystem service that needs an authenticated caller validates against `auth.madfam.io/.well-known/jwks.json`.
**Pillar**: Identity / Auth
**Type**: service
**Status**: production
**Registry product**: Janua (`janua`, live, front door janua.dev).
### Deployed services
| Service | Public domain | Container port |
| ------------- | --------------- | -------------- |
| `janua-api` | auth.madfam.io | 8000 |
| `janua-admin` | admin.janua.dev | — |
| `janua-app` | app.janua.dev | — |
| `janua-docs` | docs.janua.dev | — |
| `janua-web` | janua.dev | — |
**Kubernetes namespace**: `janua`
**Cluster**: bare-metal k3s (see topology section below).
### Upstream dependencies (this repo consumes)
- postgres (users, orgs, sessions, tokens)
- redis (session store)
- cloudflare (tunnel + DNS + SSL)
- enclii (deploy target)
### Downstream consumers (this repo is consumed by)
- enclii (switchyard-api, dispatch) — OIDC SSO
- dhanam, karafiel, forgesight, tezca, fortuna, digifab-quoting, selva-office, pravara-mes, yantra4d, avala, phynd-crm, routecraft, symbiosis-hcm — all verify tokens via JWKS
### Key environment variables
- `JANUA_DATABASE_URL` — Postgres connection.
- `JANUA_REDIS_URL` / `REDIS_URL` — session and rate-limit store.
- `JANUA_JWT_PRIVATE_KEY` / `JANUA_JWT_PUBLIC_KEY` — RS256 signing material.
- `GITHUB_OAUTH_CLIENT_ID` / `GITHUB_OAUTH_CLIENT_SECRET` — GitHub identity federation.
---
## MADFAM Ecosystem Map
Everything below is embedded here so this document stands alone. The product
tables are rendered from the public projection of the MADFAM product registry
(`madfam-org/solarpunk-foundry` → `packages/core/src/products/projection.public.json`,
generated from the registry in `madfam-org/internal-devops`). To change a row,
change the registry and re-render — never hand-edit a rendered copy.
Estate counts (services, ArgoCD applications, namespaces) are deliberately not
typed here: they move weekly. The dated figures live in the private operations
record, `madfam-org/internal-devops` (`infrastructure/topology.md`).
### Products in the registry
32 customer-facing products, grouped by the registry's category and listed in registry order. `—` means the registry records no public front door yet.
#### Infrastructure
| Product | Repo | Front door | Lifecycle | Role |
| ---------------- | ------------------------- | ---------- | ---------- | --------------------------------------------------------------------------------------- |
| **Enclii** | `madfam-org/enclii` | enclii.dev | live | PaaS control plane — every deploy goes through it |
| **Janua** | `madfam-org/janua` | janua.dev | live | OIDC/OAuth 2.0 identity provider — RS256 JWKS at `auth.madfam.io/.well-known/jwks.json` |
| **Selva** | `madfam-org/selva-office` | selva.town | live | LLM inference gateway (OpenAI-compatible `/v1`) + agent orchestration |
| **Fragua** | `madfam-org/enclii` | — | incubating | — |
| **Enclii Depot** | `madfam-org/enclii` | — | incubating | — |
#### Intelligence
| Product | Repo | Front door | Lifecycle | Role |
| -------------- | ----------------------- | ------------------ | ---------- | ------------------------------------------------------------------------- |
| **Forgesight** | `madfam-org/forgesight` | forgesight.app | live | Digital-fabrication industry intelligence (pricing/vendor feed to Cotiza) |
| **Dhanam** | `madfam-org/dhanam` | dhan.am | live | Billing, entitlements and payment gateways (Stripe, Mercado Pago, SPEI) |
| **Fortuna** | `madfam-org/fortuna` | fortuna.tube | live | Problem intelligence / zeitgeist analysis |
| **Rondelio** | `madfam-org/rondelio` | rondel.io | live | Games |
| **Factlas** | `madfam-org/factlas` | factl.as | live | Geospatial facts |
| **Tlacuilo** | `madfam-org/tlacuilo` | tlacuilo.madfam.io | beta | Document intelligence (OCR) |
| **LexiDrop** | `madfam-org/lexidrop` | ld.madfam.io | incubating | — |
#### Standards
| Product | Repo | Front door | Lifecycle | Role |
| ------------- | ---------------------- | ------------------ | ---------- | ------------------------------------------------------------------------- |
| **Karafiel** | `madfam-org/karafiel` | karafiel.mx | live | Operational compliance — CFDI, NOM-151, e.firma; owns legal-ops templates |
| **Tezca** | `madfam-org/tezca` | tezca.mx | live | Mexican law oracle (informational only — feeds Karafiel) |
| **Avala** | `madfam-org/avala` | avala.studio | live | Learning and competency verification |
| **Meridian** | `madfam-org/meridian` | meridian.madfam.io | degraded | — |
| **geom-core** | `madfam-org/geom-core` | — | incubating | — |
#### Applications
| Product | Repo | Front door | Lifecycle | Role |
| ------------------- | ---------------------------- | ---------------- | ---------- | --------------------------------------------------------------------- |
| **Yantra4D** | `madfam-org/yantra4d` | yantra4d.com | live | Phygital fabrication |
| **Cotiza** | `madfam-org/digifab-quoting` | cotiza.studio | live | Quoting engine (fabrication + services) |
| **Pravara MES** | `madfam-org/pravara-mes` | mes.madfam.io | live | Fabrication routing and dispatch (physical jobs) |
| **Voxa** | `madfam-org/voxa` | voxa.madfam.io | live | Assistive communication |
| **PhyndCRM** | `madfam-org/phynd-crm` | phynd.app | live | CRM — consent, campaigns, attribution |
| **CEQ** | `madfam-org/ceq` | ceq.lol | degraded | Generative asset pipeline — ComfyUI wrapper behind `/v1/render` |
| **Acervo** | `madfam-org/acervo` | acervo.madfam.io | live | Records engine |
| **Kalya** | `madfam-org/kalya` | kalya.app | live | Booking and scheduling |
| **Symbiosis HCM** | `madfam-org/symbiosis-hcm` | hcm.madfam.io | live | Human capital management — Mexican payroll |
| **Nauta** | `madfam-org/nauta` | nauta.quest | live | Fractional CTO practice — staff cockpit and per-client ERP workspaces |
| **Fashion Cabinet** | `madfam-org/fashion-cabinet` | fashioncabi.net | live | Parametric fashion |
| **Periplo** | `madfam-org/periplo` | — | incubating | — |
| **RouteCraft** | `madfam-org/routecraft` | routecraft.app | live | Trip planning |
| **Telesia** | `madfam-org/telesia` | telesia.quest | incubating | Completion |
| **Marca** | `madfam-org/marca` | madf.am | incubating | — |
### Retired products — never present as live
| Product | Retired on | Successor | Redirect |
| ------- | ---------- | --------- | -------- |
| PENNY | 2026-07-25 | Selva | none |
| Sim4D | 2026-08-30 | Yantra4D | none |
| SPARK | 2026-04-08 | — | none |
### Cross-repo conventions
- **Auth**: every authenticated service verifies Janua JWTs via JWKS at
`https://auth.madfam.io/.well-known/jwks.json`. RS256 only — HS256 is
banned on any path that verifies a Janua token (audit 2026-04-23 H3/H4);
an app's own session cookie needs its own secret.
- **Billing**: credit metering + entitlements flow through Dhanam. See
`madfam-org/dhanam` for the meter/entitlement/invoice APIs.
- **Inference**: every LLM call should route through Selva
(`selva-office`) at `/v1` (OpenAI-compatible). Do not talk directly
to OpenAI / Anthropic from service code.
- **Agent SaaS tools**: end-user delegated tool calls (Slack, Gmail, etc.)
route through Coupler (`madfam-org/coupler`, the Agent Tool Plane), not the
Enclii Provider Hub.
Operator infra actions stay on Enclii `providers.*` / `ops.*` (proxied as
`madfam.ops.*` from Coupler for admin agents only).
- **Third-party messages**: email/SMS/chat to people outside MADFAM go out
through Angelia Courier (`madfam-org/angelia`). Carve-outs: Janua's
customer-configured alert notifier and Selva agent tools.
- **CORS**: explicit allowlist per service. Wildcards are banned
(audit 2026-04-23 H2/H5/H6).
- **Images**: `@sha256:`-pinned in every manifest; mutable tags such as
`:latest` are a Kyverno policy violation.
- **Onboarding**: `enclii onboard` (`POST /v1/admin/onboard` on
switchyard-api) creates namespace, ArgoCD app, Cloudflare tunnel routes,
Janua client, and NetworkPolicies in one shot. See
`enclii/docs/guides/ONBOARDING_GUIDE.md`.
### Production topology
Bare-metal k3s (v1.33+), 4 nodes, described by ROLE only. This file is
generated and copied into public repos, so it never carries node hostnames,
IP addresses or hardware SKUs (2026-07-16 exposure class 1). Node identity
lives only in `madfam-org/internal-devops`.
- control-plane node — control plane + primary workload
- worker node — workloads + Longhorn second replica
- two builder nodes (labelled `role=builder`, tainted
`builder=true:NoSchedule`) — ARC runners only
**Ingress**: Cloudflare Tunnel → cloudflared pods → K8s ClusterIP → container port.
Zero exposed node ports. TLS terminated at Cloudflare edge.
**Storage**: Longhorn CSI in 2-replica mode across the control-plane and
worker nodes. Object storage: Cloudflare R2 (zero egress).
**GitOps**: ArgoCD App-of-Apps with self-heal. Push to `main` → CI builds →
GHCR → `kustomize edit set image` commits the digest →
ArgoCD syncs → Switchyard tracks lifecycle events.
**Operational access** (SSH, kubeconfigs, node identity, estate counts, cost
ledger): private repo `madfam-org/internal-devops`. Not in any public repo.
Policy: the repo-boundary contract, `internal-devops/docs/repo-boundary-contract.md`.
---
## Enclii CLI — DevOps Reference
**Strong preference: use `enclii` over `kubectl`** for all operational
tasks. The CLI routes through Switchyard API, which gives you audit
logging, lifecycle event tracking, and service-scoped context. Escape
to kubectl only for the gaps listed at the end of this section.
### Install
GitHub Releases are the verified binary channel (Linux, macOS and Windows
archives with checksums): `https://github.com/madfam-org/enclii/releases`.
Homebrew, Scoop and `get.enclii.dev` are convenience targets, not yet
monitored.
```bash
# From source (any OS with Go)
git clone https://github.com/madfam-org/enclii.git
cd enclii && make build-cli && ./bin/enclii --version
```
### Auth
```bash
enclii login # browser SSO (Janua)
enclii whoami # verify active session
enclii logout # clear local creds
```
Global flags: `--api-endpoint` (or `ENCLII_API_ENDPOINT`, default
`https://api.enclii.dev`) and `--api-token` (or `ENCLII_API_TOKEN`; legacy
`ENCLII_TOKEN` is still read) for non-interactive use. Set
`ENCLII_PROJECT=<project-slug>` (or pass `--project`) when a command has to
resolve a service name.
### Day-to-day for janua-api
The commands below default to `janua-api` — the primary service name for
this repo as registered in Switchyard. For any other service in the
ecosystem, swap the name. Environments are `dev`, `staging` and `prod`;
most commands default to `dev`, so pass `--env prod` for production.
```bash
# Status
enclii ps --env prod
# Logs
enclii logs janua-api --env prod -f # live tail
enclii logs janua-api --env prod --since 1h -n 200 # last hour
# Deploy (reads service.yaml)
enclii deploy --env staging --wait
enclii deploy --env prod --canary 10% --change-ticket <url>
# Rollback
enclii rollback janua-api --env prod # previous release
enclii rollback janua-api v42 --env prod
# Releases + deployment history
enclii releases janua-api -n 20
enclii deployments list
# Secrets (routed through Lockbox → Vault → ESO → K8s)
enclii secrets list --env prod
enclii secrets set MY_KEY=value --secret --env prod
# Chat-safe operator intake (values never pass through agent chat)
enclii secrets intake submit <target> --reason "<audit reason>" --stdin
enclii secrets intake status <intake-id>
# Domains, tunnel routes, DNS
enclii domains list --service janua-api
enclii domains add my.example.com --service janua-api # auto-provisions tunnel route + DNS
# Scheduled jobs, routing, serverless
enclii jobs list --project <project-slug>
enclii junctions list --project <project-slug>
enclii functions list
# Observability
enclii observe health --service <service-id>
# Local dev environment
enclii local up # spin up dependent services (postgres, redis, …)
enclii local logs
enclii local down
```
### Full onboarding (only used when adding a brand-new service)
```bash
# One-shot: namespace + ArgoCD app + tunnel routes + Janua client + netpol
enclii onboard --repo madfam-org/<name> --db-name <db> --secrets-file .env
```
### Enclii-first production operations
Enclii is the required control plane for routine production operations.
Use the web UI, API, or CLI before reaching for raw infrastructure tools:
- ArgoCD sync / diff / rollback — `enclii ops apps ...`
- Pod logs, diagnosis, and safe restarts — `enclii ops pods ...`
- Longhorn / PVC / PV inspection and repair planning — `enclii ops storage ...`
- Kyverno violations and time-bound waivers — `enclii ops policy ...`
- ExternalSecrets and Vault readiness — `enclii ops secrets ...`
- ARC runner inspection and drain workflows — `enclii ops runners ...`
- DNS, tunnels, SaaS hostnames, providers, and repo automation — `enclii providers ...`
- Service lifecycle, domains, secrets, jobs, and observability — `enclii deploy`, `enclii rollback`, `enclii logs`, `enclii observe`, `enclii domains`, `enclii secrets`, `enclii jobs`
### Break-glass-only access
Raw `kubectl`, `helm`, SSH, provider CLIs/APIs, `docker exec`, and direct
container access are allowed only for platform bootstrap or documented
break-glass emergencies when Enclii is unavailable or lacks an implemented
adapter. Record the actor, reason, target service/environment, commands
executed, result, and follow-up Enclii adapter gap or incident link.
### Cluster access
kubeconfig + SSH keys live in `madfam-org/internal-devops` (private repo)
for bootstrap and break-glass use only. Routine production operations must
go through Enclii web, API, or CLI.
### Exit codes (scripting against the CLI)
| Code | Meaning |
| ---- | ---------------- |
| 0 | success |
| 10 | validation error |
| 20 | build failed |
| 30 | deploy failed |
| 40 | timeout |
| 50 | auth error |
---
## Document provenance
Rendered by `madfam-org/enclii/docs/templates/ecosystem/generator.py` from this
repo's metadata entry (plus any private overlay kept in this repo) and the
public product-registry projection. First generated 2026-04-23 for the "each
repo stands alone" docs sweep. Do not hand-edit this file: change the metadata,
overlay or registry and re-render. `generator.py --check <repo-path>` fails when
this file differs from what the generator would write.