@nasebanal/cli 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1730 @@
1
+ openapi: 3.0.3
2
+ info:
3
+ title: NASEBANAL - Assurance API
4
+ description: "Backend of NASEBANAL Assurance (quality assurance for APIs and web apps, under NASEBANAL Evolution). Authenticates users via Auth0 JWT and Personal Access Tokens (PAT) and integrates with the Account API. External monitoring: register URLs to be probed on an interval, then read availability reports. Test results: report the normalised result of each CI/CD job into a named project (typically one per repository), then read its runs and suites. Every response is wrapped as `{ success, data }` (or `{ success: false, error }`)."
5
+ version: 1.0.0
6
+ contact:
7
+ name: NASEBANAL
8
+ url: https://www.nasebanal.com
9
+ servers:
10
+ - url: http://localhost:8791
11
+ description: Local dev (wrangler dev)
12
+ - url: https://api.assurance.nasebanal.com
13
+ description: Production
14
+ security:
15
+ - BearerAuth: []
16
+ tags:
17
+ - name: Health
18
+ description: Health check endpoints
19
+ - name: User
20
+ description: User profile endpoints
21
+ - name: Monitors
22
+ description: "External monitoring: URLs probed on an interval"
23
+ - name: Reports
24
+ description: Availability reports built from daily rollups and incidents
25
+ - name: Projects
26
+ description: "Test results reported from CI/CD: named projects (typically one per repository), one run per pipeline run, one suite result per job"
27
+ - name: Contracts
28
+ description: "Outsourcing contracts: deliverables tied to projects, documents and the SLA clause"
29
+ paths:
30
+ /api/v1/health:
31
+ get:
32
+ tags:
33
+ - Health
34
+ operationId: getHealth
35
+ summary: Health check
36
+ description: Returns the health status of the API.
37
+ security: []
38
+ responses:
39
+ "200":
40
+ description: API is healthy
41
+ content:
42
+ application/json:
43
+ schema:
44
+ type: object
45
+ properties:
46
+ status:
47
+ type: string
48
+ example: ok
49
+ timestamp:
50
+ type: string
51
+ format: date-time
52
+ /api/v1/me:
53
+ get:
54
+ tags:
55
+ - User
56
+ operationId: getCurrentUser
57
+ summary: Get current user profile
58
+ description: Returns the authenticated user's profile information from the Account API.
59
+ responses:
60
+ "200":
61
+ description: User profile
62
+ content:
63
+ application/json:
64
+ schema:
65
+ $ref: "#/components/schemas/UserResponse"
66
+ "401":
67
+ $ref: "#/components/responses/Unauthorized"
68
+ /api/v1/monitors:
69
+ get:
70
+ tags:
71
+ - Monitors
72
+ operationId: listMonitors
73
+ summary: List monitors
74
+ description: Monitors owned by the caller, newest first, each with its 7-day uptime.
75
+ responses:
76
+ "200":
77
+ description: Monitors
78
+ content:
79
+ application/json:
80
+ schema:
81
+ type: object
82
+ required:
83
+ - success
84
+ - data
85
+ properties:
86
+ success:
87
+ type: boolean
88
+ example: true
89
+ data:
90
+ type: object
91
+ required:
92
+ - data
93
+ - total
94
+ - limit
95
+ properties:
96
+ data:
97
+ type: array
98
+ items:
99
+ $ref: "#/components/schemas/MonitorWithUptime"
100
+ total:
101
+ type: integer
102
+ limit:
103
+ type: integer
104
+ description: Maximum monitors per user
105
+ "401":
106
+ $ref: "#/components/responses/Unauthorized"
107
+ "403":
108
+ $ref: "#/components/responses/Forbidden"
109
+ parameters:
110
+ - $ref: "#/components/parameters/ActiveOrganization"
111
+ post:
112
+ tags:
113
+ - Monitors
114
+ operationId: createMonitor
115
+ summary: Create a monitor
116
+ description: The URL must be a public http(s) host on port 80, 443, 8080 or 8443; private, loopback, link-local and single-label hosts are refused.
117
+ requestBody:
118
+ required: true
119
+ content:
120
+ application/json:
121
+ schema:
122
+ $ref: "#/components/schemas/MonitorCreate"
123
+ responses:
124
+ "201":
125
+ description: Monitor created
126
+ content:
127
+ application/json:
128
+ schema:
129
+ type: object
130
+ required:
131
+ - success
132
+ - data
133
+ properties:
134
+ success:
135
+ type: boolean
136
+ example: true
137
+ data:
138
+ $ref: "#/components/schemas/Monitor"
139
+ "400":
140
+ $ref: "#/components/responses/ValidationError"
141
+ "401":
142
+ $ref: "#/components/responses/Unauthorized"
143
+ "403":
144
+ $ref: "#/components/responses/Forbidden"
145
+ "409":
146
+ description: The per-user monitor limit is reached (`LIMIT_REACHED`)
147
+ content:
148
+ application/json:
149
+ schema:
150
+ $ref: "#/components/schemas/Error"
151
+ parameters:
152
+ - $ref: "#/components/parameters/ActiveOrganization"
153
+ /api/v1/monitors/{id}:
154
+ parameters:
155
+ - name: id
156
+ in: path
157
+ required: true
158
+ schema:
159
+ type: string
160
+ description: Monitor id
161
+ get:
162
+ tags:
163
+ - Monitors
164
+ operationId: getMonitor
165
+ summary: Get a monitor
166
+ description: One monitor with its settings and latest state.
167
+ responses:
168
+ "200":
169
+ description: Monitor
170
+ content:
171
+ application/json:
172
+ schema:
173
+ type: object
174
+ required:
175
+ - success
176
+ - data
177
+ properties:
178
+ success:
179
+ type: boolean
180
+ example: true
181
+ data:
182
+ $ref: "#/components/schemas/Monitor"
183
+ "401":
184
+ $ref: "#/components/responses/Unauthorized"
185
+ "403":
186
+ $ref: "#/components/responses/Forbidden"
187
+ "404":
188
+ $ref: "#/components/responses/NotFound"
189
+ parameters:
190
+ - $ref: "#/components/parameters/ActiveOrganization"
191
+ patch:
192
+ tags:
193
+ - Monitors
194
+ operationId: updateMonitor
195
+ summary: Update a monitor
196
+ description: Send only the fields to change. Changing `url` resets the monitor to `pending` and closes any open incident.
197
+ requestBody:
198
+ required: true
199
+ content:
200
+ application/json:
201
+ schema:
202
+ $ref: "#/components/schemas/MonitorUpdate"
203
+ responses:
204
+ "200":
205
+ description: Updated monitor
206
+ content:
207
+ application/json:
208
+ schema:
209
+ type: object
210
+ required:
211
+ - success
212
+ - data
213
+ properties:
214
+ success:
215
+ type: boolean
216
+ example: true
217
+ data:
218
+ $ref: "#/components/schemas/Monitor"
219
+ "400":
220
+ $ref: "#/components/responses/ValidationError"
221
+ "401":
222
+ $ref: "#/components/responses/Unauthorized"
223
+ "403":
224
+ $ref: "#/components/responses/Forbidden"
225
+ "404":
226
+ $ref: "#/components/responses/NotFound"
227
+ parameters:
228
+ - $ref: "#/components/parameters/ActiveOrganization"
229
+ delete:
230
+ tags:
231
+ - Monitors
232
+ operationId: deleteMonitor
233
+ summary: Delete a monitor
234
+ description: Also deletes its results, daily rollups and incidents.
235
+ responses:
236
+ "200":
237
+ description: Deleted
238
+ content:
239
+ application/json:
240
+ schema:
241
+ type: object
242
+ required:
243
+ - success
244
+ - data
245
+ properties:
246
+ success:
247
+ type: boolean
248
+ example: true
249
+ data:
250
+ type: object
251
+ properties:
252
+ id:
253
+ type: string
254
+ deleted:
255
+ type: boolean
256
+ "401":
257
+ $ref: "#/components/responses/Unauthorized"
258
+ "403":
259
+ $ref: "#/components/responses/Forbidden"
260
+ "404":
261
+ $ref: "#/components/responses/NotFound"
262
+ parameters:
263
+ - $ref: "#/components/parameters/ActiveOrganization"
264
+ /api/v1/monitors/{id}/check:
265
+ parameters:
266
+ - name: id
267
+ in: path
268
+ required: true
269
+ schema:
270
+ type: string
271
+ description: Monitor id
272
+ post:
273
+ tags:
274
+ - Monitors
275
+ operationId: checkMonitor
276
+ summary: Run a check now
277
+ description: "Probes the URL immediately and records the outcome. A target that is down still returns 200 with `ok: false` (the check ran). Refused with 429 within 10 seconds of the previous check."
278
+ responses:
279
+ "200":
280
+ description: Check outcome
281
+ content:
282
+ application/json:
283
+ schema:
284
+ type: object
285
+ required:
286
+ - success
287
+ - data
288
+ properties:
289
+ success:
290
+ type: boolean
291
+ example: true
292
+ data:
293
+ type: object
294
+ properties:
295
+ ok:
296
+ type: boolean
297
+ status_code:
298
+ type: integer
299
+ nullable: true
300
+ response_ms:
301
+ type: integer
302
+ error:
303
+ $ref: "#/components/schemas/CheckError"
304
+ monitor:
305
+ $ref: "#/components/schemas/Monitor"
306
+ "401":
307
+ $ref: "#/components/responses/Unauthorized"
308
+ "403":
309
+ $ref: "#/components/responses/Forbidden"
310
+ "404":
311
+ $ref: "#/components/responses/NotFound"
312
+ "429":
313
+ description: Checked moments ago (`RATE_LIMITED`)
314
+ content:
315
+ application/json:
316
+ schema:
317
+ $ref: "#/components/schemas/Error"
318
+ parameters:
319
+ - $ref: "#/components/parameters/ActiveOrganization"
320
+ /api/v1/monitors/{id}/results:
321
+ parameters:
322
+ - name: id
323
+ in: path
324
+ required: true
325
+ schema:
326
+ type: string
327
+ description: Monitor id
328
+ get:
329
+ tags:
330
+ - Monitors
331
+ operationId: listMonitorResults
332
+ summary: List recent check results
333
+ description: Newest first. Raw results are kept for 7 days; use the report for longer windows.
334
+ parameters:
335
+ - name: limit
336
+ in: query
337
+ required: false
338
+ schema:
339
+ type: integer
340
+ minimum: 1
341
+ maximum: 500
342
+ default: 100
343
+ - $ref: "#/components/parameters/ActiveOrganization"
344
+ responses:
345
+ "200":
346
+ description: Results
347
+ content:
348
+ application/json:
349
+ schema:
350
+ type: object
351
+ required:
352
+ - success
353
+ - data
354
+ properties:
355
+ success:
356
+ type: boolean
357
+ example: true
358
+ data:
359
+ type: object
360
+ properties:
361
+ data:
362
+ type: array
363
+ items:
364
+ $ref: "#/components/schemas/CheckResult"
365
+ total:
366
+ type: integer
367
+ "400":
368
+ $ref: "#/components/responses/ValidationError"
369
+ "401":
370
+ $ref: "#/components/responses/Unauthorized"
371
+ "403":
372
+ $ref: "#/components/responses/Forbidden"
373
+ "404":
374
+ $ref: "#/components/responses/NotFound"
375
+ /api/v1/monitors/{id}/report:
376
+ parameters:
377
+ - name: id
378
+ in: path
379
+ required: true
380
+ schema:
381
+ type: string
382
+ description: Monitor id
383
+ get:
384
+ tags:
385
+ - Reports
386
+ operationId: getMonitorReport
387
+ summary: Availability report for one monitor
388
+ description: "Availability report for one monitor over the last `days` UTC days: uptime, downtime, response times, a daily series and incidents."
389
+ parameters:
390
+ - name: days
391
+ in: query
392
+ required: false
393
+ schema:
394
+ type: integer
395
+ enum:
396
+ - 1
397
+ - 7
398
+ - 30
399
+ - 90
400
+ default: 7
401
+ description: Report window in UTC days, ending today
402
+ - $ref: "#/components/parameters/ActiveOrganization"
403
+ responses:
404
+ "200":
405
+ description: Report
406
+ content:
407
+ application/json:
408
+ schema:
409
+ type: object
410
+ required:
411
+ - success
412
+ - data
413
+ properties:
414
+ success:
415
+ type: boolean
416
+ example: true
417
+ data:
418
+ $ref: "#/components/schemas/MonitorReport"
419
+ "400":
420
+ $ref: "#/components/responses/ValidationError"
421
+ "401":
422
+ $ref: "#/components/responses/Unauthorized"
423
+ "403":
424
+ $ref: "#/components/responses/Forbidden"
425
+ "404":
426
+ $ref: "#/components/responses/NotFound"
427
+ /api/v1/report:
428
+ get:
429
+ tags:
430
+ - Reports
431
+ operationId: getReportOverview
432
+ summary: Availability report across all monitors
433
+ description: Availability report across all of the caller's monitors over the last `days` UTC days.
434
+ parameters:
435
+ - name: days
436
+ in: query
437
+ required: false
438
+ schema:
439
+ type: integer
440
+ enum:
441
+ - 1
442
+ - 7
443
+ - 30
444
+ - 90
445
+ default: 7
446
+ description: Report window in UTC days, ending today
447
+ - $ref: "#/components/parameters/ActiveOrganization"
448
+ responses:
449
+ "200":
450
+ description: Report
451
+ content:
452
+ application/json:
453
+ schema:
454
+ type: object
455
+ required:
456
+ - success
457
+ - data
458
+ properties:
459
+ success:
460
+ type: boolean
461
+ example: true
462
+ data:
463
+ $ref: "#/components/schemas/ReportOverview"
464
+ "400":
465
+ $ref: "#/components/responses/ValidationError"
466
+ "401":
467
+ $ref: "#/components/responses/Unauthorized"
468
+ "403":
469
+ $ref: "#/components/responses/Forbidden"
470
+ /api/v1/projects:
471
+ get:
472
+ tags:
473
+ - Projects
474
+ operationId: listProjects
475
+ summary: List projects
476
+ description: Projects in the caller's namespace (personal, or the active organization), newest first, each with its latest run and that run's suites.
477
+ parameters:
478
+ - $ref: "#/components/parameters/ActiveOrganization"
479
+ - name: name
480
+ in: query
481
+ required: false
482
+ description: Return only the project with this name (exact match, ignoring case).
483
+ schema:
484
+ type: string
485
+ maxLength: 100
486
+ responses:
487
+ "200":
488
+ description: Projects
489
+ content:
490
+ application/json:
491
+ schema:
492
+ type: object
493
+ required:
494
+ - success
495
+ - data
496
+ properties:
497
+ success:
498
+ type: boolean
499
+ example: true
500
+ data:
501
+ type: object
502
+ required:
503
+ - data
504
+ - total
505
+ - limit
506
+ properties:
507
+ data:
508
+ type: array
509
+ items:
510
+ $ref: "#/components/schemas/ProjectWithLatestRun"
511
+ total:
512
+ type: integer
513
+ limit:
514
+ type: integer
515
+ description: Maximum projects per namespace
516
+ "400":
517
+ $ref: "#/components/responses/ValidationError"
518
+ "401":
519
+ $ref: "#/components/responses/Unauthorized"
520
+ "403":
521
+ $ref: "#/components/responses/Forbidden"
522
+ post:
523
+ tags:
524
+ - Projects
525
+ operationId: createProject
526
+ summary: Create a project
527
+ description: One project tracks one repository's CI/CD quality record. `retention_days` is set from the caller's plan.
528
+ parameters:
529
+ - $ref: "#/components/parameters/ActiveOrganization"
530
+ requestBody:
531
+ required: true
532
+ content:
533
+ application/json:
534
+ schema:
535
+ $ref: "#/components/schemas/ProjectCreate"
536
+ responses:
537
+ "201":
538
+ description: Project created
539
+ content:
540
+ application/json:
541
+ schema:
542
+ type: object
543
+ required:
544
+ - success
545
+ - data
546
+ properties:
547
+ success:
548
+ type: boolean
549
+ example: true
550
+ data:
551
+ $ref: "#/components/schemas/Project"
552
+ "400":
553
+ $ref: "#/components/responses/ValidationError"
554
+ "401":
555
+ $ref: "#/components/responses/Unauthorized"
556
+ "403":
557
+ $ref: "#/components/responses/Forbidden"
558
+ "409":
559
+ description: The per-namespace project limit is reached (`LIMIT_REACHED`), or a project with this name already exists in the namespace (`CONFLICT`)
560
+ content:
561
+ application/json:
562
+ schema:
563
+ $ref: "#/components/schemas/Error"
564
+ /api/v1/projects/{id}:
565
+ parameters:
566
+ - name: id
567
+ in: path
568
+ required: true
569
+ description: Project id
570
+ schema:
571
+ type: string
572
+ - $ref: "#/components/parameters/ActiveOrganization"
573
+ get:
574
+ tags:
575
+ - Projects
576
+ operationId: getProject
577
+ summary: Get a project
578
+ description: One project with its settings, including the retention window.
579
+ responses:
580
+ "200":
581
+ description: Project
582
+ content:
583
+ application/json:
584
+ schema:
585
+ type: object
586
+ required:
587
+ - success
588
+ - data
589
+ properties:
590
+ success:
591
+ type: boolean
592
+ example: true
593
+ data:
594
+ $ref: "#/components/schemas/Project"
595
+ "401":
596
+ $ref: "#/components/responses/Unauthorized"
597
+ "403":
598
+ $ref: "#/components/responses/Forbidden"
599
+ "404":
600
+ $ref: "#/components/responses/NotFound"
601
+ delete:
602
+ tags:
603
+ - Projects
604
+ operationId: deleteProject
605
+ summary: Delete a project
606
+ description: Also deletes its runs and suite results.
607
+ responses:
608
+ "200":
609
+ description: Deleted
610
+ content:
611
+ application/json:
612
+ schema:
613
+ type: object
614
+ required:
615
+ - success
616
+ - data
617
+ properties:
618
+ success:
619
+ type: boolean
620
+ example: true
621
+ data:
622
+ type: object
623
+ properties:
624
+ id:
625
+ type: string
626
+ deleted:
627
+ type: boolean
628
+ "401":
629
+ $ref: "#/components/responses/Unauthorized"
630
+ "403":
631
+ $ref: "#/components/responses/Forbidden"
632
+ "404":
633
+ $ref: "#/components/responses/NotFound"
634
+ /api/v1/projects/{id}/results:
635
+ parameters:
636
+ - name: id
637
+ in: path
638
+ required: true
639
+ description: Project id
640
+ schema:
641
+ type: string
642
+ - $ref: "#/components/parameters/ActiveOrganization"
643
+ post:
644
+ tags:
645
+ - Projects
646
+ operationId: reportResult
647
+ summary: Report a test result
648
+ description: Called once per CI job with the NORMALISED summary of one report (not the raw file). The run is found or created by `run.key`; the suite is upserted by (run, `suite.kind`, `suite.name`), so a retried job replaces its own result and another job of the same pipeline adds a suite to the same run. 201 when the suite is new, 200 when it replaced an earlier report.
649
+ requestBody:
650
+ required: true
651
+ content:
652
+ application/json:
653
+ schema:
654
+ $ref: "#/components/schemas/ResultReport"
655
+ responses:
656
+ "200":
657
+ description: An earlier report of this suite was replaced
658
+ content:
659
+ application/json:
660
+ schema:
661
+ type: object
662
+ required:
663
+ - success
664
+ - data
665
+ properties:
666
+ success:
667
+ type: boolean
668
+ example: true
669
+ data:
670
+ $ref: "#/components/schemas/ResultAccepted"
671
+ "201":
672
+ description: Result stored
673
+ content:
674
+ application/json:
675
+ schema:
676
+ type: object
677
+ required:
678
+ - success
679
+ - data
680
+ properties:
681
+ success:
682
+ type: boolean
683
+ example: true
684
+ data:
685
+ $ref: "#/components/schemas/ResultAccepted"
686
+ "400":
687
+ $ref: "#/components/responses/ValidationError"
688
+ "401":
689
+ $ref: "#/components/responses/Unauthorized"
690
+ "403":
691
+ $ref: "#/components/responses/Forbidden"
692
+ "404":
693
+ $ref: "#/components/responses/NotFound"
694
+ /api/v1/projects/{id}/runs:
695
+ parameters:
696
+ - name: id
697
+ in: path
698
+ required: true
699
+ description: Project id
700
+ schema:
701
+ type: string
702
+ - $ref: "#/components/parameters/ActiveOrganization"
703
+ get:
704
+ tags:
705
+ - Projects
706
+ operationId: listRuns
707
+ summary: List runs
708
+ description: Newest first, each with its suite results.
709
+ parameters:
710
+ - name: limit
711
+ in: query
712
+ required: false
713
+ schema:
714
+ type: integer
715
+ minimum: 1
716
+ maximum: 100
717
+ default: 20
718
+ responses:
719
+ "200":
720
+ description: Runs
721
+ content:
722
+ application/json:
723
+ schema:
724
+ type: object
725
+ required:
726
+ - success
727
+ - data
728
+ properties:
729
+ success:
730
+ type: boolean
731
+ example: true
732
+ data:
733
+ type: object
734
+ required:
735
+ - data
736
+ - limit
737
+ properties:
738
+ data:
739
+ type: array
740
+ items:
741
+ $ref: "#/components/schemas/Run"
742
+ limit:
743
+ type: integer
744
+ "400":
745
+ $ref: "#/components/responses/ValidationError"
746
+ "401":
747
+ $ref: "#/components/responses/Unauthorized"
748
+ "403":
749
+ $ref: "#/components/responses/Forbidden"
750
+ "404":
751
+ $ref: "#/components/responses/NotFound"
752
+ /api/v1/projects/{id}/runs/{runId}:
753
+ parameters:
754
+ - name: id
755
+ in: path
756
+ required: true
757
+ description: Project id
758
+ schema:
759
+ type: string
760
+ - name: runId
761
+ in: path
762
+ required: true
763
+ description: Run id
764
+ schema:
765
+ type: string
766
+ - $ref: "#/components/parameters/ActiveOrganization"
767
+ get:
768
+ tags:
769
+ - Projects
770
+ operationId: getRun
771
+ summary: Get a run
772
+ description: One run with all of its suite results.
773
+ responses:
774
+ "200":
775
+ description: Run
776
+ content:
777
+ application/json:
778
+ schema:
779
+ type: object
780
+ required:
781
+ - success
782
+ - data
783
+ properties:
784
+ success:
785
+ type: boolean
786
+ example: true
787
+ data:
788
+ $ref: "#/components/schemas/Run"
789
+ "401":
790
+ $ref: "#/components/responses/Unauthorized"
791
+ "403":
792
+ $ref: "#/components/responses/Forbidden"
793
+ "404":
794
+ $ref: "#/components/responses/NotFound"
795
+ /api/v1/contracts:
796
+ parameters:
797
+ - $ref: "#/components/parameters/ActiveOrganization"
798
+ get:
799
+ tags:
800
+ - Contracts
801
+ operationId: listContracts
802
+ summary: List contracts
803
+ description: The outsourcing contracts of the active namespace, each with its deliverables, documents and SLA clause. Read-only for now.
804
+ responses:
805
+ "200":
806
+ description: Contracts
807
+ content:
808
+ application/json:
809
+ schema:
810
+ type: object
811
+ required:
812
+ - success
813
+ - data
814
+ properties:
815
+ success:
816
+ type: boolean
817
+ example: true
818
+ data:
819
+ type: object
820
+ properties:
821
+ data:
822
+ type: array
823
+ items:
824
+ $ref: "#/components/schemas/Contract"
825
+ total:
826
+ type: integer
827
+ "401":
828
+ $ref: "#/components/responses/Unauthorized"
829
+ "403":
830
+ $ref: "#/components/responses/Forbidden"
831
+ /api/v1/contracts/{id}:
832
+ parameters:
833
+ - name: id
834
+ in: path
835
+ required: true
836
+ description: Contract id
837
+ schema:
838
+ type: string
839
+ - $ref: "#/components/parameters/ActiveOrganization"
840
+ get:
841
+ tags:
842
+ - Contracts
843
+ operationId: getContract
844
+ summary: Get a contract
845
+ description: One contract. A contract outside the active namespace is reported as not found.
846
+ responses:
847
+ "200":
848
+ description: Contract
849
+ content:
850
+ application/json:
851
+ schema:
852
+ type: object
853
+ required:
854
+ - success
855
+ - data
856
+ properties:
857
+ success:
858
+ type: boolean
859
+ example: true
860
+ data:
861
+ $ref: "#/components/schemas/Contract"
862
+ "401":
863
+ $ref: "#/components/responses/Unauthorized"
864
+ "403":
865
+ $ref: "#/components/responses/Forbidden"
866
+ "404":
867
+ $ref: "#/components/responses/NotFound"
868
+ components:
869
+ securitySchemes:
870
+ BearerAuth:
871
+ type: http
872
+ scheme: bearer
873
+ bearerFormat: JWT or PAT
874
+ description: Use either an Auth0 JWT token or a Personal Access Token (PAT) starting with `nbpat_`.
875
+ schemas:
876
+ User:
877
+ type: object
878
+ properties:
879
+ id:
880
+ type: integer
881
+ auth0_sub:
882
+ type: string
883
+ email:
884
+ type: string
885
+ format: email
886
+ name:
887
+ type: string
888
+ language:
889
+ type: string
890
+ enum:
891
+ - ja
892
+ - en
893
+ plan:
894
+ type: string
895
+ enum:
896
+ - free
897
+ - pro
898
+ - family
899
+ - enterprise
900
+ subscription_status:
901
+ type: string
902
+ enum:
903
+ - active
904
+ - canceled
905
+ - past_due
906
+ - trialing
907
+ nullable: true
908
+ subscription_expires_at:
909
+ type: string
910
+ format: date-time
911
+ nullable: true
912
+ UserResponse:
913
+ type: object
914
+ properties:
915
+ data:
916
+ $ref: "#/components/schemas/User"
917
+ Error:
918
+ type: object
919
+ properties:
920
+ error:
921
+ type: object
922
+ properties:
923
+ code:
924
+ type: string
925
+ message:
926
+ type: string
927
+ CheckError:
928
+ type: string
929
+ nullable: true
930
+ enum:
931
+ - timeout
932
+ - connection_failed
933
+ - unexpected_status
934
+ - keyword_not_found
935
+ - null
936
+ description: Why a check failed; null when it passed
937
+ MonitorSettings:
938
+ type: object
939
+ properties:
940
+ name:
941
+ type: string
942
+ maxLength: 100
943
+ url:
944
+ type: string
945
+ format: uri
946
+ maxLength: 2048
947
+ method:
948
+ type: string
949
+ enum:
950
+ - GET
951
+ - HEAD
952
+ default: GET
953
+ interval_minutes:
954
+ type: integer
955
+ enum:
956
+ - 5
957
+ - 10
958
+ - 15
959
+ - 30
960
+ - 60
961
+ default: 5
962
+ timeout_ms:
963
+ type: integer
964
+ minimum: 1000
965
+ maximum: 30000
966
+ default: 10000
967
+ expected_status:
968
+ type: integer
969
+ nullable: true
970
+ minimum: 100
971
+ maximum: 599
972
+ description: Exact status that counts as up; null means any 2xx or 3xx
973
+ keyword:
974
+ type: string
975
+ nullable: true
976
+ maxLength: 200
977
+ description: Text the response body must contain (GET only)
978
+ enabled:
979
+ type: boolean
980
+ default: true
981
+ MonitorCreate:
982
+ allOf:
983
+ - $ref: "#/components/schemas/MonitorSettings"
984
+ required:
985
+ - name
986
+ - url
987
+ MonitorUpdate:
988
+ allOf:
989
+ - $ref: "#/components/schemas/MonitorSettings"
990
+ minProperties: 1
991
+ description: Any subset of the settings
992
+ Monitor:
993
+ type: object
994
+ properties:
995
+ id:
996
+ type: string
997
+ name:
998
+ type: string
999
+ url:
1000
+ type: string
1001
+ method:
1002
+ type: string
1003
+ enum:
1004
+ - GET
1005
+ - HEAD
1006
+ interval_minutes:
1007
+ type: integer
1008
+ timeout_ms:
1009
+ type: integer
1010
+ expected_status:
1011
+ type: integer
1012
+ nullable: true
1013
+ keyword:
1014
+ type: string
1015
+ nullable: true
1016
+ enabled:
1017
+ type: boolean
1018
+ state:
1019
+ type: string
1020
+ enum:
1021
+ - pending
1022
+ - up
1023
+ - down
1024
+ state_since:
1025
+ type: string
1026
+ format: date-time
1027
+ nullable: true
1028
+ last_checked_at:
1029
+ type: string
1030
+ format: date-time
1031
+ nullable: true
1032
+ last_status_code:
1033
+ type: integer
1034
+ nullable: true
1035
+ last_response_ms:
1036
+ type: integer
1037
+ nullable: true
1038
+ last_error:
1039
+ $ref: "#/components/schemas/CheckError"
1040
+ created_at:
1041
+ type: string
1042
+ format: date-time
1043
+ updated_at:
1044
+ type: string
1045
+ format: date-time
1046
+ organization_id:
1047
+ type: integer
1048
+ nullable: true
1049
+ description: Owning organization; null for a personal monitor.
1050
+ example: null
1051
+ MonitorWithUptime:
1052
+ allOf:
1053
+ - $ref: "#/components/schemas/Monitor"
1054
+ - type: object
1055
+ properties:
1056
+ uptime_7d:
1057
+ type: number
1058
+ nullable: true
1059
+ description: Percent, null before the first check
1060
+ CheckResult:
1061
+ type: object
1062
+ properties:
1063
+ id:
1064
+ type: integer
1065
+ monitor_id:
1066
+ type: string
1067
+ checked_at:
1068
+ type: string
1069
+ format: date-time
1070
+ ok:
1071
+ type: boolean
1072
+ status_code:
1073
+ type: integer
1074
+ nullable: true
1075
+ response_ms:
1076
+ type: integer
1077
+ error:
1078
+ $ref: "#/components/schemas/CheckError"
1079
+ Totals:
1080
+ type: object
1081
+ properties:
1082
+ checks:
1083
+ type: integer
1084
+ failures:
1085
+ type: integer
1086
+ uptime_pct:
1087
+ type: number
1088
+ nullable: true
1089
+ description: Percent, two decimals; null when no checks ran
1090
+ avg_response_ms:
1091
+ type: integer
1092
+ nullable: true
1093
+ description: Successful checks only
1094
+ max_response_ms:
1095
+ type: integer
1096
+ nullable: true
1097
+ description: Successful checks only
1098
+ DailyPoint:
1099
+ allOf:
1100
+ - $ref: "#/components/schemas/Totals"
1101
+ - type: object
1102
+ properties:
1103
+ day:
1104
+ type: string
1105
+ format: date
1106
+ description: UTC date
1107
+ Incident:
1108
+ type: object
1109
+ properties:
1110
+ id:
1111
+ type: integer
1112
+ monitor_id:
1113
+ type: string
1114
+ started_at:
1115
+ type: string
1116
+ format: date-time
1117
+ ended_at:
1118
+ type: string
1119
+ format: date-time
1120
+ nullable: true
1121
+ ongoing:
1122
+ type: boolean
1123
+ duration_seconds:
1124
+ type: integer
1125
+ description: Clipped to the report window; open incidents run to now
1126
+ status_code:
1127
+ type: integer
1128
+ nullable: true
1129
+ error:
1130
+ $ref: "#/components/schemas/CheckError"
1131
+ MonitorReport:
1132
+ allOf:
1133
+ - $ref: "#/components/schemas/Totals"
1134
+ - type: object
1135
+ properties:
1136
+ monitor:
1137
+ $ref: "#/components/schemas/Monitor"
1138
+ days:
1139
+ type: integer
1140
+ from:
1141
+ type: string
1142
+ format: date-time
1143
+ to:
1144
+ type: string
1145
+ format: date-time
1146
+ incident_count:
1147
+ type: integer
1148
+ total_downtime_seconds:
1149
+ type: integer
1150
+ incidents:
1151
+ type: array
1152
+ items:
1153
+ $ref: "#/components/schemas/Incident"
1154
+ description: Newest first, at most 100
1155
+ daily:
1156
+ type: array
1157
+ items:
1158
+ $ref: "#/components/schemas/DailyPoint"
1159
+ description: One entry per UTC day of the window, empty days included
1160
+ ReportOverview:
1161
+ allOf:
1162
+ - $ref: "#/components/schemas/Totals"
1163
+ - type: object
1164
+ properties:
1165
+ days:
1166
+ type: integer
1167
+ from:
1168
+ type: string
1169
+ format: date-time
1170
+ to:
1171
+ type: string
1172
+ format: date-time
1173
+ incident_count:
1174
+ type: integer
1175
+ total_downtime_seconds:
1176
+ type: integer
1177
+ incidents:
1178
+ type: array
1179
+ items:
1180
+ $ref: "#/components/schemas/Incident"
1181
+ description: Newest first, at most 100
1182
+ daily:
1183
+ type: array
1184
+ items:
1185
+ $ref: "#/components/schemas/DailyPoint"
1186
+ description: One entry per UTC day of the window, empty days included
1187
+ monitor_count:
1188
+ type: integer
1189
+ down_now:
1190
+ type: integer
1191
+ monitors:
1192
+ type: array
1193
+ items:
1194
+ allOf:
1195
+ - $ref: "#/components/schemas/Totals"
1196
+ - type: object
1197
+ properties:
1198
+ monitor:
1199
+ $ref: "#/components/schemas/Monitor"
1200
+ incident_count:
1201
+ type: integer
1202
+ total_downtime_seconds:
1203
+ type: integer
1204
+ ProjectCreate:
1205
+ type: object
1206
+ required:
1207
+ - name
1208
+ properties:
1209
+ name:
1210
+ type: string
1211
+ maxLength: 100
1212
+ description: Unique within the namespace, ignoring case. The CLI finds or creates a project by this name.
1213
+ repo:
1214
+ type: string
1215
+ nullable: true
1216
+ maxLength: 200
1217
+ description: "Where the code lives, as `owner/name` (or `group/subgroup/project`, optionally prefixed by a host). Informational: several projects may share one repository, and it may be omitted."
1218
+ example: nasebanal/nb-target-api
1219
+ Project:
1220
+ type: object
1221
+ required:
1222
+ - id
1223
+ - name
1224
+ - retention_days
1225
+ - created_at
1226
+ - updated_at
1227
+ properties:
1228
+ id:
1229
+ type: string
1230
+ organization_id:
1231
+ type: integer
1232
+ nullable: true
1233
+ description: Owning organization; null = personal
1234
+ name:
1235
+ type: string
1236
+ repo:
1237
+ type: string
1238
+ nullable: true
1239
+ retention_days:
1240
+ type: integer
1241
+ description: Runs older than this are deleted daily. Follows the reporter's plan, refreshed on every report.
1242
+ created_at:
1243
+ type: string
1244
+ format: date-time
1245
+ updated_at:
1246
+ type: string
1247
+ format: date-time
1248
+ ProjectWithLatestRun:
1249
+ allOf:
1250
+ - $ref: "#/components/schemas/Project"
1251
+ - type: object
1252
+ properties:
1253
+ latest_run:
1254
+ allOf:
1255
+ - $ref: "#/components/schemas/Run"
1256
+ nullable: true
1257
+ SuiteTests:
1258
+ type: object
1259
+ properties:
1260
+ total:
1261
+ type: integer
1262
+ minimum: 0
1263
+ nullable: true
1264
+ passed:
1265
+ type: integer
1266
+ minimum: 0
1267
+ nullable: true
1268
+ failed:
1269
+ type: integer
1270
+ minimum: 0
1271
+ nullable: true
1272
+ skipped:
1273
+ type: integer
1274
+ minimum: 0
1275
+ nullable: true
1276
+ SuiteFailure:
1277
+ type: object
1278
+ required:
1279
+ - name
1280
+ properties:
1281
+ name:
1282
+ type: string
1283
+ maxLength: 300
1284
+ message:
1285
+ type: string
1286
+ nullable: true
1287
+ maxLength: 500
1288
+ Suite:
1289
+ type: object
1290
+ required:
1291
+ - id
1292
+ - kind
1293
+ - tool
1294
+ - name
1295
+ - status
1296
+ properties:
1297
+ id:
1298
+ type: string
1299
+ kind:
1300
+ type: string
1301
+ enum:
1302
+ - unit
1303
+ - e2e
1304
+ - load
1305
+ - contract
1306
+ - security
1307
+ tool:
1308
+ type: string
1309
+ enum:
1310
+ - vitest
1311
+ - pytest
1312
+ - playwright
1313
+ - specmatic
1314
+ - zap
1315
+ - locust
1316
+ example: vitest
1317
+ name:
1318
+ type: string
1319
+ description: Tells apart several suites of one kind in a run; empty when single
1320
+ status:
1321
+ type: string
1322
+ enum:
1323
+ - passed
1324
+ - failed
1325
+ tests:
1326
+ $ref: "#/components/schemas/SuiteTests"
1327
+ duration_ms:
1328
+ type: integer
1329
+ minimum: 0
1330
+ nullable: true
1331
+ coverage:
1332
+ type: object
1333
+ properties:
1334
+ lines_pct:
1335
+ type: number
1336
+ nullable: true
1337
+ branches_pct:
1338
+ type: number
1339
+ nullable: true
1340
+ metrics:
1341
+ type: object
1342
+ nullable: true
1343
+ additionalProperties:
1344
+ type: number
1345
+ description: Kind-specific numbers
1346
+ failures:
1347
+ type: array
1348
+ nullable: true
1349
+ items:
1350
+ $ref: "#/components/schemas/SuiteFailure"
1351
+ updated_at:
1352
+ type: string
1353
+ format: date-time
1354
+ Run:
1355
+ type: object
1356
+ required:
1357
+ - id
1358
+ - key
1359
+ - status
1360
+ - suites
1361
+ - created_at
1362
+ properties:
1363
+ id:
1364
+ type: string
1365
+ key:
1366
+ type: string
1367
+ description: The caller's identity for the pipeline run
1368
+ commit_sha:
1369
+ type: string
1370
+ nullable: true
1371
+ branch:
1372
+ type: string
1373
+ nullable: true
1374
+ ci_url:
1375
+ type: string
1376
+ nullable: true
1377
+ started_at:
1378
+ type: string
1379
+ format: date-time
1380
+ nullable: true
1381
+ created_at:
1382
+ type: string
1383
+ format: date-time
1384
+ status:
1385
+ type: string
1386
+ enum:
1387
+ - passed
1388
+ - failed
1389
+ - empty
1390
+ description: failed if any suite failed; passed if there is at least one suite and none failed
1391
+ suites:
1392
+ type: array
1393
+ items:
1394
+ $ref: "#/components/schemas/Suite"
1395
+ ResultReport:
1396
+ type: object
1397
+ required:
1398
+ - run
1399
+ - suite
1400
+ properties:
1401
+ run:
1402
+ type: object
1403
+ required:
1404
+ - key
1405
+ properties:
1406
+ key:
1407
+ type: string
1408
+ maxLength: 128
1409
+ description: Stable per pipeline run, e.g. the CI run id plus attempt. Every job of one run must send the same key.
1410
+ example: 12345678-1
1411
+ commit_sha:
1412
+ type: string
1413
+ maxLength: 64
1414
+ branch:
1415
+ type: string
1416
+ maxLength: 255
1417
+ ci_url:
1418
+ type: string
1419
+ maxLength: 2048
1420
+ description: http(s) URL of the CI run
1421
+ started_at:
1422
+ type: string
1423
+ format: date-time
1424
+ suite:
1425
+ type: object
1426
+ required:
1427
+ - kind
1428
+ - tool
1429
+ - status
1430
+ properties:
1431
+ kind:
1432
+ type: string
1433
+ enum:
1434
+ - unit
1435
+ - e2e
1436
+ - load
1437
+ - contract
1438
+ - security
1439
+ tool:
1440
+ type: string
1441
+ maxLength: 50
1442
+ enum:
1443
+ - vitest
1444
+ - pytest
1445
+ - playwright
1446
+ - specmatic
1447
+ - zap
1448
+ - locust
1449
+ description: "The producing tool. Supported per kind: unit = vitest | pytest, e2e = playwright, contract = specmatic, security = zap, load = locust. Any other tool, or a tool paired with the wrong kind, is rejected with 400. Matching is case-insensitive."
1450
+ example: playwright
1451
+ name:
1452
+ type: string
1453
+ maxLength: 100
1454
+ status:
1455
+ type: string
1456
+ enum:
1457
+ - passed
1458
+ - failed
1459
+ description: Decided by the reporter, which alone knows the tool's pass/fail semantics
1460
+ tests:
1461
+ type: object
1462
+ properties:
1463
+ total:
1464
+ type: integer
1465
+ minimum: 0
1466
+ passed:
1467
+ type: integer
1468
+ minimum: 0
1469
+ failed:
1470
+ type: integer
1471
+ minimum: 0
1472
+ skipped:
1473
+ type: integer
1474
+ minimum: 0
1475
+ description: passed + failed + skipped must not exceed total
1476
+ duration_ms:
1477
+ type: integer
1478
+ minimum: 0
1479
+ coverage:
1480
+ type: object
1481
+ properties:
1482
+ lines_pct:
1483
+ type: number
1484
+ minimum: 0
1485
+ maximum: 100
1486
+ branches_pct:
1487
+ type: number
1488
+ minimum: 0
1489
+ maximum: 100
1490
+ metrics:
1491
+ type: object
1492
+ maxProperties: 20
1493
+ additionalProperties:
1494
+ type: number
1495
+ description: "snake_case keys, finite numbers. Conventional keys: load -> p95_ms, rps, error_rate_pct; security -> critical, high, medium, low, info; contract -> coverage_pct."
1496
+ example:
1497
+ p95_ms: 240
1498
+ rps: 120.5
1499
+ failures:
1500
+ type: array
1501
+ maxItems: 20
1502
+ items:
1503
+ $ref: "#/components/schemas/SuiteFailure"
1504
+ description: The first failures only
1505
+ ResultAccepted:
1506
+ type: object
1507
+ required:
1508
+ - run_id
1509
+ - suite_id
1510
+ - replaced
1511
+ properties:
1512
+ run_id:
1513
+ type: string
1514
+ suite_id:
1515
+ type: string
1516
+ replaced:
1517
+ type: boolean
1518
+ ContractCreditTier:
1519
+ type: object
1520
+ required:
1521
+ - below_pct
1522
+ - credit_pct
1523
+ properties:
1524
+ below_pct:
1525
+ type: number
1526
+ description: Below this uptime percentage the credit applies
1527
+ credit_pct:
1528
+ type: number
1529
+ description: Share of the monthly fee credited back
1530
+ ContractSla:
1531
+ type: object
1532
+ required:
1533
+ - uptime_target_pct
1534
+ - monthly_fee
1535
+ - credit_tiers
1536
+ properties:
1537
+ uptime_target_pct:
1538
+ type: number
1539
+ monthly_fee:
1540
+ type: integer
1541
+ credit_tiers:
1542
+ type: array
1543
+ items:
1544
+ $ref: "#/components/schemas/ContractCreditTier"
1545
+ ContractDeliverable:
1546
+ type: object
1547
+ required:
1548
+ - id
1549
+ - name
1550
+ - project_id
1551
+ - version
1552
+ - due
1553
+ - amount
1554
+ - paid
1555
+ properties:
1556
+ id:
1557
+ type: string
1558
+ name:
1559
+ type: string
1560
+ project_id:
1561
+ type: string
1562
+ nullable: true
1563
+ description: The project this deliverable is a version of; null once that project is deleted
1564
+ version:
1565
+ type: string
1566
+ nullable: true
1567
+ description: The delivered version, if it has been delivered
1568
+ due:
1569
+ type: string
1570
+ format: date
1571
+ amount:
1572
+ type: integer
1573
+ description: Released on acceptance
1574
+ paid:
1575
+ type: boolean
1576
+ ContractDocument:
1577
+ type: object
1578
+ required:
1579
+ - name
1580
+ - kind
1581
+ - date
1582
+ properties:
1583
+ name:
1584
+ type: string
1585
+ kind:
1586
+ type: string
1587
+ enum:
1588
+ - contract
1589
+ - spec
1590
+ - sla
1591
+ - acceptance
1592
+ date:
1593
+ type: string
1594
+ format: date
1595
+ Contract:
1596
+ type: object
1597
+ required:
1598
+ - id
1599
+ - title
1600
+ - kind
1601
+ - status
1602
+ - orderer
1603
+ - vendor
1604
+ - start
1605
+ - end
1606
+ - amount
1607
+ - oas_url
1608
+ - sla_project_id
1609
+ - sla
1610
+ - related
1611
+ - deliverables
1612
+ - documents
1613
+ - created_at
1614
+ - updated_at
1615
+ properties:
1616
+ id:
1617
+ type: string
1618
+ title:
1619
+ type: string
1620
+ description: Bilingual, "ja / en"
1621
+ kind:
1622
+ type: string
1623
+ enum:
1624
+ - development
1625
+ - maintenance
1626
+ status:
1627
+ type: string
1628
+ enum:
1629
+ - draft
1630
+ - active
1631
+ - completed
1632
+ orderer:
1633
+ type: string
1634
+ vendor:
1635
+ type: string
1636
+ start:
1637
+ type: string
1638
+ format: date
1639
+ end:
1640
+ type: string
1641
+ format: date
1642
+ amount:
1643
+ type: integer
1644
+ oas_url:
1645
+ type: string
1646
+ format: uri
1647
+ nullable: true
1648
+ description: The OpenAPI document this contract refers to, as a plain URL
1649
+ sla_project_id:
1650
+ type: string
1651
+ nullable: true
1652
+ description: "Operations contracts: the project whose uptime the SLA clause covers"
1653
+ sla:
1654
+ allOf:
1655
+ - $ref: "#/components/schemas/ContractSla"
1656
+ nullable: true
1657
+ related:
1658
+ type: object
1659
+ nullable: true
1660
+ description: "How this contract relates to another one: it follows a development contract, or is a change order on top of a running one"
1661
+ properties:
1662
+ id:
1663
+ type: string
1664
+ relation:
1665
+ type: string
1666
+ enum:
1667
+ - follows
1668
+ - change_order
1669
+ deliverables:
1670
+ type: array
1671
+ items:
1672
+ $ref: "#/components/schemas/ContractDeliverable"
1673
+ documents:
1674
+ type: array
1675
+ items:
1676
+ $ref: "#/components/schemas/ContractDocument"
1677
+ created_at:
1678
+ type: string
1679
+ format: date-time
1680
+ updated_at:
1681
+ type: string
1682
+ format: date-time
1683
+ responses:
1684
+ Unauthorized:
1685
+ description: Authentication required or invalid token
1686
+ content:
1687
+ application/json:
1688
+ schema:
1689
+ $ref: "#/components/schemas/Error"
1690
+ example:
1691
+ error:
1692
+ code: AUTH_ERROR
1693
+ message: No authentication token provided
1694
+ ValidationError:
1695
+ description: The request body or a query parameter is invalid
1696
+ content:
1697
+ application/json:
1698
+ schema:
1699
+ $ref: "#/components/schemas/Error"
1700
+ example:
1701
+ success: false
1702
+ error:
1703
+ code: VALIDATION_ERROR
1704
+ message: url must point to a public host
1705
+ NotFound:
1706
+ description: No such monitor, or it belongs to someone else
1707
+ content:
1708
+ application/json:
1709
+ schema:
1710
+ $ref: "#/components/schemas/Error"
1711
+ example:
1712
+ success: false
1713
+ error:
1714
+ code: NOT_FOUND
1715
+ message: Monitor not found
1716
+ Forbidden:
1717
+ description: The caller does not belong to the active organization (`FORBIDDEN`)
1718
+ content:
1719
+ application/json:
1720
+ schema:
1721
+ $ref: "#/components/schemas/Error"
1722
+ parameters:
1723
+ ActiveOrganization:
1724
+ name: X-Active-Organization-Id
1725
+ in: header
1726
+ required: false
1727
+ schema:
1728
+ type: string
1729
+ example: "7"
1730
+ description: "Namespace the request acts in: an organization id, or `personal` (also the default when absent or malformed). Inside an organization every member shares the same monitors, reports and output settings. An organization the caller does not belong to is refused with 403 `FORBIDDEN`."