@thinkai/tai-api-contract 2.181.0 → 2.183.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.
- package/dist/generated/openapi.d.ts +1722 -302
- package/dist/generated/openapi.d.ts.map +1 -1
- package/openapi/openapi.yaml +1863 -283
- package/package.json +2 -2
- package/src/generated/openapi.ts +1722 -302
package/openapi/openapi.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
openapi: 3.0.3
|
|
2
2
|
info:
|
|
3
3
|
title: ThinkAI API
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.183.0
|
|
5
5
|
description: >
|
|
6
6
|
Contract surface for the AI Driven SDLC backend used by ThinkAI.
|
|
7
7
|
Workspace-scoped routes use `/workspaces/{workspaceId}/...`.
|
|
@@ -65,6 +65,8 @@ tags:
|
|
|
65
65
|
AI-tool usage/spend, org chart, and readiness — never mock payloads.
|
|
66
66
|
- name: WorkspaceActivity
|
|
67
67
|
description: Workspace-wide lifecycle activity log — repo add/remove/re-add and integration lifecycle events (issue #515).
|
|
68
|
+
- name: AssessmentReports
|
|
69
|
+
description: Encrypted stored assessment buyer PDFs, secure link delivery, and hide/restore (issue #486).
|
|
68
70
|
- name: PlatformAdmin
|
|
69
71
|
description: Platform-admin operations restricted to PLATFORM_ADMIN_EMAILS. Callers must present a valid JWT from an email on that allowlist; all other callers receive 403.
|
|
70
72
|
- name: HRIS
|
|
@@ -430,7 +432,10 @@ paths:
|
|
|
430
432
|
are ignored, so an unscanned source cannot be marked fresh. The
|
|
431
433
|
five-business-day clock uses Monday–Friday in America/New_York and is
|
|
432
434
|
stored on the first passing result. A later blocker does not clear it.
|
|
433
|
-
|
|
435
|
+
The active-engineer count is loaded from stored commit authors and merged
|
|
436
|
+
pull requests in the 90-day baseline window (bots and identities not on the
|
|
437
|
+
org chart excluded). It stays unloaded until commit ingest covers the whole
|
|
438
|
+
window for every non-archived repository.
|
|
434
439
|
|
|
435
440
|
**Authorization:** Bearer JWT required. Caller email must appear in `PLATFORM_ADMIN_EMAILS`.
|
|
436
441
|
parameters:
|
|
@@ -602,7 +607,16 @@ paths:
|
|
|
602
607
|
items:
|
|
603
608
|
type: object
|
|
604
609
|
required:
|
|
605
|
-
[
|
|
610
|
+
[
|
|
611
|
+
workspaceId,
|
|
612
|
+
offerId,
|
|
613
|
+
ready,
|
|
614
|
+
blocker,
|
|
615
|
+
nextAction,
|
|
616
|
+
clockStartedOn,
|
|
617
|
+
dueDate,
|
|
618
|
+
evaluatedAt,
|
|
619
|
+
]
|
|
606
620
|
properties:
|
|
607
621
|
workspaceId:
|
|
608
622
|
type: string
|
|
@@ -625,6 +639,11 @@ paths:
|
|
|
625
639
|
href:
|
|
626
640
|
type: string
|
|
627
641
|
nullable: true
|
|
642
|
+
clockStartedOn:
|
|
643
|
+
type: string
|
|
644
|
+
nullable: true
|
|
645
|
+
format: date
|
|
646
|
+
description: America/New_York day the five-business-day clock started.
|
|
628
647
|
dueDate:
|
|
629
648
|
type: string
|
|
630
649
|
nullable: true
|
|
@@ -668,174 +687,14 @@ paths:
|
|
|
668
687
|
content:
|
|
669
688
|
application/json:
|
|
670
689
|
schema:
|
|
671
|
-
|
|
672
|
-
required:
|
|
673
|
-
- manifest
|
|
674
|
-
- workspaceId
|
|
675
|
-
- expectedWorkspaceId
|
|
676
|
-
- expectedRepositoryIds
|
|
677
|
-
- soldWindowComplete
|
|
678
|
-
- premiumAiAssessable
|
|
679
|
-
- namedPersonSectionIds
|
|
680
|
-
- tolerances
|
|
681
|
-
properties:
|
|
682
|
-
manifest:
|
|
683
|
-
type: object
|
|
684
|
-
required:
|
|
685
|
-
- offerId
|
|
686
|
-
- dictionaryVersion
|
|
687
|
-
- validation
|
|
688
|
-
- shareMode
|
|
689
|
-
- watermark
|
|
690
|
-
- scope
|
|
691
|
-
- windows
|
|
692
|
-
- sources
|
|
693
|
-
- consent
|
|
694
|
-
- sections
|
|
695
|
-
properties:
|
|
696
|
-
offerId:
|
|
697
|
-
type: string
|
|
698
|
-
enum: [engineering_readiness_baseline, agentic_ai_roi]
|
|
699
|
-
dictionaryVersion:
|
|
700
|
-
type: string
|
|
701
|
-
validation:
|
|
702
|
-
type: string
|
|
703
|
-
enum: [validated, not_validated]
|
|
704
|
-
shareMode:
|
|
705
|
-
type: string
|
|
706
|
-
enum: [internal, external]
|
|
707
|
-
watermark:
|
|
708
|
-
type: string
|
|
709
|
-
nullable: true
|
|
710
|
-
enum: ["NOT VALIDATED", "SAMPLE · SYNTHETIC DATA"]
|
|
711
|
-
scope:
|
|
712
|
-
type: object
|
|
713
|
-
required: [repositories, excluded]
|
|
714
|
-
properties:
|
|
715
|
-
repositories:
|
|
716
|
-
type: array
|
|
717
|
-
items:
|
|
718
|
-
type: object
|
|
719
|
-
required: [id, name]
|
|
720
|
-
properties:
|
|
721
|
-
id: { type: string }
|
|
722
|
-
name: { type: string }
|
|
723
|
-
excluded:
|
|
724
|
-
type: array
|
|
725
|
-
items:
|
|
726
|
-
type: object
|
|
727
|
-
required: [id, name, reason]
|
|
728
|
-
properties:
|
|
729
|
-
id: { type: string }
|
|
730
|
-
name: { type: string }
|
|
731
|
-
reason: { type: string }
|
|
732
|
-
windows:
|
|
733
|
-
type: object
|
|
734
|
-
required: [pre, post, transitionDays]
|
|
735
|
-
properties:
|
|
736
|
-
pre:
|
|
737
|
-
type: object
|
|
738
|
-
nullable: true
|
|
739
|
-
required: [start, end]
|
|
740
|
-
properties:
|
|
741
|
-
start: { type: string }
|
|
742
|
-
end: { type: string }
|
|
743
|
-
post:
|
|
744
|
-
type: object
|
|
745
|
-
nullable: true
|
|
746
|
-
required: [start, end]
|
|
747
|
-
properties:
|
|
748
|
-
start: { type: string }
|
|
749
|
-
end: { type: string }
|
|
750
|
-
transitionDays:
|
|
751
|
-
type: integer
|
|
752
|
-
sources:
|
|
753
|
-
type: array
|
|
754
|
-
items:
|
|
755
|
-
type: object
|
|
756
|
-
required: [provider, status, freshAt]
|
|
757
|
-
properties:
|
|
758
|
-
provider: { type: string }
|
|
759
|
-
status: { type: string }
|
|
760
|
-
freshAt: { type: string, nullable: true }
|
|
761
|
-
consent:
|
|
762
|
-
type: object
|
|
763
|
-
required: [aggregateUse, recordedAt]
|
|
764
|
-
properties:
|
|
765
|
-
aggregateUse:
|
|
766
|
-
type: string
|
|
767
|
-
enum: [opt_in, opt_out, unset]
|
|
768
|
-
recordedAt:
|
|
769
|
-
type: string
|
|
770
|
-
nullable: true
|
|
771
|
-
sections:
|
|
772
|
-
type: array
|
|
773
|
-
items:
|
|
774
|
-
type: object
|
|
775
|
-
required: [id, status]
|
|
776
|
-
properties:
|
|
777
|
-
id: { type: string }
|
|
778
|
-
status:
|
|
779
|
-
type: string
|
|
780
|
-
enum: [ok, failed, omitted]
|
|
781
|
-
reason: { type: string }
|
|
782
|
-
workspaceId:
|
|
783
|
-
type: string
|
|
784
|
-
expectedWorkspaceId:
|
|
785
|
-
type: string
|
|
786
|
-
expectedRepositoryIds:
|
|
787
|
-
type: array
|
|
788
|
-
items:
|
|
789
|
-
type: string
|
|
790
|
-
soldWindowComplete:
|
|
791
|
-
type: boolean
|
|
792
|
-
premiumAiAssessable:
|
|
793
|
-
type: boolean
|
|
794
|
-
namedPersonSectionIds:
|
|
795
|
-
type: array
|
|
796
|
-
items:
|
|
797
|
-
type: string
|
|
798
|
-
tolerances:
|
|
799
|
-
type: array
|
|
800
|
-
items:
|
|
801
|
-
type: object
|
|
802
|
-
required: [id, status]
|
|
803
|
-
properties:
|
|
804
|
-
id:
|
|
805
|
-
type: string
|
|
806
|
-
status:
|
|
807
|
-
type: string
|
|
808
|
-
enum: [unset, exceeded, within]
|
|
690
|
+
$ref: "#/components/schemas/AssessmentManifestValidationBodyDto"
|
|
809
691
|
responses:
|
|
810
692
|
"200":
|
|
811
693
|
description: Validation result. Client validation and watermark inputs are ignored.
|
|
812
694
|
content:
|
|
813
695
|
application/json:
|
|
814
696
|
schema:
|
|
815
|
-
|
|
816
|
-
required: [buyerDeliverable, validation, watermark, reasons, contentHash]
|
|
817
|
-
properties:
|
|
818
|
-
buyerDeliverable:
|
|
819
|
-
type: boolean
|
|
820
|
-
validation:
|
|
821
|
-
type: string
|
|
822
|
-
enum: [validated, not_validated]
|
|
823
|
-
watermark:
|
|
824
|
-
type: string
|
|
825
|
-
nullable: true
|
|
826
|
-
enum: ["NOT VALIDATED"]
|
|
827
|
-
reasons:
|
|
828
|
-
type: array
|
|
829
|
-
items:
|
|
830
|
-
type: object
|
|
831
|
-
required: [code, message]
|
|
832
|
-
properties:
|
|
833
|
-
code:
|
|
834
|
-
type: string
|
|
835
|
-
message:
|
|
836
|
-
type: string
|
|
837
|
-
contentHash:
|
|
838
|
-
type: string
|
|
697
|
+
$ref: "#/components/schemas/AssessmentManifestValidationResultDto"
|
|
839
698
|
"400":
|
|
840
699
|
description: Body failed validation.
|
|
841
700
|
content:
|
|
@@ -861,6 +720,180 @@ paths:
|
|
|
861
720
|
error: Forbidden
|
|
862
721
|
code: forbidden
|
|
863
722
|
|
|
723
|
+
/workspaces/{workspaceId}/assessment-manifest/validate:
|
|
724
|
+
post:
|
|
725
|
+
tags: [Workspace]
|
|
726
|
+
summary: Validate this workspace's assessment manifest
|
|
727
|
+
operationId: validateWorkspaceAssessmentManifest
|
|
728
|
+
description: >
|
|
729
|
+
Runs the same fail-closed manifest check as `runAssessmentManifestValidation`
|
|
730
|
+
for the workspace in the path. The server ignores `manifest.validation` and
|
|
731
|
+
`manifest.watermark` from the client. `buyerDeliverable` is true only when
|
|
732
|
+
the result is validated and `shareMode` is internal. An external share-safe
|
|
733
|
+
result can be validated and is never the buyer file. Unset or exceeded
|
|
734
|
+
tolerances fail. No numeric tolerance is assumed. GitLab and Bitbucket
|
|
735
|
+
fixtures are not part of this operation.
|
|
736
|
+
|
|
737
|
+
`workspaceId` and `expectedWorkspaceId` in the body must equal the path
|
|
738
|
+
workspace. A body that names another workspace is rejected. Comparing two
|
|
739
|
+
workspaces stays on `runAssessmentManifestValidation`.
|
|
740
|
+
|
|
741
|
+
**Authorization:** Bearer JWT required. Caller must be a workspace admin,
|
|
742
|
+
or a platform admin who is a member of this workspace. Members who are not
|
|
743
|
+
workspace admins receive 403. Non-members of an existing workspace receive
|
|
744
|
+
403. Unknown workspaces receive 404.
|
|
745
|
+
parameters:
|
|
746
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
747
|
+
requestBody:
|
|
748
|
+
required: true
|
|
749
|
+
content:
|
|
750
|
+
application/json:
|
|
751
|
+
schema:
|
|
752
|
+
$ref: "#/components/schemas/AssessmentManifestValidationBodyDto"
|
|
753
|
+
responses:
|
|
754
|
+
"200":
|
|
755
|
+
description: Validation result. Client validation and watermark inputs are ignored.
|
|
756
|
+
content:
|
|
757
|
+
application/json:
|
|
758
|
+
schema:
|
|
759
|
+
$ref: "#/components/schemas/AssessmentManifestValidationResultDto"
|
|
760
|
+
"400":
|
|
761
|
+
description: Body failed validation.
|
|
762
|
+
content:
|
|
763
|
+
application/json:
|
|
764
|
+
schema:
|
|
765
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
766
|
+
example:
|
|
767
|
+
error: manifest.offerId is not a known assessment offer
|
|
768
|
+
code: invalid_body
|
|
769
|
+
"401":
|
|
770
|
+
$ref: "#/components/responses/Unauthorized"
|
|
771
|
+
"403":
|
|
772
|
+
description: Caller cannot validate this workspace.
|
|
773
|
+
content:
|
|
774
|
+
application/json:
|
|
775
|
+
schema:
|
|
776
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
777
|
+
examples:
|
|
778
|
+
not_member:
|
|
779
|
+
value:
|
|
780
|
+
error: Forbidden
|
|
781
|
+
workspace_admin_required:
|
|
782
|
+
value:
|
|
783
|
+
error: Forbidden
|
|
784
|
+
code: workspace_admin_required
|
|
785
|
+
cross_workspace_forbidden:
|
|
786
|
+
value:
|
|
787
|
+
error: Forbidden
|
|
788
|
+
code: cross_workspace_forbidden
|
|
789
|
+
"404":
|
|
790
|
+
description: Workspace does not exist.
|
|
791
|
+
content:
|
|
792
|
+
application/json:
|
|
793
|
+
schema:
|
|
794
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
795
|
+
example:
|
|
796
|
+
error: Not found
|
|
797
|
+
|
|
798
|
+
/workspaces/{workspaceId}/assessment-manifest/build:
|
|
799
|
+
post:
|
|
800
|
+
tags: [Workspace]
|
|
801
|
+
summary: Build and validate this workspace's assessment manifest from stored evidence
|
|
802
|
+
operationId: buildWorkspaceAssessmentManifest
|
|
803
|
+
description: >
|
|
804
|
+
The client sends only the offer, share mode, the render status of each selected
|
|
805
|
+
section, and the matched-period ROI chapter it printed. The server fills scope,
|
|
806
|
+
excluded repositories, windows, sources with freshness, consent,
|
|
807
|
+
`expectedRepositoryIds`, `soldWindowComplete`, `premiumAiAssessable`, and
|
|
808
|
+
tolerances from stored data, then runs the same fail-closed check as
|
|
809
|
+
`validateWorkspaceAssessmentManifest`.
|
|
810
|
+
|
|
811
|
+
|
|
812
|
+
Scope is the non-archived workspace repositories. Above 50 repositories or 500
|
|
813
|
+
active engineers fails (custom quote). For the premium offer, repositories without
|
|
814
|
+
merged pull requests in both matched windows are listed in `excluded` and left out
|
|
815
|
+
of scope. Baseline windows: `pre` is null, `post` is the 90 calendar days ending
|
|
816
|
+
yesterday (America/New_York), and `transitionDays` is 0. Premium windows come from
|
|
817
|
+
the confirmed rollout day. Freshness: source control 24 hours, AI usage 7 days,
|
|
818
|
+
readiness scans 30 days. Aggregate-use consent is reported as stored; no row is
|
|
819
|
+
`unset`.
|
|
820
|
+
|
|
821
|
+
|
|
822
|
+
`premiumAiAssessable` needs fresh Cursor, Claude, or Copilot usage in the post
|
|
823
|
+
window and complete matched-period evidence. A live ROI refusal for incomplete
|
|
824
|
+
data blocks validation (`rollout_unset`, `window_missing`,
|
|
825
|
+
`ship_weight_incomplete`, `active_engineers_unknown`, `confounder_inputs_missing`,
|
|
826
|
+
`normalization_unset`, `output_unit_mismatch`). A refusal that is a legitimate
|
|
827
|
+
result does not (`non_positive_output`, `confounder`, `missing_cost`,
|
|
828
|
+
`non_usd_cost`, `cost_not_attributable`); the report prints "not assessable" with
|
|
829
|
+
no figure. The premium `roi` tolerance is `unset` when the ROI section did not
|
|
830
|
+
render or `roi` is missing, `exceeded` when the printed chapter differs from the
|
|
831
|
+
server result (USD figures within the dictionary money tolerance), and `within`
|
|
832
|
+
otherwise. Named-person sections always fail.
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
Send `result.contentHash` with the PDF to `storeAssessmentReport`, which rebuilds
|
|
836
|
+
the manifest and stores only when it is still a validated internal buyer file
|
|
837
|
+
with the same hash.
|
|
838
|
+
|
|
839
|
+
|
|
840
|
+
**Authorization:** Bearer JWT required. Caller must be a workspace admin, or a
|
|
841
|
+
platform admin who is a member of this workspace. Members who are not workspace
|
|
842
|
+
admins receive 403. Non-members of an existing workspace receive 403. Unknown
|
|
843
|
+
workspaces receive 404.
|
|
844
|
+
parameters:
|
|
845
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
846
|
+
requestBody:
|
|
847
|
+
required: true
|
|
848
|
+
content:
|
|
849
|
+
application/json:
|
|
850
|
+
schema:
|
|
851
|
+
$ref: "#/components/schemas/BuildAssessmentManifestBodyDto"
|
|
852
|
+
responses:
|
|
853
|
+
"200":
|
|
854
|
+
description: Server-built manifest body and its validation result.
|
|
855
|
+
content:
|
|
856
|
+
application/json:
|
|
857
|
+
schema:
|
|
858
|
+
$ref: "#/components/schemas/BuildAssessmentManifestResponseDto"
|
|
859
|
+
"400":
|
|
860
|
+
description: Body failed validation.
|
|
861
|
+
content:
|
|
862
|
+
application/json:
|
|
863
|
+
schema:
|
|
864
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
865
|
+
example:
|
|
866
|
+
error: offerId is not a known assessment offer
|
|
867
|
+
code: invalid_body
|
|
868
|
+
"401":
|
|
869
|
+
$ref: "#/components/responses/Unauthorized"
|
|
870
|
+
"403":
|
|
871
|
+
description: Caller cannot build this workspace's manifest.
|
|
872
|
+
content:
|
|
873
|
+
application/json:
|
|
874
|
+
schema:
|
|
875
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
876
|
+
example:
|
|
877
|
+
error: Forbidden
|
|
878
|
+
code: workspace_admin_required
|
|
879
|
+
"404":
|
|
880
|
+
description: Workspace does not exist.
|
|
881
|
+
content:
|
|
882
|
+
application/json:
|
|
883
|
+
schema:
|
|
884
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
885
|
+
example:
|
|
886
|
+
error: Not found
|
|
887
|
+
"503":
|
|
888
|
+
description: Stored evidence could not be loaded (no database or a load failure).
|
|
889
|
+
content:
|
|
890
|
+
application/json:
|
|
891
|
+
schema:
|
|
892
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
893
|
+
example:
|
|
894
|
+
error: Service unavailable
|
|
895
|
+
code: evidence_unavailable
|
|
896
|
+
|
|
864
897
|
/admin/readiness/token-usage:
|
|
865
898
|
get:
|
|
866
899
|
tags: [PlatformAdmin]
|
|
@@ -7154,26 +7187,25 @@ paths:
|
|
|
7154
7187
|
schema:
|
|
7155
7188
|
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7156
7189
|
|
|
7157
|
-
/workspaces/{workspaceId}/
|
|
7190
|
+
/workspaces/{workspaceId}/assessment-rollout:
|
|
7158
7191
|
get:
|
|
7159
7192
|
tags: [Workspace]
|
|
7160
|
-
summary: Read
|
|
7161
|
-
operationId:
|
|
7193
|
+
summary: Read the customer-confirmed assessment rollout day
|
|
7194
|
+
operationId: getWorkspaceAssessmentRollout
|
|
7162
7195
|
description: >
|
|
7163
|
-
Returns
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
Any workspace member may read it.
|
|
7196
|
+
Returns the AI rollout day the customer confirmed for the Agentic AI ROI
|
|
7197
|
+
assessment, interpreted at 00:00 America/New_York, plus who set it and when.
|
|
7198
|
+
This is the only rollout source for the matched pre and post windows.
|
|
7199
|
+
`rolloutDay` is null until an admin sets it. Any workspace member may read it.
|
|
7168
7200
|
parameters:
|
|
7169
7201
|
- $ref: "#/components/parameters/WorkspaceId"
|
|
7170
7202
|
responses:
|
|
7171
7203
|
"200":
|
|
7172
|
-
description: Current
|
|
7204
|
+
description: Current rollout day
|
|
7173
7205
|
content:
|
|
7174
7206
|
application/json:
|
|
7175
7207
|
schema:
|
|
7176
|
-
$ref: "#/components/schemas/
|
|
7208
|
+
$ref: "#/components/schemas/AssessmentRolloutDto"
|
|
7177
7209
|
"401":
|
|
7178
7210
|
$ref: "#/components/responses/Unauthorized"
|
|
7179
7211
|
"403":
|
|
@@ -7184,17 +7216,21 @@ paths:
|
|
|
7184
7216
|
application/json:
|
|
7185
7217
|
schema:
|
|
7186
7218
|
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7219
|
+
"503":
|
|
7220
|
+
description: Rollout storage is not configured
|
|
7221
|
+
content:
|
|
7222
|
+
application/json:
|
|
7223
|
+
schema:
|
|
7224
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7187
7225
|
put:
|
|
7188
7226
|
tags: [Workspace]
|
|
7189
|
-
summary: Set
|
|
7190
|
-
operationId:
|
|
7227
|
+
summary: Set the customer-confirmed assessment rollout day
|
|
7228
|
+
operationId: putWorkspaceAssessmentRollout
|
|
7191
7229
|
description: >
|
|
7192
|
-
Workspace admins
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
approved, opt-in returns `409 aggregate_use_notice_unapproved`. Opt-out is always
|
|
7197
|
-
accepted. A refusal does not change price, delivery, support, or assessment output.
|
|
7230
|
+
Workspace admins, or platform admins who are workspace members, set the rollout
|
|
7231
|
+
day. The day must be a real calendar date that has already started in
|
|
7232
|
+
America/New_York. Each save records the caller and time and writes one
|
|
7233
|
+
`workspace.assessment_rollout.changed` activity-log row.
|
|
7198
7234
|
parameters:
|
|
7199
7235
|
- $ref: "#/components/parameters/WorkspaceId"
|
|
7200
7236
|
requestBody:
|
|
@@ -7202,16 +7238,16 @@ paths:
|
|
|
7202
7238
|
content:
|
|
7203
7239
|
application/json:
|
|
7204
7240
|
schema:
|
|
7205
|
-
$ref: "#/components/schemas/
|
|
7241
|
+
$ref: "#/components/schemas/AssessmentRolloutPutDto"
|
|
7206
7242
|
responses:
|
|
7207
7243
|
"200":
|
|
7208
|
-
description: Saved
|
|
7244
|
+
description: Saved rollout day
|
|
7209
7245
|
content:
|
|
7210
7246
|
application/json:
|
|
7211
7247
|
schema:
|
|
7212
|
-
$ref: "#/components/schemas/
|
|
7248
|
+
$ref: "#/components/schemas/AssessmentRolloutDto"
|
|
7213
7249
|
"400":
|
|
7214
|
-
description: "Invalid body (`code`: `invalid_input`)"
|
|
7250
|
+
description: "Invalid body, impossible date, or future day (`code`: `invalid_input`)"
|
|
7215
7251
|
content:
|
|
7216
7252
|
application/json:
|
|
7217
7253
|
schema:
|
|
@@ -7230,45 +7266,38 @@ paths:
|
|
|
7230
7266
|
application/json:
|
|
7231
7267
|
schema:
|
|
7232
7268
|
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7233
|
-
"
|
|
7234
|
-
description:
|
|
7235
|
-
Opt-in refused because no notice is approved (`aggregate_use_notice_unapproved`)
|
|
7236
|
-
or the submitted notice version is not current (`aggregate_use_notice_stale`).
|
|
7269
|
+
"503":
|
|
7270
|
+
description: Rollout storage is not configured
|
|
7237
7271
|
content:
|
|
7238
7272
|
application/json:
|
|
7239
7273
|
schema:
|
|
7240
7274
|
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7241
7275
|
|
|
7242
|
-
/workspaces/{workspaceId}/
|
|
7243
|
-
|
|
7244
|
-
tags: [
|
|
7245
|
-
summary:
|
|
7246
|
-
operationId:
|
|
7276
|
+
/workspaces/{workspaceId}/assessment-roi:
|
|
7277
|
+
get:
|
|
7278
|
+
tags: [Workspace]
|
|
7279
|
+
summary: Read the matched-period ROI from stored evidence
|
|
7280
|
+
operationId: getWorkspaceAssessmentRoi
|
|
7247
7281
|
description: >
|
|
7248
|
-
|
|
7249
|
-
|
|
7250
|
-
|
|
7282
|
+
Derives the 90-day pre window, the 14-day transition, and the 90-day post
|
|
7283
|
+
window from the confirmed rollout day, then loads calendar-day coverage,
|
|
7284
|
+
merged pull request Ship Weight per window, and recorded USD AI spend for the
|
|
7285
|
+
post window. The figure is USD cost per incremental normalized Ship Weight
|
|
7286
|
+
(per active engineer and Mon–Fri America/New_York working day). Fails closed:
|
|
7287
|
+
`status` is `not_assessable` with a `reason` when a window is incomplete, cost
|
|
7288
|
+
is missing, non-USD, or not attributable by day, Ship Weight is unscored,
|
|
7289
|
+
active engineers are not countable, incremental output is not positive, or a
|
|
7290
|
+
confounder is flagged or cannot be checked. Cost is never estimated. Any
|
|
7291
|
+
workspace member may read it.
|
|
7251
7292
|
parameters:
|
|
7252
7293
|
- $ref: "#/components/parameters/WorkspaceId"
|
|
7253
|
-
requestBody:
|
|
7254
|
-
required: true
|
|
7255
|
-
content:
|
|
7256
|
-
application/json:
|
|
7257
|
-
schema:
|
|
7258
|
-
$ref: "#/components/schemas/ReportCenterExportRecordBodyDto"
|
|
7259
7294
|
responses:
|
|
7260
|
-
"
|
|
7261
|
-
description:
|
|
7262
|
-
content:
|
|
7263
|
-
application/json:
|
|
7264
|
-
schema:
|
|
7265
|
-
$ref: "#/components/schemas/ReportCenterExportRecordResponseDto"
|
|
7266
|
-
"400":
|
|
7267
|
-
description: Invalid body
|
|
7295
|
+
"200":
|
|
7296
|
+
description: Matched-period ROI result
|
|
7268
7297
|
content:
|
|
7269
7298
|
application/json:
|
|
7270
7299
|
schema:
|
|
7271
|
-
$ref: "#/components/schemas/
|
|
7300
|
+
$ref: "#/components/schemas/AssessmentRoiDto"
|
|
7272
7301
|
"401":
|
|
7273
7302
|
$ref: "#/components/responses/Unauthorized"
|
|
7274
7303
|
"403":
|
|
@@ -7279,37 +7308,521 @@ paths:
|
|
|
7279
7308
|
application/json:
|
|
7280
7309
|
schema:
|
|
7281
7310
|
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7282
|
-
"
|
|
7283
|
-
description:
|
|
7311
|
+
"503":
|
|
7312
|
+
description: Evidence storage is not configured or could not be read
|
|
7284
7313
|
content:
|
|
7285
7314
|
application/json:
|
|
7286
7315
|
schema:
|
|
7287
7316
|
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7288
7317
|
|
|
7289
|
-
/workspaces/{workspaceId}/
|
|
7318
|
+
/workspaces/{workspaceId}/aggregate-use-consent:
|
|
7290
7319
|
get:
|
|
7291
|
-
tags: [
|
|
7292
|
-
summary:
|
|
7293
|
-
operationId:
|
|
7320
|
+
tags: [Workspace]
|
|
7321
|
+
summary: Read anonymized aggregate-use permission
|
|
7322
|
+
operationId: getAggregateUseConsent
|
|
7294
7323
|
description: >
|
|
7295
|
-
|
|
7296
|
-
and
|
|
7297
|
-
|
|
7298
|
-
|
|
7299
|
-
|
|
7324
|
+
Returns whether ThinkAI may use this workspace's anonymized aggregate results in
|
|
7325
|
+
marketing and peer benchmarks. A workspace that never chose returns `unset`, which
|
|
7326
|
+
behaves as opted out (`effective: false`). The permission never covers company name,
|
|
7327
|
+
logo, quote, raw report, repository or person identity, or customer reference.
|
|
7328
|
+
Any workspace member may read it.
|
|
7300
7329
|
parameters:
|
|
7301
7330
|
- $ref: "#/components/parameters/WorkspaceId"
|
|
7302
|
-
|
|
7303
|
-
|
|
7304
|
-
|
|
7305
|
-
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7331
|
+
responses:
|
|
7332
|
+
"200":
|
|
7333
|
+
description: Current permission and the sentence reports must print
|
|
7334
|
+
content:
|
|
7335
|
+
application/json:
|
|
7336
|
+
schema:
|
|
7337
|
+
$ref: "#/components/schemas/AggregateUseConsentDto"
|
|
7338
|
+
"401":
|
|
7339
|
+
$ref: "#/components/responses/Unauthorized"
|
|
7340
|
+
"403":
|
|
7341
|
+
$ref: "#/components/responses/Forbidden"
|
|
7342
|
+
"404":
|
|
7343
|
+
description: Workspace does not exist
|
|
7344
|
+
content:
|
|
7345
|
+
application/json:
|
|
7346
|
+
schema:
|
|
7347
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7348
|
+
put:
|
|
7349
|
+
tags: [Workspace]
|
|
7350
|
+
summary: Set anonymized aggregate-use permission
|
|
7351
|
+
operationId: putAggregateUseConsent
|
|
7352
|
+
description: >
|
|
7353
|
+
Workspace admins opt in or out. Every change writes one
|
|
7354
|
+
`workspace.aggregate_use.changed` activity-log row in the same transaction.
|
|
7355
|
+
Moving from `opt_in` to `opt_out` records a withdrawal and stops future extraction.
|
|
7356
|
+
Opt-in requires the current legal-approved notice version; while no notice is
|
|
7357
|
+
approved, opt-in returns `409 aggregate_use_notice_unapproved`. Opt-out is always
|
|
7358
|
+
accepted. A refusal does not change price, delivery, support, or assessment output.
|
|
7359
|
+
parameters:
|
|
7360
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
7361
|
+
requestBody:
|
|
7362
|
+
required: true
|
|
7363
|
+
content:
|
|
7364
|
+
application/json:
|
|
7365
|
+
schema:
|
|
7366
|
+
$ref: "#/components/schemas/AggregateUseConsentPutDto"
|
|
7367
|
+
responses:
|
|
7368
|
+
"200":
|
|
7369
|
+
description: Saved permission
|
|
7370
|
+
content:
|
|
7371
|
+
application/json:
|
|
7372
|
+
schema:
|
|
7373
|
+
$ref: "#/components/schemas/AggregateUseConsentDto"
|
|
7374
|
+
"400":
|
|
7375
|
+
description: "Invalid body (`code`: `invalid_input`)"
|
|
7376
|
+
content:
|
|
7377
|
+
application/json:
|
|
7378
|
+
schema:
|
|
7379
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7380
|
+
"401":
|
|
7381
|
+
$ref: "#/components/responses/Unauthorized"
|
|
7382
|
+
"403":
|
|
7383
|
+
description: "Caller is not a workspace admin (`code`: `workspace_admin_required`)"
|
|
7384
|
+
content:
|
|
7385
|
+
application/json:
|
|
7386
|
+
schema:
|
|
7387
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7388
|
+
"404":
|
|
7389
|
+
description: Workspace does not exist
|
|
7390
|
+
content:
|
|
7391
|
+
application/json:
|
|
7392
|
+
schema:
|
|
7393
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7394
|
+
"409":
|
|
7395
|
+
description: >
|
|
7396
|
+
Opt-in refused because no notice is approved (`aggregate_use_notice_unapproved`)
|
|
7397
|
+
or the submitted notice version is not current (`aggregate_use_notice_stale`).
|
|
7398
|
+
content:
|
|
7399
|
+
application/json:
|
|
7400
|
+
schema:
|
|
7401
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7402
|
+
|
|
7403
|
+
/workspaces/{workspaceId}/report-center/exports:
|
|
7404
|
+
post:
|
|
7405
|
+
tags: [WorkspaceActivity]
|
|
7406
|
+
summary: Record a Report Center PDF export
|
|
7407
|
+
operationId: recordReportCenterExport
|
|
7408
|
+
description: >
|
|
7409
|
+
Workspace admin (or platform admin) records that a Report Center PDF was downloaded.
|
|
7410
|
+
Inserts one `report.exported` activity-log row with the request body as secret-free metadata.
|
|
7411
|
+
Does not store PDF bytes. Members who are not workspace admins receive 403.
|
|
7412
|
+
parameters:
|
|
7413
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
7414
|
+
requestBody:
|
|
7415
|
+
required: true
|
|
7416
|
+
content:
|
|
7417
|
+
application/json:
|
|
7418
|
+
schema:
|
|
7419
|
+
$ref: "#/components/schemas/ReportCenterExportRecordBodyDto"
|
|
7420
|
+
responses:
|
|
7421
|
+
"201":
|
|
7422
|
+
description: Export recorded
|
|
7423
|
+
content:
|
|
7424
|
+
application/json:
|
|
7425
|
+
schema:
|
|
7426
|
+
$ref: "#/components/schemas/ReportCenterExportRecordResponseDto"
|
|
7427
|
+
"400":
|
|
7428
|
+
description: Invalid body
|
|
7429
|
+
content:
|
|
7430
|
+
application/json:
|
|
7431
|
+
schema:
|
|
7432
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7433
|
+
"401":
|
|
7434
|
+
$ref: "#/components/responses/Unauthorized"
|
|
7435
|
+
"403":
|
|
7436
|
+
$ref: "#/components/responses/Forbidden"
|
|
7437
|
+
"404":
|
|
7438
|
+
description: Workspace does not exist
|
|
7439
|
+
content:
|
|
7440
|
+
application/json:
|
|
7441
|
+
schema:
|
|
7442
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7443
|
+
"501":
|
|
7444
|
+
description: Activity log is not supported by this backend build
|
|
7445
|
+
content:
|
|
7446
|
+
application/json:
|
|
7447
|
+
schema:
|
|
7448
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7449
|
+
|
|
7450
|
+
/workspaces/{workspaceId}/assessment-reports:
|
|
7451
|
+
get:
|
|
7452
|
+
tags: [AssessmentReports]
|
|
7453
|
+
summary: List stored assessment reports and their secure links
|
|
7454
|
+
operationId: listAssessmentReports
|
|
7455
|
+
description: >
|
|
7456
|
+
Workspace admin (or platform admin who is a workspace member). Lists stored buyer PDFs
|
|
7457
|
+
(metadata only, never bytes) with every secure link grant. Link tokens and token hashes are
|
|
7458
|
+
never returned. A hidden report stays listed: `hidden_restorable` until `restoreUntil`,
|
|
7459
|
+
then `restore_window_ended`. The restore window is restore capability, not erasure.
|
|
7460
|
+
Responses carry `Cache-Control: no-store`.
|
|
7461
|
+
parameters:
|
|
7462
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
7463
|
+
responses:
|
|
7464
|
+
"200":
|
|
7465
|
+
description: Stored reports, newest first
|
|
7466
|
+
content:
|
|
7467
|
+
application/json:
|
|
7468
|
+
schema:
|
|
7469
|
+
$ref: "#/components/schemas/AssessmentReportListDto"
|
|
7470
|
+
"401":
|
|
7471
|
+
$ref: "#/components/responses/Unauthorized"
|
|
7472
|
+
"403":
|
|
7473
|
+
$ref: "#/components/responses/Forbidden"
|
|
7474
|
+
"404":
|
|
7475
|
+
description: Workspace does not exist
|
|
7476
|
+
content:
|
|
7477
|
+
application/json:
|
|
7478
|
+
schema:
|
|
7479
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7480
|
+
"501":
|
|
7481
|
+
description: Stored reports are not supported by this backend build (no database)
|
|
7482
|
+
content:
|
|
7483
|
+
application/json:
|
|
7484
|
+
schema:
|
|
7485
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7486
|
+
post:
|
|
7487
|
+
tags: [AssessmentReports]
|
|
7488
|
+
summary: Store a validated buyer PDF for secure delivery
|
|
7489
|
+
operationId: storeAssessmentReport
|
|
7490
|
+
description: >
|
|
7491
|
+
Workspace admin (or platform admin who is a workspace member). The client never supplies
|
|
7492
|
+
evidence: the server rebuilds the manifest from stored data with the same builder as
|
|
7493
|
+
`buildWorkspaceAssessmentManifest`, using only `build` (offer, share mode, section
|
|
7494
|
+
status, printed ROI), and stores the PDF only when `buyerDeliverable` is true (validated
|
|
7495
|
+
and internal) and the rebuilt `contentHash` equals the one sent. An external
|
|
7496
|
+
share-safe file is never stored here. The PDF is encrypted with AES-256-GCM and kept in
|
|
7497
|
+
Postgres with its sha256; it is limited to 10 MiB. Records `report.assessment_stored`
|
|
7498
|
+
without report content.
|
|
7499
|
+
parameters:
|
|
7500
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
7501
|
+
requestBody:
|
|
7502
|
+
required: true
|
|
7503
|
+
content:
|
|
7504
|
+
application/json:
|
|
7505
|
+
schema:
|
|
7506
|
+
$ref: "#/components/schemas/StoreAssessmentReportBodyDto"
|
|
7507
|
+
responses:
|
|
7508
|
+
"201":
|
|
7509
|
+
description: Report stored
|
|
7510
|
+
content:
|
|
7511
|
+
application/json:
|
|
7512
|
+
schema:
|
|
7513
|
+
$ref: "#/components/schemas/AssessmentReportDto"
|
|
7514
|
+
"400":
|
|
7515
|
+
description: Body is not valid, or the file is not a PDF or is too large
|
|
7516
|
+
content:
|
|
7517
|
+
application/json:
|
|
7518
|
+
schema:
|
|
7519
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7520
|
+
"401":
|
|
7521
|
+
$ref: "#/components/responses/Unauthorized"
|
|
7522
|
+
"403":
|
|
7523
|
+
$ref: "#/components/responses/Forbidden"
|
|
7524
|
+
"404":
|
|
7525
|
+
description: Workspace does not exist
|
|
7526
|
+
content:
|
|
7527
|
+
application/json:
|
|
7528
|
+
schema:
|
|
7529
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7530
|
+
"422":
|
|
7531
|
+
description: >
|
|
7532
|
+
`not_buyer_deliverable` (the rebuilt manifest did not validate as an internal buyer
|
|
7533
|
+
file; includes `reasons`) or `manifest_changed` (stored evidence changed since the PDF
|
|
7534
|
+
was built, so `contentHash` differs; export again).
|
|
7535
|
+
content:
|
|
7536
|
+
application/json:
|
|
7537
|
+
schema:
|
|
7538
|
+
$ref: "#/components/schemas/StoreAssessmentReportRejectedDto"
|
|
7539
|
+
"503":
|
|
7540
|
+
description: Stored evidence could not be loaded to rebuild the manifest.
|
|
7541
|
+
content:
|
|
7542
|
+
application/json:
|
|
7543
|
+
schema:
|
|
7544
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7545
|
+
"501":
|
|
7546
|
+
description: Stored reports are not supported by this backend build (no database)
|
|
7547
|
+
content:
|
|
7548
|
+
application/json:
|
|
7549
|
+
schema:
|
|
7550
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7551
|
+
|
|
7552
|
+
/workspaces/{workspaceId}/assessment-reports/{reportId}/links:
|
|
7553
|
+
post:
|
|
7554
|
+
tags: [AssessmentReports]
|
|
7555
|
+
summary: Create a secure link and email it to a workspace member
|
|
7556
|
+
operationId: createAssessmentReportLink
|
|
7557
|
+
description: >
|
|
7558
|
+
Workspace admin (or platform admin who is a workspace member). Creates one link grant for a
|
|
7559
|
+
current workspace member and emails them the link only: generic text and
|
|
7560
|
+
`{siteUrl}/reports/secure?t=<opaque token>`. The email carries no PDF attachment, report
|
|
7561
|
+
name, metrics, repository, or person names. Only the sha256 of the token is stored and the
|
|
7562
|
+
token is never returned. Expiry defaults to 14 days and can be shorter. When SMTP is not
|
|
7563
|
+
configured the grant still stands and `email` says why it was skipped. Hidden reports
|
|
7564
|
+
cannot be shared (`409 report_hidden`).
|
|
7565
|
+
parameters:
|
|
7566
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
7567
|
+
- $ref: "#/components/parameters/AssessmentReportId"
|
|
7568
|
+
requestBody:
|
|
7569
|
+
required: true
|
|
7570
|
+
content:
|
|
7571
|
+
application/json:
|
|
7572
|
+
schema:
|
|
7573
|
+
$ref: "#/components/schemas/CreateAssessmentReportLinkBodyDto"
|
|
7574
|
+
responses:
|
|
7575
|
+
"201":
|
|
7576
|
+
description: Link created
|
|
7577
|
+
content:
|
|
7578
|
+
application/json:
|
|
7579
|
+
schema:
|
|
7580
|
+
$ref: "#/components/schemas/CreateAssessmentReportLinkResponseDto"
|
|
7581
|
+
"400":
|
|
7582
|
+
description: Body is not valid
|
|
7583
|
+
content:
|
|
7584
|
+
application/json:
|
|
7585
|
+
schema:
|
|
7586
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7587
|
+
"401":
|
|
7588
|
+
$ref: "#/components/responses/Unauthorized"
|
|
7589
|
+
"403":
|
|
7590
|
+
$ref: "#/components/responses/Forbidden"
|
|
7591
|
+
"404":
|
|
7592
|
+
description: Workspace or report not found (`report_not_found`)
|
|
7593
|
+
content:
|
|
7594
|
+
application/json:
|
|
7595
|
+
schema:
|
|
7596
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7597
|
+
"409":
|
|
7598
|
+
description: The report is hidden (`report_hidden`)
|
|
7599
|
+
content:
|
|
7600
|
+
application/json:
|
|
7601
|
+
schema:
|
|
7602
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7603
|
+
"422":
|
|
7604
|
+
description: The recipient is not a current workspace member (`recipient_not_member`)
|
|
7605
|
+
content:
|
|
7606
|
+
application/json:
|
|
7607
|
+
schema:
|
|
7608
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7609
|
+
"501":
|
|
7610
|
+
description: Stored reports or member listing are not supported by this backend build
|
|
7611
|
+
content:
|
|
7612
|
+
application/json:
|
|
7613
|
+
schema:
|
|
7614
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7615
|
+
|
|
7616
|
+
/workspaces/{workspaceId}/assessment-reports/{reportId}/links/{grantId}/revoke:
|
|
7617
|
+
post:
|
|
7618
|
+
tags: [AssessmentReports]
|
|
7619
|
+
summary: Revoke a secure link
|
|
7620
|
+
operationId: revokeAssessmentReportLink
|
|
7621
|
+
description: >
|
|
7622
|
+
Workspace admin (or platform admin who is a workspace member). The link stops working
|
|
7623
|
+
immediately. Idempotent: revoking again keeps the first `revokedAt`. Revoking a link does
|
|
7624
|
+
not affect a file the recipient already downloaded. Records `report.assessment_link_revoked`.
|
|
7625
|
+
parameters:
|
|
7626
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
7627
|
+
- $ref: "#/components/parameters/AssessmentReportId"
|
|
7628
|
+
- name: grantId
|
|
7629
|
+
in: path
|
|
7630
|
+
required: true
|
|
7631
|
+
schema:
|
|
7632
|
+
type: string
|
|
7633
|
+
format: uuid
|
|
7634
|
+
responses:
|
|
7635
|
+
"200":
|
|
7636
|
+
description: Revoked link
|
|
7637
|
+
content:
|
|
7638
|
+
application/json:
|
|
7639
|
+
schema:
|
|
7640
|
+
$ref: "#/components/schemas/AssessmentReportLinkDto"
|
|
7641
|
+
"401":
|
|
7642
|
+
$ref: "#/components/responses/Unauthorized"
|
|
7643
|
+
"403":
|
|
7644
|
+
$ref: "#/components/responses/Forbidden"
|
|
7645
|
+
"404":
|
|
7646
|
+
description: Workspace, report, or link not found
|
|
7647
|
+
content:
|
|
7648
|
+
application/json:
|
|
7649
|
+
schema:
|
|
7650
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7651
|
+
"501":
|
|
7652
|
+
description: Stored reports are not supported by this backend build (no database)
|
|
7653
|
+
content:
|
|
7654
|
+
application/json:
|
|
7655
|
+
schema:
|
|
7656
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7657
|
+
|
|
7658
|
+
/workspaces/{workspaceId}/assessment-reports/{reportId}/hide:
|
|
7659
|
+
post:
|
|
7660
|
+
tags: [AssessmentReports]
|
|
7661
|
+
summary: Hide a stored report
|
|
7662
|
+
operationId: hideAssessmentReport
|
|
7663
|
+
description: >
|
|
7664
|
+
Workspace admin (or platform admin who is a workspace member). Same semantics as workspace
|
|
7665
|
+
delete: the report is hidden immediately and every link stops downloading. It can be
|
|
7666
|
+
restored for 30 days (`restoreUntil`). That window is restore capability, not erasure; no
|
|
7667
|
+
backup purge date is promised, and a file the buyer already downloaded stays with them.
|
|
7668
|
+
Idempotent. Records `report.assessment_hidden`.
|
|
7669
|
+
parameters:
|
|
7670
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
7671
|
+
- $ref: "#/components/parameters/AssessmentReportId"
|
|
7672
|
+
responses:
|
|
7673
|
+
"200":
|
|
7674
|
+
description: Hidden report (`links` is empty in this response; list again for links)
|
|
7675
|
+
content:
|
|
7676
|
+
application/json:
|
|
7677
|
+
schema:
|
|
7678
|
+
$ref: "#/components/schemas/AssessmentReportDto"
|
|
7679
|
+
"401":
|
|
7680
|
+
$ref: "#/components/responses/Unauthorized"
|
|
7681
|
+
"403":
|
|
7682
|
+
$ref: "#/components/responses/Forbidden"
|
|
7683
|
+
"404":
|
|
7684
|
+
description: Workspace or report not found
|
|
7685
|
+
content:
|
|
7686
|
+
application/json:
|
|
7687
|
+
schema:
|
|
7688
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7689
|
+
"501":
|
|
7690
|
+
description: Stored reports are not supported by this backend build (no database)
|
|
7691
|
+
content:
|
|
7692
|
+
application/json:
|
|
7693
|
+
schema:
|
|
7694
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7695
|
+
|
|
7696
|
+
/workspaces/{workspaceId}/assessment-reports/{reportId}/restore:
|
|
7697
|
+
post:
|
|
7698
|
+
tags: [AssessmentReports]
|
|
7699
|
+
summary: Restore a hidden report within the 30-day window
|
|
7700
|
+
operationId: restoreAssessmentReport
|
|
7701
|
+
description: >
|
|
7702
|
+
Workspace admin (or platform admin who is a workspace member). Allowed only before
|
|
7703
|
+
`restoreUntil`; afterwards it fails with `409 restore_window_ended`. Links that were not
|
|
7704
|
+
revoked or expired work again after restore. Records `report.assessment_restored`.
|
|
7705
|
+
parameters:
|
|
7706
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
7707
|
+
- $ref: "#/components/parameters/AssessmentReportId"
|
|
7708
|
+
responses:
|
|
7709
|
+
"200":
|
|
7710
|
+
description: Restored report (`links` is empty in this response; list again for links)
|
|
7711
|
+
content:
|
|
7712
|
+
application/json:
|
|
7713
|
+
schema:
|
|
7714
|
+
$ref: "#/components/schemas/AssessmentReportDto"
|
|
7715
|
+
"401":
|
|
7716
|
+
$ref: "#/components/responses/Unauthorized"
|
|
7717
|
+
"403":
|
|
7718
|
+
$ref: "#/components/responses/Forbidden"
|
|
7719
|
+
"404":
|
|
7720
|
+
description: Workspace or report not found
|
|
7721
|
+
content:
|
|
7722
|
+
application/json:
|
|
7723
|
+
schema:
|
|
7724
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7725
|
+
"409":
|
|
7726
|
+
description: "`not_hidden` or `restore_window_ended`"
|
|
7727
|
+
content:
|
|
7728
|
+
application/json:
|
|
7729
|
+
schema:
|
|
7730
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7731
|
+
"501":
|
|
7732
|
+
description: Stored reports are not supported by this backend build (no database)
|
|
7733
|
+
content:
|
|
7734
|
+
application/json:
|
|
7735
|
+
schema:
|
|
7736
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7737
|
+
|
|
7738
|
+
/assessment-reports/secure:
|
|
7739
|
+
get:
|
|
7740
|
+
tags: [AssessmentReports]
|
|
7741
|
+
summary: Download a stored report through a secure link
|
|
7742
|
+
operationId: downloadAssessmentReport
|
|
7743
|
+
description: >
|
|
7744
|
+
Bearer JWT required. The caller must be the link recipient and a current member of the
|
|
7745
|
+
report's workspace. Access follows `decideReportAccess`: `leaked_token`, `removed_member`,
|
|
7746
|
+
and `wrong_workspace` answer 403; `expired` and `revoked` answer 410; `invalid_grant`
|
|
7747
|
+
answers 404. A hidden report answers `410 report_hidden`. Every response carries
|
|
7748
|
+
`Cache-Control: no-store`. Records `report.assessment_downloaded` without report content.
|
|
7749
|
+
parameters:
|
|
7750
|
+
- name: t
|
|
7751
|
+
in: query
|
|
7752
|
+
required: true
|
|
7753
|
+
description: Opaque link token from the email (`secureLinkQuery`).
|
|
7754
|
+
schema:
|
|
7755
|
+
type: string
|
|
7756
|
+
responses:
|
|
7757
|
+
"200":
|
|
7758
|
+
description: The decrypted PDF
|
|
7759
|
+
headers:
|
|
7760
|
+
Cache-Control:
|
|
7761
|
+
schema:
|
|
7762
|
+
type: string
|
|
7763
|
+
enum: [no-store]
|
|
7764
|
+
content:
|
|
7765
|
+
application/pdf:
|
|
7766
|
+
schema:
|
|
7767
|
+
type: string
|
|
7768
|
+
format: binary
|
|
7769
|
+
"401":
|
|
7770
|
+
$ref: "#/components/responses/Unauthorized"
|
|
7771
|
+
"403":
|
|
7772
|
+
description: "`leaked_token`, `removed_member`, or `wrong_workspace`"
|
|
7773
|
+
content:
|
|
7774
|
+
application/json:
|
|
7775
|
+
schema:
|
|
7776
|
+
$ref: "#/components/schemas/AssessmentReportAccessErrorDto"
|
|
7777
|
+
"404":
|
|
7778
|
+
description: "`invalid_grant`"
|
|
7779
|
+
content:
|
|
7780
|
+
application/json:
|
|
7781
|
+
schema:
|
|
7782
|
+
$ref: "#/components/schemas/AssessmentReportAccessErrorDto"
|
|
7783
|
+
"410":
|
|
7784
|
+
description: "`expired`, `revoked`, or `report_hidden`"
|
|
7785
|
+
content:
|
|
7786
|
+
application/json:
|
|
7787
|
+
schema:
|
|
7788
|
+
$ref: "#/components/schemas/AssessmentReportAccessErrorDto"
|
|
7789
|
+
"500":
|
|
7790
|
+
description: The stored report could not be decrypted (`report_unreadable`)
|
|
7791
|
+
content:
|
|
7792
|
+
application/json:
|
|
7793
|
+
schema:
|
|
7794
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7795
|
+
"501":
|
|
7796
|
+
description: Stored reports are not supported by this backend build (no database)
|
|
7797
|
+
content:
|
|
7798
|
+
application/json:
|
|
7799
|
+
schema:
|
|
7800
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
7801
|
+
|
|
7802
|
+
/workspaces/{workspaceId}/activity:
|
|
7803
|
+
get:
|
|
7804
|
+
tags: [WorkspaceActivity]
|
|
7805
|
+
summary: Workspace activity log (paginated)
|
|
7806
|
+
operationId: listWorkspaceActivity
|
|
7807
|
+
description: >
|
|
7808
|
+
Paginated, chronological feed of workspace-scoped lifecycle events: repository add/remove/re-add
|
|
7809
|
+
and GitHub integration add/remove. Inactive repos remain visible in this log.
|
|
7810
|
+
Filter by a single `eventType`, a coarse `eventCategory`/`productArea`, an `eventSubcategory`
|
|
7811
|
+
(a dotted event-type prefix that matches a whole lifecycle subgroup in one call, e.g.
|
|
7812
|
+
`integrations.cursor.execution_key`), `actorUserId`, or date range (`since`/`until`).
|
|
7813
|
+
parameters:
|
|
7814
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
7815
|
+
- $ref: "#/components/parameters/PaginationLimit"
|
|
7816
|
+
- $ref: "#/components/parameters/PaginationOffset"
|
|
7817
|
+
- $ref: "#/components/parameters/PaginationOrder"
|
|
7818
|
+
- name: sort
|
|
7819
|
+
in: query
|
|
7820
|
+
required: false
|
|
7821
|
+
description: >
|
|
7822
|
+
Server-side sort column (the activity "5 W's"). Combined with `order` (asc/desc).
|
|
7823
|
+
Defaults to `when` (occurredAt). `occurredAt`/`id` is always the tiebreaker.
|
|
7824
|
+
schema:
|
|
7825
|
+
type: string
|
|
7313
7826
|
enum: [when, who, what, why, where]
|
|
7314
7827
|
- name: productArea
|
|
7315
7828
|
in: query
|
|
@@ -9154,7 +9667,10 @@ paths:
|
|
|
9154
9667
|
description: >
|
|
9155
9668
|
Any workspace member when chat is ready. Validates size/type against the active
|
|
9156
9669
|
provider profile (`attachmentLimits` from readiness). Returns metadata; pass `id`
|
|
9157
|
-
as `attachmentIds` on the next POST message. Max 5 MB per file
|
|
9670
|
+
as `attachmentIds` on the next POST message. Max 5 MB per file (JSON bodyLimit is
|
|
9671
|
+
raised for `contentBase64`). When unbound uploads already sit at the per-message
|
|
9672
|
+
file cap (e.g. after an aborted send), the oldest unbound rows are pruned so a new
|
|
9673
|
+
attach can proceed.
|
|
9158
9674
|
operationId: postCodeChatAttachment
|
|
9159
9675
|
x-test-coverage-skip: thin HTTP over validateAttachment + store insert
|
|
9160
9676
|
parameters:
|
|
@@ -9173,7 +9689,11 @@ paths:
|
|
|
9173
9689
|
schema:
|
|
9174
9690
|
$ref: "#/components/schemas/CodeChatAttachmentMetaDto"
|
|
9175
9691
|
"400":
|
|
9176
|
-
description:
|
|
9692
|
+
description: >
|
|
9693
|
+
Validation failed after decode (size, type, totals). Stable codes include
|
|
9694
|
+
`attachment_too_large`, `attachment_total_too_large`, `attachment_too_many`,
|
|
9695
|
+
`attachment_type_unsupported`, `attachment_pdf_too_long`, `attachment_failed`,
|
|
9696
|
+
`invalid_input`.
|
|
9177
9697
|
content:
|
|
9178
9698
|
application/json:
|
|
9179
9699
|
schema:
|
|
@@ -9192,6 +9712,19 @@ paths:
|
|
|
9192
9712
|
application/json:
|
|
9193
9713
|
schema:
|
|
9194
9714
|
$ref: "#/components/schemas/ErrorMessageDto"
|
|
9715
|
+
"413":
|
|
9716
|
+
description: >
|
|
9717
|
+
Fastify rejected the JSON body before the handler (`request_body_too_large`).
|
|
9718
|
+
Typical when `contentBase64` exceeds the route bodyLimit (aligned with the
|
|
9719
|
+
5 MB per-file cap after base64 expansion). Decoded-size overruns still return
|
|
9720
|
+
`400` `attachment_too_large`.
|
|
9721
|
+
content:
|
|
9722
|
+
application/json:
|
|
9723
|
+
schema:
|
|
9724
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
9725
|
+
example:
|
|
9726
|
+
error: Request body is too large.
|
|
9727
|
+
code: request_body_too_large
|
|
9195
9728
|
"422":
|
|
9196
9729
|
description: Could not process the file
|
|
9197
9730
|
content:
|
|
@@ -10969,7 +11502,7 @@ paths:
|
|
|
10969
11502
|
derives teams client-side and saves the org structure via `POST /workspaces/{workspaceId}/org-chart`.
|
|
10970
11503
|
Required columns: employee_id, name, email, title, department, team, manager_id, location.
|
|
10971
11504
|
Optional: github_username (GitHub login for productivity ingest), bitbucket_nickname,
|
|
10972
|
-
bitbucket_uuid, alternate_emails (comma-separated alternate work emails for AI tool spend
|
|
11505
|
+
bitbucket_uuid, gitlab_username (GitLab.com or self-managed username), alternate_emails (comma-separated alternate work emails for AI tool spend
|
|
10973
11506
|
attribution). Saving the SPA snapshot also materializes a scoring `org_chart` tree for
|
|
10974
11507
|
team/person metrics when import members are present. Parse-only responses may include
|
|
10975
11508
|
duplicateEmailWarnings, identityEmailPreview (cross-check against connected AI tool seat
|
|
@@ -11985,6 +12518,106 @@ paths:
|
|
|
11985
12518
|
"403":
|
|
11986
12519
|
$ref: "#/components/responses/Forbidden"
|
|
11987
12520
|
|
|
12521
|
+
/workspaces/{workspaceId}/sources/discover:
|
|
12522
|
+
post:
|
|
12523
|
+
tags: [Workspace]
|
|
12524
|
+
summary: List repositories a GitLab or Bitbucket source can read (does not persist)
|
|
12525
|
+
description: >
|
|
12526
|
+
Lists projects (GitLab.com, self-managed GitLab) or repositories (Bitbucket Cloud,
|
|
12527
|
+
Bitbucket Data Center) for repository selection. Nothing is stored. Self-managed and
|
|
12528
|
+
Data Center `baseUrl` must be `https`, public, and without credentials; private,
|
|
12529
|
+
loopback, and link-local hosts are rejected before any request. `env:` token
|
|
12530
|
+
references are rejected for self-hosted providers and never resolved from the request
|
|
12531
|
+
for cloud providers. A blank or `***` token reuses the stored source with the same
|
|
12532
|
+
provider, host, and account, and requires the editor or admin role. The list covers
|
|
12533
|
+
the whole account (group or workspace/project key), not only `projects`/`repos`.
|
|
12534
|
+
`repoCap` is the standard repository cap (50); ingest refuses to auto-select more
|
|
12535
|
+
than that. Tokens are never returned.
|
|
12536
|
+
operationId: postWorkspaceVcsRepoDiscovery
|
|
12537
|
+
parameters:
|
|
12538
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
12539
|
+
requestBody:
|
|
12540
|
+
required: true
|
|
12541
|
+
content:
|
|
12542
|
+
application/json:
|
|
12543
|
+
schema:
|
|
12544
|
+
$ref: "#/components/schemas/GitVcsSourceDto"
|
|
12545
|
+
examples:
|
|
12546
|
+
gitlabSelfManaged:
|
|
12547
|
+
summary: Self-managed GitLab group
|
|
12548
|
+
value:
|
|
12549
|
+
type: gitlab
|
|
12550
|
+
deployment: self_managed
|
|
12551
|
+
baseUrl: https://gitlab.example.com
|
|
12552
|
+
group: platform
|
|
12553
|
+
token: glpat-example
|
|
12554
|
+
bitbucketDataCenter:
|
|
12555
|
+
summary: Bitbucket Data Center project
|
|
12556
|
+
value:
|
|
12557
|
+
type: bitbucket
|
|
12558
|
+
deployment: data_center
|
|
12559
|
+
baseUrl: https://bitbucket.example.com
|
|
12560
|
+
workspace: PLAT
|
|
12561
|
+
token: "***"
|
|
12562
|
+
responses:
|
|
12563
|
+
"200":
|
|
12564
|
+
description: Repositories the source can read
|
|
12565
|
+
content:
|
|
12566
|
+
application/json:
|
|
12567
|
+
schema:
|
|
12568
|
+
$ref: "#/components/schemas/VcsRepoDiscoveryResponseDto"
|
|
12569
|
+
"400":
|
|
12570
|
+
description: >
|
|
12571
|
+
Invalid source (`error` is a code such as `base_url_required`, `base_url_invalid`,
|
|
12572
|
+
`base_url_not_https`, `base_url_has_credentials`, `base_url_has_path`,
|
|
12573
|
+
`base_url_host_blocked`, `env_ref_not_allowed`, `account_missing`, `token_missing`,
|
|
12574
|
+
`unsupported_type`).
|
|
12575
|
+
content:
|
|
12576
|
+
application/json:
|
|
12577
|
+
schema:
|
|
12578
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
12579
|
+
"401":
|
|
12580
|
+
$ref: "#/components/responses/Unauthorized"
|
|
12581
|
+
"403":
|
|
12582
|
+
$ref: "#/components/responses/Forbidden"
|
|
12583
|
+
"502":
|
|
12584
|
+
description: >
|
|
12585
|
+
The provider rejected or failed the listing (`error` is `unauthorized`, `forbidden`,
|
|
12586
|
+
`not_found`, `rate_limited`, or `discovery_failed`).
|
|
12587
|
+
content:
|
|
12588
|
+
application/json:
|
|
12589
|
+
schema:
|
|
12590
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
12591
|
+
|
|
12592
|
+
/workspaces/{workspaceId}/vcs-provider-coverage:
|
|
12593
|
+
get:
|
|
12594
|
+
tags: [Workspace]
|
|
12595
|
+
summary: GitLab and Bitbucket Data Coverage freshness (server-computed)
|
|
12596
|
+
operationId: getWorkspaceVcsProviderCoverage
|
|
12597
|
+
description: >
|
|
12598
|
+
One row per configured GitLab or Bitbucket source. Freshness is computed on the server
|
|
12599
|
+
from batch-written sync rows and succeeded readiness runs; no request field can mark a
|
|
12600
|
+
row fresh. Git is fresh when the last complete ingest finished within
|
|
12601
|
+
`gitFreshnessHours` (24) and no error was recorded after it. A readiness scan is fresh
|
|
12602
|
+
within `readinessScanFreshnessDays` (30, America/New_York calendar days); `scansFresh`
|
|
12603
|
+
requires every in-scope repository to have a fresh scan. A source with an invalid base
|
|
12604
|
+
URL or missing account is `misconfigured`. Requires workspace membership.
|
|
12605
|
+
parameters:
|
|
12606
|
+
- $ref: "#/components/parameters/WorkspaceId"
|
|
12607
|
+
responses:
|
|
12608
|
+
"200":
|
|
12609
|
+
description: Server-computed provider coverage
|
|
12610
|
+
content:
|
|
12611
|
+
application/json:
|
|
12612
|
+
schema:
|
|
12613
|
+
$ref: "#/components/schemas/VcsProviderCoverageDto"
|
|
12614
|
+
"401":
|
|
12615
|
+
$ref: "#/components/responses/Unauthorized"
|
|
12616
|
+
"403":
|
|
12617
|
+
$ref: "#/components/responses/Forbidden"
|
|
12618
|
+
"501":
|
|
12619
|
+
description: Store does not support provider coverage
|
|
12620
|
+
|
|
11988
12621
|
/workspaces/{workspaceId}/ingest/productivity/repos/{slug}/retry:
|
|
11989
12622
|
post:
|
|
11990
12623
|
tags: [Workspace]
|
|
@@ -12895,6 +13528,14 @@ components:
|
|
|
12895
13528
|
required: true
|
|
12896
13529
|
schema:
|
|
12897
13530
|
type: string
|
|
13531
|
+
AssessmentReportId:
|
|
13532
|
+
name: reportId
|
|
13533
|
+
in: path
|
|
13534
|
+
required: true
|
|
13535
|
+
schema:
|
|
13536
|
+
type: string
|
|
13537
|
+
format: uuid
|
|
13538
|
+
description: Stored assessment report id (`tai_workspace_assessment_reports.id`).
|
|
12898
13539
|
EvalSuiteId:
|
|
12899
13540
|
name: suiteId
|
|
12900
13541
|
in: path
|
|
@@ -13295,29 +13936,196 @@ components:
|
|
|
13295
13936
|
enum: [asc, desc]
|
|
13296
13937
|
default: asc
|
|
13297
13938
|
|
|
13298
|
-
responses:
|
|
13299
|
-
Unauthorized:
|
|
13300
|
-
description: Missing or invalid bearer token
|
|
13301
|
-
content:
|
|
13302
|
-
application/json:
|
|
13303
|
-
schema:
|
|
13304
|
-
$ref: "#/components/schemas/ErrorMessageDto"
|
|
13305
|
-
Forbidden:
|
|
13306
|
-
description: Authenticated but not allowed
|
|
13307
|
-
content:
|
|
13308
|
-
application/json:
|
|
13309
|
-
schema:
|
|
13310
|
-
$ref: "#/components/schemas/ErrorMessageDto"
|
|
13311
|
-
ZenHrSyncInProgress:
|
|
13312
|
-
description: HRIS sync or ZenHR OAuth refresh already in progress for this workspace
|
|
13313
|
-
content:
|
|
13314
|
-
application/json:
|
|
13315
|
-
schema:
|
|
13316
|
-
$ref: "#/components/schemas/ErrorMessageDto"
|
|
13317
|
-
example:
|
|
13318
|
-
error: zenhr_sync_in_progress
|
|
13939
|
+
responses:
|
|
13940
|
+
Unauthorized:
|
|
13941
|
+
description: Missing or invalid bearer token
|
|
13942
|
+
content:
|
|
13943
|
+
application/json:
|
|
13944
|
+
schema:
|
|
13945
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
13946
|
+
Forbidden:
|
|
13947
|
+
description: Authenticated but not allowed
|
|
13948
|
+
content:
|
|
13949
|
+
application/json:
|
|
13950
|
+
schema:
|
|
13951
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
13952
|
+
ZenHrSyncInProgress:
|
|
13953
|
+
description: HRIS sync or ZenHR OAuth refresh already in progress for this workspace
|
|
13954
|
+
content:
|
|
13955
|
+
application/json:
|
|
13956
|
+
schema:
|
|
13957
|
+
$ref: "#/components/schemas/ErrorMessageDto"
|
|
13958
|
+
example:
|
|
13959
|
+
error: zenhr_sync_in_progress
|
|
13960
|
+
|
|
13961
|
+
schemas:
|
|
13962
|
+
AssessmentManifestValidationBodyDto:
|
|
13963
|
+
description: Body of runAssessmentManifestValidation; buildWorkspaceAssessmentManifest returns the server-built object as `validation`.
|
|
13964
|
+
type: object
|
|
13965
|
+
required:
|
|
13966
|
+
- manifest
|
|
13967
|
+
- workspaceId
|
|
13968
|
+
- expectedWorkspaceId
|
|
13969
|
+
- expectedRepositoryIds
|
|
13970
|
+
- soldWindowComplete
|
|
13971
|
+
- premiumAiAssessable
|
|
13972
|
+
- namedPersonSectionIds
|
|
13973
|
+
- tolerances
|
|
13974
|
+
properties:
|
|
13975
|
+
manifest:
|
|
13976
|
+
type: object
|
|
13977
|
+
required:
|
|
13978
|
+
- offerId
|
|
13979
|
+
- dictionaryVersion
|
|
13980
|
+
- validation
|
|
13981
|
+
- shareMode
|
|
13982
|
+
- watermark
|
|
13983
|
+
- scope
|
|
13984
|
+
- windows
|
|
13985
|
+
- sources
|
|
13986
|
+
- consent
|
|
13987
|
+
- sections
|
|
13988
|
+
properties:
|
|
13989
|
+
offerId:
|
|
13990
|
+
type: string
|
|
13991
|
+
enum: [engineering_readiness_baseline, agentic_ai_roi]
|
|
13992
|
+
dictionaryVersion:
|
|
13993
|
+
type: string
|
|
13994
|
+
validation:
|
|
13995
|
+
type: string
|
|
13996
|
+
enum: [validated, not_validated]
|
|
13997
|
+
shareMode:
|
|
13998
|
+
type: string
|
|
13999
|
+
enum: [internal, external]
|
|
14000
|
+
watermark:
|
|
14001
|
+
type: string
|
|
14002
|
+
nullable: true
|
|
14003
|
+
enum: ["NOT VALIDATED", "SAMPLE · SYNTHETIC DATA"]
|
|
14004
|
+
scope:
|
|
14005
|
+
type: object
|
|
14006
|
+
required: [repositories, excluded]
|
|
14007
|
+
properties:
|
|
14008
|
+
repositories:
|
|
14009
|
+
type: array
|
|
14010
|
+
items:
|
|
14011
|
+
type: object
|
|
14012
|
+
required: [id, name]
|
|
14013
|
+
properties:
|
|
14014
|
+
id: { type: string }
|
|
14015
|
+
name: { type: string }
|
|
14016
|
+
excluded:
|
|
14017
|
+
type: array
|
|
14018
|
+
items:
|
|
14019
|
+
type: object
|
|
14020
|
+
required: [id, name, reason]
|
|
14021
|
+
properties:
|
|
14022
|
+
id: { type: string }
|
|
14023
|
+
name: { type: string }
|
|
14024
|
+
reason: { type: string }
|
|
14025
|
+
windows:
|
|
14026
|
+
type: object
|
|
14027
|
+
required: [pre, post, transitionDays]
|
|
14028
|
+
properties:
|
|
14029
|
+
pre:
|
|
14030
|
+
type: object
|
|
14031
|
+
nullable: true
|
|
14032
|
+
required: [start, end]
|
|
14033
|
+
properties:
|
|
14034
|
+
start: { type: string }
|
|
14035
|
+
end: { type: string }
|
|
14036
|
+
post:
|
|
14037
|
+
type: object
|
|
14038
|
+
nullable: true
|
|
14039
|
+
required: [start, end]
|
|
14040
|
+
properties:
|
|
14041
|
+
start: { type: string }
|
|
14042
|
+
end: { type: string }
|
|
14043
|
+
transitionDays:
|
|
14044
|
+
type: integer
|
|
14045
|
+
sources:
|
|
14046
|
+
type: array
|
|
14047
|
+
items:
|
|
14048
|
+
type: object
|
|
14049
|
+
required: [provider, status, freshAt]
|
|
14050
|
+
properties:
|
|
14051
|
+
provider: { type: string }
|
|
14052
|
+
status: { type: string }
|
|
14053
|
+
freshAt: { type: string, nullable: true }
|
|
14054
|
+
consent:
|
|
14055
|
+
type: object
|
|
14056
|
+
required: [aggregateUse, recordedAt]
|
|
14057
|
+
properties:
|
|
14058
|
+
aggregateUse:
|
|
14059
|
+
type: string
|
|
14060
|
+
enum: [opt_in, opt_out, unset]
|
|
14061
|
+
recordedAt:
|
|
14062
|
+
type: string
|
|
14063
|
+
nullable: true
|
|
14064
|
+
sections:
|
|
14065
|
+
type: array
|
|
14066
|
+
items:
|
|
14067
|
+
type: object
|
|
14068
|
+
required: [id, status]
|
|
14069
|
+
properties:
|
|
14070
|
+
id: { type: string }
|
|
14071
|
+
status:
|
|
14072
|
+
type: string
|
|
14073
|
+
enum: [ok, failed, omitted]
|
|
14074
|
+
reason: { type: string }
|
|
14075
|
+
workspaceId:
|
|
14076
|
+
type: string
|
|
14077
|
+
expectedWorkspaceId:
|
|
14078
|
+
type: string
|
|
14079
|
+
expectedRepositoryIds:
|
|
14080
|
+
type: array
|
|
14081
|
+
items:
|
|
14082
|
+
type: string
|
|
14083
|
+
soldWindowComplete:
|
|
14084
|
+
type: boolean
|
|
14085
|
+
premiumAiAssessable:
|
|
14086
|
+
type: boolean
|
|
14087
|
+
namedPersonSectionIds:
|
|
14088
|
+
type: array
|
|
14089
|
+
items:
|
|
14090
|
+
type: string
|
|
14091
|
+
tolerances:
|
|
14092
|
+
type: array
|
|
14093
|
+
items:
|
|
14094
|
+
type: object
|
|
14095
|
+
required: [id, status]
|
|
14096
|
+
properties:
|
|
14097
|
+
id:
|
|
14098
|
+
type: string
|
|
14099
|
+
status:
|
|
14100
|
+
type: string
|
|
14101
|
+
enum: [unset, exceeded, within]
|
|
14102
|
+
|
|
14103
|
+
AssessmentManifestValidationResultDto:
|
|
14104
|
+
type: object
|
|
14105
|
+
required: [buyerDeliverable, validation, watermark, reasons, contentHash]
|
|
14106
|
+
properties:
|
|
14107
|
+
buyerDeliverable:
|
|
14108
|
+
type: boolean
|
|
14109
|
+
validation:
|
|
14110
|
+
type: string
|
|
14111
|
+
enum: [validated, not_validated]
|
|
14112
|
+
watermark:
|
|
14113
|
+
type: string
|
|
14114
|
+
nullable: true
|
|
14115
|
+
enum: ["NOT VALIDATED"]
|
|
14116
|
+
reasons:
|
|
14117
|
+
type: array
|
|
14118
|
+
items:
|
|
14119
|
+
type: object
|
|
14120
|
+
required: [code, message]
|
|
14121
|
+
properties:
|
|
14122
|
+
code:
|
|
14123
|
+
type: string
|
|
14124
|
+
message:
|
|
14125
|
+
type: string
|
|
14126
|
+
contentHash:
|
|
14127
|
+
type: string
|
|
13319
14128
|
|
|
13320
|
-
schemas:
|
|
13321
14129
|
TeamsInstallUrlDto:
|
|
13322
14130
|
type: object
|
|
13323
14131
|
required: [url]
|
|
@@ -13658,6 +14466,9 @@ components:
|
|
|
13658
14466
|
bitbucketUuid:
|
|
13659
14467
|
type: string
|
|
13660
14468
|
description: Bitbucket account UUID (e.g. "{aeefb6b0-...}") to attribute merged PRs and reviews to this person in productivity ingest. Preferred over bitbucketNickname — Bitbucket PR payloads expose a stable uuid but not nickname. Resolves to the same person_id (email) as githubUsername.
|
|
14469
|
+
gitlabUsername:
|
|
14470
|
+
type: string
|
|
14471
|
+
description: GitLab username (no @; GitLab.com or self-managed) to map merged merge requests and commits to this person in productivity ingest and the assessment active-engineer count. Stored lowercased. Resolves to the same person_id (email) as githubUsername.
|
|
13661
14472
|
alternateEmails:
|
|
13662
14473
|
type: string
|
|
13663
14474
|
description: Optional comma-separated work emails that map to the same person for AI tool spend/usage (mirrors multi-login github_username). Primary email remains canonical person_id.
|
|
@@ -13732,6 +14543,8 @@ components:
|
|
|
13732
14543
|
type: string
|
|
13733
14544
|
bitbucketUuid:
|
|
13734
14545
|
type: string
|
|
14546
|
+
gitlabUsername:
|
|
14547
|
+
type: string
|
|
13735
14548
|
alternateEmails:
|
|
13736
14549
|
type: string
|
|
13737
14550
|
description: Comma-separated alternate work emails for AI tool attribution.
|
|
@@ -19052,17 +19865,199 @@ components:
|
|
|
19052
19865
|
- platform-governance
|
|
19053
19866
|
- delivery
|
|
19054
19867
|
|
|
19868
|
+
ExternalVcsProviderDto:
|
|
19869
|
+
type: string
|
|
19870
|
+
enum: [gitlab_cloud, gitlab_self_managed, bitbucket_cloud, bitbucket_server]
|
|
19871
|
+
description: >
|
|
19872
|
+
`bitbucket_server` is Bitbucket Data Center. Self-hosted providers
|
|
19873
|
+
(`gitlab_self_managed`, `bitbucket_server`) always carry `hostBaseUrl`.
|
|
19874
|
+
|
|
19875
|
+
GitVcsSourceDto:
|
|
19876
|
+
type: object
|
|
19877
|
+
description: >
|
|
19878
|
+
GitLab or Bitbucket tenant source entry. GitLab: optional `group` (full path) and
|
|
19879
|
+
`projects` (`group/sub/project`). Bitbucket: `workspace` (Cloud workspace or Data Center
|
|
19880
|
+
project key) and optional `repos` (repository slugs). `deployment` selects self-hosted;
|
|
19881
|
+
it then requires `baseUrl`.
|
|
19882
|
+
required: [type]
|
|
19883
|
+
additionalProperties: true
|
|
19884
|
+
properties:
|
|
19885
|
+
type:
|
|
19886
|
+
type: string
|
|
19887
|
+
enum: [gitlab, bitbucket]
|
|
19888
|
+
deployment:
|
|
19889
|
+
type: string
|
|
19890
|
+
enum: [cloud, self_managed, data_center]
|
|
19891
|
+
baseUrl:
|
|
19892
|
+
type: string
|
|
19893
|
+
maxLength: 512
|
|
19894
|
+
group:
|
|
19895
|
+
type: string
|
|
19896
|
+
maxLength: 512
|
|
19897
|
+
projects:
|
|
19898
|
+
type: array
|
|
19899
|
+
items:
|
|
19900
|
+
type: string
|
|
19901
|
+
maxLength: 512
|
|
19902
|
+
workspace:
|
|
19903
|
+
type: string
|
|
19904
|
+
maxLength: 256
|
|
19905
|
+
repos:
|
|
19906
|
+
type: array
|
|
19907
|
+
items:
|
|
19908
|
+
type: string
|
|
19909
|
+
maxLength: 256
|
|
19910
|
+
token:
|
|
19911
|
+
type: string
|
|
19912
|
+
maxLength: 4096
|
|
19913
|
+
description: Personal / project / HTTP access token, or `***` to reuse the stored token.
|
|
19914
|
+
|
|
19915
|
+
VcsDiscoveredRepoDto:
|
|
19916
|
+
type: object
|
|
19917
|
+
required: [slug, name, defaultBranch, webUrl]
|
|
19918
|
+
properties:
|
|
19919
|
+
slug:
|
|
19920
|
+
type: string
|
|
19921
|
+
description: "`group/sub/project` (GitLab) or `workspace/repo` / `PROJECT/repo` (Bitbucket)"
|
|
19922
|
+
name:
|
|
19923
|
+
type: string
|
|
19924
|
+
defaultBranch:
|
|
19925
|
+
type: string
|
|
19926
|
+
nullable: true
|
|
19927
|
+
webUrl:
|
|
19928
|
+
type: string
|
|
19929
|
+
nullable: true
|
|
19930
|
+
|
|
19931
|
+
VcsRepoDiscoveryResponseDto:
|
|
19932
|
+
type: object
|
|
19933
|
+
required: [provider, hostBaseUrl, account, truncated, repoCap, repositories]
|
|
19934
|
+
properties:
|
|
19935
|
+
provider:
|
|
19936
|
+
$ref: "#/components/schemas/ExternalVcsProviderDto"
|
|
19937
|
+
hostBaseUrl:
|
|
19938
|
+
type: string
|
|
19939
|
+
nullable: true
|
|
19940
|
+
account:
|
|
19941
|
+
type: string
|
|
19942
|
+
description: GitLab group path (empty = token membership), Bitbucket workspace, or project key
|
|
19943
|
+
truncated:
|
|
19944
|
+
type: boolean
|
|
19945
|
+
description: True when the provider page limit was reached; the list is incomplete.
|
|
19946
|
+
repoCap:
|
|
19947
|
+
type: integer
|
|
19948
|
+
repositories:
|
|
19949
|
+
type: array
|
|
19950
|
+
items:
|
|
19951
|
+
$ref: "#/components/schemas/VcsDiscoveredRepoDto"
|
|
19952
|
+
|
|
19953
|
+
VcsProviderCoverageRowDto:
|
|
19954
|
+
type: object
|
|
19955
|
+
required:
|
|
19956
|
+
- provider
|
|
19957
|
+
- hostBaseUrl
|
|
19958
|
+
- account
|
|
19959
|
+
- selfHosted
|
|
19960
|
+
- state
|
|
19961
|
+
- isFresh
|
|
19962
|
+
- lastIngestSuccessAt
|
|
19963
|
+
- lastErrorKind
|
|
19964
|
+
- lastDiscoveryAt
|
|
19965
|
+
- discoveredRepoCount
|
|
19966
|
+
- staleForMs
|
|
19967
|
+
- repoCount
|
|
19968
|
+
- scannedRepoCount
|
|
19969
|
+
- freshScanRepoCount
|
|
19970
|
+
- scansFresh
|
|
19971
|
+
- mergedHistorySince
|
|
19972
|
+
- commitHistorySince
|
|
19973
|
+
properties:
|
|
19974
|
+
provider:
|
|
19975
|
+
$ref: "#/components/schemas/ExternalVcsProviderDto"
|
|
19976
|
+
hostBaseUrl:
|
|
19977
|
+
type: string
|
|
19978
|
+
nullable: true
|
|
19979
|
+
account:
|
|
19980
|
+
type: string
|
|
19981
|
+
selfHosted:
|
|
19982
|
+
type: boolean
|
|
19983
|
+
state:
|
|
19984
|
+
type: string
|
|
19985
|
+
enum: [fresh, stale, never_synced, error, misconfigured]
|
|
19986
|
+
isFresh:
|
|
19987
|
+
type: boolean
|
|
19988
|
+
description: Server-computed; true only when `state` is `fresh`.
|
|
19989
|
+
lastIngestSuccessAt:
|
|
19990
|
+
type: string
|
|
19991
|
+
format: date-time
|
|
19992
|
+
nullable: true
|
|
19993
|
+
lastErrorKind:
|
|
19994
|
+
type: string
|
|
19995
|
+
nullable: true
|
|
19996
|
+
lastDiscoveryAt:
|
|
19997
|
+
type: string
|
|
19998
|
+
format: date-time
|
|
19999
|
+
nullable: true
|
|
20000
|
+
discoveredRepoCount:
|
|
20001
|
+
type: integer
|
|
20002
|
+
nullable: true
|
|
20003
|
+
staleForMs:
|
|
20004
|
+
type: integer
|
|
20005
|
+
nullable: true
|
|
20006
|
+
description: Milliseconds past the Git freshness limit when `state` is `stale`.
|
|
20007
|
+
repoCount:
|
|
20008
|
+
type: integer
|
|
20009
|
+
description: In-scope repositories stored for this source.
|
|
20010
|
+
scannedRepoCount:
|
|
20011
|
+
type: integer
|
|
20012
|
+
freshScanRepoCount:
|
|
20013
|
+
type: integer
|
|
20014
|
+
scansFresh:
|
|
20015
|
+
type: boolean
|
|
20016
|
+
mergedHistorySince:
|
|
20017
|
+
type: string
|
|
20018
|
+
format: date-time
|
|
20019
|
+
nullable: true
|
|
20020
|
+
description: >-
|
|
20021
|
+
Earliest merge time reached by the assessment merged-request history backfill for this
|
|
20022
|
+
source; null when no backfill window has been written.
|
|
20023
|
+
commitHistorySince:
|
|
20024
|
+
type: string
|
|
20025
|
+
format: date-time
|
|
20026
|
+
nullable: true
|
|
20027
|
+
description: >-
|
|
20028
|
+
Instant from which every in-scope repository of this source has contiguous
|
|
20029
|
+
default-branch commit-author coverage (latest per-repo coverage start); null when any
|
|
20030
|
+
repository has no coverage.
|
|
20031
|
+
|
|
20032
|
+
VcsProviderCoverageDto:
|
|
20033
|
+
type: object
|
|
20034
|
+
required: [generatedAt, gitFreshnessHours, readinessScanFreshnessDays, sources]
|
|
20035
|
+
properties:
|
|
20036
|
+
generatedAt:
|
|
20037
|
+
type: string
|
|
20038
|
+
format: date-time
|
|
20039
|
+
gitFreshnessHours:
|
|
20040
|
+
type: integer
|
|
20041
|
+
readinessScanFreshnessDays:
|
|
20042
|
+
type: integer
|
|
20043
|
+
sources:
|
|
20044
|
+
type: array
|
|
20045
|
+
items:
|
|
20046
|
+
$ref: "#/components/schemas/VcsProviderCoverageRowDto"
|
|
20047
|
+
|
|
19055
20048
|
RepoProviderDto:
|
|
19056
20049
|
type: object
|
|
19057
20050
|
required: [kind, slug, webUrl]
|
|
19058
20051
|
properties:
|
|
19059
20052
|
kind:
|
|
19060
20053
|
type: string
|
|
19061
|
-
enum: [github, bitbucket_cloud, bitbucket_server]
|
|
20054
|
+
enum: [github, bitbucket_cloud, bitbucket_server, gitlab_cloud, gitlab_self_managed]
|
|
19062
20055
|
slug:
|
|
19063
20056
|
type: string
|
|
19064
20057
|
maxLength: 256
|
|
19065
|
-
description:
|
|
20058
|
+
description: >
|
|
20059
|
+
owner/repo (GitHub), workspace/repo_slug (Bitbucket Cloud), PROJECT_KEY/repo_slug
|
|
20060
|
+
(Bitbucket Server / Data Center), or group/sub/project (GitLab)
|
|
19066
20061
|
webUrl:
|
|
19067
20062
|
type: string
|
|
19068
20063
|
format: uri
|
|
@@ -19080,7 +20075,9 @@ components:
|
|
|
19080
20075
|
type: string
|
|
19081
20076
|
format: uri
|
|
19082
20077
|
nullable: true
|
|
19083
|
-
description:
|
|
20078
|
+
description: >
|
|
20079
|
+
Required for bitbucket_server and gitlab_self_managed (self-hosted); null for cloud
|
|
20080
|
+
providers
|
|
19084
20081
|
|
|
19085
20082
|
ReadinessAnalyzeBodyDto:
|
|
19086
20083
|
type: object
|
|
@@ -22257,29 +23254,309 @@ components:
|
|
|
22257
23254
|
- integrations.zelt.added
|
|
22258
23255
|
- integrations.zelt.removed
|
|
22259
23256
|
- report.exported
|
|
23257
|
+
- report.assessment_stored
|
|
23258
|
+
- report.assessment_link_sent
|
|
23259
|
+
- report.assessment_link_revoked
|
|
23260
|
+
- report.assessment_downloaded
|
|
23261
|
+
- report.assessment_hidden
|
|
23262
|
+
- report.assessment_restored
|
|
22260
23263
|
- workspace.aggregate_use.changed
|
|
23264
|
+
- workspace.assessment_rollout.changed
|
|
23265
|
+
|
|
23266
|
+
AggregateUseNoticeStatusDto:
|
|
23267
|
+
type: object
|
|
23268
|
+
additionalProperties: false
|
|
23269
|
+
required: [status]
|
|
23270
|
+
description: Current legal-approved opt-in notice, or `unset` while opt-in is unavailable.
|
|
23271
|
+
properties:
|
|
23272
|
+
status:
|
|
23273
|
+
type: string
|
|
23274
|
+
enum: [approved, unset]
|
|
23275
|
+
version:
|
|
23276
|
+
type: string
|
|
23277
|
+
description: Present only when `status` is `approved`. Send it back on opt-in.
|
|
23278
|
+
|
|
23279
|
+
AssessmentNamedEventDto:
|
|
23280
|
+
type: string
|
|
23281
|
+
enum: [major_release, migration, acquisition, policy_change]
|
|
23282
|
+
description: Confounder-relevant named event from the assessment dictionary.
|
|
23283
|
+
|
|
23284
|
+
AssessmentRolloutDto:
|
|
23285
|
+
type: object
|
|
23286
|
+
additionalProperties: false
|
|
23287
|
+
required:
|
|
23288
|
+
- rolloutDay
|
|
23289
|
+
- timezone
|
|
23290
|
+
- boundary
|
|
23291
|
+
- startsAt
|
|
23292
|
+
- setBy
|
|
23293
|
+
- setAt
|
|
23294
|
+
- namedEvents
|
|
23295
|
+
- namedEventsConfirmedBy
|
|
23296
|
+
- namedEventsConfirmedAt
|
|
23297
|
+
properties:
|
|
23298
|
+
rolloutDay:
|
|
23299
|
+
type: string
|
|
23300
|
+
format: date
|
|
23301
|
+
nullable: true
|
|
23302
|
+
description: Confirmed rollout day (`YYYY-MM-DD`); null until set.
|
|
23303
|
+
timezone:
|
|
23304
|
+
type: string
|
|
23305
|
+
enum: [America/New_York]
|
|
23306
|
+
boundary:
|
|
23307
|
+
type: string
|
|
23308
|
+
enum: [midnight]
|
|
23309
|
+
startsAt:
|
|
23310
|
+
type: string
|
|
23311
|
+
format: date-time
|
|
23312
|
+
nullable: true
|
|
23313
|
+
description: UTC instant of 00:00 America/New_York on `rolloutDay`.
|
|
23314
|
+
setBy:
|
|
23315
|
+
type: object
|
|
23316
|
+
nullable: true
|
|
23317
|
+
additionalProperties: false
|
|
23318
|
+
required: [userId, displayName]
|
|
23319
|
+
properties:
|
|
23320
|
+
userId:
|
|
23321
|
+
type: string
|
|
23322
|
+
format: uuid
|
|
23323
|
+
displayName:
|
|
23324
|
+
type: string
|
|
23325
|
+
nullable: true
|
|
23326
|
+
setAt:
|
|
23327
|
+
type: string
|
|
23328
|
+
format: date-time
|
|
23329
|
+
nullable: true
|
|
23330
|
+
namedEvents:
|
|
23331
|
+
type: array
|
|
23332
|
+
nullable: true
|
|
23333
|
+
items:
|
|
23334
|
+
$ref: "#/components/schemas/AssessmentNamedEventDto"
|
|
23335
|
+
description: >
|
|
23336
|
+
Named events confirmed during either matched window. Null means
|
|
23337
|
+
the customer or operator has not confirmed yet, so the ROI
|
|
23338
|
+
confounder check reports `confounder_inputs_missing`. An empty
|
|
23339
|
+
array confirms none occurred.
|
|
23340
|
+
namedEventsConfirmedBy:
|
|
23341
|
+
type: object
|
|
23342
|
+
nullable: true
|
|
23343
|
+
additionalProperties: false
|
|
23344
|
+
required: [userId, displayName]
|
|
23345
|
+
properties:
|
|
23346
|
+
userId:
|
|
23347
|
+
type: string
|
|
23348
|
+
format: uuid
|
|
23349
|
+
displayName:
|
|
23350
|
+
type: string
|
|
23351
|
+
nullable: true
|
|
23352
|
+
namedEventsConfirmedAt:
|
|
23353
|
+
type: string
|
|
23354
|
+
format: date-time
|
|
23355
|
+
nullable: true
|
|
23356
|
+
|
|
23357
|
+
AssessmentRolloutPutDto:
|
|
23358
|
+
type: object
|
|
23359
|
+
additionalProperties: false
|
|
23360
|
+
required: [rolloutDay]
|
|
23361
|
+
properties:
|
|
23362
|
+
rolloutDay:
|
|
23363
|
+
type: string
|
|
23364
|
+
format: date
|
|
23365
|
+
description: Real calendar date, not after today in America/New_York.
|
|
23366
|
+
namedEvents:
|
|
23367
|
+
type: array
|
|
23368
|
+
items:
|
|
23369
|
+
$ref: "#/components/schemas/AssessmentNamedEventDto"
|
|
23370
|
+
description: >
|
|
23371
|
+
Omit to leave the stored named-event confirmation unchanged. Send
|
|
23372
|
+
an empty array to confirm no named event occurred during either
|
|
23373
|
+
matched window, or the events that did.
|
|
23374
|
+
|
|
23375
|
+
AssessmentRoiReasonDto:
|
|
23376
|
+
type: string
|
|
23377
|
+
enum:
|
|
23378
|
+
- rollout_unset
|
|
23379
|
+
- window_missing
|
|
23380
|
+
- missing_cost
|
|
23381
|
+
- non_usd_cost
|
|
23382
|
+
- cost_not_attributable
|
|
23383
|
+
- ship_weight_incomplete
|
|
23384
|
+
- active_engineers_unknown
|
|
23385
|
+
- non_positive_output
|
|
23386
|
+
- normalization_unset
|
|
23387
|
+
- confounder
|
|
23388
|
+
- confounder_inputs_missing
|
|
23389
|
+
- output_unit_mismatch
|
|
23390
|
+
description: >
|
|
23391
|
+
Why the matched-period ROI is not assessable. `cost_not_attributable` means a
|
|
23392
|
+
billing-cycle bill (GitHub Copilot) overlaps the post window and cannot be split
|
|
23393
|
+
by day. `active_engineers_unknown` means stored identities cannot yet be counted.
|
|
23394
|
+
`confounder_inputs_missing` means a named-event, headcount, or repository-scope
|
|
23395
|
+
check has no stored input.
|
|
23396
|
+
|
|
23397
|
+
AssessmentRoiDayRangeDto:
|
|
23398
|
+
type: object
|
|
23399
|
+
additionalProperties: false
|
|
23400
|
+
required: [from, to]
|
|
23401
|
+
properties:
|
|
23402
|
+
from:
|
|
23403
|
+
type: string
|
|
23404
|
+
format: date
|
|
23405
|
+
to:
|
|
23406
|
+
type: string
|
|
23407
|
+
format: date
|
|
23408
|
+
|
|
23409
|
+
AssessmentRoiWindowDto:
|
|
23410
|
+
type: object
|
|
23411
|
+
additionalProperties: false
|
|
23412
|
+
required:
|
|
23413
|
+
- from
|
|
23414
|
+
- to
|
|
23415
|
+
- requiredDays
|
|
23416
|
+
- coveredDays
|
|
23417
|
+
- complete
|
|
23418
|
+
- workingDays
|
|
23419
|
+
- activeEngineers
|
|
23420
|
+
- mergedPullRequests
|
|
23421
|
+
- shipWeight
|
|
23422
|
+
- normalizedShipWeight
|
|
23423
|
+
properties:
|
|
23424
|
+
from:
|
|
23425
|
+
type: string
|
|
23426
|
+
format: date
|
|
23427
|
+
to:
|
|
23428
|
+
type: string
|
|
23429
|
+
format: date
|
|
23430
|
+
requiredDays:
|
|
23431
|
+
type: integer
|
|
23432
|
+
description: Calendar days in the window (90).
|
|
23433
|
+
coveredDays:
|
|
23434
|
+
type: integer
|
|
23435
|
+
description: Calendar days with stored evidence.
|
|
23436
|
+
complete:
|
|
23437
|
+
type: boolean
|
|
23438
|
+
description: Every calendar day is covered and the window ended before today.
|
|
23439
|
+
workingDays:
|
|
23440
|
+
type: integer
|
|
23441
|
+
description: Monday–Friday days in America/New_York. No holidays.
|
|
23442
|
+
activeEngineers:
|
|
23443
|
+
type: integer
|
|
23444
|
+
nullable: true
|
|
23445
|
+
mergedPullRequests:
|
|
23446
|
+
type: integer
|
|
23447
|
+
shipWeight:
|
|
23448
|
+
type: number
|
|
23449
|
+
nullable: true
|
|
23450
|
+
description: Sum of stored Ship Weight for unique merged pull requests; null if any is unscored.
|
|
23451
|
+
normalizedShipWeight:
|
|
23452
|
+
type: number
|
|
23453
|
+
nullable: true
|
|
23454
|
+
description: Ship Weight per active engineer per working day.
|
|
22261
23455
|
|
|
22262
|
-
|
|
23456
|
+
AssessmentRoiDto:
|
|
22263
23457
|
type: object
|
|
22264
23458
|
additionalProperties: false
|
|
22265
|
-
required:
|
|
23459
|
+
required:
|
|
23460
|
+
- dictionaryVersion
|
|
23461
|
+
- rolloutDay
|
|
23462
|
+
- rolloutBoundary
|
|
23463
|
+
- windows
|
|
23464
|
+
- cost
|
|
23465
|
+
- confounders
|
|
23466
|
+
- status
|
|
23467
|
+
- reason
|
|
23468
|
+
- incrementalNormalizedShipWeight
|
|
23469
|
+
- costPerIncrementalShipWeightUsd
|
|
23470
|
+
- costPerMergedPullRequestUsd
|
|
22266
23471
|
properties:
|
|
22267
|
-
|
|
23472
|
+
dictionaryVersion:
|
|
22268
23473
|
type: string
|
|
22269
|
-
|
|
22270
|
-
|
|
22271
|
-
AggregateUseNoticeStatusDto:
|
|
22272
|
-
type: object
|
|
22273
|
-
additionalProperties: false
|
|
22274
|
-
required: [status]
|
|
22275
|
-
description: Current legal-approved opt-in notice, or `unset` while opt-in is unavailable.
|
|
22276
|
-
properties:
|
|
22277
|
-
status:
|
|
23474
|
+
rolloutDay:
|
|
22278
23475
|
type: string
|
|
22279
|
-
|
|
22280
|
-
|
|
23476
|
+
format: date
|
|
23477
|
+
nullable: true
|
|
23478
|
+
rolloutBoundary:
|
|
23479
|
+
type: object
|
|
23480
|
+
additionalProperties: false
|
|
23481
|
+
required: [timezone, boundary, startsAt]
|
|
23482
|
+
properties:
|
|
23483
|
+
timezone:
|
|
23484
|
+
type: string
|
|
23485
|
+
enum: [America/New_York]
|
|
23486
|
+
boundary:
|
|
23487
|
+
type: string
|
|
23488
|
+
enum: [midnight]
|
|
23489
|
+
startsAt:
|
|
23490
|
+
type: string
|
|
23491
|
+
format: date-time
|
|
23492
|
+
nullable: true
|
|
23493
|
+
windows:
|
|
23494
|
+
type: object
|
|
23495
|
+
additionalProperties: false
|
|
23496
|
+
required: [pre, transition, post]
|
|
23497
|
+
properties:
|
|
23498
|
+
pre:
|
|
23499
|
+
allOf:
|
|
23500
|
+
- $ref: "#/components/schemas/AssessmentRoiWindowDto"
|
|
23501
|
+
nullable: true
|
|
23502
|
+
transition:
|
|
23503
|
+
allOf:
|
|
23504
|
+
- $ref: "#/components/schemas/AssessmentRoiDayRangeDto"
|
|
23505
|
+
nullable: true
|
|
23506
|
+
post:
|
|
23507
|
+
allOf:
|
|
23508
|
+
- $ref: "#/components/schemas/AssessmentRoiWindowDto"
|
|
23509
|
+
nullable: true
|
|
23510
|
+
cost:
|
|
23511
|
+
type: object
|
|
23512
|
+
additionalProperties: false
|
|
23513
|
+
required: [amountUsd, currency, providers]
|
|
23514
|
+
description: Recorded daily AI spend inside the post window. Never estimated.
|
|
23515
|
+
properties:
|
|
23516
|
+
amountUsd:
|
|
23517
|
+
type: number
|
|
23518
|
+
nullable: true
|
|
23519
|
+
currency:
|
|
23520
|
+
type: string
|
|
23521
|
+
enum: [USD]
|
|
23522
|
+
nullable: true
|
|
23523
|
+
providers:
|
|
23524
|
+
type: array
|
|
23525
|
+
items:
|
|
23526
|
+
type: string
|
|
23527
|
+
confounders:
|
|
23528
|
+
type: object
|
|
23529
|
+
additionalProperties: false
|
|
23530
|
+
required: [namedEvent, headcountChangeRatio, repositoryScopeChangeRatio]
|
|
23531
|
+
properties:
|
|
23532
|
+
namedEvent:
|
|
23533
|
+
type: boolean
|
|
23534
|
+
nullable: true
|
|
23535
|
+
description: Null when no named-event input is stored.
|
|
23536
|
+
headcountChangeRatio:
|
|
23537
|
+
type: number
|
|
23538
|
+
nullable: true
|
|
23539
|
+
repositoryScopeChangeRatio:
|
|
23540
|
+
type: number
|
|
23541
|
+
nullable: true
|
|
23542
|
+
description: Repositories with merged pull requests in only one window, over pre-window repositories.
|
|
23543
|
+
status:
|
|
22281
23544
|
type: string
|
|
22282
|
-
|
|
23545
|
+
enum: [assessable, not_assessable]
|
|
23546
|
+
reason:
|
|
23547
|
+
allOf:
|
|
23548
|
+
- $ref: "#/components/schemas/AssessmentRoiReasonDto"
|
|
23549
|
+
nullable: true
|
|
23550
|
+
incrementalNormalizedShipWeight:
|
|
23551
|
+
type: number
|
|
23552
|
+
nullable: true
|
|
23553
|
+
costPerIncrementalShipWeightUsd:
|
|
23554
|
+
type: number
|
|
23555
|
+
nullable: true
|
|
23556
|
+
costPerMergedPullRequestUsd:
|
|
23557
|
+
type: number
|
|
23558
|
+
nullable: true
|
|
23559
|
+
description: Separate correlation. Never the sold ROI figure.
|
|
22283
23560
|
|
|
22284
23561
|
AggregateUseConsentDto:
|
|
22285
23562
|
type: object
|
|
@@ -22384,7 +23661,7 @@ components:
|
|
|
22384
23661
|
properties:
|
|
22385
23662
|
version:
|
|
22386
23663
|
type: string
|
|
22387
|
-
enum: ["2026-10-
|
|
23664
|
+
enum: ["2026-10-24.1"]
|
|
22388
23665
|
periodDays:
|
|
22389
23666
|
type: integer
|
|
22390
23667
|
enum: [90]
|
|
@@ -22556,9 +23833,21 @@ components:
|
|
|
22556
23833
|
- countryAllowList
|
|
22557
23834
|
properties:
|
|
22558
23835
|
baselinePrice:
|
|
22559
|
-
|
|
23836
|
+
type: object
|
|
23837
|
+
additionalProperties: false
|
|
23838
|
+
required: [status, amountUsd, taxes]
|
|
23839
|
+
properties:
|
|
23840
|
+
status: { type: string, enum: [set] }
|
|
23841
|
+
amountUsd: { type: integer, enum: [4999] }
|
|
23842
|
+
taxes: { type: string, enum: [extra] }
|
|
22560
23843
|
premiumPrice:
|
|
22561
|
-
|
|
23844
|
+
type: object
|
|
23845
|
+
additionalProperties: false
|
|
23846
|
+
required: [status, amountUsd, taxes]
|
|
23847
|
+
properties:
|
|
23848
|
+
status: { type: string, enum: [set] }
|
|
23849
|
+
amountUsd: { type: integer, enum: [9999] }
|
|
23850
|
+
taxes: { type: string, enum: [extra] }
|
|
22562
23851
|
currency:
|
|
22563
23852
|
type: object
|
|
22564
23853
|
additionalProperties: false
|
|
@@ -22621,7 +23910,18 @@ components:
|
|
|
22621
23910
|
enum: [monday, tuesday, wednesday, thursday, friday]
|
|
22622
23911
|
holidays: { type: string, enum: [none] }
|
|
22623
23912
|
countryAllowList:
|
|
22624
|
-
|
|
23913
|
+
type: object
|
|
23914
|
+
additionalProperties: false
|
|
23915
|
+
required: [status, countries, counselAccepted]
|
|
23916
|
+
description: Owner decision without counsel acceptance; `counselAccepted` stays false.
|
|
23917
|
+
properties:
|
|
23918
|
+
status: { type: string, enum: [set] }
|
|
23919
|
+
countries:
|
|
23920
|
+
type: array
|
|
23921
|
+
items:
|
|
23922
|
+
type: string
|
|
23923
|
+
enum: [US, BH, KW, OM, QA, SA, AE]
|
|
23924
|
+
counselAccepted: { type: boolean, enum: [false] }
|
|
22625
23925
|
|
|
22626
23926
|
ReportCenterExportRecordBodyDto:
|
|
22627
23927
|
type: object
|
|
@@ -22707,6 +24007,286 @@ components:
|
|
|
22707
24007
|
minLength: 1
|
|
22708
24008
|
maxLength: 256
|
|
22709
24009
|
|
|
24010
|
+
StoreAssessmentReportBodyDto:
|
|
24011
|
+
type: object
|
|
24012
|
+
additionalProperties: false
|
|
24013
|
+
required: [pdfBase64, build, contentHash]
|
|
24014
|
+
properties:
|
|
24015
|
+
pdfBase64:
|
|
24016
|
+
type: string
|
|
24017
|
+
description: The buyer PDF, base64-encoded. Must start with `%PDF-`; at most 10 MiB decoded.
|
|
24018
|
+
build:
|
|
24019
|
+
$ref: "#/components/schemas/BuildAssessmentManifestBodyDto"
|
|
24020
|
+
contentHash:
|
|
24021
|
+
type: string
|
|
24022
|
+
pattern: "^[0-9a-f]{64}$"
|
|
24023
|
+
description: >
|
|
24024
|
+
`result.contentHash` from the `buildWorkspaceAssessmentManifest` call the PDF was
|
|
24025
|
+
rendered from. The server rebuilds the manifest and rejects a different hash.
|
|
24026
|
+
|
|
24027
|
+
BuildAssessmentManifestBodyDto:
|
|
24028
|
+
type: object
|
|
24029
|
+
additionalProperties: false
|
|
24030
|
+
required: [offerId, shareMode, sections]
|
|
24031
|
+
properties:
|
|
24032
|
+
offerId:
|
|
24033
|
+
type: string
|
|
24034
|
+
enum: [engineering_readiness_baseline, agentic_ai_roi]
|
|
24035
|
+
shareMode:
|
|
24036
|
+
type: string
|
|
24037
|
+
enum: [internal, external]
|
|
24038
|
+
sections:
|
|
24039
|
+
type: array
|
|
24040
|
+
minItems: 1
|
|
24041
|
+
maxItems: 64
|
|
24042
|
+
description: Every selected section with its render status. Ids are unique.
|
|
24043
|
+
items:
|
|
24044
|
+
type: object
|
|
24045
|
+
additionalProperties: false
|
|
24046
|
+
required: [id, status]
|
|
24047
|
+
properties:
|
|
24048
|
+
id:
|
|
24049
|
+
type: string
|
|
24050
|
+
minLength: 1
|
|
24051
|
+
maxLength: 128
|
|
24052
|
+
status:
|
|
24053
|
+
type: string
|
|
24054
|
+
enum: [ok, failed, omitted]
|
|
24055
|
+
reason:
|
|
24056
|
+
type: string
|
|
24057
|
+
maxLength: 500
|
|
24058
|
+
roi:
|
|
24059
|
+
description: >
|
|
24060
|
+
The matched-period ROI chapter as printed, copied from the
|
|
24061
|
+
`getWorkspaceAssessmentRoi` result it rendered. Null or omitted when the chapter
|
|
24062
|
+
did not print one.
|
|
24063
|
+
allOf:
|
|
24064
|
+
- $ref: "#/components/schemas/PrintedAssessmentRoiDto"
|
|
24065
|
+
nullable: true
|
|
24066
|
+
|
|
24067
|
+
PrintedAssessmentRoiDto:
|
|
24068
|
+
type: object
|
|
24069
|
+
additionalProperties: false
|
|
24070
|
+
required:
|
|
24071
|
+
- status
|
|
24072
|
+
- reason
|
|
24073
|
+
- incrementalNormalizedShipWeight
|
|
24074
|
+
- costPerIncrementalShipWeightUsd
|
|
24075
|
+
- costPerMergedPullRequestUsd
|
|
24076
|
+
properties:
|
|
24077
|
+
status:
|
|
24078
|
+
type: string
|
|
24079
|
+
enum: [assessable, not_assessable]
|
|
24080
|
+
reason:
|
|
24081
|
+
type: string
|
|
24082
|
+
nullable: true
|
|
24083
|
+
incrementalNormalizedShipWeight:
|
|
24084
|
+
type: number
|
|
24085
|
+
nullable: true
|
|
24086
|
+
costPerIncrementalShipWeightUsd:
|
|
24087
|
+
type: number
|
|
24088
|
+
nullable: true
|
|
24089
|
+
costPerMergedPullRequestUsd:
|
|
24090
|
+
type: number
|
|
24091
|
+
nullable: true
|
|
24092
|
+
|
|
24093
|
+
BuildAssessmentManifestResponseDto:
|
|
24094
|
+
type: object
|
|
24095
|
+
required: [validation, result]
|
|
24096
|
+
properties:
|
|
24097
|
+
validation:
|
|
24098
|
+
$ref: "#/components/schemas/AssessmentManifestValidationBodyDto"
|
|
24099
|
+
result:
|
|
24100
|
+
$ref: "#/components/schemas/AssessmentManifestValidationResultDto"
|
|
24101
|
+
|
|
24102
|
+
StoreAssessmentReportRejectedDto:
|
|
24103
|
+
type: object
|
|
24104
|
+
required: [error, code]
|
|
24105
|
+
properties:
|
|
24106
|
+
error:
|
|
24107
|
+
type: string
|
|
24108
|
+
code:
|
|
24109
|
+
type: string
|
|
24110
|
+
enum: [not_buyer_deliverable, manifest_changed]
|
|
24111
|
+
validation:
|
|
24112
|
+
type: string
|
|
24113
|
+
enum: [validated, not_validated]
|
|
24114
|
+
reasons:
|
|
24115
|
+
type: array
|
|
24116
|
+
items:
|
|
24117
|
+
type: object
|
|
24118
|
+
required: [code, message]
|
|
24119
|
+
properties:
|
|
24120
|
+
code:
|
|
24121
|
+
type: string
|
|
24122
|
+
message:
|
|
24123
|
+
type: string
|
|
24124
|
+
|
|
24125
|
+
AssessmentReportLinkDto:
|
|
24126
|
+
type: object
|
|
24127
|
+
required:
|
|
24128
|
+
[
|
|
24129
|
+
id,
|
|
24130
|
+
reportId,
|
|
24131
|
+
recipientUserId,
|
|
24132
|
+
recipientEmail,
|
|
24133
|
+
recipientName,
|
|
24134
|
+
expiresAt,
|
|
24135
|
+
revokedAt,
|
|
24136
|
+
createdAt,
|
|
24137
|
+
lastAccessedAt,
|
|
24138
|
+
status,
|
|
24139
|
+
]
|
|
24140
|
+
properties:
|
|
24141
|
+
id:
|
|
24142
|
+
type: string
|
|
24143
|
+
format: uuid
|
|
24144
|
+
reportId:
|
|
24145
|
+
type: string
|
|
24146
|
+
format: uuid
|
|
24147
|
+
recipientUserId:
|
|
24148
|
+
type: string
|
|
24149
|
+
format: uuid
|
|
24150
|
+
recipientEmail:
|
|
24151
|
+
type: string
|
|
24152
|
+
nullable: true
|
|
24153
|
+
description: Null when the recipient is no longer a workspace member.
|
|
24154
|
+
recipientName:
|
|
24155
|
+
type: string
|
|
24156
|
+
nullable: true
|
|
24157
|
+
expiresAt:
|
|
24158
|
+
type: string
|
|
24159
|
+
format: date-time
|
|
24160
|
+
revokedAt:
|
|
24161
|
+
type: string
|
|
24162
|
+
format: date-time
|
|
24163
|
+
nullable: true
|
|
24164
|
+
createdAt:
|
|
24165
|
+
type: string
|
|
24166
|
+
format: date-time
|
|
24167
|
+
lastAccessedAt:
|
|
24168
|
+
type: string
|
|
24169
|
+
format: date-time
|
|
24170
|
+
nullable: true
|
|
24171
|
+
status:
|
|
24172
|
+
type: string
|
|
24173
|
+
enum: [active, expired, revoked]
|
|
24174
|
+
|
|
24175
|
+
AssessmentReportDto:
|
|
24176
|
+
type: object
|
|
24177
|
+
required:
|
|
24178
|
+
[
|
|
24179
|
+
id,
|
|
24180
|
+
offerId,
|
|
24181
|
+
sizeBytes,
|
|
24182
|
+
sha256,
|
|
24183
|
+
manifestHash,
|
|
24184
|
+
createdAt,
|
|
24185
|
+
createdBy,
|
|
24186
|
+
hiddenAt,
|
|
24187
|
+
restoreUntil,
|
|
24188
|
+
status,
|
|
24189
|
+
links,
|
|
24190
|
+
]
|
|
24191
|
+
properties:
|
|
24192
|
+
id:
|
|
24193
|
+
type: string
|
|
24194
|
+
format: uuid
|
|
24195
|
+
offerId:
|
|
24196
|
+
type: string
|
|
24197
|
+
enum: [engineering_readiness_baseline, agentic_ai_roi]
|
|
24198
|
+
sizeBytes:
|
|
24199
|
+
type: integer
|
|
24200
|
+
sha256:
|
|
24201
|
+
type: string
|
|
24202
|
+
description: sha256 of the plaintext PDF.
|
|
24203
|
+
manifestHash:
|
|
24204
|
+
type: string
|
|
24205
|
+
description: "`contentHash` of the validated manifest."
|
|
24206
|
+
createdAt:
|
|
24207
|
+
type: string
|
|
24208
|
+
format: date-time
|
|
24209
|
+
createdBy:
|
|
24210
|
+
type: string
|
|
24211
|
+
format: uuid
|
|
24212
|
+
nullable: true
|
|
24213
|
+
hiddenAt:
|
|
24214
|
+
type: string
|
|
24215
|
+
format: date-time
|
|
24216
|
+
nullable: true
|
|
24217
|
+
restoreUntil:
|
|
24218
|
+
type: string
|
|
24219
|
+
format: date-time
|
|
24220
|
+
nullable: true
|
|
24221
|
+
description: End of the restore window. Not an erasure or backup purge date.
|
|
24222
|
+
status:
|
|
24223
|
+
type: string
|
|
24224
|
+
enum: [available, hidden_restorable, restore_window_ended]
|
|
24225
|
+
links:
|
|
24226
|
+
type: array
|
|
24227
|
+
items:
|
|
24228
|
+
$ref: "#/components/schemas/AssessmentReportLinkDto"
|
|
24229
|
+
|
|
24230
|
+
AssessmentReportListDto:
|
|
24231
|
+
type: object
|
|
24232
|
+
required: [restoreWindowDays, secureLinkDays, reports]
|
|
24233
|
+
properties:
|
|
24234
|
+
restoreWindowDays:
|
|
24235
|
+
type: integer
|
|
24236
|
+
enum: [30]
|
|
24237
|
+
secureLinkDays:
|
|
24238
|
+
type: integer
|
|
24239
|
+
enum: [14]
|
|
24240
|
+
description: Default and maximum secure link lifetime in days.
|
|
24241
|
+
reports:
|
|
24242
|
+
type: array
|
|
24243
|
+
items:
|
|
24244
|
+
$ref: "#/components/schemas/AssessmentReportDto"
|
|
24245
|
+
|
|
24246
|
+
CreateAssessmentReportLinkBodyDto:
|
|
24247
|
+
type: object
|
|
24248
|
+
additionalProperties: false
|
|
24249
|
+
required: [recipientUserId]
|
|
24250
|
+
properties:
|
|
24251
|
+
recipientUserId:
|
|
24252
|
+
type: string
|
|
24253
|
+
format: uuid
|
|
24254
|
+
description: A current workspace member (`TeamMemberDto.id`).
|
|
24255
|
+
expiresInDays:
|
|
24256
|
+
type: integer
|
|
24257
|
+
minimum: 1
|
|
24258
|
+
maximum: 14
|
|
24259
|
+
default: 14
|
|
24260
|
+
|
|
24261
|
+
CreateAssessmentReportLinkResponseDto:
|
|
24262
|
+
type: object
|
|
24263
|
+
required: [link, email]
|
|
24264
|
+
properties:
|
|
24265
|
+
link:
|
|
24266
|
+
$ref: "#/components/schemas/AssessmentReportLinkDto"
|
|
24267
|
+
email:
|
|
24268
|
+
type: string
|
|
24269
|
+
enum: [sent, skipped_missing_smtp, skipped_missing_base_url, failed]
|
|
24270
|
+
|
|
24271
|
+
AssessmentReportAccessErrorDto:
|
|
24272
|
+
type: object
|
|
24273
|
+
required: [error, code]
|
|
24274
|
+
properties:
|
|
24275
|
+
error:
|
|
24276
|
+
type: string
|
|
24277
|
+
code:
|
|
24278
|
+
type: string
|
|
24279
|
+
enum:
|
|
24280
|
+
[
|
|
24281
|
+
leaked_token,
|
|
24282
|
+
removed_member,
|
|
24283
|
+
wrong_workspace,
|
|
24284
|
+
expired,
|
|
24285
|
+
revoked,
|
|
24286
|
+
invalid_grant,
|
|
24287
|
+
report_hidden,
|
|
24288
|
+
]
|
|
24289
|
+
|
|
22710
24290
|
ReportCenterExportRecordResponseDto:
|
|
22711
24291
|
type: object
|
|
22712
24292
|
required: [ok, activityEntryId]
|