Pular para conteúdo

Contratos de API

Versão: 1.0

  • < Backward:
    • Container “API Backend” (C4 Nível 2, 01-Contexto-Container.md);
    • RF-001 a RF-024;
    • UC-001 a UC-028.
  • > Forward:
    • TASK-001 a TASK-082.

Convenções gerais:

  • Base URL: /api (sem prefixo de versão — convenção já em uso nas tasks TASK-001 a TASK-070; caso o projeto evolua para múltiplas versões públicas, adotar /api/v1 a partir daí, mediante ADR de breaking change)
  • Autenticação: Access Token JWT via cookie httpOnly, Secure, SameSite (RF-021); rotas protegidas por AuthGuard global (ADR-008), exceto as marcadas como @Public()
  • Formato: JSON (Content-Type: application/json)
  • Erros seguem o padrão: { "erro": string, "codigo": string }
  • Paginação: ?page=1&limit=20
  • Datas: ISO 8601 (UTC)
  • Toda rota protegida aplica RNF-002 (isolamento por usuário) implicitamente — o userId nunca é recebido no corpo da requisição, sempre extraído do Access Token

Autenticação

POST /auth/register

< Backward: RF-017, G-014.1, UC-019, US-036, US-037

Autenticação: Não requerida (@Public())

Request:

{
  "name": "Maria Silva",
  "email": "maria@exemplo.com",
  "password": "Senha123"
}

Response 201:

{
  "id": "uuid",
  "name": "Maria Silva",
  "email": "maria@exemplo.com",
  "status": "ATIVA",
  "createdAt": "2026-07-24T12:00:00Z"
}

Response 400/409:

{ "erro": "E-mail já cadastrado", "codigo": "EMAIL_ALREADY_EXISTS" }
{ "erro": "Senha deve ter ao menos 8 caracteres, com letra e número", "codigo": "WEAK_PASSWORD" }

Não dispara verificação de e-mail (RNF-003) — conta criada Ativa imediatamente.

> Forward: TASK-061, TASK-062, TASK-063


POST /auth/login

< Backward: RF-018, RF-019, RF-020, G-014.2, G-014.2.3, UC-015, UC-016, UC-018, US-030, US-031, US-032, US-035

Autenticação: Não requerida (@Public())

Request:

{
  "email": "maria@exemplo.com",
  "password": "Senha123"
}

Response 200 (sucesso):

{
  "status": "success",
  "user": { "id": "uuid", "name": "Maria Silva", "email": "maria@exemplo.com" }
}

Tokens setados via cookie httpOnly/Secure/SameSite (accessToken, refreshToken) — não retornados no corpo (ADR-006, ASR-003).

Response 403 (conta desativada, credenciais válidas — ver ADR-011):

{ "status": "requires_reactivation", "erro": "Conta desativada", "codigo": "ACCOUNT_REQUIRES_REACTIVATION" }

Response 401 (credenciais inválidas — genérico, RF-018):

{ "erro": "Credenciais inválidas", "codigo": "INVALID_CREDENTIALS" }

Response 429 (bloqueio por força bruta, RF-019 — ver ADR-029):

{ "erro": "Conta temporariamente bloqueada. Tente novamente em 15 minutos.", "codigo": "ACCOUNT_LOCKED" }

> Forward: TASK-050, TASK-051, TASK-052, TASK-053, TASK-054, TASK-059, TASK-060


POST /auth/refresh

< Backward: RF-021, G-014.3, ASR-003, ADR-028

Autenticação: Requerida (via cookie refreshToken, não via Access Token)

Request: Corpo vazio — o Refresh Token é lido do cookie httpOnly.

Response 200:

{ "status": "success" }

Novo Access Token (e, conforme rotação adotada, novo Refresh Token) é setado via cookie.

Response 401:

{ "erro": "Sessão expirada ou revogada", "codigo": "SESSION_INVALID" }

> Forward: TASK-071


POST /user/reactivate

< Backward: RF-020, G-014.2.3, ASR-007, ADR-011, UC-018, US-035

Autenticação: Não requerida — mas exige e-mail + senha novamente como prova de identidade (não reaproveita sessão, pois nenhuma foi criada em /auth/login)

Request:

{
  "email": "maria@exemplo.com",
  "password": "Senha123",
  "confirm": true
}

Response 200:

{
  "status": "success",
  "user": { "id": "uuid", "name": "Maria Silva", "email": "maria@exemplo.com" }
}

Conta alterada para Ativa; sessão gerada normalmente (mesmos cookies de /auth/login).

Response 401:

{ "erro": "Credenciais inválidas", "codigo": "INVALID_CREDENTIALS" }

Response 400 (recusa de reativação — UC-018, fluxo 3a):

{ "erro": "Confirmação de reativação obrigatória", "codigo": "REACTIVATION_NOT_CONFIRMED" }

> Forward: TASK-059, TASK-060


GET /auth/sessions

< Backward: RF-021, G-014.3, UC-017, US-033, ADR-027

Autenticação: Requerida

Response 200:

[
  {
    "id": "uuid-sessao-A",
    "userAgent": "Chrome no Windows",
    "createdAt": "2026-07-20T10:00:00Z",
    "isCurrent": true
  },
  {
    "id": "uuid-sessao-B",
    "userAgent": "Safari no iPhone",
    "createdAt": "2026-07-22T09:00:00Z",
    "isCurrent": false
  }
]

O campo isCurrent (ADR-027) evita que o frontend precise decodificar o token para identificar a sessão corrente antes de permitir revogação em massa.

> Forward: TASK-055, TASK-056


DELETE /auth/sessions/{id}

< Backward: RF-021, G-014.3.1, UC-017, US-034

Autenticação: Requerida

Path params: id — UUID da sessão a revogar

Response 204: (sem corpo)

Response 404:

{ "erro": "Sessão não encontrada ou já revogada", "codigo": "SESSION_NOT_FOUND" }

Response 403 (tentativa de revogar sessão de outro usuário):

{ "erro": "Acesso negado", "codigo": "FORBIDDEN" }

> Forward: TASK-057, TASK-058


DELETE /auth/sessions

< Backward: RF-021, G-014.3.2, UC-017, US-034, ADR-027

Autenticação: Requerida

Request: Corpo vazio. Revoga todas as sessões exceto a sessão corrente (identificada pelo cookie da própria requisição), reutilizando revokeAllSessions(userId, exceptSessionId) (ADR-007).

Response 204: (sem corpo)

> Forward: TASK-081


Configurações / Conta

GET /user/me

< Backward: RF-016, G-013.1, UC-020

Autenticação: Requerida

Response 200:

{
  "id": "uuid",
  "name": "Maria Silva",
  "email": "maria@exemplo.com",
  "status": "ATIVA",
  "createdAt": "2026-01-10T08:00:00Z"
}

> Forward: TASK-082, TASK-049


PUT /user/account

< Backward: RF-016, G-013.1, G-013.2, UC-020, US-038

Autenticação: Requerida

Request:

{
  "name": "Maria S. Silva",
  "email": "maria.nova@exemplo.com"
}

Response 200:

{
  "id": "uuid",
  "name": "Maria S. Silva",
  "email": "maria.nova@exemplo.com",
  "updatedAt": "2026-07-24T12:00:00Z"
}

Response 409:

{ "erro": "E-mail já em uso", "codigo": "EMAIL_ALREADY_EXISTS" }

> Forward: TASK-048, TASK-049


PUT /user/password

< Backward: RF-024, G-014.6, UC-021, US-039, US-040

Autenticação: Requerida

Request:

{
  "currentPassword": "Senha123",
  "newPassword": "NovaSenha456"
}

Response 200:

{ "status": "success" }

Efeito colateral (RF-024): revoga todas as demais sessões ativas, preservando a corrente (via revokeAllSessions(userId, exceptSessionId) — ADR-007).

Response 401:

{ "erro": "Senha atual incorreta", "codigo": "CURRENT_PASSWORD_INVALID" }

Response 400:

{ "erro": "Nova senha não atende à política mínima", "codigo": "WEAK_PASSWORD" }

> Forward: TASK-064, TASK-065, TASK-066


POST /user/deactivate

< Backward: RF-022, G-014.4.1, UC-022, US-041

Autenticação: Requerida

Request: Corpo vazio.

Response 200:

{ "status": "success", "accountStatus": "DESATIVADA" }

Todas as sessões (incluindo a corrente) são revogadas imediatamente (RF-021); cookies do cliente devem ser limpos no redirecionamento ao login público.

> Forward: TASK-067, TASK-068


DELETE /user/account

< Backward: RF-023, G-014.4.2, UC-022, US-042, ADR-010

Autenticação: Requerida

Request:

{ "confirmationPhrase": "Excluir minha conta" }

Response 204: (sem corpo) — deleção em cascata transacional de todos os Cadernos, Itens, Sub-itens e Sessões (ADR-010).

Response 400:

{ "erro": "Frase de confirmação inválida", "codigo": "ACCOUNT_DELETE_CONFIRMATION_REQUIRED" }

> Forward: TASK-069, TASK-070


Cadernos

POST /notebooks

< Backward: RF-001, G-001.1, UC-001, US-001

Autenticação: Requerida

Request:

{ "name": "Trabalho" }

Response 201:

{ "id": "uuid", "name": "Trabalho", "createdAt": "2026-07-24T12:00:00Z" }

Response 400:

{ "erro": "Nome do caderno é obrigatório", "codigo": "NOTEBOOK_NAME_REQUIRED" }

> Forward: TASK-001, TASK-002


GET /notebooks

< Backward: RF-001, UC-001, US-002

Autenticação: Requerida

Response 200:

[
  { "id": "uuid-1", "name": "Trabalho", "createdAt": "2026-07-20T09:00:00Z" },
  { "id": "uuid-2", "name": "Pessoal", "createdAt": "2026-07-21T09:00:00Z" }
]

> Forward: TASK-003


DELETE /notebooks/{id}

< Backward: RF-011, G-008, G-008.1, ADR-010, ADR-020

Autenticação: Requerida

Path params: id — UUID do caderno

Response 200 (retorna a contagem afetada para feedback de UI):

{ "status": "success", "itemsMovedToInbox": 7 }

Todos os itens do caderno têm notebookId setado para null (retorno à Inbox) em transação — nunca cascade automático (ADR-010, ADR-020).

Response 404:

{ "erro": "Caderno não encontrado", "codigo": "NOTEBOOK_NOT_FOUND" }

> Forward: TASK-072, TASK-073


Inbox

POST /inbox

< Backward: RF-004, G-002, UC-002, US-003

Autenticação: Requerida

Request:

{ "title": "Ligar para o dentista" }

Response 201:

{
  "id": "uuid",
  "type": "TODO",
  "title": "Ligar para o dentista",
  "notebookId": null,
  "isCompleted": false,
  "createdAt": "2026-07-24T12:00:00Z"
}

Todo item capturado na Inbox nasce implicitamente como TODO (SCHEDULE sempre exige data/hora e não faz sentido em captura rápida sem classificação).

> Forward: TASK-004, TASK-005


GET /inbox

< Backward: RF-004, UC-002, US-004

Autenticação: Requerida

Response 200:

[
  { "id": "uuid-1", "title": "Ligar para o dentista", "createdAt": "2026-07-24T12:00:00Z" }
]

Equivalente a GET /items?notebookId=null, exposto como rota dedicada por clareza semântica do módulo Inbox.

> Forward: TASK-006


PATCH /items/{id}/classify

< Backward: RF-002, G-001.2, UC-003, US-005, US-006

Autenticação: Requerida

Path params: id — UUID do item na Inbox

Request:

{ "notebookId": "uuid-do-caderno" }

Response 200:

{ "id": "uuid", "notebookId": "uuid-do-caderno", "status": "ATIVO" }

Response 404:

{ "erro": "Caderno de destino não encontrado", "codigo": "NOTEBOOK_NOT_FOUND" }

> Forward: TASK-007, TASK-008, TASK-009


Itens

POST /items

< Backward: RF-005, RF-006, G-003, G-003.1, G-003.2, UC-004, US-007, US-008, US-009

Autenticação: Requerida

Request (TODO):

{
  "type": "TODO",
  "title": "Finalizar relatório",
  "notebookId": "uuid-do-caderno",
  "priority": 2,
  "dueDate": "2026-07-30T00:00:00Z",
  "scheduleId": null,
  "recurrence": null
}

Request (SCHEDULE):

{
  "type": "SCHEDULE",
  "title": "Consulta médica",
  "notebookId": "uuid-do-caderno",
  "startAt": "2026-07-25T14:00:00Z",
  "endAt": "2026-07-25T15:00:00Z",
  "recurrence": { "frequency": "WEEKLY", "endDate": null }
}

Response 201:

{
  "id": "uuid",
  "type": "TODO",
  "title": "Finalizar relatório",
  "notebookId": "uuid-do-caderno",
  "priority": 2,
  "status": "ATIVO",
  "isCompleted": false,
  "dueDate": "2026-07-30T00:00:00Z",
  "createdAt": "2026-07-24T12:00:00Z"
}

Response 400:

{ "erro": "SCHEDULE exige data/hora de início e término", "codigo": "SCHEDULE_DATES_REQUIRED" }
{ "erro": "scheduleId deve referenciar um item do tipo SCHEDULE", "codigo": "SCHEDULE_ID_MUST_REFERENCE_SCHEDULE" }
{ "erro": "Prioridade deve estar entre 1 e 4", "codigo": "INVALID_PRIORITY" }

> Forward: TASK-010, TASK-011, TASK-012, TASK-013, TASK-014, TASK-027, TASK-028


GET /items/{id}

< Backward: RF-005, RF-006, ADR-004

Autenticação: Requerida

Path params: id — UUID do item

Response 200: (mesmo formato de POST /items, incluindo subItems quando type = TODO)

{
  "id": "uuid",
  "type": "TODO",
  "title": "Finalizar relatório",
  "notebookId": "uuid-do-caderno",
  "priority": 2,
  "status": "ATIVO",
  "isCompleted": false,
  "dueDate": "2026-07-30T00:00:00Z",
  "subItems": [
    { "id": "uuid-sub-1", "title": "Revisar dados", "isCompleted": true }
  ]
}

Response 404:

{ "erro": "Item não encontrado", "codigo": "ITEM_NOT_FOUND" }

> Forward: TASK-074


GET /items

< Backward: RF-012, G-009, UC-014, US-028, US-029

Autenticação: Requerida

Query params:

  • sort — manual (default) | priority | dueDate | createdAt | notebook
  • notebookId — filtra por caderno
  • status — ATIVO | ARQUIVADO

Response 200:

{
  "sort": "priority",
  "items": [
    { "id": "uuid-1", "title": "Tarefa crítica", "priority": 1, "dueDate": "2026-07-25T00:00:00Z" },
    { "id": "uuid-2", "title": "Tarefa sem prioridade", "priority": null, "dueDate": null }
  ]
}

Quando sort não é informado ou é omitido, o backend aplica a combinação padrão (prioridade > data limite > data de criação) — RF-012.

> Forward: TASK-045, TASK-047


PATCH /items/{id}

< Backward: RF-006, RF-007, RF-008, ADR-004, ADR-012

Autenticação: Requerida

Path params: id — UUID do item

Request (campos parciais aceitos):

{
  "title": "Finalizar relatório trimestral",
  "priority": 1,
  "dueDate": "2026-08-01T00:00:00Z",
  "recurrence": { "frequency": "MONTHLY", "endDate": null }
}

Response 200: (item atualizado, mesmo formato de GET /items/{id})

Response 400:

{ "erro": "Campo não editável para este tipo de item", "codigo": "INVALID_FIELD_FOR_ITEM_TYPE" }

Este endpoint não altera status, isCompleted ou snoozedUntil — essas transições possuem endpoints dedicados (/complete, /archive, /snooze) por serem transições de domínio validadas na entidade rica Item (ADR-012).

> Forward: TASK-075, TASK-027, TASK-028


PATCH /items/{id}/complete

< Backward: RF-010, G-007, G-007.1, ADR-024

Autenticação: Requerida

Path params: id — UUID do item (apenas type = TODO)

Request:

{ "isCompleted": true }

Response 200:

{ "id": "uuid", "isCompleted": true, "status": "ATIVO" }

Conforme ADR-024, marcar como concluído não altera status (permanece ATIVO); apenas o arquivamento manual (RF-010) transiciona para ARQUIVADO.

Response 400 (tentativa em SCHEDULE):

{ "erro": "Apenas itens do tipo TODO possuem estado de conclusão", "codigo": "INVALID_ITEM_TYPE" }

> Forward: TASK-076


PATCH /items/{id}/archive

< Backward: RF-010, G-007.2, UC-008, US-016, ADR-012, ADR-024

Autenticação: Requerida

Path params: id — UUID do item

Request: Corpo vazio.

Response 200:

{ "id": "uuid", "status": "ARQUIVADO" }

Response 400 (item ainda não concluído — pré-condição de domínio, ADR-012):

{ "erro": "Apenas itens concluídos podem ser arquivados", "codigo": "ARCHIVE_REQUIRES_COMPLETION" }

> Forward: TASK-025, TASK-026


PATCH /items/{id}/snooze

< Backward: RF-009, G-006, UC-010, US-019, US-020

Autenticação: Requerida

Path params: id — UUID do item ativo

Request (atalho rápido):

{ "shortcut": "TOMORROW" }

Valores aceitos de shortcut: TOMORROW (08:00 do dia seguinte), IN_3_DAYS, NEXT_MONDAY.

Request (data manual):

{ "snoozedUntil": "2026-08-05T09:00:00Z" }

Response 200:

{ "id": "uuid", "snoozedUntil": "2026-07-25T08:00:00Z" }

Response 400:

{ "erro": "Informe 'shortcut' ou 'snoozedUntil', não ambos", "codigo": "INVALID_SNOOZE_PAYLOAD" }

> Forward: TASK-030, TASK-031, TASK-032


POST /items/{id}/duplication

< Backward: RF-015, G-012, UC-006, US-012, US-013

Autenticação: Requerida

Path params: id — UUID do item original

Request:

{ "titlePrefix": "Cópia de" }

titlePrefix é opcional; se omitido, o título é duplicado sem prefixo.

Response 201:

{
  "id": "uuid-novo",
  "title": "Cópia de Finalizar relatório",
  "notebookId": "uuid-do-caderno-original",
  "priority": 2,
  "status": "ATIVO",
  "isCompleted": false,
  "dueDate": null,
  "scheduleId": null
}

Não copia isCompleted (nasce false), sub-itens nem scheduleId (RF-015).

> Forward: TASK-018, TASK-019, TASK-020


PATCH /items/reorder

< Backward: RF-012, G-009, UC-014, US-028, ADR-026

Autenticação: Requerida

Request:

{
  "notebookId": "uuid-do-caderno",
  "orderedItemIds": ["uuid-3", "uuid-1", "uuid-2"]
}

Conforme ADR-026, a reordenação manual é enviada como lote (array ordenado completo do escopo afetado), não como atualização de posição individual — evita inconsistências de concorrência entre múltiplos PATCH de posição isolados.

Response 200:

{ "status": "success", "sort": "manual" }

Response 400:

{ "erro": "Lista de IDs não corresponde aos itens do escopo informado", "codigo": "REORDER_MISMATCH" }

> Forward: TASK-079, TASK-046


DELETE /items/{id}

< Backward: RF-011, G-007.3, G-008, G-008.2, UC-007, US-014, US-015, ADR-025, ADR-021

Autenticação: Requerida

Path params: id — UUID do item

Query params: confirm (boolean, opcional — obrigatório apenas se o item possuir sub-itens, ver ADR-025)

Response 204: (sem corpo — item e, se houver, seus sub-itens removidos fisicamente da base, ADR-021)

Response 409 (item possui sub-itens e confirm não foi enviado — ver ADR-025):

{
  "erro": "Item possui sub-itens vinculados; reenvie com confirm=true",
  "codigo": "ITEM_HAS_SUBITEMS_CONFIRM_REQUIRED",
  "subItemsCount": 3
}

> Forward: TASK-021, TASK-022, TASK-023, TASK-024


Sub-itens

POST /items/{todoId}/subitems

< Backward: RF-003, G-001.3, UC-005, US-010, US-011

Autenticação: Requerida

Path params: todoId — UUID do item pai (deve ser type = TODO)

Request:

{ "title": "Revisar dados financeiros" }

Response 201:

{ "id": "uuid-sub", "itemId": "uuid-todo", "title": "Revisar dados financeiros", "isCompleted": false }

Response 400 (tentativa em SCHEDULE):

{ "erro": "Sub-itens só podem ser vinculados a itens do tipo TODO", "codigo": "SUBITEM_PARENT_NOT_TODO" }

> Forward: TASK-015, TASK-016


PATCH /items/{todoId}/subitems/{subItemId}

< Backward: RF-003, G-001.3, UC-005, US-011, ASR-013 (Arquitetura)

Autenticação: Requerida

Path params: todoId, subItemId

Request:

{ "isCompleted": true }

Response 200:

{ "id": "uuid-sub", "isCompleted": true }

A conclusão afeta exclusivamente o escopo daquele sub-item — sem propagação a outros TODOs (US-011).

Response 404:

{ "erro": "Sub-item não encontrado neste item", "codigo": "SUBITEM_NOT_FOUND" }

> Forward: TASK-077, TASK-016, TASK-017


DELETE /items/{todoId}/subitems/{subItemId}

< Backward: RF-003, G-001.3, ADR-021

Autenticação: Requerida

Path params: todoId, subItemId

Response 204: (sem corpo)

Response 404:

{ "erro": "Sub-item não encontrado neste item", "codigo": "SUBITEM_NOT_FOUND" }

> Forward: TASK-078


Calendário

GET /calendar/daily

< Backward: RF-014, G-011.1, G-011.3, UC-011, US-021, US-023

Autenticação: Requerida

Query params: date (ISO 8601, obrigatório)

Response 200:

{
  "date": "2026-07-25",
  "items": [
    { "id": "uuid-1", "type": "SCHEDULE", "title": "Consulta médica", "startAt": "2026-07-25T14:00:00Z", "endAt": "2026-07-25T15:00:00Z" },
    { "id": "uuid-2", "type": "TODO", "title": "Entregar relatório", "dueDate": "2026-07-25T00:00:00Z" }
  ]
}

Regras de visibilidade centralizadas em CalendarVisibilityService (ADR-015): SCHEDULEs sempre aparecem; TODOs aparecem apenas com horário ou dueDate.

> Forward: TASK-033, TASK-034, TASK-037


GET /calendar/weekly

< Backward: RF-014, G-011.1, UC-011, US-022, US-023

Autenticação: Requerida

Query params: weekStart (ISO 8601, obrigatório — segunda-feira de referência)

Response 200:

{
  "weekStart": "2026-07-20",
  "days": [
    { "date": "2026-07-20", "items": [] },
    { "date": "2026-07-21", "items": [ { "id": "uuid-1", "type": "SCHEDULE", "title": "Reunião", "startAt": "2026-07-21T10:00:00Z", "endAt": "2026-07-21T11:00:00Z" } ] }
  ]
}

> Forward: TASK-035, TASK-036, TASK-037


GET /calendar/monthly

< Backward: RF-014, G-011.1, UC-011, US-022, US-023

Autenticação: Requerida

Query params: month (formato YYYY-MM, obrigatório)

Response 200:

{
  "month": "2026-07",
  "days": [
    { "date": "2026-07-01", "itemCount": 2 },
    { "date": "2026-07-02", "itemCount": 0 }
  ]
}

Visão mensal retorna contagem agregada por dia (grade); detalhamento por item fica a cargo da visão Diária/Agenda ao selecionar um dia específico.

> Forward: TASK-035, TASK-036, TASK-037


GET /calendar/agenda

< Backward: RF-014, G-011.1, UC-011, US-022, US-023

Autenticação: Requerida

Query params: from (ISO 8601, obrigatório), limit (default 20)

Response 200:

{
  "items": [
    { "id": "uuid-1", "type": "SCHEDULE", "title": "Consulta médica", "startAt": "2026-07-25T14:00:00Z" },
    { "id": "uuid-2", "type": "TODO", "title": "Entregar relatório", "dueDate": "2026-07-26T00:00:00Z" }
  ]
}

Lista puramente cronológica, ordenada por startAt/dueDate ascendente.

> Forward: TASK-035, TASK-036, TASK-037


Planner Diário

GET /planner/daily

< Backward: RF-014, G-011.2, UC-012, US-024, US-025

Autenticação: Requerida

Query params: date (ISO 8601, obrigatório)

Response 200:

{
  "date": "2026-07-25",
  "items": [
    { "id": "uuid-1", "title": "Entregar relatório", "dueDate": "2026-07-25T00:00:00Z", "priority": 1 },
    { "id": "uuid-2", "title": "Ler artigo", "dueDate": null, "priority": null }
  ]
}

Inclui TODOs do dia selecionado e TODOs sem qualquer data associada (RF-014); SCHEDULEs nunca retornados nesta rota (validado em CalendarVisibilityService, ADR-015).

> Forward: TASK-038, TASK-039, TASK-040


Busca

< Backward: RF-013, G-010, UC-013, US-026, US-027

Autenticação: Requerida

Query params:

  • q — termo de busca (obrigatório, mínimo 1 caractere)
  • status — ATIVO | ARQUIVADO (opcional)
  • notebookId — filtra por caderno (opcional)
  • priority — 1–4 (opcional)
  • from, to — intervalo de período por dueDate (opcional)

Response 200:

{
  "query": "relatório",
  "results": [
    { "id": "uuid-1", "title": "Finalizar relatório trimestral", "priority": 1, "dueDate": "2026-07-25T00:00:00Z" }
  ]
}

Restrito a itens type = TODO (RF-013) via ILIKE + índice trigram (ADR-016); nunca retorna Cadernos ou SCHEDULEs.

> Forward: TASK-041, TASK-042, TASK-043, TASK-044