Fix golangci-lint unused failure — export OpenAPI response types
CI / Canvas Deploy Reminder (pull_request) Blocked by required conditions
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Waiting to run
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 3s
CI / Detect changes (pull_request) Successful in 7s
CI / Python Lint & Test (pull_request) Successful in 4s
E2E API Smoke Test / detect-changes (pull_request) Successful in 7s
E2E Chat / detect-changes (pull_request) Successful in 9s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 6s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 5s
Harness Replays / detect-changes (pull_request) Successful in 2s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 4s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 3s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 4s
gate-check-v3 / gate-check (pull_request) Successful in 9s
qa-review / approved (pull_request) Failing after 3s
security-review / approved (pull_request) Failing after 3s
sop-checklist / review-refire (pull_request) Has been skipped
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request) Successful in 5s
sop-tier-check / tier-check (pull_request) Successful in 4s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m8s
CI / Canvas (Next.js) (pull_request) Successful in 7s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 3s
E2E Chat / E2E Chat (pull_request) Successful in 5s
Harness Replays / Harness Replays (pull_request) Successful in 3s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m7s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 2m19s
CI / Platform (Go) (pull_request) Successful in 5m50s
CI / all-required (pull_request) Successful in 14m14s
audit-force-merge / audit (pull_request) Successful in 3s
CI / Canvas Deploy Reminder (pull_request) Blocked by required conditions
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Waiting to run
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 3s
CI / Detect changes (pull_request) Successful in 7s
CI / Python Lint & Test (pull_request) Successful in 4s
E2E API Smoke Test / detect-changes (pull_request) Successful in 7s
E2E Chat / detect-changes (pull_request) Successful in 9s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 6s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 5s
Harness Replays / detect-changes (pull_request) Successful in 2s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 4s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 3s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 4s
gate-check-v3 / gate-check (pull_request) Successful in 9s
qa-review / approved (pull_request) Failing after 3s
security-review / approved (pull_request) Failing after 3s
sop-checklist / review-refire (pull_request) Has been skipped
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request) Successful in 5s
sop-tier-check / tier-check (pull_request) Successful in 4s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m8s
CI / Canvas (Next.js) (pull_request) Successful in 7s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 3s
E2E Chat / E2E Chat (pull_request) Successful in 5s
Harness Replays / Harness Replays (pull_request) Successful in 3s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m7s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 2m19s
CI / Platform (Go) (pull_request) Successful in 5m50s
CI / all-required (pull_request) Successful in 14m14s
audit-force-merge / audit (pull_request) Successful in 3s
CI / Platform (Go) flagged `internal/handlers/schedules.go:19:6: type
errorResponse is unused (unused)` because golangci-lint's `unused`
checker doesn't recognise swaggo's `@Success {object} errorResponse`
annotations as references — the types are only used in comments
from Go's perspective.
Fix: export all OpenAPI request/response types. Exported names are
skipped by the unused-checker (package consumers may exist outside
the package, even if absent inside it).
Renamed:
- errorResponse → ErrorResponse
- statusResponse → StatusResponse
- createScheduleResponse → CreateScheduleResponse
- runNowResponse → RunNowResponse
- historyEntry → HistoryEntry
- scheduleResponse → ScheduleResponse
- createScheduleRequest → CreateScheduleRequest
- updateScheduleRequest → UpdateScheduleRequest
- scheduleHealthResponse → ScheduleHealthResponse (test ref updated)
Regenerated docs/openapi/swagger.{yaml,json} with new type names.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -42,14 +42,14 @@
|
|||||||
"schema": {
|
"schema": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/handlers.scheduleResponse"
|
"$ref": "#/definitions/handlers.ScheduleResponse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
"description": "Internal Server Error",
|
"description": "Internal Server Error",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.createScheduleRequest"
|
"$ref": "#/definitions/handlers.CreateScheduleRequest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -93,19 +93,19 @@
|
|||||||
"201": {
|
"201": {
|
||||||
"description": "Created",
|
"description": "Created",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.createScheduleResponse"
|
"$ref": "#/definitions/handlers.CreateScheduleResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"description": "Bad Request",
|
"description": "Bad Request",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
"description": "Internal Server Error",
|
"description": "Internal Server Error",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -146,19 +146,19 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.statusResponse"
|
"$ref": "#/definitions/handlers.StatusResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"description": "Not Found",
|
"description": "Not Found",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
"description": "Internal Server Error",
|
"description": "Internal Server Error",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -201,7 +201,7 @@
|
|||||||
"in": "body",
|
"in": "body",
|
||||||
"required": true,
|
"required": true,
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.updateScheduleRequest"
|
"$ref": "#/definitions/handlers.UpdateScheduleRequest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -209,25 +209,25 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.scheduleResponse"
|
"$ref": "#/definitions/handlers.ScheduleResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"400": {
|
"400": {
|
||||||
"description": "Bad Request",
|
"description": "Bad Request",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"description": "Not Found",
|
"description": "Not Found",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
"description": "Internal Server Error",
|
"description": "Internal Server Error",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,14 +270,14 @@
|
|||||||
"schema": {
|
"schema": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/handlers.historyEntry"
|
"$ref": "#/definitions/handlers.HistoryEntry"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
"description": "Internal Server Error",
|
"description": "Internal Server Error",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -318,19 +318,19 @@
|
|||||||
"200": {
|
"200": {
|
||||||
"description": "OK",
|
"description": "OK",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.runNowResponse"
|
"$ref": "#/definitions/handlers.RunNowResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"404": {
|
"404": {
|
||||||
"description": "Not Found",
|
"description": "Not Found",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"500": {
|
"500": {
|
||||||
"description": "Internal Server Error",
|
"description": "Internal Server Error",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/handlers.errorResponse"
|
"$ref": "#/definitions/handlers.ErrorResponse"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -338,7 +338,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"definitions": {
|
"definitions": {
|
||||||
"handlers.createScheduleRequest": {
|
"handlers.CreateScheduleRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"required": [
|
"required": [
|
||||||
"cron_expr",
|
"cron_expr",
|
||||||
@@ -362,7 +362,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"handlers.createScheduleResponse": {
|
"handlers.CreateScheduleResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"id": {
|
"id": {
|
||||||
@@ -376,7 +376,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"handlers.errorResponse": {
|
"handlers.ErrorResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"error": {
|
"error": {
|
||||||
@@ -384,7 +384,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"handlers.historyEntry": {
|
"handlers.HistoryEntry": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"duration_ms": {
|
"duration_ms": {
|
||||||
@@ -404,7 +404,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"handlers.runNowResponse": {
|
"handlers.RunNowResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"prompt": {
|
"prompt": {
|
||||||
@@ -418,7 +418,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"handlers.scheduleResponse": {
|
"handlers.ScheduleResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"created_at": {
|
"created_at": {
|
||||||
@@ -469,7 +469,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"handlers.statusResponse": {
|
"handlers.StatusResponse": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"status": {
|
"status": {
|
||||||
@@ -477,7 +477,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"handlers.updateScheduleRequest": {
|
"handlers.UpdateScheduleRequest": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
"cron_expr": {
|
"cron_expr": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
basePath: /
|
basePath: /
|
||||||
definitions:
|
definitions:
|
||||||
handlers.createScheduleRequest:
|
handlers.CreateScheduleRequest:
|
||||||
properties:
|
properties:
|
||||||
cron_expr:
|
cron_expr:
|
||||||
type: string
|
type: string
|
||||||
@@ -16,7 +16,7 @@ definitions:
|
|||||||
- cron_expr
|
- cron_expr
|
||||||
- prompt
|
- prompt
|
||||||
type: object
|
type: object
|
||||||
handlers.createScheduleResponse:
|
handlers.CreateScheduleResponse:
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
type: string
|
type: string
|
||||||
@@ -25,12 +25,12 @@ definitions:
|
|||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
handlers.errorResponse:
|
handlers.ErrorResponse:
|
||||||
properties:
|
properties:
|
||||||
error:
|
error:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
handlers.historyEntry:
|
handlers.HistoryEntry:
|
||||||
properties:
|
properties:
|
||||||
duration_ms:
|
duration_ms:
|
||||||
type: integer
|
type: integer
|
||||||
@@ -43,7 +43,7 @@ definitions:
|
|||||||
timestamp:
|
timestamp:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
handlers.runNowResponse:
|
handlers.RunNowResponse:
|
||||||
properties:
|
properties:
|
||||||
prompt:
|
prompt:
|
||||||
type: string
|
type: string
|
||||||
@@ -52,7 +52,7 @@ definitions:
|
|||||||
workspace_id:
|
workspace_id:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
handlers.scheduleResponse:
|
handlers.ScheduleResponse:
|
||||||
properties:
|
properties:
|
||||||
created_at:
|
created_at:
|
||||||
type: string
|
type: string
|
||||||
@@ -87,12 +87,12 @@ definitions:
|
|||||||
workspace_id:
|
workspace_id:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
handlers.statusResponse:
|
handlers.StatusResponse:
|
||||||
properties:
|
properties:
|
||||||
status:
|
status:
|
||||||
type: string
|
type: string
|
||||||
type: object
|
type: object
|
||||||
handlers.updateScheduleRequest:
|
handlers.UpdateScheduleRequest:
|
||||||
properties:
|
properties:
|
||||||
cron_expr:
|
cron_expr:
|
||||||
type: string
|
type: string
|
||||||
@@ -130,12 +130,12 @@ paths:
|
|||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/handlers.scheduleResponse'
|
$ref: '#/definitions/handlers.ScheduleResponse'
|
||||||
type: array
|
type: array
|
||||||
"500":
|
"500":
|
||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
OrgSlugAuth: []
|
OrgSlugAuth: []
|
||||||
@@ -156,22 +156,22 @@ paths:
|
|||||||
name: body
|
name: body
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.createScheduleRequest'
|
$ref: '#/definitions/handlers.CreateScheduleRequest'
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
"201":
|
"201":
|
||||||
description: Created
|
description: Created
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.createScheduleResponse'
|
$ref: '#/definitions/handlers.CreateScheduleResponse'
|
||||||
"400":
|
"400":
|
||||||
description: Bad Request
|
description: Bad Request
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
"500":
|
"500":
|
||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
OrgSlugAuth: []
|
OrgSlugAuth: []
|
||||||
@@ -197,15 +197,15 @@ paths:
|
|||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.statusResponse'
|
$ref: '#/definitions/handlers.StatusResponse'
|
||||||
"404":
|
"404":
|
||||||
description: Not Found
|
description: Not Found
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
"500":
|
"500":
|
||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
OrgSlugAuth: []
|
OrgSlugAuth: []
|
||||||
@@ -231,26 +231,26 @@ paths:
|
|||||||
name: body
|
name: body
|
||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.updateScheduleRequest'
|
$ref: '#/definitions/handlers.UpdateScheduleRequest'
|
||||||
produces:
|
produces:
|
||||||
- application/json
|
- application/json
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.scheduleResponse'
|
$ref: '#/definitions/handlers.ScheduleResponse'
|
||||||
"400":
|
"400":
|
||||||
description: Bad Request
|
description: Bad Request
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
"404":
|
"404":
|
||||||
description: Not Found
|
description: Not Found
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
"500":
|
"500":
|
||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
OrgSlugAuth: []
|
OrgSlugAuth: []
|
||||||
@@ -277,12 +277,12 @@ paths:
|
|||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
items:
|
items:
|
||||||
$ref: '#/definitions/handlers.historyEntry'
|
$ref: '#/definitions/handlers.HistoryEntry'
|
||||||
type: array
|
type: array
|
||||||
"500":
|
"500":
|
||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
OrgSlugAuth: []
|
OrgSlugAuth: []
|
||||||
@@ -308,15 +308,15 @@ paths:
|
|||||||
"200":
|
"200":
|
||||||
description: OK
|
description: OK
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.runNowResponse'
|
$ref: '#/definitions/handlers.RunNowResponse'
|
||||||
"404":
|
"404":
|
||||||
description: Not Found
|
description: Not Found
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
"500":
|
"500":
|
||||||
description: Internal Server Error
|
description: Internal Server Error
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/definitions/handlers.errorResponse'
|
$ref: '#/definitions/handlers.ErrorResponse'
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- BearerAuth: []
|
||||||
OrgSlugAuth: []
|
OrgSlugAuth: []
|
||||||
|
|||||||
@@ -15,32 +15,32 @@ import (
|
|||||||
"github.com/Molecule-AI/molecule-monorepo/platform/internal/scheduler"
|
"github.com/Molecule-AI/molecule-monorepo/platform/internal/scheduler"
|
||||||
)
|
)
|
||||||
|
|
||||||
// errorResponse is returned for 4xx/5xx errors. (OpenAPI doc shape — used by swaggo.)
|
// ErrorResponse is returned for 4xx/5xx errors. (OpenAPI doc shape — used by swaggo.)
|
||||||
type errorResponse struct {
|
type ErrorResponse struct {
|
||||||
Error string `json:"error"`
|
Error string `json:"error"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// statusResponse is returned by mutating endpoints that only echo a status verb.
|
// StatusResponse is returned by mutating endpoints that only echo a status verb.
|
||||||
type statusResponse struct {
|
type StatusResponse struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// createScheduleResponse is returned by POST /workspaces/{id}/schedules.
|
// CreateScheduleResponse is returned by POST /workspaces/{id}/schedules.
|
||||||
type createScheduleResponse struct {
|
type CreateScheduleResponse struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
NextRunAt time.Time `json:"next_run_at"`
|
NextRunAt time.Time `json:"next_run_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// runNowResponse is returned by POST /workspaces/{id}/schedules/{scheduleId}/run.
|
// RunNowResponse is returned by POST /workspaces/{id}/schedules/{scheduleId}/run.
|
||||||
type runNowResponse struct {
|
type RunNowResponse struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
WorkspaceID string `json:"workspace_id"`
|
WorkspaceID string `json:"workspace_id"`
|
||||||
Prompt string `json:"prompt"`
|
Prompt string `json:"prompt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// historyEntry is one row of /workspaces/{id}/schedules/{scheduleId}/history.
|
// HistoryEntry is one row of /workspaces/{id}/schedules/{scheduleId}/history.
|
||||||
type historyEntry struct {
|
type HistoryEntry struct {
|
||||||
Timestamp time.Time `json:"timestamp"`
|
Timestamp time.Time `json:"timestamp"`
|
||||||
DurationMs *int `json:"duration_ms"`
|
DurationMs *int `json:"duration_ms"`
|
||||||
Status *string `json:"status"`
|
Status *string `json:"status"`
|
||||||
@@ -54,7 +54,7 @@ func NewScheduleHandler() *ScheduleHandler {
|
|||||||
return &ScheduleHandler{}
|
return &ScheduleHandler{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type scheduleResponse struct {
|
type ScheduleResponse struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
WorkspaceID string `json:"workspace_id"`
|
WorkspaceID string `json:"workspace_id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -78,8 +78,8 @@ type scheduleResponse struct {
|
|||||||
// @Tags schedules
|
// @Tags schedules
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "Workspace ID"
|
// @Param id path string true "Workspace ID"
|
||||||
// @Success 200 {array} scheduleResponse
|
// @Success 200 {array} ScheduleResponse
|
||||||
// @Failure 500 {object} errorResponse
|
// @Failure 500 {object} ErrorResponse
|
||||||
// @Router /workspaces/{id}/schedules [get]
|
// @Router /workspaces/{id}/schedules [get]
|
||||||
// @Security BearerAuth && OrgSlugAuth
|
// @Security BearerAuth && OrgSlugAuth
|
||||||
func (h *ScheduleHandler) List(c *gin.Context) {
|
func (h *ScheduleHandler) List(c *gin.Context) {
|
||||||
@@ -100,9 +100,9 @@ func (h *ScheduleHandler) List(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
schedules := make([]scheduleResponse, 0)
|
schedules := make([]ScheduleResponse, 0)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var s scheduleResponse
|
var s ScheduleResponse
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&s.ID, &s.WorkspaceID, &s.Name, &s.CronExpr, &s.Timezone,
|
&s.ID, &s.WorkspaceID, &s.Name, &s.CronExpr, &s.Timezone,
|
||||||
&s.Prompt, &s.Enabled, &s.LastRunAt, &s.NextRunAt, &s.RunCount,
|
&s.Prompt, &s.Enabled, &s.LastRunAt, &s.NextRunAt, &s.RunCount,
|
||||||
@@ -120,7 +120,7 @@ func (h *ScheduleHandler) List(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, schedules)
|
c.JSON(http.StatusOK, schedules)
|
||||||
}
|
}
|
||||||
|
|
||||||
type createScheduleRequest struct {
|
type CreateScheduleRequest struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
CronExpr string `json:"cron_expr" binding:"required"`
|
CronExpr string `json:"cron_expr" binding:"required"`
|
||||||
Timezone string `json:"timezone"`
|
Timezone string `json:"timezone"`
|
||||||
@@ -135,17 +135,17 @@ type createScheduleRequest struct {
|
|||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "Workspace ID"
|
// @Param id path string true "Workspace ID"
|
||||||
// @Param body body createScheduleRequest true "Schedule fields"
|
// @Param body body CreateScheduleRequest true "Schedule fields"
|
||||||
// @Success 201 {object} createScheduleResponse
|
// @Success 201 {object} CreateScheduleResponse
|
||||||
// @Failure 400 {object} errorResponse
|
// @Failure 400 {object} ErrorResponse
|
||||||
// @Failure 500 {object} errorResponse
|
// @Failure 500 {object} ErrorResponse
|
||||||
// @Router /workspaces/{id}/schedules [post]
|
// @Router /workspaces/{id}/schedules [post]
|
||||||
// @Security BearerAuth && OrgSlugAuth
|
// @Security BearerAuth && OrgSlugAuth
|
||||||
func (h *ScheduleHandler) Create(c *gin.Context) {
|
func (h *ScheduleHandler) Create(c *gin.Context) {
|
||||||
workspaceID := c.Param("id")
|
workspaceID := c.Param("id")
|
||||||
ctx := c.Request.Context()
|
ctx := c.Request.Context()
|
||||||
|
|
||||||
var body createScheduleRequest
|
var body CreateScheduleRequest
|
||||||
if err := c.ShouldBindJSON(&body); err != nil {
|
if err := c.ShouldBindJSON(&body); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "cron_expr and prompt are required"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "cron_expr and prompt are required"})
|
||||||
return
|
return
|
||||||
@@ -199,7 +199,7 @@ func (h *ScheduleHandler) Create(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type updateScheduleRequest struct {
|
type UpdateScheduleRequest struct {
|
||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
CronExpr *string `json:"cron_expr"`
|
CronExpr *string `json:"cron_expr"`
|
||||||
Timezone *string `json:"timezone"`
|
Timezone *string `json:"timezone"`
|
||||||
@@ -216,11 +216,11 @@ type updateScheduleRequest struct {
|
|||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "Workspace ID"
|
// @Param id path string true "Workspace ID"
|
||||||
// @Param scheduleId path string true "Schedule ID"
|
// @Param scheduleId path string true "Schedule ID"
|
||||||
// @Param body body updateScheduleRequest true "Partial schedule fields (only provided keys are updated)"
|
// @Param body body UpdateScheduleRequest true "Partial schedule fields (only provided keys are updated)"
|
||||||
// @Success 200 {object} scheduleResponse
|
// @Success 200 {object} ScheduleResponse
|
||||||
// @Failure 400 {object} errorResponse
|
// @Failure 400 {object} ErrorResponse
|
||||||
// @Failure 404 {object} errorResponse
|
// @Failure 404 {object} ErrorResponse
|
||||||
// @Failure 500 {object} errorResponse
|
// @Failure 500 {object} ErrorResponse
|
||||||
// @Router /workspaces/{id}/schedules/{scheduleId} [patch]
|
// @Router /workspaces/{id}/schedules/{scheduleId} [patch]
|
||||||
// @Security BearerAuth && OrgSlugAuth
|
// @Security BearerAuth && OrgSlugAuth
|
||||||
func (h *ScheduleHandler) Update(c *gin.Context) {
|
func (h *ScheduleHandler) Update(c *gin.Context) {
|
||||||
@@ -228,7 +228,7 @@ func (h *ScheduleHandler) Update(c *gin.Context) {
|
|||||||
workspaceID := c.Param("id") // #113: bind to owning workspace to prevent IDOR
|
workspaceID := c.Param("id") // #113: bind to owning workspace to prevent IDOR
|
||||||
ctx := c.Request.Context()
|
ctx := c.Request.Context()
|
||||||
|
|
||||||
var body updateScheduleRequest
|
var body UpdateScheduleRequest
|
||||||
if err := c.ShouldBindJSON(&body); err != nil {
|
if err := c.ShouldBindJSON(&body); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid JSON"})
|
||||||
return
|
return
|
||||||
@@ -304,9 +304,9 @@ func (h *ScheduleHandler) Update(c *gin.Context) {
|
|||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "Workspace ID"
|
// @Param id path string true "Workspace ID"
|
||||||
// @Param scheduleId path string true "Schedule ID"
|
// @Param scheduleId path string true "Schedule ID"
|
||||||
// @Success 200 {object} statusResponse
|
// @Success 200 {object} StatusResponse
|
||||||
// @Failure 404 {object} errorResponse
|
// @Failure 404 {object} ErrorResponse
|
||||||
// @Failure 500 {object} errorResponse
|
// @Failure 500 {object} ErrorResponse
|
||||||
// @Router /workspaces/{id}/schedules/{scheduleId} [delete]
|
// @Router /workspaces/{id}/schedules/{scheduleId} [delete]
|
||||||
// @Security BearerAuth && OrgSlugAuth
|
// @Security BearerAuth && OrgSlugAuth
|
||||||
func (h *ScheduleHandler) Delete(c *gin.Context) {
|
func (h *ScheduleHandler) Delete(c *gin.Context) {
|
||||||
@@ -337,9 +337,9 @@ func (h *ScheduleHandler) Delete(c *gin.Context) {
|
|||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "Workspace ID"
|
// @Param id path string true "Workspace ID"
|
||||||
// @Param scheduleId path string true "Schedule ID"
|
// @Param scheduleId path string true "Schedule ID"
|
||||||
// @Success 200 {object} runNowResponse
|
// @Success 200 {object} RunNowResponse
|
||||||
// @Failure 404 {object} errorResponse
|
// @Failure 404 {object} ErrorResponse
|
||||||
// @Failure 500 {object} errorResponse
|
// @Failure 500 {object} ErrorResponse
|
||||||
// @Router /workspaces/{id}/schedules/{scheduleId}/run [post]
|
// @Router /workspaces/{id}/schedules/{scheduleId}/run [post]
|
||||||
// @Security BearerAuth && OrgSlugAuth
|
// @Security BearerAuth && OrgSlugAuth
|
||||||
func (h *ScheduleHandler) RunNow(c *gin.Context) {
|
func (h *ScheduleHandler) RunNow(c *gin.Context) {
|
||||||
@@ -378,8 +378,8 @@ func (h *ScheduleHandler) RunNow(c *gin.Context) {
|
|||||||
// @Produce json
|
// @Produce json
|
||||||
// @Param id path string true "Workspace ID"
|
// @Param id path string true "Workspace ID"
|
||||||
// @Param scheduleId path string true "Schedule ID"
|
// @Param scheduleId path string true "Schedule ID"
|
||||||
// @Success 200 {array} historyEntry
|
// @Success 200 {array} HistoryEntry
|
||||||
// @Failure 500 {object} errorResponse
|
// @Failure 500 {object} ErrorResponse
|
||||||
// @Router /workspaces/{id}/schedules/{scheduleId}/history [get]
|
// @Router /workspaces/{id}/schedules/{scheduleId}/history [get]
|
||||||
// @Security BearerAuth && OrgSlugAuth
|
// @Security BearerAuth && OrgSlugAuth
|
||||||
func (h *ScheduleHandler) History(c *gin.Context) {
|
func (h *ScheduleHandler) History(c *gin.Context) {
|
||||||
@@ -407,9 +407,9 @@ func (h *ScheduleHandler) History(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
entries := make([]historyEntry, 0)
|
entries := make([]HistoryEntry, 0)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var e historyEntry
|
var e HistoryEntry
|
||||||
var reqStr string
|
var reqStr string
|
||||||
if err := rows.Scan(&e.Timestamp, &e.DurationMs, &e.Status, &e.ErrorDetail, &reqStr); err != nil {
|
if err := rows.Scan(&e.Timestamp, &e.DurationMs, &e.Status, &e.ErrorDetail, &reqStr); err != nil {
|
||||||
continue
|
continue
|
||||||
@@ -421,11 +421,11 @@ func (h *ScheduleHandler) History(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, entries)
|
c.JSON(http.StatusOK, entries)
|
||||||
}
|
}
|
||||||
|
|
||||||
// scheduleHealthResponse is the read-only health view of a schedule.
|
// ScheduleHealthResponse is the read-only health view of a schedule.
|
||||||
// It deliberately omits prompt and cron_expr so sensitive task content is
|
// It deliberately omits prompt and cron_expr so sensitive task content is
|
||||||
// never exposed to peer workspaces — only execution-state fields needed to
|
// never exposed to peer workspaces — only execution-state fields needed to
|
||||||
// detect silent cron failures are returned (issue #249).
|
// detect silent cron failures are returned (issue #249).
|
||||||
type scheduleHealthResponse struct {
|
type ScheduleHealthResponse struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
@@ -494,9 +494,9 @@ func (h *ScheduleHandler) Health(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
schedules := make([]scheduleHealthResponse, 0)
|
schedules := make([]ScheduleHealthResponse, 0)
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var s scheduleHealthResponse
|
var s ScheduleHealthResponse
|
||||||
if err := rows.Scan(
|
if err := rows.Scan(
|
||||||
&s.ID, &s.Name, &s.Enabled, &s.LastRunAt, &s.NextRunAt,
|
&s.ID, &s.Name, &s.Enabled, &s.LastRunAt, &s.NextRunAt,
|
||||||
&s.RunCount, &s.LastStatus, &s.LastError,
|
&s.RunCount, &s.LastStatus, &s.LastError,
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ func TestScheduleHealth_SelfCall_Allowed(t *testing.T) {
|
|||||||
t.Fatalf("expected 200 for self-call, got %d: %s", w.Code, w.Body.String())
|
t.Fatalf("expected 200 for self-call, got %d: %s", w.Code, w.Body.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp []scheduleHealthResponse
|
var resp []ScheduleHealthResponse
|
||||||
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
|
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
|
||||||
t.Fatalf("failed to parse response: %v", err)
|
t.Fatalf("failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
@@ -284,7 +284,7 @@ func TestScheduleHealth_CanCommunicatePeer_LegacyNoToken(t *testing.T) {
|
|||||||
t.Fatalf("expected 200 for peer with no tokens, got %d: %s", w.Code, w.Body.String())
|
t.Fatalf("expected 200 for peer with no tokens, got %d: %s", w.Code, w.Body.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
var resp []scheduleHealthResponse
|
var resp []ScheduleHealthResponse
|
||||||
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
|
if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil {
|
||||||
t.Fatalf("failed to parse response: %v", err)
|
t.Fatalf("failed to parse response: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user