Running the AIPM Service
An operator’s guide to starting, configuring, and looking after the AIPM web service — written for the person who runs the service, not for a developer setting up a build.
Starting it (Windows)
On Windows the service is started with the launcher script scripts\run_aipm_dashboard.cmd. It accepts optional positional arguments [PROJECT_ID] [PORT] [HOST] and, when those are omitted, defaults to port 8088 on host 127.0.0.1 (loopback only).
rem Defaults: port 8088, host 127.0.0.1
scripts\run_aipm_dashboard.cmd
rem Explicit project, port and host
scripts\run_aipm_dashboard.cmd my-project 8088 127.0.0.1
You can also start the service manually, which is handy when diagnosing a problem and you want to watch its console output:
python -m aipm.web --project <id> --host 127.0.0.1 --port 8088
In production the service is run as a Windows service or scheduled task so that it stays up across logouts and reboots, restarting automatically if the machine is rebooted.
Where the data lives
AIPM stores all of its data in a PostgreSQL database, addressed by the AIPM_DATABASE_URL environment variable. There is no local file database to back up by copying.
Within that database the data is split across two schemas:
| Schema | Contents |
|---|---|
aipm | The live working data — projects, requirements, items, approvals, and current state. |
aipm_audit | The append-only audit trail. Records are added, never edited or deleted, so the history of who did what stays intact. |
Configuration
The service is configured entirely through operator-level environment variables. The table below describes what each one is for. Secrets (database passwords, the cookie-signing key, mailbox credentials) are supplied through the environment only — they are never stored in the code or in the database.
| Setting | Purpose |
|---|---|
AIPM_DATABASE_URL | Connection string for the PostgreSQL database. Required — the service cannot run without it. |
AIPM_WEB_SECRET | Key used to sign session cookies. Must be set to a private value in production so that session cookies cannot be forged. |
AIPM_READ_ONLY | When set, the service refuses all writes and serves reads only. Useful for a safe demo or inspection mode. |
AIPM_NOTIFY_CHANNELS | Which channels approval notices go out on (for example in-app, Windows notifications). |
| Email (SMTP / IMAP) settings | SMTP for outbound notification and approval mail; IMAP for the inbound reply-to-approve poller. Credentials are supplied via the environment only. |
User accounts & passwords
Each user signs in with a password. There is no self-registration — accounts and passwords are provisioned by an administrator:
aipm-db set-password <identity> --password '<password>'
A user who has no stored password simply cannot log in. This is a fail-safe deny: until an administrator sets a password for an identity, that identity is locked out rather than open.
Network & TLS
By default the service binds to loopback (127.0.0.1), so it is reachable only from the machine it runs on. It will refuse to bind to a non-loopback address unless TLS is configured — in other words, it will not expose itself unencrypted on the network. If you need the service reachable from other machines, configure TLS first.
Read-only / demo mode
Set AIPM_READ_ONLY to run the service in a safe inspection mode: it continues to serve pages and answer read requests, but refuses every write. This is the right setting for showing the system to a sponsor or auditor without any risk of accidental changes.
Restarting safely
The service listens on its configured port (default 8088). To fully restart it you must stop the running Python process bound to that port and then start the service again.
Stopping only the scheduled task is not enough — it can leave a detached Python process still bound to the port and serving stale code. After restarting, confirm that the process listening on the port is the freshly started one.
Publishing the public docs
The public documentation site at thehansens.com is published by a separate TAR-and-upload step. Editing these help files changes only the local source — the live public site does not change until that publish step is run.