Commit Graph

13 Commits

Author SHA1 Message Date
f7e850068b feat: custom fields per project
Text, number, date or option-list fields defined in the project settings
(archived, never removed; their type is fixed once saved). Tickets hold
them, edited in the side panel, listed under the title and filtered by
option in the list view; also over GraphQL, REST (?field=ID:value) and MCP.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 09:31:12 +02:00
2c501a50d0 feat: uuid ids everywhere, pickers for linked tickets, @pi/ui checkboxes
- Postgres: every table has a uuid `id` (gen_random_uuid()); the event
  store keeps its relay order in `seq`, and the lookup tables their
  uniqueness in constraints of their own.
- MongoDB: `_id` is Mongo's ObjectId; `id` is the domain id (the same
  uuid as the aggregate's stream in Postgres), unique, and every query
  goes by it. Production starts from empty databases.
- Web: linking tickets and hanging one from a parent are picked from a
  searchable select (links across projects, parents within the project)
  instead of typing a key; every checkbox is @pi/ui's pi-checkbox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 19:16:43 +02:00
f2001aca88 feat: formatted text, a list view, ticket details, public proposals and votes
Formatted text
- Descriptions, comments, replies and release notes render Markdown,
  sanitised with DOMPurify (tested against scripts, handlers and
  javascript: links). A pasted image is uploaded and written as
  ![name](attachment:<id>); the web fetches it with the reader's session,
  so it works on private projects. Every text box has a preview. The
  attachment upload now answers its attachmentId.

List view
- /p/:key/list: every ticket as rows, sortable by any column, filtered by
  text, open/closed, type, priority and assignee; status, priority and
  assignee change in place; bulk edit (the backlog's bar, now shared).

Ticket details
- Reactions on comments (GitHub's eight), for members and viewers.
- Duplicate a ticket: what it says, not where it stands.
- blockedBy: open tickets it waits for (BLOCKS / DEPENDS_ON), worked out
  when reading with one query per board or page; shown on cards, list
  rows and the ticket.

Public proposals
- A public project can take bug reports and ideas from anyone
  (acceptsProposals): POST /api/explore/projects/{project}/proposals and
  the form at /p/:key/proponer. They become tickets labelled «propuesta»,
  opened by TaskStream; a honeypot field and 5 per address every 15
  minutes keep spam out. No e-mail is asked: it would be public.

Votes
- Anyone signed in votes on a public project's tickets, members on a
  private one (voteIssue, PUT/DELETE /api/issues/{issue}/vote): votes and
  voted on each ticket, buttons on the ticket and the roadmap, a column
  in the list. The showcase carries votes and the open proposals.

MCP: vote_issue, duplicate_issue, react_to_comment; listings show
blockers and votes. Docs, Word and PDF updated; chat notifications
(Discord, Slack, Telegram) noted for later.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:36:11 +02:00
58fe5e8301 fix: settings cards with the page's padding and compact buttons
The Git, automations, webhooks and import cards had no inner padding and
oversized buttons, because the settings page's styles do not reach child
components; they now share a stylesheet with the same pills. The template
button gets its own column instead of squeezing the type's name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 20:23:20 +02:00
5863d773be feat: templates per ticket type
Each ticket type can carry a starting description and a checklist, edited
in the project settings. New tickets of that type get the description
when they come without one and always get the checklist; the new ticket
form says what the template will add.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:58:37 +02:00
8994590b54 feat: automation rules
Owners and admins can set rules of the kind «when a ticket is created,
moves, gets assigned, gets a comment or its pull request merges; if it is
of this type, priority, area or label; then move it, assign it, label it,
change its priority, comment or put it in the active sprint». Rules act as
TaskStream within the workflow, run once per event and trigger no others.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:53:31 +02:00
1076205acc feat: import and export tickets as CSV
Every ticket of a project can be downloaded as CSV, and a CSV exported
from TaskStream or from Jira can be imported: types, statuses, priorities
and people are matched by id or name, the rest falls back with a warning,
and parents are rebuilt. The settings page previews an import before it
creates anything.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:43:02 +02:00
d43fc620e9 feat: outgoing webhooks
Owners and admins can point a project at other systems: a signed JSON
POST (HMAC-SHA256 of the body) when tickets, comments, releases or sprints
change, filtered by event or family. Deliveries are retried a couple of
times, the last one is shown, and a ping can be sent from the settings.
Private addresses are refused unless WEBHOOKS_ALLOW_PRIVATE is set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:36:19 +02:00
046d77c813 feat: link commits, branches and pull requests to tickets
A project can turn on a webhook for GitHub, Gitea or GitLab. Pushes and
pull or merge requests that name a ticket key show on that ticket under
Desarrollo, with the state of each pull request; the secret is shown and
rotated from the project settings.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:28:12 +02:00
45a3dc1e16 feat: a roadmap of epics over time
Tickets get a start date next to their due date, both editable on the
ticket page. The Hoja de ruta tab lays the epics out over the months as
bars filled with their progress, with sprints and releases as landmarks
and a line for today.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:14:32 +02:00
09bd8c19a3 feat: work-in-progress limits and swimlanes on the board
Each status can carry a WIP limit in the project settings; the board shows
it next to the count, marks a column that goes over it and says so when a
card is dropped there. The board can also be grouped in rows by person,
epic, priority or type, remembered per browser.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 15:09:21 +02:00
e656222b54 feat: public projects, project deletion and sagas
Public projects:
- Project.isPublic (create/update, owners and admins). Anyone can read a
  public project without a token: project, board, tickets, comments,
  history, releases, activity, tracking and statistics, over GraphQL and
  REST. Writes stay for members (401 anonymous, 403 outsiders).
- @OptionalAuth() / @ApiOptionalPireonAuth(): anonymous callers allowed,
  invalid tokens still rejected. ReadAccess lets anonymous viewers read
  public projects only; linked tickets are filtered by visibility.
- publicProjects (GraphQL) and GET /api/explore/projects (REST).
- Web: «Explorar» page, project pages open without a session (read-only
  notice, sign-in hints), public badge, visibility switch in settings,
  no realtime subscriptions without a session.

Project deletion:
- Owner only, confirming the key (deleteProject / DELETE
  /api/projects/{project}?confirm=KEY). The key is freed; the read model
  drops the project and members are notified (web goes home).

Sagas (run by the EventsBridge after projections, durable and ordered):
- ProjectDeletionSaga: project deleted → delete its tickets and releases;
  ticket deleted → purge its comments and drop links from other tickets.
- ReleaseArchivedSaga: unfinished tickets leave an archived release.
- UserDeactivatedSaga: the Pireon webhook records UserDeactivatedEvent in
  the event store (EventRecorder); the tracker unassigns that user's open
  tickets as the system actor.
- Internal idempotent commands; domain refusals are logged and skipped,
  concurrency conflicts retried. Affected streams come from the event store
  (TrackerStreamsRepository).

Tests: domain lifecycle specs, saga specs run like the bridge, facade
tests, e2e for public access, cascade deletion, archived releases and
deactivation webhook. Docs, READMEs, schema.gql/openapi.json and Word/PDF
updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 07:04:20 +02:00
0e301ad545 feat: per-project workflow settings, statistics and "my work" home
Per-project settings (owners/admins, «Configuración» tab):
- Statuses with category (TODO, IN_PROGRESS, QA, DONE, CANCELLED), colour and
  "requires reason"; configurable transitions; ticket types (icon, colour) and
  areas. Defaults are the previous fixed values; projects created before keep
  them without migration.
- Values are archived, never deleted: tickets, history and statistics keep
  referring to them. Validated in the domain (ProjectSettingsChangedEvent).
- Releases, board, tracking and "my work" use categories, so custom statuses
  keep working. Status changes carry name/category metadata for history.
- GraphQL: status/type/area are strings (breaking for clients sending enum
  literals); Project.settings, updateProjectSettings, statusCategory,
  myIssues(categories). REST: PUT /projects/{project}/settings, category filters.
- Read model: statusCategory on issues (backfilled at startup).

Statistics («Estadísticas» tab):
- New issue_timeline projection; pure functions compute created vs resolved,
  cumulative flow, cycle/lead time (avg + p85), throughput per person, QA
  pass/fail and release burnup. GraphQL Project.analytics(days),
  Release.burnup; REST /projects/{project}/analytics, /releases/{id}/burnup.
- Web: SVG charts with validated light/dark palette, crosshair tooltip,
  keyboard navigation, legend and data table.

Home "Mi trabajo": my open tickets across projects grouped by category (QA
failures first), tickets waiting for QA, upcoming releases and "Ir a…".

Tests: domain/application specs, e2e scenario for settings and analytics,
facade tests. Docs, READMEs, schema.gql/openapi.json and Word/PDF updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 20:53:45 +02:00