Commit graph

22 commits

Author SHA1 Message Date
75c321bad2 feat(pwa): icon build script and committed PNG outputs
Phase 8b Task 2. @resvg/resvg-js renders public/icons/source.svg
into the four PNG sizes the manifest + iOS expect: 192, 512,
maskable-512 (Android safe-zone), and apple-touch-icon-180.
Build is one-shot — outputs are committed, runtime doesn't ship
the dep.
2026-09-21 11:22:32 +02:00
c11d378483 fix(intake-links): three PocketBase quirks the schema shipped with
The schema the plan specified had three places where a PocketBase
quirk blocked normal use of intake_links / activity rows. None of
them surfaced in Task 1 because the unit-level test there only
checked rule application, not inserts.

1. intake_links.submission_count and submission_count_today were
   required: true with min: 0. PocketBase treats 0 as blank for
   required number fields, so every insert 400'd. Made optional.
2. intake_links.active was required: true, which rejects false as
   blank (the same quirk). The owner can mint an already-revoked
   link (the test exercises this); made optional.
3. activity.actor was a required relation. The public route writes
   a card_submitted_anonymously row for a submitter who has no user
   account; empty string is not a valid relation. Made optional and
   dropped actor: '' from the route.
2026-09-21 06:30:49 +02:00
c99be4d49e feat(schema): intake_links and anonymous submitter role
Phase 8a Task 1. Adds the new intake_links collection (per-token
public entry point, owner-only rules), extends cards.created_by_role
with 'anonymous', and extends activity.action with
'card_submitted_anonymously'.

Note: getOrCreateCollection is a no-op on existing collections, so
the two existing-value extensions are applied by new/extended
ensure functions (ensureCardsCreatedByRoleValues and
ensureActivityActionValues respectively). Re-runs are idempotent.
2026-09-21 01:54:11 +02:00
b3aac9ba4f feat(plan): Plan Puzzle v1 backend — proposal fields, server actions, Done-column guards
Adds the three proposal fields (proposed_target_date, proposed_by,
proposed_at) to the cards collection with a partial index that backs
the 'pending proposals' query, plus two new ActivityAction values
(date_proposed, date_proposal_resolved) and column_changed for
return-to-scheduled.

New server actions under src/app/actions/:
  - client-proposal.ts: client-manager drag creates a proposal (not
    a target_date write); 404 (not 403) on cross-tenant failures and
    Done-column cards, matching the rest of /api/client/*.
  - owner-plan.ts: accept and dismiss clear the three proposal
    fields together and emit the audit rows; returnToScheduledAction
    moves a Done card back to the first working column.

Server-side Done-column guards added to:
  - src/app/actions/reschedule.ts (was UI-only)
  - src/app/api/client/cards/[id]/route.ts (was UI-only)

Both pass through the new writeCardWithAudit helper at
src/lib/cards/write-with-audit.ts — single source of truth for
'patch card + emit activity rows', replacing the inline copies in
the PATCH route and rescheduleCardAction.

Adds src/lib/roadmap/slot-date.ts (slot <-> target_date mapping)
consumed by Pixel's puzzle UI; named SlotId API rather than the
plan's numeric indices for self-documenting callers.

CLIENT_EDITABLE_CARD_FIELDS stays at priority + target_date per
the brief; proposals go through the dedicated action so they get
their own audit row type.
2026-09-19 18:35:33 +02:00
4d1e6cf412 fix(commits): set source on ingest/backfill writes, tidy Task 1 review findings
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 10:22:26 +02:00
65b09170af feat(commits): add source and manual_minutes fields
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-09-19 10:14:51 +02:00
5dae0946eb feat(projects): add kind field (project | prototype) 2026-09-17 10:42:46 +02:00
05ce52a6bf feat(schema): card brief, transcript and size band 2026-09-16 18:04:22 +02:00
7ca2798561 feat(schema): card narrative fields 2026-09-16 16:24:18 +02:00
bce71a666a feat(schema): commit summary fields 2026-09-16 16:15:18 +02:00
19e9dc29ac feat(dashboard): remove session-clustering paragraph from methodology
The methodology panel still explains 'what hours are' and 'what they cannot
see'. The session-clustering detail — the constants — was the part a client
might want to interrogate rather than just be told. With this removed, the
constants are still stored inside the payload (so a future question can be
answered) but the visible panel is shorter.

Also dropped the now-unused destructured local in Methodology().
2026-09-16 15:30:46 +02:00
cc20cf4bfd feat(metrics): cached project metrics recomputed on ingest 2026-09-16 13:51:03 +02:00
a1ef2ff55c chore(relink): CLI helper for off-server relink runs 2026-09-16 13:36:42 +02:00
25b504c901 feat(linking): idempotent relink engine preserving manual links 2026-09-16 13:23:33 +02:00
d06d1e99ec feat(cards): per-project card numbers for commit references
- number field on cards, unique per project
- backfilled existing cards in created order
- both create paths (owner action, client API) assign on creation
- seed script is idempotent across re-runs
2026-09-16 13:20:24 +02:00
9289bf3511 chore(backfill): CLI helper for off-server backfill runs 2026-09-16 11:54:37 +02:00
a05c1b8ae0 feat(schema): commits collection and project ingest fields 2026-09-16 11:46:57 +02:00
287d70c42c feat(users): active flag, backfilled, enforced at sign-in 2026-09-16 11:26:16 +02:00
2a8d6f2505 fix(security): lock the users collection against privilege escalation
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>
2026-09-16 11:18:13 +02:00
b08303b3b7 fix(seed): spread ColumnInput to satisfy Record type in upsert 2026-09-16 09:47:15 +02:00
857ef1a994 chore(seed): demo client, project, users and cards 2026-09-16 09:44:19 +02:00
ba990f0109 feat(schema): all collections + role-scoped API rules on remote PB
- migrations/ documented in pocketbase/pb_migrations/ for local PB
- scripts/setup-remote.ts applies them via admin API to remote PB
- collections: clients, projects, columns, cards, subtasks, comments, activity, settings
- user extension: role (owner|client_manager), client (relation)
- writes: owner only for app collections, superuser-only for activity and settings
2026-09-16 09:41:20 +02:00