Every task carries its
own paper trail.
Project management with testing built in, not bolted on. Who moved a task, when, and what changed is recorded on the task — not in someone's memory, and not in a third-party bucket.
- Sign-in
- Email + code
- Database
- PostgreSQL
- Files
- Your own disk
7 of 20 done · 2 overdue · 1 awaiting test
- APP-118Discount code ignored at checkoutReady for test
- APP-124Confirmation email templatesIn progress
- APP-131Payment screens — visual passIn review
One project, six ways to look at it
The view changes. The work doesn't.
A board answers “what state is everything in”. A graph answers “what's blocking what”. Those are different questions, and forcing one layout to serve both is why people end up keeping a spreadsheet on the side.
Board
Drag work across seven states. Multi-select to change fifty tasks at once.
Timeline
Dated work against a calendar, with milestones as labelled markers.
Calendar
Tasks and milestones projected from their own dates — one home per date.
Graph
The dependency graph. A board shows state; this shows what blocks what.
Quality
Bugs, test cases, and runs against a named build.
Chat
Threads, pins, search and files, scoped to the project's members.
Built for IT teams
Testing isn't a separate tool.
A bug is a task. That one decision means attachments, comments, history, watchers, search and the board all work on it with no parallel implementation to keep in step — and testers and developers share one queue instead of reconciling two.
The fix-and-retest loop
- 1
Tester · Reports a bug
Steps, expected, actual — plus a screenshot or screen recording.
- 2
Developer · Fixes and marks ready
Names the build it landed in. The reporter is notified.
- 3
Tester · Verifies — or reopens
A reopen needs a note. The count is kept, so regressions surface.
Severity and priority, separately
Impact and urgency are different questions. A trivial-severity bug on the checkout page can still be urgent, and conflating the two loses that.
Test cases and runs
Write the checks you repeat every release, group them into suites, and execute them against a named build. A failed case opens a bug report prefilled and links the two.
Sprint 12 regression · build 2.4.1-rc3 · 12/19 passed
Evidence, not descriptions
Screenshots paste straight in with Ctrl/⌘V. Video keeps its seek bar. Android builds attach too, so a tester can hand back the exact .apk that misbehaved — with its SHA-256 to verify against.
Client portal
Show the customer progress, not your board.
Clients get their own view: a single completion figure, stages as plain bars, and the updates your team actually wrote. Internal statuses collapse to three words — complete, being worked on, not started.
Nothing is visible by default
Publish by exception. Adding a client shows them nothing until you tick items — the opposite arrangement leaks the first time somebody forgets.
Descriptions and assignees never leave
A client sees titles, states and dates. Implementation notes and who's doing what stay internal.
A channel of their own
Clients can message the team. They can't reach project chat at all — enforced in the access check, the list query, and a database trigger.
What the client sees
Stages
Access
Two layers of roles that compose.
Organisation roles set the floor, project roles set the ceiling. An org admin is a manager on every project without being added to each one; a guest sees only what they were invited to.
Project roles — manager, contributor, viewer — layer on top. Chat membership is derived from project membership rather than maintained separately, because the two drift apart the first time someone leaves a project and nobody thinks about the channel.
Run it yourself
Your database. Your disk. No middleman.
Attachments are written to local storage, not an object store you don't control. There's no vendor holding your project history, and no per-seat meter running while you think about who to invite.
Two commands
cp .env.example .env # set JWT_SECRET, OTP_PEPPER
docker compose up --buildPostgres comes up alongside the API, migrations apply themselves at boot, and the service refuses to start on an unsafe configuration rather than running quietly with a placeholder signing key.
What it's made of
One binary. Migrations embedded; no separate step.
Native enums, trigram search, triggers doing real work.
Board, timeline, calendar, graph, chat.
iOS and Android against the same API.
Thumbnails in-process. Range requests, so video seeks.
No passwords to leak. Rotating refresh tokens.
Questions
Before you install it.
Is there a hosted version?
Not today. CatzPRM is built to be self-hosted: the whole design assumes your data stays on infrastructure you control, which is also why attachments go to local disk rather than an object store.
Why passwordless?
There is no password database to leak, no reset flow to phish, and nothing for anyone to reuse from another breach. You get a six-digit code by email; it's hashed with a server-side pepper, rate limited, and burns after five wrong attempts.
Can clients see our internal discussion?
No. Clients rank below every internal role, so the ordinary access checks already exclude them. Project chat is private to the project's members, and a database trigger refuses to put a client in an internal channel even if application code tried.
What happens to files if I move servers?
The database stores a relative path, so the upload tree can be moved to another disk or volume without touching a row. Back up the directory alongside your database dump.
Does it work offline or on a phone?
There's a Flutter app for iOS and Android covering the things you do standing up — your assigned work, filing a bug with a photo, chat, notifications. Timeline, graph and test runs stay on the desktop, where there's room for them.
How does it handle a team that isn't doing QA?
Every QA field is optional and issue type defaults to task. If you never file a bug you'll never see a severity picker.
Put it on a box and try it for a week.
Nothing to sign up for, no card, no trial clock. Clone it, run two commands, invite one colleague, and see whether it survives contact with your actual work.
- Runs on one small server
- Postgres you already know how to back up
- Files on disk, not in someone's bucket
- No per-seat pricing to plan around