modified: README.md

This commit is contained in:
2026-04-23 12:39:36 +02:00
parent cbaf3319ce
commit aee79ddbfa
15 changed files with 2371 additions and 108 deletions

393
README.md
View File

@@ -1,123 +1,300 @@
You are helping implement an internal web application called **Support Provisioning Portal**.
# Support Provisioning Portal
Your task is to bootstrap the project based on the local `README.md` in this repository and then implement the first vertical slice with strong engineering discipline.
Internal WordPress plugin for support staff to provision standardized Proxmox VE VMs without direct Proxmox access.
## Product context
The application runs as a WordPress plugin and exposes both:
The application is an internal self-service portal for support staff. It provisions standardized VMs on **Proxmox VE** through a backend service. Users must never interact with Proxmox directly.
- an admin page at **Support Provisioning**
- a frontend shortcode: `[support_provisioning_portal]`
## Implemented First Slice
- WordPress plugin bootstrap with activation hook
- Custom database tables:
- `wp_spp_templates`
- `wp_spp_deployments`
- `wp_spp_audit_logs`
- Seed data for 3 approved templates
- WordPress REST API endpoints:
- `GET /wp-json/support-provisioning/v1/templates`
- `GET /wp-json/support-provisioning/v1/quota`
- `GET /wp-json/support-provisioning/v1/deployments`
- `GET /wp-json/support-provisioning/v1/deployments/:id`
- `POST /wp-json/support-provisioning/v1/deployments`
- `POST /wp-json/support-provisioning/v1/deployments/:id/start`
- `POST /wp-json/support-provisioning/v1/deployments/:id/stop`
- `POST /wp-json/support-provisioning/v1/deployments/:id/prolong`
- `POST /wp-json/support-provisioning/v1/deployments/:id/refresh-ips`
- `DELETE /wp-json/support-provisioning/v1/deployments/:id`
- Mock Proxmox adapter for local/no-cluster use
- HTTP token-auth Proxmox adapter behind the same interface
- Audit log rows for every mutating action
- Optional `Never expire` deployments
- Per-user and global RAM contingents
- IP address display for deployments when available from the mock adapter or Proxmox guest agent
- Manual IP refresh action for deployments
- Non-destructive expiration: expired VMs are stopped and locked, not deleted
- Minimal admin/frontend UI for:
- deployment dashboard
- templates
- create deployment form
- deployment detail view
- start/stop/delete actions
- TTL prolongation for expired or active deployments
- theme-inherited form controls and colors for shortcode rendering
## Install
1. Copy the `support-provisioning-portal` folder into:
```text
wp-content/plugins/support-provisioning-portal
```
2. Activate **Support Provisioning Portal** in WordPress admin.
3. Open **Support Provisioning** in the WordPress admin menu.
4. Optional: add this shortcode to an internal page:
```text
[support_provisioning_portal]
```
## Permissions
- Logged-in users with `read` can view templates and deployments.
- Logged-in users with `edit_posts` can create, start, stop, and delete deployments.
- WordPress REST nonces are required for UI mutations.
## Expiration And Contingents
Deployment creation supports either a TTL in hours or **Never expire**.
When a deployment reaches its TTL:
- WordPress cron and REST requests detect the expiration.
- The plugin attempts to stop the VM.
- The deployment status becomes `EXPIRED`.
- The VM cannot be started again until the user prolongs its TTL.
- The user can either prolong the TTL or delete the deployment.
- Deleted deployments are hidden from the active deployment list, but audit rows remain.
RAM contingents are configured from **Support Provisioning > Proxmox Settings**:
- Default per-user RAM limit (MB)
- Global RAM limit (MB)
Set either value to `0` for unlimited. Active allocations include deployments in `PROVISIONING`, `STOPPED`, `RUNNING`, and `DELETING` states.
Per-user overrides are available on each WordPress user profile under **Support Provisioning Contingent**. Leave the override empty to use the default per-user limit.
## IP Addresses
Deployments include an `ipAddresses` field in REST responses and show those addresses in the UI. In mock mode, deterministic documentation-range IPs are assigned. In HTTP mode, the plugin reads IPs from the Proxmox guest-agent `network-get-interfaces` endpoint when available.
If the guest agent reports IPs only after boot, use **Refresh IPs** in the deployment detail view.
## Proxmox Settings
The plugin defaults to mock mode. Configure live Proxmox access from the **Support Provisioning** admin page:
- Mode: `Mock` or `HTTP token auth`
- Base URL, for example `https://proxmox.example.internal:8006`
- Token ID, for example `user@realm!token-name`
- Token Secret
- Node, for example `pve-01`
No Proxmox secrets are committed to the repository.
## Configure A Live Proxmox Link
Use this section when moving from mock mode to a real Proxmox VE node.
### 1. Prepare Proxmox Templates
The plugin only provisions from approved templates. For a first real test, either create Proxmox VM templates with the seeded IDs or update the plugin database rows to match your real template IDs.
Seeded template IDs:
| Plugin template | Proxmox template VMID |
| --- | ---: |
| Turnkey PBX Test Appliance | `9001` |
| Windows Support Client | `9002` |
| Linux Utility VM | `9003` |
The fastest first test is to create one real Proxmox template with VMID `9003`, then use the **Linux Utility VM** option in the plugin.
Template requirements:
- The VM must be converted to a Proxmox template.
- The template must exist on the Proxmox node configured in the plugin.
- The plugin currently performs a full clone (`full=1`), so the target storage must have enough free capacity.
- CPU and memory are set by the plugin after clone based on the template policy row.
- For IP address display, install and enable `qemu-guest-agent` inside the guest and enable the guest agent option on the VM/template.
If you do not want to use VMIDs `9001`, `9002`, or `9003`, update the template rows after activation:
```sql
UPDATE wp_spp_templates
SET proxmox_template_id = 1234
WHERE template_key = 'linux-utility-vm';
```
Replace `wp_` with your WordPress table prefix.
### 2. Create A Dedicated Proxmox API User
In Proxmox, create a dedicated user instead of using `root@pam` for the plugin.
Example via Proxmox shell:
```bash
pveum user add wp-support@pve --comment "WordPress Support Provisioning Portal"
```
You can also create the user in the Proxmox UI under **Datacenter > Permissions > Users**.
### 3. Create An API Token
In the Proxmox UI:
1. Go to **Datacenter > Permissions > API Tokens**.
2. Click **Add**.
3. User: `wp-support@pve`
4. Token ID: `support-portal`
5. Enable **Privilege Separation**.
6. Save the token secret immediately. Proxmox only shows it once.
The plugin stores these fields separately:
- **Token ID**: `wp-support@pve!support-portal`
- **Token Secret**: the secret value shown by Proxmox
Do not include the `=` between token ID and secret in the WordPress settings. The plugin builds the required `PVEAPIToken=tokenid=secret` header internally.
### 4. Grant Proxmox Permissions
Proxmox permissions are path based. For a first controlled test, grant the token access only to the node/storage/template area you intend to use.
The plugin needs permissions for:
- getting the next VMID
- cloning a template VM
- changing CPU and memory after clone
- starting and stopping VMs
- deleting VMs
- reading VM status
- reading guest-agent network interfaces for IP display
Practical first-test option:
```bash
pveum aclmod / -user wp-support@pve -role PVEVMAdmin
```
If the clone fails because storage permissions are missing, also grant datastore access on the storage path used by your templates/clones:
```bash
pveum aclmod /storage/local-lvm -user wp-support@pve -role PVEDatastoreAdmin
```
For a tighter production setup, create a custom role with only the required privileges and assign it to the API token or user:
```bash
pveum role add SupportProvisioner -privs "VM.Allocate VM.Audit VM.Clone VM.Config.CPU VM.Config.Memory VM.PowerMgmt Datastore.AllocateSpace Datastore.Audit Sys.Audit"
pveum aclmod / -user wp-support@pve -role SupportProvisioner
```
Depending on your Proxmox version and storage layout, you may need to scope storage permissions separately, for example:
```bash
pveum aclmod /storage/local-lvm -user wp-support@pve -role SupportProvisioner
```
### 5. Check Proxmox TLS
The plugin uses WordPress HTTP requests to call Proxmox. That means PHP/WordPress must trust the Proxmox HTTPS certificate.
Recommended:
- Use a DNS name for Proxmox, not a raw IP address.
- Install a valid certificate on Proxmox, or install your internal CA certificate so the WordPress/PHP host trusts it.
If Proxmox still uses its default self-signed certificate, WordPress may reject the request with an SSL/cURL certificate error. Fix the trust chain before debugging plugin credentials.
### 6. Configure WordPress Plugin Settings
In WordPress admin, open **Support Provisioning > Proxmox Settings**:
| Setting | Value |
| --- | --- |
| Mode | `HTTP token auth` |
| Base URL | `https://proxmox.example.internal:8006` |
| Token ID | `wp-support@pve!support-portal` |
| Token Secret | token secret from Proxmox |
| Node | Proxmox node name, for example `pve-01` |
The **Node** value must match the Proxmox node name exactly as shown in the Proxmox UI under **Datacenter**.
### 7. First Live Test Checklist
Before creating a deployment:
- Confirm WordPress can reach Proxmox on TCP `8006`.
- Confirm the Proxmox base URL opens from the WordPress server.
- Confirm the configured node name is exact.
- Confirm the selected plugin template points to a real Proxmox template VMID.
- Confirm the token has clone, VM config, power, delete, audit, and datastore permissions.
- Confirm target storage has enough capacity for a full clone.
- Confirm RAM contingents in WordPress are not blocking the selected template.
Then test in this order:
1. Switch plugin mode to `HTTP token auth`.
2. Create a deployment from **Linux Utility VM** or whichever template VMID you mapped.
3. Open the deployment detail view.
4. Click **Start**.
5. Wait for the guest to boot.
6. Click **Refresh IPs**.
7. Confirm IP addresses appear.
8. Click **Stop**.
9. Click **Delete** when done.
### 8. Common Failure Points
| Symptom | Likely cause |
| --- | --- |
| `Missing Proxmox HTTP configuration` | One of Base URL, Token ID, Token Secret, or Node is empty. |
| `Proxmox request failed with HTTP 401` | Token ID/secret is wrong, token was deleted, or the secret was copied incorrectly. |
| `Proxmox request failed with HTTP 403` | Token exists but lacks permissions for clone/config/power/delete/storage. |
| `Proxmox request failed with HTTP 404` | Node name or template VMID is wrong, or the template is on a different node. |
| SSL/cURL certificate error | WordPress/PHP does not trust the Proxmox certificate. |
| Deployment created but no IPs | Guest agent is missing, disabled, not running, or the VM has not finished booting. |
| Start is blocked | Deployment is `EXPIRED`; prolong the TTL first. |
## Design Notes
- Templates are the only provisioning path.
- Resource limits come from approved templates, not user input.
- Deployment lifecycle operations are routed through a dedicated Proxmox client interface.
- Live Proxmox access can be replaced or expanded without changing REST or UI code.
- WordPress users are used as actors for audit logging. This keeps the first slice simple and leaves room for later RBAC/SSO mapping.
## Original Bootstrap Brief
The application is an internal self-service portal for support staff. It provisions standardized VMs on **Proxmox VE** through a backend service. Users must never interact with Proxmox directly. The application MUST run as a WordPress plugin.
Typical resources:
- turnkey PBX/test appliances
- Windows support clients
- Linux utility VMs
The system must enforce:
- template-based provisioning only
- policy-controlled resource limits
- audit logging
- lifecycle actions
- TTL / expiration support
## Technical direction
Use this stack unless the repository already contains an equivalent decision:
- Monorepo with pnpm
- Next.js + TypeScript for `apps/web`
- Node.js + TypeScript for `apps/api`
- Fastify preferred for the API
- PostgreSQL + Prisma
- Tailwind CSS for the web UI
- Zod for request/response validation
## Constraints
- Do not overengineer.
- Prefer a clean vertical slice over broad scaffolding.
- Keep Proxmox integration behind a dedicated adapter/module.
- Use clear domain names and explicit types.
- Avoid magic strings.
- Add TODOs only when truly necessary.
- Document all non-obvious decisions in code comments or small docs.
- Make the codebase easy to extend toward RBAC, SSO, and multi-cluster support later.
## Initial implementation goals
Implement a usable first slice with the following:
1. Monorepo structure
- `apps/web`
- `apps/api`
- `packages/types`
- `packages/proxmox-client`
- `prisma`
2. Database schema with at least:
- users
- templates
- deployments
- audit_logs
3. Backend API endpoints
- `GET /api/templates`
- `GET /api/deployments`
- `GET /api/deployments/:id`
- `POST /api/deployments`
- `POST /api/deployments/:id/start`
- `POST /api/deployments/:id/stop`
- `DELETE /api/deployments/:id`
4. Proxmox adapter
- token auth support
- stubbed or mockable implementation if no live environment is available
- methods for clone/start/stop/delete/getStatus
- clear interface separation between domain service and transport
5. Web UI
- dashboard page listing deployments
- templates page
- create deployment form
- deployment detail view
- simple status badges and action buttons
6. Seed data
- at least 3 sample templates
7. Audit logging
- every mutating action must write an audit log row
8. Developer experience
- `.env.example`
- scripts for dev/build/lint
- basic README sections updated if needed
## Working style
Proceed in small, reviewable steps:
1. inspect repository
2. propose concrete file plan
3. implement foundation
4. implement backend slice
5. implement frontend slice
6. verify types/build consistency
7. summarize what was created and what remains
## Output requirements
- Start by reading the local `README.md` and align implementation with it.
- Show the file/folder plan before making broad changes.
- Then create the project incrementally.
- When assumptions are required, state them briefly and choose the most pragmatic path.
- Favor production-style code structure over tutorial-style code.
- Where live Proxmox access is unavailable, create a mock adapter that can later be replaced without touching domain logic.
## Quality bar
- TypeScript strict mode
- input validation at API boundaries
- no secrets committed
- minimal but coherent UI
- compile-ready code where possible
- no dead code
- no fake features presented as complete
Begin by inspecting the repository and proposing the exact bootstrap structure to create.