# Customer onboarding guide This guide is for an **integrator** standing up vibe_erp for a new customer end-to-end. It is written from a Tier 1 perspective: no plug-in code is required to follow it. Where Tier 2 plug-ins are useful, the guide says so. For the architectural background, see [`../architecture/overview.md`](../architecture/overview.md). For the full v1.0 cut line, see section 11 of [`../superpowers/specs/2026-04-07-vibe-erp-architecture-design.md`](../superpowers/specs/2026-04-07-vibe-erp-architecture-design.md). ## Honest scope note vibe_erp is a framework, not a turnkey product. **The Tier 1 customization UIs (custom field designer, form designer, BPMN designer, list view editor, role editor) are v1.0 deliverables.** The current build ships only the underlying API surface — the metadata tables, the REST endpoints, the seed data — without the polished UIs on top of them. Until v1.0 ships, the steps below that say "use the Customize UI" mean "POST to the metadata REST endpoints" or "edit a YAML seed file in your plug-in JAR". See [`PROGRESS.md`](../../PROGRESS.md) for the current per-feature status. This guide is written against the v1.0 experience. Where the current build deviates, the step is annotated **(current: API only)**. ## 1. Install the host vibe_erp ships as a single Docker image with PostgreSQL as the only mandatory external dependency. ```bash docker run -d --name vibe-erp \ -p 8080:8080 \ -v /srv/vibeerp:/opt/vibe-erp \ -e DB_URL=jdbc:postgresql://db.internal:5432/vibeerp \ -e DB_USER=vibeerp \ -e DB_PASSWORD=... \ ghcr.io/vibeerp/vibe-erp:1.0.0 ``` What happens on first boot: 1. The host connects to Postgres. 2. Liquibase runs every core PBC's migrations (plus `flowable_*` once that lands). 3. A bootstrap admin user is created and its one-time password is printed to the boot log. 4. The metadata loader walks the host classpath and seeds `metadata__entity` / `metadata__permission` / `metadata__menu` from each PBC's YAML file. 5. Each plug-in JAR is linted, migrated, metadata-loaded, and started in turn. 6. The host is ready in under 30 seconds. The mounted volume `/srv/vibeerp` (mapped to `/opt/vibe-erp` inside the container) holds: ``` /opt/vibe-erp/ ├── config/vibe-erp.yaml single config file (closed key set) ├── plugins/ drop *.jar to install ├── i18n-overrides/ operator translation overrides ├── files/ file store (if not using S3) └── logs/ ``` Customer extensions live entirely outside the image. Upgrading the host is `docker rm` plus `docker run` with the new image tag — extensions and config stay put. **vibe_erp is single-tenant per instance: this container serves exactly one company. Hosting a second customer means provisioning a second container with its own Postgres.** ## 2. Log in as the bootstrap admin Open `http://:8080/`, log in with `admin` and the one-time password from the boot log, and change the password immediately. Configure OIDC (Keycloak-compatible) at this point if the customer has an existing identity provider — built-in JWT auth is live today; OIDC is P4.2 in the implementation plan and not yet wired. ## 3. Configure the instance Set the company name, default locale, default currency, and default time zone in `vibe-erp.yaml` under `vibeerp.instance.*`. There is no "create a tenant" step — this entire instance belongs to one company. ## 4. Use the Customize UI to model the customer's reality This is where most of the integrator's time is spent. Everything here is **Tier 1**: rows in `metadata__*` tables, tagged `source = 'user'`. No build, no restart, no deploy. **(current: API only — POST to the metadata endpoints; the UIs ship in v1.0.)** ### Custom fields Add custom fields to existing entities (item, partner, order, work order, …). Each custom field is a row in `metadata__custom_field` and a JSON key in the entity's `ext` JSONB column at runtime. A GIN index on `ext` keeps custom fields queryable. The form designer, list views, OpenAPI spec, and AI-agent function catalog all auto-update from the metadata. For the rare hot-path field, an operator can promote a JSON key to a real generated column via an auto-generated Liquibase changeset. This is an optimization, not the default. ### Custom forms Define how each entity is displayed and edited. Forms are JSON Schema (data shape) plus UI Schema (layout and widgets), stored in `metadata__form`. Forms can reference custom fields by their key. See the [form authoring guide](../form-authoring/guide.md). ### Custom workflows Draw the customer's process flow in the BPMN designer. Workflows are stored in `metadata__workflow` and deployed to the embedded Flowable engine. User tasks render forms; service tasks call typed `TaskHandler` implementations registered by plug-ins. See the [workflow authoring guide](../workflow-authoring/guide.md). ### Custom list views, rules, menus, reports - **List views** (`metadata__list_view`): which columns, which filters, which default sort. - **Rules** (`metadata__rule`): simple "if X then Y" automations for the cases that do not warrant a full BPMN workflow. - **Menus** (`metadata__menu`): the navigation tree the user sees. - **Reports** (`metadata__report`): JasperReports templates the customer can run on demand or on a schedule. ## 5. Import master data vibe_erp accepts master data through two paths: - **CSV import** through the Customize UI for one-off bulk loads (catalog items, partners, opening stock, chart of accounts). **(current: API only.)** - **REST API** for ongoing integration with the customer's existing systems. Every entity, including custom fields, is exposed through OpenAPI-documented REST endpoints. The OpenAPI spec auto-updates as you add custom fields and custom entities, so the integration code is never out of date. ## 6. Configure roles and permissions Define the customer's roles (e.g. *sales clerk*, *production planner*, *warehouse operator*, *finance reviewer*) and assign permissions. Permissions are auto-discovered from: - Core PBCs. - Plug-ins (each plug-in registers its own permissions through `api.v1.security.PermissionCheck`). - Custom entities (each generates a standard CRUD permission set). Bind users to roles. Once OIDC (P4.2) lands, roles can also be bound via the identity provider's group claims. ## 7. Add Tier 2 plug-ins as needed When Tier 1 metadata is not expressive enough — for example, a printing-specific entity like *plate spec* with its own validation logic, or a workflow service task that calls an external MIS — install a Tier 2 plug-in. To install a plug-in: 1. Drop the JAR into `/opt/vibe-erp/plugins/`. 2. Restart the host (`docker restart vibe-erp`). Hot reload is on the v1.2+ roadmap. 3. The plug-in loader scans the JAR, validates the manifest, runs the plug-in linter, runs the plug-in's Liquibase migrations in `plugin___*`, seeds the plug-in's metadata, and starts the plug-in. 4. Verify the plug-in shows up under `/actuator/health` and in the boot log. The reference printing-shop plug-in (`reference-customer/plugin-printing-shop/`) is a worked example of a non-trivial Tier 2 plug-in. It expresses the workflows in `raw/业务流程设计文档/` using **only `api.v1`** and is built and CI-tested on every PR. It is **not** loaded by default — drop its JAR into `./plugins/` to use it. A guiding principle: **anything a Tier 2 plug-in does should also become possible as Tier 1 over time.** Tier 2 is the escape hatch where Tier 1 is not yet expressive enough. When you find yourself reaching for a plug-in to do something a metadata row could express, file an issue against the framework. ## 8. Go-live checklist - [ ] Backups configured against the Postgres instance. Customer data lives there exclusively (plus the file store). - [ ] Audit log enabled for PII fields if the customer is subject to GDPR or equivalent. - [ ] DSAR export and erasure jobs tested against a non-production copy. - [ ] Locale, currency, time zone defaults set in `vibe-erp.yaml`. - [ ] OIDC integration tested with the customer's identity provider (once P4.2 lands). - [ ] Health check (`/actuator/health`) wired into the customer's monitoring. - [ ] Documented upgrade procedure for the operator: `docker rm` plus `docker run` with the new image tag, plug-ins and config stay put. ## What this guide deliberately does not cover - **Plug-in development.** That is the [plug-in author getting-started guide](../plugin-author/getting-started.md). - **Hosted operations** (provisioning many independent vibe_erp instances, one per customer; billing; an operator console). vibe_erp is single-tenant per instance — hosting many customers means running many independent containers with their own databases. The provisioning console is a post-v1.0 deliverable. - **MCP / AI-agent endpoint.** v1.1 deliverable. The seam exists today; the endpoint does not.