Portfolio case study
NoPM is a live, hosted proof-piece for that thesis. It is a lite, API-first project management tool where governance — immutable audit, scoped tokens, four-eyes approval — is engineered into the data and API layer, not bolted onto the UI. Shipped solo in eight waves using an AI multi-agent workflow.
The thesis
Most PM tools treat audit trails and change control as UI features — export logs, activity feeds, manual history. They can be bypassed by anyone with a database connection or a sufficiently permissive service key.
NoPM inverts that. Every mutation flows through the route() API wrapper and calls writeAudit() exactly once — fail-closed. Postgres triggers enforce append-only semantics. A service key cannot rewrite history. The UI is just a consumer of the same governed API your agent calls.
“The same surface a human uses — 82 documented endpoints, OpenAPI, an
llms.txtindex, and scoped Bearer tokens — is the surface an AI agent uses. No special mode, no privileged bypass.”
The wedge
resource:action tokens, OpenAPI, an llms.txt index, a nopm CLI. Any agent drives it over plain HTTP, identical to the console.CHECK constraint. Even a service key can't rewrite history.What was built
NoPM is the governed record beside Jira, Slack and Teams, not a replacement for them.
$ nopm tasks rm task_8f3a --reason "superseded by revised cutover plan" ⏸ delete requested — pending a checker's approval (four-eyes) $ nopm approve req_2c91 # a different token: task:delete:approve ✓ approved & committed # one immutable audit row written $ nopm audit --limit 1 created_at actor_label action target 2026-06-08T… checker (agent) task.delete task_8f3a
Proof metrics
These numbers are not typed into this page — they are generated from the RTM, the test run, and the API route tree, and CI fails if they drift from reality. Every requirement has an R-ID, a status, and a traceability row. Tests target the governance rules first: can a maker self-approve? Does a missing scope return 403? Does a delete without a four-eyes approval fail?
Reviewed, then closed
On 2026-09-06 a six-lens review tested the thesis “NoPM is the governed record beside Jira, Slack and Teams” against the code, and a separate verifier confirmed ten defects. The same day, two sprints closed or narrowed them, and the verifier re-ran. The record below is the re-run, not the plan.
| Finding (morning) | State (evening) |
|---|---|
| Eleven mutating routes never wrote an audit row, including the BYOK key set and delete. | Closed. A coverage test fails the build for any unaudited write; the key lifecycle is audited without the key. |
| Ordinary writes persist before the audit row; only two flows are transactional. | Open by decision. The Trust Center now says so in plain words. |
| One scope both raised and decided change requests; a token requester left the DB check vacuous. | Closed. change:decide is a separate scope agents never hold; requester and decider are typed identities checked in the API and the database. |
| Unlocking a frozen baseline took no reason. | Partly closed. A reason is required in the API, the dialog and the CLI; the same person can still unlock. |
| Audit rows carried no client origin or request id. | Partly closed. Every row records the declared client and a request id echoed on the response, including rows written inside database functions. No hash chain yet. |
| No record could point at a Jira key or a Slack thread. | Closed. Tasks, projects, risks, issues and decisions carry source, external_ref and external_url, in the API, the MCP tools and the CLI. |
| No public page said the product complements Jira, Slack or Teams. | Closed. README, landing, this page and the product doc say it. |
| The lock and rebaseline flow had no navigation home; a demo page sat in the Governance section. | Closed. Baselines lives under Governance; the demo page moved to My Work. |
| The audit immutability triggers had no regression test. | Closed. A migration-text test fails if any migration drops, disables or bypasses them. |
| Tool and metric counts drifted between surfaces. | Closed. Counts are generated and CI-checked; the pitch notes were realigned. |
The review, the sprint receipts and the re-verification are in the repo under docs/research and sprint-log.
Stack & method
Technology
Discipline
Every endpoint is documented. Every mutation is audited. The console is open.