@ttctl/core 0.0.0 → 0.1.0-rc.1
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/README.md +49 -9
- package/dist/__generated__/gateway.d.ts +4546 -0
- package/dist/__generated__/gateway.d.ts.map +1 -0
- package/dist/__generated__/gateway.js +9 -0
- package/dist/__generated__/gateway.js.map +1 -0
- package/dist/__generated__/talent-profile-zod-schemas.d.ts +1187 -0
- package/dist/__generated__/talent-profile-zod-schemas.d.ts.map +1 -0
- package/dist/__generated__/talent-profile-zod-schemas.js +1136 -0
- package/dist/__generated__/talent-profile-zod-schemas.js.map +1 -0
- package/dist/__generated__/talent-profile.d.ts +1397 -0
- package/dist/__generated__/talent-profile.d.ts.map +1 -0
- package/dist/__generated__/talent-profile.js +9 -0
- package/dist/__generated__/talent-profile.js.map +1 -0
- package/dist/__generated__/zod-schemas.d.ts +2895 -0
- package/dist/__generated__/zod-schemas.d.ts.map +1 -0
- package/dist/__generated__/zod-schemas.js +3121 -0
- package/dist/__generated__/zod-schemas.js.map +1 -0
- package/dist/__tests__/fixtures/profile/builders.d.ts +74 -0
- package/dist/__tests__/fixtures/profile/builders.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/builders.js +196 -0
- package/dist/__tests__/fixtures/profile/builders.js.map +1 -0
- package/dist/__tests__/fixtures/profile/data.d.ts +39 -0
- package/dist/__tests__/fixtures/profile/data.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/data.js +230 -0
- package/dist/__tests__/fixtures/profile/data.js.map +1 -0
- package/dist/__tests__/fixtures/profile/index.d.ts +9 -0
- package/dist/__tests__/fixtures/profile/index.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/index.js +10 -0
- package/dist/__tests__/fixtures/profile/index.js.map +1 -0
- package/dist/__tests__/fixtures/profile/types.d.ts +53 -0
- package/dist/__tests__/fixtures/profile/types.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/types.js +4 -0
- package/dist/__tests__/fixtures/profile/types.js.map +1 -0
- package/dist/auth/errors.d.ts +82 -0
- package/dist/auth/errors.d.ts.map +1 -0
- package/dist/auth/errors.js +68 -0
- package/dist/auth/errors.js.map +1 -0
- package/dist/auth.d.ts +192 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +294 -0
- package/dist/auth.js.map +1 -0
- package/dist/config.d.ts +212 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +349 -0
- package/dist/config.js.map +1 -0
- package/dist/configLock.d.ts +50 -0
- package/dist/configLock.d.ts.map +1 -0
- package/dist/configLock.js +88 -0
- package/dist/configLock.js.map +1 -0
- package/dist/configWriter.d.ts +97 -0
- package/dist/configWriter.d.ts.map +1 -0
- package/dist/configWriter.js +687 -0
- package/dist/configWriter.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/kill-switch.d.ts +161 -0
- package/dist/kill-switch.d.ts.map +1 -0
- package/dist/kill-switch.js +235 -0
- package/dist/kill-switch.js.map +1 -0
- package/dist/lib/date.d.ts +58 -0
- package/dist/lib/date.d.ts.map +1 -0
- package/dist/lib/date.js +104 -0
- package/dist/lib/date.js.map +1 -0
- package/dist/lib/diagnostic-log.d.ts +159 -0
- package/dist/lib/diagnostic-log.d.ts.map +1 -0
- package/dist/lib/diagnostic-log.js +186 -0
- package/dist/lib/diagnostic-log.js.map +1 -0
- package/dist/lib/package-version.d.ts +19 -0
- package/dist/lib/package-version.d.ts.map +1 -0
- package/dist/lib/package-version.js +38 -0
- package/dist/lib/package-version.js.map +1 -0
- package/dist/lib/redact.d.ts +153 -0
- package/dist/lib/redact.d.ts.map +1 -0
- package/dist/lib/redact.js +207 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/text.d.ts +14 -0
- package/dist/lib/text.d.ts.map +1 -0
- package/dist/lib/text.js +21 -0
- package/dist/lib/text.js.map +1 -0
- package/dist/lib/wire-shape.d.ts +131 -0
- package/dist/lib/wire-shape.d.ts.map +1 -0
- package/dist/lib/wire-shape.js +376 -0
- package/dist/lib/wire-shape.js.map +1 -0
- package/dist/onepassword.d.ts +29 -0
- package/dist/onepassword.d.ts.map +1 -0
- package/dist/onepassword.js +112 -0
- package/dist/onepassword.js.map +1 -0
- package/dist/services/_shared/transport.d.ts +148 -0
- package/dist/services/_shared/transport.d.ts.map +1 -0
- package/dist/services/_shared/transport.js +102 -0
- package/dist/services/_shared/transport.js.map +1 -0
- package/dist/services/applications/index.d.ts +210 -0
- package/dist/services/applications/index.d.ts.map +1 -0
- package/dist/services/applications/index.js +240 -0
- package/dist/services/applications/index.js.map +1 -0
- package/dist/services/availability/index.d.ts +254 -0
- package/dist/services/availability/index.d.ts.map +1 -0
- package/dist/services/availability/index.js +310 -0
- package/dist/services/availability/index.js.map +1 -0
- package/dist/services/contracts/index.d.ts +132 -0
- package/dist/services/contracts/index.d.ts.map +1 -0
- package/dist/services/contracts/index.js +211 -0
- package/dist/services/contracts/index.js.map +1 -0
- package/dist/services/engagements/index.d.ts +504 -0
- package/dist/services/engagements/index.d.ts.map +1 -0
- package/dist/services/engagements/index.js +613 -0
- package/dist/services/engagements/index.js.map +1 -0
- package/dist/services/jobs/index.d.ts +490 -0
- package/dist/services/jobs/index.d.ts.map +1 -0
- package/dist/services/jobs/index.js +753 -0
- package/dist/services/jobs/index.js.map +1 -0
- package/dist/services/payments/index.d.ts +415 -0
- package/dist/services/payments/index.d.ts.map +1 -0
- package/dist/services/payments/index.js +636 -0
- package/dist/services/payments/index.js.map +1 -0
- package/dist/services/profile/__tests__/fixtures.d.ts +214 -0
- package/dist/services/profile/__tests__/fixtures.d.ts.map +1 -0
- package/dist/services/profile/__tests__/fixtures.js +176 -0
- package/dist/services/profile/__tests__/fixtures.js.map +1 -0
- package/dist/services/profile/basic/index.d.ts +390 -0
- package/dist/services/profile/basic/index.d.ts.map +1 -0
- package/dist/services/profile/basic/index.js +1007 -0
- package/dist/services/profile/basic/index.js.map +1 -0
- package/dist/services/profile/certifications/index.d.ts +74 -0
- package/dist/services/profile/certifications/index.d.ts.map +1 -0
- package/dist/services/profile/certifications/index.js +169 -0
- package/dist/services/profile/certifications/index.js.map +1 -0
- package/dist/services/profile/education/index.d.ts +73 -0
- package/dist/services/profile/education/index.d.ts.map +1 -0
- package/dist/services/profile/education/index.js +168 -0
- package/dist/services/profile/education/index.js.map +1 -0
- package/dist/services/profile/employment/index.d.ts +111 -0
- package/dist/services/profile/employment/index.d.ts.map +1 -0
- package/dist/services/profile/employment/index.js +202 -0
- package/dist/services/profile/employment/index.js.map +1 -0
- package/dist/services/profile/external/index.d.ts +219 -0
- package/dist/services/profile/external/index.d.ts.map +1 -0
- package/dist/services/profile/external/index.js +560 -0
- package/dist/services/profile/external/index.js.map +1 -0
- package/dist/services/profile/index.d.ts +24 -0
- package/dist/services/profile/index.d.ts.map +1 -0
- package/dist/services/profile/index.js +26 -0
- package/dist/services/profile/index.js.map +1 -0
- package/dist/services/profile/industries/index.d.ts +130 -0
- package/dist/services/profile/industries/index.d.ts.map +1 -0
- package/dist/services/profile/industries/index.js +292 -0
- package/dist/services/profile/industries/index.js.map +1 -0
- package/dist/services/profile/portfolio/index.d.ts +352 -0
- package/dist/services/profile/portfolio/index.d.ts.map +1 -0
- package/dist/services/profile/portfolio/index.js +833 -0
- package/dist/services/profile/portfolio/index.js.map +1 -0
- package/dist/services/profile/resume/index.d.ts +60 -0
- package/dist/services/profile/resume/index.d.ts.map +1 -0
- package/dist/services/profile/resume/index.js +212 -0
- package/dist/services/profile/resume/index.js.map +1 -0
- package/dist/services/profile/reviews/index.d.ts +137 -0
- package/dist/services/profile/reviews/index.d.ts.map +1 -0
- package/dist/services/profile/reviews/index.js +431 -0
- package/dist/services/profile/reviews/index.js.map +1 -0
- package/dist/services/profile/shared.d.ts +127 -0
- package/dist/services/profile/shared.d.ts.map +1 -0
- package/dist/services/profile/shared.js +155 -0
- package/dist/services/profile/shared.js.map +1 -0
- package/dist/services/profile/skills/index.d.ts +212 -0
- package/dist/services/profile/skills/index.d.ts.map +1 -0
- package/dist/services/profile/skills/index.js +461 -0
- package/dist/services/profile/skills/index.js.map +1 -0
- package/dist/services/profile/visas/index.d.ts +74 -0
- package/dist/services/profile/visas/index.d.ts.map +1 -0
- package/dist/services/profile/visas/index.js +306 -0
- package/dist/services/profile/visas/index.js.map +1 -0
- package/dist/services/timesheet/index.d.ts +326 -0
- package/dist/services/timesheet/index.d.ts.map +1 -0
- package/dist/services/timesheet/index.js +324 -0
- package/dist/services/timesheet/index.js.map +1 -0
- package/dist/services/translations.d.ts +79 -0
- package/dist/services/translations.d.ts.map +1 -0
- package/dist/services/translations.js +136 -0
- package/dist/services/translations.js.map +1 -0
- package/dist/transport-resilience.d.ts +136 -0
- package/dist/transport-resilience.d.ts.map +1 -0
- package/dist/transport-resilience.js +247 -0
- package/dist/transport-resilience.js.map +1 -0
- package/dist/transport.d.ts +408 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +691 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/package.json +40 -12
- package/index.js +0 -7
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
/**
|
|
4
|
+
* Realistic senior-developer fixture data, deliberately fixed (no
|
|
5
|
+
* `new Date()` calls — every date is a hard-coded ISO 8601 string or
|
|
6
|
+
* integer year/month) so snapshot diffs stay deterministic across runs
|
|
7
|
+
* and CI hosts. IDs follow `<entity>_test_<NNN>` so a snapshot diff
|
|
8
|
+
* reads cleanly.
|
|
9
|
+
*
|
|
10
|
+
* No PII: every URL points at the IANA-reserved `example.com` test
|
|
11
|
+
* domain; every company / institution name is a fictitious placeholder
|
|
12
|
+
* (`Acme Financial`, `Mercury Health`, `Stellar Logistics`,
|
|
13
|
+
* `Test Institution`). The fixture entities don't carry email or
|
|
14
|
+
* person-name fields directly — those live on shapes outside this
|
|
15
|
+
* fixture's scope (e.g., the GraphQL `Viewer` type used by
|
|
16
|
+
* `services/profile/__tests__/fixtures.ts`).
|
|
17
|
+
*
|
|
18
|
+
* The persona is loosely modeled on a Toptal-eligible senior backend
|
|
19
|
+
* engineer — enough domain detail (TypeScript / PostgreSQL / Kubernetes
|
|
20
|
+
* stack, distributed-systems portfolio, Stanford CS degree, AWS
|
|
21
|
+
* certifications, fintech/healthtech industry tags) that table-format
|
|
22
|
+
* rendering tests exercise realistic column widths instead of toy data
|
|
23
|
+
* like `"foo"` / `"bar"`.
|
|
24
|
+
*/
|
|
25
|
+
// -----------------------------------------------------------------------
|
|
26
|
+
// Skills
|
|
27
|
+
// -----------------------------------------------------------------------
|
|
28
|
+
// `experience` is a count of months on the wire (see `ProfileSkillSet` —
|
|
29
|
+
// the CLI converts a duration string like `"5y"` to months before
|
|
30
|
+
// calling `set()`). The trailing `// N years` comments below name the
|
|
31
|
+
// month count's intent so readers don't have to divide by 12.
|
|
32
|
+
export const SKILL_TYPESCRIPT = {
|
|
33
|
+
id: "sk_test_001",
|
|
34
|
+
experience: 96, // 8 years
|
|
35
|
+
rating: "EXPERT",
|
|
36
|
+
public: true,
|
|
37
|
+
position: 1,
|
|
38
|
+
skill: { id: "skill_cat_ts", name: "TypeScript" },
|
|
39
|
+
connectionsCount: 4,
|
|
40
|
+
};
|
|
41
|
+
export const SKILL_POSTGRES = {
|
|
42
|
+
id: "sk_test_002",
|
|
43
|
+
experience: 84, // 7 years
|
|
44
|
+
rating: "EXPERT",
|
|
45
|
+
public: true,
|
|
46
|
+
position: 2,
|
|
47
|
+
skill: { id: "skill_cat_pg", name: "PostgreSQL" },
|
|
48
|
+
connectionsCount: 3,
|
|
49
|
+
};
|
|
50
|
+
export const SKILL_KUBERNETES = {
|
|
51
|
+
id: "sk_test_003",
|
|
52
|
+
experience: 48, // 4 years
|
|
53
|
+
rating: "STRONG",
|
|
54
|
+
public: true,
|
|
55
|
+
position: 3,
|
|
56
|
+
skill: { id: "skill_cat_k8s", name: "Kubernetes" },
|
|
57
|
+
connectionsCount: 2,
|
|
58
|
+
};
|
|
59
|
+
export const SKILL_GRAPHQL = {
|
|
60
|
+
id: "sk_test_004",
|
|
61
|
+
experience: 60, // 5 years
|
|
62
|
+
rating: "STRONG",
|
|
63
|
+
public: true,
|
|
64
|
+
position: 4,
|
|
65
|
+
skill: { id: "skill_cat_gql", name: "GraphQL" },
|
|
66
|
+
connectionsCount: 2,
|
|
67
|
+
};
|
|
68
|
+
// -----------------------------------------------------------------------
|
|
69
|
+
// Portfolio — paragraph-bearing entities (description + accomplishment)
|
|
70
|
+
// -----------------------------------------------------------------------
|
|
71
|
+
export const PORTFOLIO_DISTRIBUTED_LEDGER = {
|
|
72
|
+
id: "port_test_001",
|
|
73
|
+
title: "Distributed transaction ledger",
|
|
74
|
+
description: "Designed and shipped a multi-region transaction ledger handling 12k writes/sec at p99 latency under 35ms. " +
|
|
75
|
+
"Built on PostgreSQL logical replication with a custom conflict-resolution layer and an audit trail wired " +
|
|
76
|
+
"into Kafka. Stack: TypeScript, Node 20, PostgreSQL 15, Kafka, Kubernetes on AWS EKS.",
|
|
77
|
+
link: "https://example.com/case-studies/ledger",
|
|
78
|
+
highlight: true,
|
|
79
|
+
coverImage: "https://example.com/covers/ledger.png",
|
|
80
|
+
accomplishment: "Cut reconciliation lead time from 18 hours to under 4 minutes; eliminated a recurring weekend on-call class.",
|
|
81
|
+
publicationPermit: true,
|
|
82
|
+
clientOrCompanyName: "Acme Financial",
|
|
83
|
+
websiteUrl: "https://example.com/acme",
|
|
84
|
+
toptalRelated: true,
|
|
85
|
+
showViaToptal: true,
|
|
86
|
+
kind: "classic",
|
|
87
|
+
skills: [{ id: "sk_test_typescript", name: "TypeScript" }],
|
|
88
|
+
industries: [{ id: "ind_test_finance", name: "Financial Software" }],
|
|
89
|
+
};
|
|
90
|
+
export const PORTFOLIO_EHR_GATEWAY = {
|
|
91
|
+
id: "port_test_002",
|
|
92
|
+
title: "FHIR-compliant EHR gateway",
|
|
93
|
+
description: "Built a HIPAA-compliant gateway exposing a subset of FHIR R4 resources to third-party clinical apps. " +
|
|
94
|
+
"Authentication via SMART-on-FHIR (OAuth 2 + OIDC); per-resource consent enforcement at the API gateway. " +
|
|
95
|
+
"Operated 99.97% uptime over 14 months across three AWS regions.",
|
|
96
|
+
link: "https://example.com/case-studies/fhir-gateway",
|
|
97
|
+
highlight: true,
|
|
98
|
+
coverImage: null,
|
|
99
|
+
accomplishment: "Onboarded 11 partner clinics in the first quarter; passed an external HIPAA audit on first attempt.",
|
|
100
|
+
publicationPermit: true,
|
|
101
|
+
clientOrCompanyName: "Mercury Health",
|
|
102
|
+
websiteUrl: "https://example.com/mercury",
|
|
103
|
+
toptalRelated: false,
|
|
104
|
+
showViaToptal: true,
|
|
105
|
+
kind: "code_base",
|
|
106
|
+
skills: [{ id: "sk_test_typescript", name: "TypeScript" }],
|
|
107
|
+
industries: [{ id: "ind_test_healthcare", name: "Healthcare Software" }],
|
|
108
|
+
};
|
|
109
|
+
export const PORTFOLIO_OBSERVABILITY = {
|
|
110
|
+
id: "port_test_003",
|
|
111
|
+
title: "Internal observability platform",
|
|
112
|
+
description: "Replaced a legacy logging stack with an OpenTelemetry-native observability platform for a 200-engineer org. " +
|
|
113
|
+
"Unified logs, metrics, and traces under a single retention policy; reduced infra spend by 38% while " +
|
|
114
|
+
"doubling cardinality.",
|
|
115
|
+
link: "https://example.com/case-studies/observability",
|
|
116
|
+
highlight: false,
|
|
117
|
+
coverImage: null,
|
|
118
|
+
accomplishment: "MTTR for production incidents dropped from 47 minutes to 11 minutes within two quarters of rollout.",
|
|
119
|
+
publicationPermit: true,
|
|
120
|
+
clientOrCompanyName: "Stellar Logistics",
|
|
121
|
+
websiteUrl: null,
|
|
122
|
+
toptalRelated: false,
|
|
123
|
+
showViaToptal: false,
|
|
124
|
+
kind: "basic",
|
|
125
|
+
skills: [{ id: "sk_test_typescript", name: "TypeScript" }],
|
|
126
|
+
industries: [{ id: "ind_test_software", name: "Software" }],
|
|
127
|
+
};
|
|
128
|
+
// -----------------------------------------------------------------------
|
|
129
|
+
// Employment — paragraph-bearing experienceItems
|
|
130
|
+
// -----------------------------------------------------------------------
|
|
131
|
+
export const EMPLOYMENT_PRINCIPAL_ENGINEER = {
|
|
132
|
+
id: "emp_test_001",
|
|
133
|
+
company: "Acme Financial",
|
|
134
|
+
position: "Principal Engineer",
|
|
135
|
+
companyWebsite: "https://example.com/acme",
|
|
136
|
+
noWebsite: false,
|
|
137
|
+
startDate: 2021,
|
|
138
|
+
endDate: null, // current role
|
|
139
|
+
experienceItems: [
|
|
140
|
+
"Owned the architecture of the multi-region transaction ledger from prototype to production at 12k writes/sec.",
|
|
141
|
+
"Mentored a team of 6 engineers; ran weekly architecture-review forums and pairing sessions on hard-to-debug latency tails.",
|
|
142
|
+
"Drove the migration off a hand-rolled ORM onto Drizzle, removing ~14k lines of bespoke SQL plumbing.",
|
|
143
|
+
],
|
|
144
|
+
highlight: true,
|
|
145
|
+
showViaToptal: true,
|
|
146
|
+
toptalRelated: false,
|
|
147
|
+
};
|
|
148
|
+
export const EMPLOYMENT_SENIOR_ENGINEER = {
|
|
149
|
+
id: "emp_test_002",
|
|
150
|
+
company: "Mercury Health",
|
|
151
|
+
position: "Senior Software Engineer",
|
|
152
|
+
companyWebsite: "https://example.com/mercury",
|
|
153
|
+
noWebsite: false,
|
|
154
|
+
startDate: 2017,
|
|
155
|
+
endDate: 2021,
|
|
156
|
+
experienceItems: [
|
|
157
|
+
"Built the FHIR-compliant EHR gateway from green field to 11 partner clinics in production.",
|
|
158
|
+
"Led the SMART-on-FHIR auth integration; co-authored an internal RFC adopted across two sister product teams.",
|
|
159
|
+
],
|
|
160
|
+
highlight: true,
|
|
161
|
+
showViaToptal: true,
|
|
162
|
+
toptalRelated: false,
|
|
163
|
+
};
|
|
164
|
+
// -----------------------------------------------------------------------
|
|
165
|
+
// Education
|
|
166
|
+
// -----------------------------------------------------------------------
|
|
167
|
+
export const EDUCATION_STANFORD_BS = {
|
|
168
|
+
id: "edu_test_001",
|
|
169
|
+
institution: "Stanford University",
|
|
170
|
+
degree: "Bachelor of Science",
|
|
171
|
+
fieldOfStudy: "Computer Science",
|
|
172
|
+
location: "Stanford, CA",
|
|
173
|
+
title: "BS, Computer Science",
|
|
174
|
+
yearFrom: 2010,
|
|
175
|
+
yearTo: 2014,
|
|
176
|
+
highlight: true,
|
|
177
|
+
};
|
|
178
|
+
// -----------------------------------------------------------------------
|
|
179
|
+
// Certifications
|
|
180
|
+
// -----------------------------------------------------------------------
|
|
181
|
+
export const CERT_AWS_PRO = {
|
|
182
|
+
id: "cert_test_001",
|
|
183
|
+
certificate: "AWS Certified Solutions Architect — Professional",
|
|
184
|
+
institution: "Amazon Web Services",
|
|
185
|
+
link: "https://example.com/cert/aws-pro",
|
|
186
|
+
number: "AWS-SAP-12345",
|
|
187
|
+
validFromMonth: 3,
|
|
188
|
+
validFromYear: 2023,
|
|
189
|
+
validToMonth: 3,
|
|
190
|
+
validToYear: 2026,
|
|
191
|
+
highlight: true,
|
|
192
|
+
};
|
|
193
|
+
export const CERT_CKAD = {
|
|
194
|
+
id: "cert_test_002",
|
|
195
|
+
certificate: "Certified Kubernetes Application Developer",
|
|
196
|
+
institution: "Cloud Native Computing Foundation",
|
|
197
|
+
link: "https://example.com/cert/ckad",
|
|
198
|
+
number: "CKAD-67890",
|
|
199
|
+
validFromMonth: 6,
|
|
200
|
+
validFromYear: 2022,
|
|
201
|
+
validToMonth: 6,
|
|
202
|
+
validToYear: 2025,
|
|
203
|
+
highlight: false,
|
|
204
|
+
};
|
|
205
|
+
// -----------------------------------------------------------------------
|
|
206
|
+
// Industries
|
|
207
|
+
// -----------------------------------------------------------------------
|
|
208
|
+
export const INDUSTRY_FINTECH = {
|
|
209
|
+
id: "ind_test_001",
|
|
210
|
+
title: "Financial services",
|
|
211
|
+
about: "8 years building ledger, payments, and reconciliation systems for B2B fintech.",
|
|
212
|
+
domainArea: "Payments and ledger",
|
|
213
|
+
};
|
|
214
|
+
export const INDUSTRY_HEALTHTECH = {
|
|
215
|
+
id: "ind_test_002",
|
|
216
|
+
title: "Healthcare",
|
|
217
|
+
about: "4 years on HIPAA-compliant clinical-data infrastructure and FHIR integrations.",
|
|
218
|
+
domainArea: "Clinical data exchange",
|
|
219
|
+
};
|
|
220
|
+
// -----------------------------------------------------------------------
|
|
221
|
+
// Travel visas
|
|
222
|
+
// -----------------------------------------------------------------------
|
|
223
|
+
export const VISA_US = {
|
|
224
|
+
id: "visa_test_001",
|
|
225
|
+
countryId: "country_us",
|
|
226
|
+
countryName: "United States",
|
|
227
|
+
visaType: "B1/B2",
|
|
228
|
+
expiryDate: "2030-06-15",
|
|
229
|
+
};
|
|
230
|
+
//# sourceMappingURL=data.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../../../../src/__tests__/fixtures/profile/data.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAYpC;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,0EAA0E;AAC1E,SAAS;AACT,0EAA0E;AAE1E,yEAAyE;AACzE,kEAAkE;AAClE,sEAAsE;AACtE,8DAA8D;AAE9D,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,EAAE,EAAE,aAAa;IACjB,UAAU,EAAE,EAAE,EAAE,UAAU;IAC1B,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,YAAY,EAAE;IACjD,gBAAgB,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,EAAE,EAAE,aAAa;IACjB,UAAU,EAAE,EAAE,EAAE,UAAU;IAC1B,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,YAAY,EAAE;IACjD,gBAAgB,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,EAAE,EAAE,aAAa;IACjB,UAAU,EAAE,EAAE,EAAE,UAAU;IAC1B,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY,EAAE;IAClD,gBAAgB,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAoB;IAC5C,EAAE,EAAE,aAAa;IACjB,UAAU,EAAE,EAAE,EAAE,UAAU;IAC1B,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,IAAI;IACZ,QAAQ,EAAE,CAAC;IACX,KAAK,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE;IAC/C,gBAAgB,EAAE,CAAC;CACpB,CAAC;AAEF,0EAA0E;AAC1E,wEAAwE;AACxE,0EAA0E;AAE1E,MAAM,CAAC,MAAM,4BAA4B,GAAkB;IACzD,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,gCAAgC;IACvC,WAAW,EACT,4GAA4G;QAC5G,2GAA2G;QAC3G,sFAAsF;IACxF,IAAI,EAAE,yCAAyC;IAC/C,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,uCAAuC;IACnD,cAAc,EACZ,8GAA8G;IAChH,iBAAiB,EAAE,IAAI;IACvB,mBAAmB,EAAE,gBAAgB;IACrC,UAAU,EAAE,0BAA0B;IACtC,aAAa,EAAE,IAAI;IACnB,aAAa,EAAE,IAAI;IACnB,IAAI,EAAE,SAAS;IACf,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC1D,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC;CACrE,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAkB;IAClD,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,4BAA4B;IACnC,WAAW,EACT,uGAAuG;QACvG,0GAA0G;QAC1G,iEAAiE;IACnE,IAAI,EAAE,+CAA+C;IACrD,SAAS,EAAE,IAAI;IACf,UAAU,EAAE,IAAI;IAChB,cAAc,EAAE,qGAAqG;IACrH,iBAAiB,EAAE,IAAI;IACvB,mBAAmB,EAAE,gBAAgB;IACrC,UAAU,EAAE,6BAA6B;IACzC,aAAa,EAAE,KAAK;IACpB,aAAa,EAAE,IAAI;IACnB,IAAI,EAAE,WAAW;IACjB,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC1D,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,qBAAqB,EAAE,IAAI,EAAE,qBAAqB,EAAE,CAAC;CACzE,CAAC;AAEF,MAAM,CAAC,MAAM,uBAAuB,GAAkB;IACpD,EAAE,EAAE,eAAe;IACnB,KAAK,EAAE,iCAAiC;IACxC,WAAW,EACT,8GAA8G;QAC9G,sGAAsG;QACtG,uBAAuB;IACzB,IAAI,EAAE,gDAAgD;IACtD,SAAS,EAAE,KAAK;IAChB,UAAU,EAAE,IAAI;IAChB,cAAc,EAAE,qGAAqG;IACrH,iBAAiB,EAAE,IAAI;IACvB,mBAAmB,EAAE,mBAAmB;IACxC,UAAU,EAAE,IAAI;IAChB,aAAa,EAAE,KAAK;IACpB,aAAa,EAAE,KAAK;IACpB,IAAI,EAAE,OAAO;IACb,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;IAC1D,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,mBAAmB,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;CAC5D,CAAC;AAEF,0EAA0E;AAC1E,iDAAiD;AACjD,0EAA0E;AAE1E,MAAM,CAAC,MAAM,6BAA6B,GAAe;IACvD,EAAE,EAAE,cAAc;IAClB,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,oBAAoB;IAC9B,cAAc,EAAE,0BAA0B;IAC1C,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,IAAI,EAAE,eAAe;IAC9B,eAAe,EAAE;QACf,+GAA+G;QAC/G,4HAA4H;QAC5H,sGAAsG;KACvG;IACD,SAAS,EAAE,IAAI;IACf,aAAa,EAAE,IAAI;IACnB,aAAa,EAAE,KAAK;CACrB,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAe;IACpD,EAAE,EAAE,cAAc;IAClB,OAAO,EAAE,gBAAgB;IACzB,QAAQ,EAAE,0BAA0B;IACpC,cAAc,EAAE,6BAA6B;IAC7C,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,IAAI;IACf,OAAO,EAAE,IAAI;IACb,eAAe,EAAE;QACf,4FAA4F;QAC5F,8GAA8G;KAC/G;IACD,SAAS,EAAE,IAAI;IACf,aAAa,EAAE,IAAI;IACnB,aAAa,EAAE,KAAK;CACrB,CAAC;AAEF,0EAA0E;AAC1E,YAAY;AACZ,0EAA0E;AAE1E,MAAM,CAAC,MAAM,qBAAqB,GAAc;IAC9C,EAAE,EAAE,cAAc;IAClB,WAAW,EAAE,qBAAqB;IAClC,MAAM,EAAE,qBAAqB;IAC7B,YAAY,EAAE,kBAAkB;IAChC,QAAQ,EAAE,cAAc;IACxB,KAAK,EAAE,sBAAsB;IAC7B,QAAQ,EAAE,IAAI;IACd,MAAM,EAAE,IAAI;IACZ,SAAS,EAAE,IAAI;CAChB,CAAC;AAEF,0EAA0E;AAC1E,iBAAiB;AACjB,0EAA0E;AAE1E,MAAM,CAAC,MAAM,YAAY,GAAkB;IACzC,EAAE,EAAE,eAAe;IACnB,WAAW,EAAE,kDAAkD;IAC/D,WAAW,EAAE,qBAAqB;IAClC,IAAI,EAAE,kCAAkC;IACxC,MAAM,EAAE,eAAe;IACvB,cAAc,EAAE,CAAC;IACjB,aAAa,EAAE,IAAI;IACnB,YAAY,EAAE,CAAC;IACf,WAAW,EAAE,IAAI;IACjB,SAAS,EAAE,IAAI;CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAkB;IACtC,EAAE,EAAE,eAAe;IACnB,WAAW,EAAE,4CAA4C;IACzD,WAAW,EAAE,mCAAmC;IAChD,IAAI,EAAE,+BAA+B;IACrC,MAAM,EAAE,YAAY;IACpB,cAAc,EAAE,CAAC;IACjB,aAAa,EAAE,IAAI;IACnB,YAAY,EAAE,CAAC;IACf,WAAW,EAAE,IAAI;IACjB,SAAS,EAAE,KAAK;CACjB,CAAC;AAEF,0EAA0E;AAC1E,aAAa;AACb,0EAA0E;AAE1E,MAAM,CAAC,MAAM,gBAAgB,GAAoB;IAC/C,EAAE,EAAE,cAAc;IAClB,KAAK,EAAE,oBAAoB;IAC3B,KAAK,EAAE,gFAAgF;IACvF,UAAU,EAAE,qBAAqB;CAClC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAoB;IAClD,EAAE,EAAE,cAAc;IAClB,KAAK,EAAE,YAAY;IACnB,KAAK,EAAE,gFAAgF;IACvF,UAAU,EAAE,wBAAwB;CACrC,CAAC;AAEF,0EAA0E;AAC1E,eAAe;AACf,0EAA0E;AAE1E,MAAM,CAAC,MAAM,OAAO,GAAe;IACjC,EAAE,EAAE,eAAe;IACnB,SAAS,EAAE,YAAY;IACvB,WAAW,EAAE,eAAe;IAC5B,QAAQ,EAAE,OAAO;IACjB,UAAU,EAAE,YAAY;CACzB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile rendering fixtures — reusable test data for empty / single-item
|
|
3
|
+
* / paragraph-bearing / full / minimal list scenarios. See `README.md`
|
|
4
|
+
* for the full builder API and the rationale behind the
|
|
5
|
+
* `buildParagraphBearingList` shape.
|
|
6
|
+
*/
|
|
7
|
+
export { buildEmptyProfile, buildFullProfile, buildMinimalProfile, buildParagraphBearingList, buildSingleItemList, } from "./builders.js";
|
|
8
|
+
export type { Certification, Education, Employment, IndustryProfile, PortfolioItem, ProfileFixture, ProfileSkillSet, TravelVisa, } from "./types.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/fixtures/profile/index.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AAEH,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,YAAY,EACV,aAAa,EACb,SAAS,EACT,UAAU,EACV,eAAe,EACf,aAAa,EACb,cAAc,EACd,eAAe,EACf,UAAU,GACX,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
/**
|
|
4
|
+
* Profile rendering fixtures — reusable test data for empty / single-item
|
|
5
|
+
* / paragraph-bearing / full / minimal list scenarios. See `README.md`
|
|
6
|
+
* for the full builder API and the rationale behind the
|
|
7
|
+
* `buildParagraphBearingList` shape.
|
|
8
|
+
*/
|
|
9
|
+
export { buildEmptyProfile, buildFullProfile, buildMinimalProfile, buildParagraphBearingList, buildSingleItemList, } from "./builders.js";
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/__tests__/fixtures/profile/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC;;;;;GAKG;AAEH,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,mBAAmB,EACnB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Certification } from "../../../services/profile/certifications/index.js";
|
|
2
|
+
import type { Education } from "../../../services/profile/education/index.js";
|
|
3
|
+
import type { Employment } from "../../../services/profile/employment/index.js";
|
|
4
|
+
import type { IndustryProfile } from "../../../services/profile/industries/index.js";
|
|
5
|
+
import type { PortfolioItem } from "../../../services/profile/portfolio/index.js";
|
|
6
|
+
import type { ProfileSkillSet } from "../../../services/profile/skills/index.js";
|
|
7
|
+
import type { TravelVisa } from "../../../services/profile/visas/index.js";
|
|
8
|
+
/**
|
|
9
|
+
* Fixture-only aggregate bundling every per-domain list a CLI/MCP rendering
|
|
10
|
+
* test might want to drive against in one shape. Production code does not
|
|
11
|
+
* have an aggregate `Profile` — each sub-domain (`profile.skills`,
|
|
12
|
+
* `profile.portfolio`, …) returns its own list — so this aggregate exists
|
|
13
|
+
* solely so test code can write
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* const fx = buildEmptyProfile();
|
|
17
|
+
* expect(fx.skills).toEqual([]);
|
|
18
|
+
* expect(fx.portfolio).toEqual([]);
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Each member is the production entity type verbatim (re-exported from the
|
|
22
|
+
* sub-domain modules — no type duplication, no hand-rolled mock shapes).
|
|
23
|
+
*
|
|
24
|
+
* Note: the issue body referenced a `reviews` list with paragraph-bearing
|
|
25
|
+
* body text, but the production `reviews` domain (`profile.reviews`) is the
|
|
26
|
+
* admin section-review queue (`SectionReview`) with no prose body. The
|
|
27
|
+
* paragraph-bearing fixture therefore populates `portfolio` items with
|
|
28
|
+
* realistic multi-sentence `description` + `accomplishment` content (the
|
|
29
|
+
* actual paragraph-bearing fields in production). See the `README.md`
|
|
30
|
+
* sibling for the rationale.
|
|
31
|
+
*/
|
|
32
|
+
export interface ProfileFixture {
|
|
33
|
+
skills: ProfileSkillSet[];
|
|
34
|
+
portfolio: PortfolioItem[];
|
|
35
|
+
employment: Employment[];
|
|
36
|
+
education: Education[];
|
|
37
|
+
certifications: Certification[];
|
|
38
|
+
industries: IndustryProfile[];
|
|
39
|
+
visas: TravelVisa[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Re-exports of the per-domain entity types so consumers can pull
|
|
43
|
+
* everything they need from one fixture-module path:
|
|
44
|
+
*
|
|
45
|
+
* ```ts
|
|
46
|
+
* import type { ProfileFixture, ProfileSkillSet } from "../fixtures/profile";
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* The re-exports point at the production types — there is no
|
|
50
|
+
* fixture-private variant.
|
|
51
|
+
*/
|
|
52
|
+
export type { Certification, Education, Employment, IndustryProfile, PortfolioItem, ProfileSkillSet, TravelVisa };
|
|
53
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/__tests__/fixtures/profile/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mDAAmD,CAAC;AACvF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8CAA8C,CAAC;AAC9E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+CAA+C,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AACrF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAC;AAClF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0CAA0C,CAAC;AAE3E;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,SAAS,EAAE,aAAa,EAAE,CAAC;IAC3B,UAAU,EAAE,UAAU,EAAE,CAAC;IACzB,SAAS,EAAE,SAAS,EAAE,CAAC;IACvB,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/__tests__/fixtures/profile/types.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-cutting typed-error contract for authentication failures.
|
|
3
|
+
*
|
|
4
|
+
* Each Toptal Talent backend (gateway, talent_profile, scheduler) reports
|
|
5
|
+
* authentication failures with a different wire shape:
|
|
6
|
+
*
|
|
7
|
+
* - gateway → JSON `{ errors: [{ extensions: { code: 'AUTHENTICATION_REQUIRED' } }] }`
|
|
8
|
+
* - talent_profile → JSON `{ errors: [{ extensions: { code: 'UNAUTHENTICATED' } }] }`
|
|
9
|
+
* OR HTML Cloudflare challenge (HTTP 403)
|
|
10
|
+
* - scheduler → JSON `{ error: 'unauthorized' }` (post-v1)
|
|
11
|
+
*
|
|
12
|
+
* Transport and service modules detect each shape and throw a concrete
|
|
13
|
+
* `TtctlError` subclass. Errors are NOT caught at the service layer — they
|
|
14
|
+
* propagate to `@ttctl/cli` (CLI) and `@ttctl/mcp` (MCP) which present them
|
|
15
|
+
* per surface conventions (CLI: human-readable text + exit code; MCP:
|
|
16
|
+
* structured tool-error response).
|
|
17
|
+
*
|
|
18
|
+
* Each subclass carries:
|
|
19
|
+
* - `code` — stable machine-readable identifier (e.g. `'AUTH_REVOKED'`).
|
|
20
|
+
* Script consumers branch on this without parsing prose.
|
|
21
|
+
* - `recovery` — short, actionable user-facing string explaining how to
|
|
22
|
+
* recover. Phrasing should match what the user CAN do, not
|
|
23
|
+
* what TTCtl COULD do internally.
|
|
24
|
+
* - `autoRecover` (optional) — when `true`, signals that the transport or
|
|
25
|
+
* service layer SHOULD attempt recovery once before
|
|
26
|
+
* surfacing the error (e.g. scheduler-bearer re-mint via
|
|
27
|
+
* `GetTopSchedulerToken` post-v1). Defaults to `false`.
|
|
28
|
+
*
|
|
29
|
+
* See `hq/engineering/adr/ADR-005-auth-model.md` for the cross-surface
|
|
30
|
+
* auth model. See issue #77 for the full failure-mode table.
|
|
31
|
+
*/
|
|
32
|
+
export declare abstract class TtctlError extends Error {
|
|
33
|
+
/**
|
|
34
|
+
* Stable, machine-readable error code. Subclasses provide a literal string
|
|
35
|
+
* (e.g. `'AUTH_REVOKED'`, `'CF_403_CLEARANCE'`). Script consumers branch
|
|
36
|
+
* on this; the value is part of the public API and should not change
|
|
37
|
+
* casually.
|
|
38
|
+
*/
|
|
39
|
+
abstract readonly code: string;
|
|
40
|
+
/**
|
|
41
|
+
* Short, actionable user-facing string. Phrased imperatively where the
|
|
42
|
+
* user can take an action (e.g. `Run \`ttctl auth signin\` to
|
|
43
|
+
* re-authenticate.`). Phrased descriptively where there is no clean user
|
|
44
|
+
* action (e.g. `Cloudflare's bot-management has flipped a feature flag.
|
|
45
|
+
* File an issue at ...`). Surface-renderers (CLI / MCP) pass this through
|
|
46
|
+
* verbatim.
|
|
47
|
+
*/
|
|
48
|
+
abstract readonly recovery: string;
|
|
49
|
+
/**
|
|
50
|
+
* When `true`, the transport or service layer should attempt automated
|
|
51
|
+
* recovery once before surfacing this error to the user. Concrete
|
|
52
|
+
* subclasses opt in by overriding to `true` (e.g. `SchedulerBearerExpired`
|
|
53
|
+
* post-v1, where `GetTopSchedulerToken` re-mints transparently).
|
|
54
|
+
*
|
|
55
|
+
* Default `false` — most auth failures (revoked token, Cloudflare block)
|
|
56
|
+
* require user intervention and cannot be auto-recovered.
|
|
57
|
+
*/
|
|
58
|
+
readonly autoRecover: boolean;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Authentication revoked or expired — the token TTCtl is replaying as
|
|
62
|
+
* `Authorization: Token token=<X>` is no longer accepted by the gateway.
|
|
63
|
+
*
|
|
64
|
+
* Detected at the service layer when:
|
|
65
|
+
* - HTTP response is 401, OR
|
|
66
|
+
* - GraphQL response carries `errors[0].extensions.code` equal to
|
|
67
|
+
* `'AUTHENTICATION_REQUIRED'` (gateway form) or `'UNAUTHENTICATED'`
|
|
68
|
+
* (talent_profile form).
|
|
69
|
+
*
|
|
70
|
+
* Recovery is unambiguous: the user runs `ttctl auth signin` to re-mint a
|
|
71
|
+
* session token. There is no automated path — sign-in requires credentials
|
|
72
|
+
* the agent does not have.
|
|
73
|
+
*/
|
|
74
|
+
export declare class AuthRevokedError extends TtctlError {
|
|
75
|
+
readonly name = "AuthRevokedError";
|
|
76
|
+
readonly code = "AUTH_REVOKED";
|
|
77
|
+
readonly recovery = "Run `ttctl auth signin` to re-authenticate.";
|
|
78
|
+
constructor(message?: string, options?: {
|
|
79
|
+
cause?: unknown;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/auth/errors.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,8BAAsB,UAAW,SAAQ,KAAK;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAE/B;;;;;;;OAOG;IACH,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAEnC;;;;;;;;OAQG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAS;CACvC;AAED;;;;;;;;;;;;;GAaG;AACH,qBAAa,gBAAiB,SAAQ,UAAU;IAC9C,SAAkB,IAAI,sBAAsB;IAC5C,QAAQ,CAAC,IAAI,kBAAkB;IAC/B,QAAQ,CAAC,QAAQ,iDAAiD;gBAEtD,OAAO,GAAE,MAAyC,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAG9F"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
/**
|
|
4
|
+
* Cross-cutting typed-error contract for authentication failures.
|
|
5
|
+
*
|
|
6
|
+
* Each Toptal Talent backend (gateway, talent_profile, scheduler) reports
|
|
7
|
+
* authentication failures with a different wire shape:
|
|
8
|
+
*
|
|
9
|
+
* - gateway → JSON `{ errors: [{ extensions: { code: 'AUTHENTICATION_REQUIRED' } }] }`
|
|
10
|
+
* - talent_profile → JSON `{ errors: [{ extensions: { code: 'UNAUTHENTICATED' } }] }`
|
|
11
|
+
* OR HTML Cloudflare challenge (HTTP 403)
|
|
12
|
+
* - scheduler → JSON `{ error: 'unauthorized' }` (post-v1)
|
|
13
|
+
*
|
|
14
|
+
* Transport and service modules detect each shape and throw a concrete
|
|
15
|
+
* `TtctlError` subclass. Errors are NOT caught at the service layer — they
|
|
16
|
+
* propagate to `@ttctl/cli` (CLI) and `@ttctl/mcp` (MCP) which present them
|
|
17
|
+
* per surface conventions (CLI: human-readable text + exit code; MCP:
|
|
18
|
+
* structured tool-error response).
|
|
19
|
+
*
|
|
20
|
+
* Each subclass carries:
|
|
21
|
+
* - `code` — stable machine-readable identifier (e.g. `'AUTH_REVOKED'`).
|
|
22
|
+
* Script consumers branch on this without parsing prose.
|
|
23
|
+
* - `recovery` — short, actionable user-facing string explaining how to
|
|
24
|
+
* recover. Phrasing should match what the user CAN do, not
|
|
25
|
+
* what TTCtl COULD do internally.
|
|
26
|
+
* - `autoRecover` (optional) — when `true`, signals that the transport or
|
|
27
|
+
* service layer SHOULD attempt recovery once before
|
|
28
|
+
* surfacing the error (e.g. scheduler-bearer re-mint via
|
|
29
|
+
* `GetTopSchedulerToken` post-v1). Defaults to `false`.
|
|
30
|
+
*
|
|
31
|
+
* See `hq/engineering/adr/ADR-005-auth-model.md` for the cross-surface
|
|
32
|
+
* auth model. See issue #77 for the full failure-mode table.
|
|
33
|
+
*/
|
|
34
|
+
export class TtctlError extends Error {
|
|
35
|
+
/**
|
|
36
|
+
* When `true`, the transport or service layer should attempt automated
|
|
37
|
+
* recovery once before surfacing this error to the user. Concrete
|
|
38
|
+
* subclasses opt in by overriding to `true` (e.g. `SchedulerBearerExpired`
|
|
39
|
+
* post-v1, where `GetTopSchedulerToken` re-mints transparently).
|
|
40
|
+
*
|
|
41
|
+
* Default `false` — most auth failures (revoked token, Cloudflare block)
|
|
42
|
+
* require user intervention and cannot be auto-recovered.
|
|
43
|
+
*/
|
|
44
|
+
autoRecover = false;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Authentication revoked or expired — the token TTCtl is replaying as
|
|
48
|
+
* `Authorization: Token token=<X>` is no longer accepted by the gateway.
|
|
49
|
+
*
|
|
50
|
+
* Detected at the service layer when:
|
|
51
|
+
* - HTTP response is 401, OR
|
|
52
|
+
* - GraphQL response carries `errors[0].extensions.code` equal to
|
|
53
|
+
* `'AUTHENTICATION_REQUIRED'` (gateway form) or `'UNAUTHENTICATED'`
|
|
54
|
+
* (talent_profile form).
|
|
55
|
+
*
|
|
56
|
+
* Recovery is unambiguous: the user runs `ttctl auth signin` to re-mint a
|
|
57
|
+
* session token. There is no automated path — sign-in requires credentials
|
|
58
|
+
* the agent does not have.
|
|
59
|
+
*/
|
|
60
|
+
export class AuthRevokedError extends TtctlError {
|
|
61
|
+
name = "AuthRevokedError";
|
|
62
|
+
code = "AUTH_REVOKED";
|
|
63
|
+
recovery = "Run `ttctl auth signin` to re-authenticate.";
|
|
64
|
+
constructor(message = "Session is invalid or expired.", options) {
|
|
65
|
+
super(message, options);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/auth/errors.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,OAAgB,UAAW,SAAQ,KAAK;IAmB5C;;;;;;;;OAQG;IACM,WAAW,GAAY,KAAK,CAAC;CACvC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,gBAAiB,SAAQ,UAAU;IAC5B,IAAI,GAAG,kBAAkB,CAAC;IACnC,IAAI,GAAG,cAAc,CAAC;IACtB,QAAQ,GAAG,6CAA6C,CAAC;IAElE,YAAY,UAAkB,gCAAgC,EAAE,OAA6B;QAC3F,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC1B,CAAC;CACF"}
|