carlos@cesaints: ~/projects/project-office.md — zsh

Command: cat projects/project-office.md

projects/project-office.md · 1.4 KB

A product and project management office, with concurrent editing and no lost work

An internal system to manage product, projects and people: Scrum and Kanban with sprints, a prioritized backlog, burndown and velocity, workload per person, a dossier for each project, a mind map and an executive view. Several people edit the same project at the same time without anyone wiping out someone else's work, and each project only reaches those allowed to see it, checked on the server on every request.

open the demoa simulation of the system with fictional data · 6 screens

Role
Sole engineer, from product to operations
Period
Jul 2026 – Sep 2026
What I did

Me: Product, architecture, an edge backend without Node, data model, syncing and merging edits, login security, every screen and the tests.

Private project, described without identifying the client, product or company.

Diagram

Save with a version, merge on conflict

In the browser, the React SPA saves each project with the version it knows and, periodically, polls only the current version. The Worker, built on Web APIs only and with no Node, checks the project access list on every request and guards the login with PBKDF2 and a bot check that fails closed; it writes to D1 with prepared statements and keeps files in KV, out of the database. If someone saved first, the Worker answers with a conflict, and the browser runs a three-way merge and resends after a random wait.

Context

The group needed one place to manage product, projects and people: sprints, backlog, deadlines, each person’s workload and the reasons behind decisions, with several people working on the same board at the same time.

What I built

  • Execution. A Kanban board with drag and drop, plus moving by selection for keyboard users; sprints with a goal and dates; a MoSCoW backlog with Fibonacci points; and a dashboard with burndown, velocity, task distribution and upcoming deadlines.
  • People & Performance. Load against capacity, cycle time, 14-day throughput and delay risk, computed from each person’s tasks.
  • Knowledge. Each project’s dossier (vision, business model, OKRs, risks and decisions), a mind map on an infinite canvas with automatic layout, documents viewed inside the app and a directory of tools by department.
  • Executive view. A roll-up by period, by project and by person, counting the same person across projects once, by e-mail.
  • Collaboration without loss. Automatic saving with versions, an item-by-item merge on conflict, and the team’s changes showing up on screen on their own.

What I would do differently

I would ship the multi-editor load test together with the first version of the merge. The livelock only showed up when eight editors saved at the same time, and the random wait that came later could have been born together with the conflict handling.

Constraints

  • Several people editing the same project at the same time, without losing work.
  • Each person sees only the projects shared with them, and the server is what enforces it.
  • A backend on the edge runtime, with no Node and no ORM.
  • A single technical person to build and run it.

Decisions

Optimistic concurrency with a three-way merge

Context
Each project is saved as one document. With two people editing, whoever saved last would silently erase the other's change.
Choice
Every save carries the version the browser knows. If someone saved first, the server answers with a conflict, and the browser merges base, local and server versions item by item (task, sprint, map block) and sends it again after a random wait.
Gains
  • A conflict becomes a merge, not an overwrite.
  • The random wait came from a livelock measured in a load test with eight editors.
Costs
  • The merge has to know every kind of item in the document; a new kind needs a new rule.

Syncing through a lightweight version check

Context
Persistent connections would add infrastructure for a small team with few people editing at the same time.
Choice
Every 4 seconds, with random jitter, the browser asks only for the project's version, and it pauses while the tab is hidden. The database indexes were built for that path.
Gains
  • Simple and cheap, with no open connection.
Costs
  • Someone else's change can take a few seconds to show up.
  • Constant, if light, traffic while the tab is open.

Per-project permission on the server, on every request

Context
Hiding a project on screen does not stop a member from asking the API for it.
Choice
A user × project access list checked on every request; admins see everything, with safeguards so an admin cannot lock themselves out.
Gains
  • Anyone not on a project's list does not get the project from the server.
Costs
  • Every new route has to apply the check, which takes discipline and a test per route.

A login that fails closed

Context
Brute force and bots are the most obvious risk for a system on the internet, and a forgotten setting must not open the door.
Choice
PBKDF2 with 100,000 iterations, constant-time comparison and the same cost for unknown e-mails, an atomic lockout per account, a per-IP limit in its own table, and a bot check that blocks the login when its secret is not configured.
Gains
  • A missing setting blocks instead of silently letting people in.
Costs
  • A misconfigured deployment locks everyone out until it is fixed.

Stack and why

React 18 and Vite
A single-page app served by the Worker itself.
Cloudflare Workers, D1 and KV
A backend on the runtime's Web APIs, SQL with prepared statements and files kept out of the database.
Recharts and React Flow
Burndown, velocity and distribution; a mind map on an infinite canvas.
WebCrypto and Turnstile
PBKDF2 without dependencies and a bot check that fails closed.
Vitest
Worker routes, security, merging and state tested in CI.

Results

  • 23 test files with about 220 cases, covering Worker routes, security, edit merging and state, running in CI.

    audited private repositoryThe repository's tests and CI workflow(Audit of the private repository, Sep 2026)
  • A single route table, with a test that fails if any handler is left out.

    audited private repositoryThe Worker's code and tests(Audit of the private repository, Sep 2026)
  • A fix round of 19 security and data integrity items, all closed with tests.

    self-reportedThe project's fix log

Security angle

Attack surface

  • Password login with a bot check.
  • The API for projects, documents and users.
  • Document upload and in-app viewing.
  • Several people editing the same project.

Controls in place

  • PBKDF2 with 100,000 iterations, constant-time comparison and the same cost for unknown e-mails.
  • An atomic lockout per account and a per-IP attempt limit.
  • A bot check and an origin check that fail closed.
  • A per-project access list checked on every request.
  • Uploads restricted to an allowlist, with no executables, and files served under a restrictive policy.
  • Links accepted only over http and https.

What I would test today

  • A member asking the API for a project that was not shared with them.
  • Two editors saving the same item at the same instant.
  • A mutation sent from another origin.

Evidence

  • audited private repositoryAudited private repository(Audit of the private repository, Sep 2026)