2b closes a gap between the spec and the schema: the spec's [#42] explicit
link had nothing to reference, because cards only had PocketBase ids. Adds
per-project card numbers, and sharpens two rules the spec left loose — a
scope rule is bounded by start_date OR created, and ties go to the card
with the latest bound rather than the most recently edited one.
2c builds the dashboard. The South African holiday table is verified
against the Hermes build log: 24 May to 8 Sep 2026 gives 108 calendar days
and 75 workdays, both exact, and that is now a regression test.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Verified against the live instance: status 200, total 787 commits, first
sha 1bc0da40... 'feat(customers): lift active/inactive toggle to top of
customer form'.
Eleven tasks covering conventional-commit parsing, HMAC webhook
verification, the Forgejo client, a shared idempotent ingest core, the
webhook and reconciliation endpoints, and the backfill admin panel.
The Forgejo API shape, pagination headers and merge counts are measured
against the live instance rather than recalled, and the plan says so, so
the implementer builds against facts.
Surfaces one unresolved issue for decision: projects.webhook_secret is
readable by a client manager straight from PocketBase, because rules are
record-level and cannot hide a field.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Palette:
#051a2d Deep Navy -> page (dark base) + text-primary (light)
#068187 Teal Green -> brand (light mode, AA contrast on white)
#10bbc3 Aqua Blue -> brand (dark mode, vibrant on navy)
#fea24f Sunset Orange -> priority-high
#a60e35 Crimson Red -> accent + priority-critical
The plan's reservation rules are preserved: the crimson accent still appears
only on overdue dates, the inbox count badge, and critical priority.
Builds on the Hermes build log Dave produced by hand from WFDASH-WEBAPP,
adopting its metric set, activity calendar and workdays-not-calendar-days
framing, and correcting three things: the "6 contributors" who were one
person plus AI agents, two undocumented hour methodologies, and monetary
framing that suited an internal audience but not a client-facing page.
Settles the effort methodology with named constants shown on the page,
excludes merge commits (verified: 787 total, 779 non-merge, 8 merges), and
requires HMAC verification on the webhook endpoint.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Fourteen tasks covering clients, projects, manager accounts, column
management and the archive, so the owner can run the product without the
PocketBase console or the seed script.
Records why account creation must use a superuser connection: the users
write rules are locked because role is an ordinary field there, and both
the signup and self-promotion paths were verified exploitable. Adds a
verification step that re-runs the escalation guard, since this is the
phase most likely to reopen it.
Corrects Plan 1c's deferred list: the AI settings screen belongs to
Phase 3 per spec section 5.3, not here.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The users collection kept PocketBase's defaults because the Plan 1a rules
migration covered eight collections and missed this one:
createRule "" -> anyone could sign up
updateRule "id = @request.auth.id" -> anyone could edit their own record
`role` is an ordinary field here, so both were escalations. Verified
exploitable against the live instance: an anonymous request created an
account with role "owner", and a client manager promoted themselves to
owner by patching their own record. Either route yields read and write
access to every client's board.
Create, update and delete are now superuser-only; list and view are
owner-or-self. Adds four integration tests so a regression fails loudly.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Fourteen tasks covering the card detail page, checklists, comments, a
readable activity timeline, card creation for both roles, and the accept
flow that stamps start_date.
Owner mutations are Server Actions on the caller's own token; client
mutations keep going through the whitelisted /api/client routes. Records
the constraint that activity.createRule is superuser-only, so audit rows
need a dedicated helper even for the owner.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
activeId clears the instant the pointer is released, so gating the
focus-refresh on it alone left a window between drop and server
confirmation where a refresh could overwrite the optimistic position with
stale state and the card would appear to snap back. Tracks a separate
saving flag, and reverts on a thrown fetch as well as a non-ok response.
Also corrects a comment: sensors are created unconditionally; what keeps a
client manager from dragging is that they never render DndContext.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The login page was still on Plan 1a's dark-only palette, so in light theme
it rendered a near-black card on a light page with the heading black-on-black
and effectively invisible. This is the first screen a client ever sees.
Plan 1b Task 13 required the hardcoded-colour grep to return nothing; it was
not run.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There is one PocketBase instance and it is hosted. Removes the `npm run pb`
script, which started a local server nothing used.
The schema had two apparent sources of truth. scripts/setup-remote.ts is the
one that actually runs; pb_migrations/ only executes on PocketBase server
start, which never happens here. Both now say so, so nobody edits a migration
and believes the schema changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>