Skip to content

Phase 00: Foundation & Prerequisites

Duration: 2-3 days (reduced from 1 week) Goal: Scaffold Legacy ERP WMS app and development environment

Update (Jan 2026): Framework M Phases 1-6 are now substantially complete. Phase 00 is primarily about app scaffolding.


Phase Status Notes
Phase 1: Core Kernel βœ… Complete Hexagonal architecture, DI
Phase 2: DocType Engine βœ… Complete Pydantic models, SQLAlchemy mapping
Phase 3: API & Authorization βœ… Complete Auto-CRUD, RBAC, RLS
Phase 4: Jobs & Events βœ… Complete Taskiq + NATS, Event Bus
Phase 5: CLI Tools βœ… Complete m start, m migrate, m new:app
Phase 6: Built-in DocTypes βœ… Complete User, Session, File, APIKey, Auth
  • User DocType with password hashing (argon2)
  • Session management (Redis/DB backends)
  • JWT authentication
  • API Key authentication
  • OAuth2/OIDC support
  • File upload/download (Local + S3)
  • Permission system (RBAC + Citadel/Cedar ready)

Terminal window
m new:app legacy_erp_wms

Structure:

apps/legacy_erp_wms/
β”œβ”€β”€ pyproject.toml
β”œβ”€β”€ src/legacy_erp_wms/
β”‚ β”œβ”€β”€ __init__.py
β”‚ β”œβ”€β”€ doctypes/
β”‚ β”‚ β”œβ”€β”€ __init__.py
β”‚ β”‚ β”œβ”€β”€ item.py
β”‚ β”‚ └── warehouse.py
β”‚ β”œβ”€β”€ controllers/
β”‚ └── services/
└── tests/
  • Define legacy_erp_wms entry point in pyproject.toml
  • Register with Framework M app registry
  • Configure database connection (PostgreSQL)

  • PostgreSQL 15+ (Docker or native)
  • Redis 7+
  • Python 3.12+ environment
services:
db:
image: postgres:15
environment:
POSTGRES_DB: legacy_erp_wms
POSTGRES_USER: legacy_erp
POSTGRES_PASSWORD: dev_password
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
pgdata:
.env
DATABASE_URL=postgresql+asyncpg://legacy_erp:dev_password@localhost:5432/legacy_erp_wms
REDIS_URL=redis://localhost:6379
SECRET_KEY=dev-secret-key-change-in-prod
DEBUG=true

  • Generate initial migration: m migrate create "initial" --autogenerate
  • Run migration: m migrate
  • Create admin user
  • Basic permission setup

  • m start runs without errors
  • POST /api/v1/auth/login works
  • Database migrations apply cleanly
  • Docker build succeeds
  • Basic test suite passes

Citadel IAM is an abstraction layer over upstream OIDC-compatible IdPs. It handles user onboarding (admin invite, self-service) and normalizes identity from any IdP.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Upstream IdP (configurable) β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ Keycloak β”‚ β”‚ Citadel β”‚ β”‚ Any OIDC β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ OIDC Token
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Citadel IAM β”‚
β”‚ β€’ Validates token with upstream IdP β”‚
β”‚ β€’ Enriches request with X-* headers: β”‚
β”‚ X-User-Id, X-User-Attributes, X-User-Roles, etc. β”‚
β”‚ β€’ If headers too large β†’ adds X-Profile-Lookup header β”‚
β”‚ β€’ Publishes user events to NATS β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ X-* Headers (enriched)
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ WMS App (Framework M) β”‚
β”‚ β€’ Reads X-User-Id, X-User-Roles from headers β”‚
β”‚ β€’ If X-Attributes-Truncated=true set β†’ calls Citadel /profile API β”‚
β”‚ β€’ Maps roles β†’ WMS permissions β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
User Type Method Citadel Config
HQ Staff Admin invite (email) invite_only: true
Depot Staff Admin invite (email) invite_only: true
Outlet Operators Self-service (phone OTP) self_service: phone
Suppliers Self-service (email + GSTIN) self_service: email
Beneficiaries External app (Smart Card) custom_flow: smart_card
Terminal window
# .env - Upstream IdP (tokens come from here)
OIDC_ISSUER=https://auth.example.com/realms/legacy_erp # Keycloak/Zitadel
OIDC_CLIENT_ID=wms-app
OIDC_CLIENT_SECRET=<from-idp-admin>
# Citadel IAM API (for onboarding/user management)
CITADEL_API_URL=https://citadel.castlecraft.in/api
CITADEL_API_KEY=<from-citadel-admin>
# WMS maps IdP roles (normalized by Citadel) to permissions
ROLE_MAPPING = {
"wms_admin": ["*:*"], # Full access
"ho_staff": ["Item:*", "Supplier:*", "Warehouse:read"],
"depot_staff": ["StockEntry:*", "SupplyOrder:*", "Warehouse:read"],
"outlet_operator": ["Order:create", "Stock:read"],
"supplier": ["SupplierPortal:*"],
}
  • Deploy upstream IdP (Keycloak/Zitadel) or use existing
  • Deploy Citadel IAM (or use citadel.castlecraft.in)
  • Configure Citadel to use upstream IdP
  • Set up onboarding flows (admin invite, self-service)
  • Create WMS client in IdP
  • Set env variables in WMS
  • Test login + onboarding end-to-end

Task Duration
App scaffolding 2 hours
Dev environment 2 hours
Database setup 1 hour
Citadel IAM setup 2 hours
Verification 1 hour
Total ~1 day