Commit Graph

2465 Commits

Author SHA1 Message Date
kolaente 711545e9f2 docs(api/v2): tag bulk task fields for the v2 schema 2026-06-09 20:13:02 +00:00
kolaente 1aa9493bc3 feat(api/v2): add project duplication on /api/v2 2026-06-09 20:11:43 +00:00
kolaente d5bcbe39b4 docs(api/v2): tag project duplication fields for the v2 schema 2026-06-09 20:11:43 +00:00
kolaente 51e5c86f69 feat(api/v2): add kanban task-bucket moves on /api/v2 2026-06-09 20:01:20 +00:00
kolaente 9eca20fe43 docs(api/v2): tag task bucket fields for the v2 schema 2026-06-09 20:01:20 +00:00
kolaente aa144b9a39 feat(api/v2): add task read-status marking on /api/v2 2026-06-09 19:50:58 +00:00
kolaente bf2a65dcaf feat(api/v2): add bulk assignee replacement on /api/v2 2026-06-09 19:42:16 +00:00
kolaente 732cd115a5 docs(api/v2): tag bulk assignee fields for the v2 schema 2026-06-09 19:42:16 +00:00
Claude c9c2c58c16 feat(labels): let bot owners manage labels created by their bots
Bot owners inherit read/update/delete permission on labels created by
bots they own, mirroring the bot-owner branch already used by API tokens
(see api_tokens_permissions.go). Without this, a label a bot creates is
permanently locked to that bot and the human owner cannot maintain it.

https://claude.ai/code/session_016x6mUPJuuQEeXpHY814iLh
2026-06-09 11:40:04 +00:00
Frederick [Bot] 9e181bfc55 [skip ci] Updated swagger docs 2026-06-08 14:15:20 +00:00
kolaente 0bd7f956f5 fix(time-tracking): reject inverted time-entry intervals 2026-06-08 13:54:09 +00:00
kolaente 4a558fc57a fix(api/v2): expose v2-only token route groups via the routes endpoint 2026-06-08 13:54:09 +00:00
kolaente 74510bb00a fix(api/v2): group time-entries token routes under their own scope 2026-06-08 13:54:09 +00:00
kolaente 2858b8b827 test(time-tracking): cover the v2 time-entry routes 2026-06-08 13:54:09 +00:00
kolaente b8b376c53a test(time-tracking): cover the time_entries model 2026-06-08 13:54:09 +00:00
kolaente aef584c9fa feat(time-tracking): let clients subscribe to timer events 2026-06-08 13:54:09 +00:00
kolaente cf22f08974 feat(time-tracking): broadcast timer changes over websocket 2026-06-08 13:54:09 +00:00
kolaente e197b1912f feat(time-tracking): count tracked time entries per task 2026-06-08 13:54:09 +00:00
kolaente 0c5a0a99ec feat(time-tracking): dispatch time-entry events 2026-06-08 13:54:09 +00:00
kolaente 9454cd3ec5 feat(time-tracking): expose time entries on the v2 API 2026-06-08 13:54:09 +00:00
kolaente 4bd6a6c4f7 feat(time-tracking): filter time entries with the task DSL 2026-06-08 13:54:09 +00:00
kolaente 42795518e9 feat(time-tracking): add the time_entries model 2026-06-08 13:54:09 +00:00
kolaente 26c067cc38 refactor: extract preprocessFilterString from task filter parsing 2026-06-08 13:54:09 +00:00
kolaente 6387d8138a feat(time-tracking): add the time_entries table migration 2026-06-08 13:54:09 +00:00
kolaente c2e1b078ce feat(api/v2): add project team shares CRUD on /api/v2 2026-06-07 15:33:20 +00:00
kolaente 627cd0a6f4 docs(api/v2): tag project team share fields for the v2 schema 2026-06-07 15:33:20 +00:00
Frederick [Bot] a2be36b5fe [skip ci] Updated swagger docs 2026-06-07 11:36:48 +00:00
kolaente c2d1e48c8c feat(api/v2): add team members (add/remove/admin-toggle) on /api/v2
The admin-toggle handler delegates to handler.DoUpdate — the same pipeline
v1's UpdateWeb wraps — instead of re-implementing the session/permission/commit
orchestration. TeamMember.Update now carries the persisted row back onto the
receiver so both v1 and v2 responses include id/created.
2026-06-07 10:48:23 +00:00
kolaente ef256273e0 docs(api/v2): annotate TeamMember fields for the v2 schema 2026-06-07 10:48:23 +00:00
kolaente ed4ae0cd43 feat(api/v2): add saved filter CRUD on /api/v2 2026-06-07 10:40:20 +00:00
kolaente a52ee1593a docs(api/v2): tag SavedFilter fields for the v2 schema 2026-06-07 10:40:20 +00:00
kolaente 9cddc137c5 feat(api/v2): add project user shares CRUD on /api/v2 2026-06-07 10:37:59 +00:00
kolaente 2c0608e47b docs(api/v2): tag project user share fields for the v2 schema 2026-06-07 10:37:59 +00:00
kolaente 7158334699 fix(api/v2): return 200 from notifications mark-all (creates nothing) 2026-06-07 10:05:24 +00:00
kolaente 604e5850bc docs: trim wordy comments in v2 notifications 2026-06-07 10:05:24 +00:00
kolaente 1ca5367f27 feat(api/v2): add notifications list/mark-read + mark-all on /api/v2
Ports the v1 DatabaseNotifications routes to the Huma /api/v2 API:
- GET /notifications lists the caller's own notifications (paginated)
- PUT /notifications/{notificationid} marks one (un-)read
- POST /notifications is a custom action marking all as read; the
  link-share guard, session and commit live in the handler since there
  is no CRUDable Do* for a bulk mark.

Adds fixture rows and a webtest matrix mirroring the v1 model behaviour
(own-only visibility, mark-(un)read, link-share refusal on every route).
2026-06-07 10:05:24 +00:00
kolaente 05c9c07e19 docs(api/v2): add doc/readOnly tags to notification model fields 2026-06-07 10:05:24 +00:00
kolaente fb4bca34dd docs: trim wordy comments to load-bearing whys 2026-06-07 09:57:51 +00:00
kolaente 1b47932916 feat(api/v2): add subscribe/unsubscribe on /api/v2
Port the Subscription resource from /api/v1 to the Huma-backed /api/v2:
POST /subscriptions/{entity}/{entityID} subscribes, DELETE unsubscribes.

The {entity} discriminator is bound as a string path param with an
enum:"project,task" tag; the model's CanCreate/CanDelete derive the numeric
EntityType from it and reject unknown kinds. Permissions and the
already-subscribed/forbidden checks come from the shared model via DoCreate/
DoDelete, identical to v1's generic handler. Mark the model's server-controlled
fields readOnly and add doc tags for the v2 schema.
2026-06-07 09:57:51 +00:00
kolaente 67bc3ff4f1 test(api/v2): cover central validation (422, invalid_fields, full-body webhook updates) 2026-06-06 21:09:56 +00:00
kolaente 24188480c4 feat(api/v2): return 422 with invalid_fields for validation errors 2026-06-06 21:09:56 +00:00
kolaente 45e05a5d27 feat(api/v2): enforce validation centrally in the Register wrapper 2026-06-06 21:09:56 +00:00
kolaente 5855ccc1d4 docs(webhooks): version-qualify the events endpoint link in the events field doc
In the v2 OpenAPI context a bare /webhooks/events reads as /api/v2/webhooks/events,
which does not exist — the events listing endpoint lives only on /api/v1. Point the
doc string at the absolute v1 path so v2 clients are not misled.
2026-06-06 19:50:41 +00:00
kolaente aac0322975 refactor(webhooks): mask write-only credentials in the model so create/update never echo them
Webhook.ReadAll already cleared the secret and basic-auth from responses,
but Create and Update did not, so the v2 handler patched the gap with a
maskWebhookCredentials helper. Centralize the masking in the model via a
maskCredentials helper called after every DB write (ReadAll, Create,
Update) and drop the v2 handler helper.

The credentials are client-provided, not server-generated: the DB row
keeps them and outgoing deliveries reload + HMAC-sign from the DB copy,
so clearing the returned in-memory struct is correct write-only handling.

Webhook is a shared model, so v1's create/update responses also stop
echoing the submitted secret/auth — intended, and approved by the
maintainer.
2026-06-06 19:50:41 +00:00
kolaente 98741d8171 test(api/v2): webhook CRUD permission matrix and config gate
Port the v1 webhook webtest to /api/v2 and extend it to the full
permission gradient the model enforces: list needs read access while
create/update/delete need write (Project.CanWrite), exercised across an
owned project and read/write/admin shares plus a no-access project. Also
assert credential masking, events-only updates, the 412 validation path,
and that the routes 404 when webhooks.enabled is false.

Add fixture webhooks 2-5 in projects 9/10/11/2 to back the matrix; they
do not collide with the e2e tests, which scope to project 1.
2026-06-06 19:50:41 +00:00
kolaente cf1f7c3309 feat(api/v2): add project webhooks CRUD on /api/v2
Port the project-webhook routes under /projects/{project}/webhooks to
the Huma /api/v2: list, create, update (events only), delete. There is
no ReadOne — webhooks carry secrets — so no max_permission and no
AutoPatch PATCH; update is PUT only, mirroring v1.

The resource self-registers and is gated by the webhooks.enabled config
flag inside the registrar (RegisterAll runs after config loads). The
write-only secret and basic-auth credentials are cleared from
create/update responses, matching how ReadAll masks them.
2026-06-06 19:50:41 +00:00
kolaente 3647551a79 docs(api/v2): tag Webhook fields for the v2 schema
Add doc tags to every exposed Webhook field, mark the server-controlled
ones (id, project_id, user_id, created_by, created, updated) readOnly,
and mark the secret and basic-auth credentials writeOnly. All three tags
are ignored by swaggo/XORM/govalidator, so v1 is unaffected.
2026-06-06 19:50:41 +00:00
kolaente d76c009808 fix(api/v2): map ValidationHTTPError to its HTTP status
translateDomainError only recognized web.HTTPErrorProcessor, so a
ValidationHTTPError from InvalidFieldError (e.g. an unknown webhook
event) leaked as a 500 instead of the 412 v1 returns. It carries the
status via GetHTTPCode() but cannot implement HTTPErrorProcessor because
the embedded web.HTTPError field shadows the method name. Add a
GetHTTPCode/GetCode branch so v2 surfaces the right status and preserves
the v1 numeric code on the body.
2026-06-06 19:50:41 +00:00
kolaente 43bbeed1c8 feat(api/v2): add task assignees (create/list/delete) on /api/v2
Port the v1 /tasks/{projecttask}/assignees routes to the Huma-backed
/api/v2. The resource self-registers (RegisterTaskAssigneeRoutes) and
reuses the model's Can* methods via the generic Do* handlers:

- POST /tasks/{projecttask}/assignees  → assign a user (body: user_id)
- GET  /tasks/{projecttask}/assignees  → list assignees (as users)
- DELETE /tasks/{projecttask}/assignees/{user} → un-assign

The list element type is []*user.User (assignees are returned as the
assigned users), which differs from the create body (a TaskAssginee
carrying user_id); the list handler type-asserts to []*user.User.
create/delete require write access to the task's project, list requires
read — enforced at the model level.

The webtest re-proves the full v1 permission matrix on the v2 surface
(read-only shares forbidden, write/admin allowed for create and delete;
already-assigned, no-project-access, missing-user, and missing-task
error codes) so v1's routes can be removed later.
2026-06-06 19:06:12 +00:00
kolaente f90868c595 docs(models): tag TaskAssignee fields for the v2 schema
Add doc: tags so Huma can describe user_id and created in the /api/v2
OpenAPI spec (it can't read Go comments), mark the server-set created
field readOnly, and give it an explicit json:"created" tag so it
serializes in snake_case like the rest of the v2 surface.
2026-06-06 19:06:12 +00:00