@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.
Files changed (195) hide show
  1. package/README.md +49 -9
  2. package/dist/__generated__/gateway.d.ts +4546 -0
  3. package/dist/__generated__/gateway.d.ts.map +1 -0
  4. package/dist/__generated__/gateway.js +9 -0
  5. package/dist/__generated__/gateway.js.map +1 -0
  6. package/dist/__generated__/talent-profile-zod-schemas.d.ts +1187 -0
  7. package/dist/__generated__/talent-profile-zod-schemas.d.ts.map +1 -0
  8. package/dist/__generated__/talent-profile-zod-schemas.js +1136 -0
  9. package/dist/__generated__/talent-profile-zod-schemas.js.map +1 -0
  10. package/dist/__generated__/talent-profile.d.ts +1397 -0
  11. package/dist/__generated__/talent-profile.d.ts.map +1 -0
  12. package/dist/__generated__/talent-profile.js +9 -0
  13. package/dist/__generated__/talent-profile.js.map +1 -0
  14. package/dist/__generated__/zod-schemas.d.ts +2895 -0
  15. package/dist/__generated__/zod-schemas.d.ts.map +1 -0
  16. package/dist/__generated__/zod-schemas.js +3121 -0
  17. package/dist/__generated__/zod-schemas.js.map +1 -0
  18. package/dist/__tests__/fixtures/profile/builders.d.ts +74 -0
  19. package/dist/__tests__/fixtures/profile/builders.d.ts.map +1 -0
  20. package/dist/__tests__/fixtures/profile/builders.js +196 -0
  21. package/dist/__tests__/fixtures/profile/builders.js.map +1 -0
  22. package/dist/__tests__/fixtures/profile/data.d.ts +39 -0
  23. package/dist/__tests__/fixtures/profile/data.d.ts.map +1 -0
  24. package/dist/__tests__/fixtures/profile/data.js +230 -0
  25. package/dist/__tests__/fixtures/profile/data.js.map +1 -0
  26. package/dist/__tests__/fixtures/profile/index.d.ts +9 -0
  27. package/dist/__tests__/fixtures/profile/index.d.ts.map +1 -0
  28. package/dist/__tests__/fixtures/profile/index.js +10 -0
  29. package/dist/__tests__/fixtures/profile/index.js.map +1 -0
  30. package/dist/__tests__/fixtures/profile/types.d.ts +53 -0
  31. package/dist/__tests__/fixtures/profile/types.d.ts.map +1 -0
  32. package/dist/__tests__/fixtures/profile/types.js +4 -0
  33. package/dist/__tests__/fixtures/profile/types.js.map +1 -0
  34. package/dist/auth/errors.d.ts +82 -0
  35. package/dist/auth/errors.d.ts.map +1 -0
  36. package/dist/auth/errors.js +68 -0
  37. package/dist/auth/errors.js.map +1 -0
  38. package/dist/auth.d.ts +192 -0
  39. package/dist/auth.d.ts.map +1 -0
  40. package/dist/auth.js +294 -0
  41. package/dist/auth.js.map +1 -0
  42. package/dist/config.d.ts +212 -0
  43. package/dist/config.d.ts.map +1 -0
  44. package/dist/config.js +349 -0
  45. package/dist/config.js.map +1 -0
  46. package/dist/configLock.d.ts +50 -0
  47. package/dist/configLock.d.ts.map +1 -0
  48. package/dist/configLock.js +88 -0
  49. package/dist/configLock.js.map +1 -0
  50. package/dist/configWriter.d.ts +97 -0
  51. package/dist/configWriter.d.ts.map +1 -0
  52. package/dist/configWriter.js +687 -0
  53. package/dist/configWriter.js.map +1 -0
  54. package/dist/index.d.ts +37 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +28 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/kill-switch.d.ts +161 -0
  59. package/dist/kill-switch.d.ts.map +1 -0
  60. package/dist/kill-switch.js +235 -0
  61. package/dist/kill-switch.js.map +1 -0
  62. package/dist/lib/date.d.ts +58 -0
  63. package/dist/lib/date.d.ts.map +1 -0
  64. package/dist/lib/date.js +104 -0
  65. package/dist/lib/date.js.map +1 -0
  66. package/dist/lib/diagnostic-log.d.ts +159 -0
  67. package/dist/lib/diagnostic-log.d.ts.map +1 -0
  68. package/dist/lib/diagnostic-log.js +186 -0
  69. package/dist/lib/diagnostic-log.js.map +1 -0
  70. package/dist/lib/package-version.d.ts +19 -0
  71. package/dist/lib/package-version.d.ts.map +1 -0
  72. package/dist/lib/package-version.js +38 -0
  73. package/dist/lib/package-version.js.map +1 -0
  74. package/dist/lib/redact.d.ts +153 -0
  75. package/dist/lib/redact.d.ts.map +1 -0
  76. package/dist/lib/redact.js +207 -0
  77. package/dist/lib/redact.js.map +1 -0
  78. package/dist/lib/text.d.ts +14 -0
  79. package/dist/lib/text.d.ts.map +1 -0
  80. package/dist/lib/text.js +21 -0
  81. package/dist/lib/text.js.map +1 -0
  82. package/dist/lib/wire-shape.d.ts +131 -0
  83. package/dist/lib/wire-shape.d.ts.map +1 -0
  84. package/dist/lib/wire-shape.js +376 -0
  85. package/dist/lib/wire-shape.js.map +1 -0
  86. package/dist/onepassword.d.ts +29 -0
  87. package/dist/onepassword.d.ts.map +1 -0
  88. package/dist/onepassword.js +112 -0
  89. package/dist/onepassword.js.map +1 -0
  90. package/dist/services/_shared/transport.d.ts +148 -0
  91. package/dist/services/_shared/transport.d.ts.map +1 -0
  92. package/dist/services/_shared/transport.js +102 -0
  93. package/dist/services/_shared/transport.js.map +1 -0
  94. package/dist/services/applications/index.d.ts +210 -0
  95. package/dist/services/applications/index.d.ts.map +1 -0
  96. package/dist/services/applications/index.js +240 -0
  97. package/dist/services/applications/index.js.map +1 -0
  98. package/dist/services/availability/index.d.ts +254 -0
  99. package/dist/services/availability/index.d.ts.map +1 -0
  100. package/dist/services/availability/index.js +310 -0
  101. package/dist/services/availability/index.js.map +1 -0
  102. package/dist/services/contracts/index.d.ts +132 -0
  103. package/dist/services/contracts/index.d.ts.map +1 -0
  104. package/dist/services/contracts/index.js +211 -0
  105. package/dist/services/contracts/index.js.map +1 -0
  106. package/dist/services/engagements/index.d.ts +504 -0
  107. package/dist/services/engagements/index.d.ts.map +1 -0
  108. package/dist/services/engagements/index.js +613 -0
  109. package/dist/services/engagements/index.js.map +1 -0
  110. package/dist/services/jobs/index.d.ts +490 -0
  111. package/dist/services/jobs/index.d.ts.map +1 -0
  112. package/dist/services/jobs/index.js +753 -0
  113. package/dist/services/jobs/index.js.map +1 -0
  114. package/dist/services/payments/index.d.ts +415 -0
  115. package/dist/services/payments/index.d.ts.map +1 -0
  116. package/dist/services/payments/index.js +636 -0
  117. package/dist/services/payments/index.js.map +1 -0
  118. package/dist/services/profile/__tests__/fixtures.d.ts +214 -0
  119. package/dist/services/profile/__tests__/fixtures.d.ts.map +1 -0
  120. package/dist/services/profile/__tests__/fixtures.js +176 -0
  121. package/dist/services/profile/__tests__/fixtures.js.map +1 -0
  122. package/dist/services/profile/basic/index.d.ts +390 -0
  123. package/dist/services/profile/basic/index.d.ts.map +1 -0
  124. package/dist/services/profile/basic/index.js +1007 -0
  125. package/dist/services/profile/basic/index.js.map +1 -0
  126. package/dist/services/profile/certifications/index.d.ts +74 -0
  127. package/dist/services/profile/certifications/index.d.ts.map +1 -0
  128. package/dist/services/profile/certifications/index.js +169 -0
  129. package/dist/services/profile/certifications/index.js.map +1 -0
  130. package/dist/services/profile/education/index.d.ts +73 -0
  131. package/dist/services/profile/education/index.d.ts.map +1 -0
  132. package/dist/services/profile/education/index.js +168 -0
  133. package/dist/services/profile/education/index.js.map +1 -0
  134. package/dist/services/profile/employment/index.d.ts +111 -0
  135. package/dist/services/profile/employment/index.d.ts.map +1 -0
  136. package/dist/services/profile/employment/index.js +202 -0
  137. package/dist/services/profile/employment/index.js.map +1 -0
  138. package/dist/services/profile/external/index.d.ts +219 -0
  139. package/dist/services/profile/external/index.d.ts.map +1 -0
  140. package/dist/services/profile/external/index.js +560 -0
  141. package/dist/services/profile/external/index.js.map +1 -0
  142. package/dist/services/profile/index.d.ts +24 -0
  143. package/dist/services/profile/index.d.ts.map +1 -0
  144. package/dist/services/profile/index.js +26 -0
  145. package/dist/services/profile/index.js.map +1 -0
  146. package/dist/services/profile/industries/index.d.ts +130 -0
  147. package/dist/services/profile/industries/index.d.ts.map +1 -0
  148. package/dist/services/profile/industries/index.js +292 -0
  149. package/dist/services/profile/industries/index.js.map +1 -0
  150. package/dist/services/profile/portfolio/index.d.ts +352 -0
  151. package/dist/services/profile/portfolio/index.d.ts.map +1 -0
  152. package/dist/services/profile/portfolio/index.js +833 -0
  153. package/dist/services/profile/portfolio/index.js.map +1 -0
  154. package/dist/services/profile/resume/index.d.ts +60 -0
  155. package/dist/services/profile/resume/index.d.ts.map +1 -0
  156. package/dist/services/profile/resume/index.js +212 -0
  157. package/dist/services/profile/resume/index.js.map +1 -0
  158. package/dist/services/profile/reviews/index.d.ts +137 -0
  159. package/dist/services/profile/reviews/index.d.ts.map +1 -0
  160. package/dist/services/profile/reviews/index.js +431 -0
  161. package/dist/services/profile/reviews/index.js.map +1 -0
  162. package/dist/services/profile/shared.d.ts +127 -0
  163. package/dist/services/profile/shared.d.ts.map +1 -0
  164. package/dist/services/profile/shared.js +155 -0
  165. package/dist/services/profile/shared.js.map +1 -0
  166. package/dist/services/profile/skills/index.d.ts +212 -0
  167. package/dist/services/profile/skills/index.d.ts.map +1 -0
  168. package/dist/services/profile/skills/index.js +461 -0
  169. package/dist/services/profile/skills/index.js.map +1 -0
  170. package/dist/services/profile/visas/index.d.ts +74 -0
  171. package/dist/services/profile/visas/index.d.ts.map +1 -0
  172. package/dist/services/profile/visas/index.js +306 -0
  173. package/dist/services/profile/visas/index.js.map +1 -0
  174. package/dist/services/timesheet/index.d.ts +326 -0
  175. package/dist/services/timesheet/index.d.ts.map +1 -0
  176. package/dist/services/timesheet/index.js +324 -0
  177. package/dist/services/timesheet/index.js.map +1 -0
  178. package/dist/services/translations.d.ts +79 -0
  179. package/dist/services/translations.d.ts.map +1 -0
  180. package/dist/services/translations.js +136 -0
  181. package/dist/services/translations.js.map +1 -0
  182. package/dist/transport-resilience.d.ts +136 -0
  183. package/dist/transport-resilience.d.ts.map +1 -0
  184. package/dist/transport-resilience.js +247 -0
  185. package/dist/transport-resilience.js.map +1 -0
  186. package/dist/transport.d.ts +408 -0
  187. package/dist/transport.d.ts.map +1 -0
  188. package/dist/transport.js +691 -0
  189. package/dist/transport.js.map +1 -0
  190. package/dist/types.d.ts +41 -0
  191. package/dist/types.d.ts.map +1 -0
  192. package/dist/types.js +18 -0
  193. package/dist/types.js.map +1 -0
  194. package/package.json +40 -12
  195. package/index.js +0 -7
@@ -0,0 +1,104 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ /**
4
+ * Typed error thrown by {@link parseDateInput} for malformed user input.
5
+ * Callers render the standard `<command> failed (<code>): <message>` shape
6
+ * and exit non-zero before any network call is made.
7
+ */
8
+ export class DateInputError extends Error {
9
+ code;
10
+ name = "DateInputError";
11
+ constructor(code, message) {
12
+ super(message);
13
+ this.code = code;
14
+ }
15
+ }
16
+ const ISO_DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
17
+ const YEAR_ONLY_RE = /^(\d{4})$/;
18
+ /**
19
+ * Parse a free-form date flag value into a {@link ParsedDate}.
20
+ *
21
+ * Accepts:
22
+ * - **ISO-8601 date** (`YYYY-MM-DD`, e.g. `2023-01-15`) — preserves all three
23
+ * fields. Validates the date is a real calendar date (rejects 2023-02-30,
24
+ * 2023-13-01, etc.).
25
+ * - **Year-only** (`YYYY`, e.g. `2023`) — defaults `month` and `day` to `1`
26
+ * per issue #74's "internally treated as January 1st" rule.
27
+ *
28
+ * Throws {@link DateInputError} with code `INVALID_DATE` on:
29
+ * - Empty / non-string input
30
+ * - Format that matches neither shape
31
+ * - Out-of-range year (rejects years before 1900 or after the current year + 30
32
+ * to catch obvious typos like `203` or `20230` being written as a YYYY)
33
+ * - Out-of-range month or day for a real calendar date
34
+ *
35
+ * The helper is pure — no I/O — so it can be unit-tested directly.
36
+ *
37
+ * @param raw - the raw flag value as supplied by the user
38
+ * @param flagName - the user-facing flag name (e.g. `"from"`, `"issued"`),
39
+ * surfaced in error messages so the user knows which flag is wrong
40
+ */
41
+ export function parseDateInput(raw, flagName) {
42
+ if (typeof raw !== "string" || raw.length === 0) {
43
+ throw new DateInputError("INVALID_DATE", `--${flagName}: expected ISO-8601 date (YYYY-MM-DD) or year (YYYY); got empty input`);
44
+ }
45
+ const trimmed = raw.trim();
46
+ const isoMatch = ISO_DATE_RE.exec(trimmed);
47
+ if (isoMatch !== null) {
48
+ const year = Number(isoMatch[1]);
49
+ const month = Number(isoMatch[2]);
50
+ const day = Number(isoMatch[3]);
51
+ validateYear(year, flagName, trimmed);
52
+ validateMonth(month, flagName, trimmed);
53
+ validateDay(year, month, day, flagName, trimmed);
54
+ return { year, month, day };
55
+ }
56
+ const yearMatch = YEAR_ONLY_RE.exec(trimmed);
57
+ if (yearMatch !== null) {
58
+ const year = Number(yearMatch[1]);
59
+ validateYear(year, flagName, trimmed);
60
+ return { year, month: 1, day: 1 };
61
+ }
62
+ throw new DateInputError("INVALID_DATE", `--${flagName}: expected ISO-8601 date (YYYY-MM-DD) or year (YYYY); got "${trimmed}"`);
63
+ }
64
+ /**
65
+ * Year sanity check. The issue spec says "ISO-8601 (`2023-01-15`) or
66
+ * year-only (`2023`)" — anything dramatically before or after the
67
+ * professional-history range is almost certainly a typo. We use a loose
68
+ * 1900..(currentYear+30) window so the helper isn't a maintenance burden
69
+ * but still catches `203` (a typo for `2023`) and `20230` (a typo too).
70
+ */
71
+ function validateYear(year, flagName, raw) {
72
+ const currentYear = new Date().getUTCFullYear();
73
+ if (year < 1900 || year > currentYear + 30) {
74
+ throw new DateInputError("INVALID_DATE", `--${flagName}: year ${year.toString()} is out of plausible range (1900..${(currentYear + 30).toString()}); got "${raw}"`);
75
+ }
76
+ }
77
+ function validateMonth(month, flagName, raw) {
78
+ if (month < 1 || month > 12) {
79
+ throw new DateInputError("INVALID_DATE", `--${flagName}: month ${month.toString()} is out of range (1..12); got "${raw}"`);
80
+ }
81
+ }
82
+ /**
83
+ * Validate `day` falls within the given `month` of the given `year`. Uses
84
+ * `Date` round-tripping rather than a hand-rolled days-per-month table so
85
+ * leap-year edge cases (Feb 29 of a leap year, NOT of a non-leap year) are
86
+ * handled correctly.
87
+ *
88
+ * `Date.UTC(year, monthZeroIndexed, day)` returns NaN for impossible dates
89
+ * but more importantly silently rolls over (e.g. `Date.UTC(2023, 1, 30)` =
90
+ * March 2). The reconstruction check catches the rollover.
91
+ */
92
+ function validateDay(year, month, day, flagName, raw) {
93
+ if (day < 1 || day > 31) {
94
+ throw new DateInputError("INVALID_DATE", `--${flagName}: day ${day.toString()} is out of range (1..31); got "${raw}"`);
95
+ }
96
+ const utc = Date.UTC(year, month - 1, day);
97
+ const reconstructed = new Date(utc);
98
+ if (reconstructed.getUTCFullYear() !== year ||
99
+ reconstructed.getUTCMonth() !== month - 1 ||
100
+ reconstructed.getUTCDate() !== day) {
101
+ throw new DateInputError("INVALID_DATE", `--${flagName}: ${raw} is not a real calendar date`);
102
+ }
103
+ }
104
+ //# sourceMappingURL=date.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"date.js","sourceRoot":"","sources":["../../src/lib/date.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,159 @@
1
+ /**
2
+ * Diagnostic log level controlling transport-side observability emitted
3
+ * to stderr (issue #139). Three states:
4
+ *
5
+ * - `"none"` — default; all log functions are no-ops. The disabled path
6
+ * is constant-folded against the module-scoped `currentLevel` so
7
+ * the cost is a single integer comparison per transport call.
8
+ * - `"verbose"` — emit one line per transport request and one line per
9
+ * response, of shape: `POST <url> operation=<op>` and
10
+ * `<status> <reasonPhrase> (elapsedMs=<n>)`. Suitable for "what is
11
+ * the CLI doing" diagnostics without exposing wire content.
12
+ * - `"debug"` — emit a single JSON-encoded record per request and per
13
+ * response, including redacted headers and redacted body. Suitable
14
+ * for paste-into-issue debugging. The bearer token (in the
15
+ * `authorization` header) and any cookie values are redacted before
16
+ * serialization per the `redact` module.
17
+ *
18
+ * Output channel is `process.stderr` exclusively (AC #5 of issue #139).
19
+ * The data channel (`process.stdout`, the json/yaml/pretty envelopes
20
+ * locked under #126 / #128) is never touched by this module.
21
+ */
22
+ export type DiagnosticLevel = "none" | "verbose" | "debug";
23
+ /**
24
+ * Set the diagnostic level. Called by the CLI's `preAction` hook once
25
+ * per invocation when `--verbose` or `--debug` is present. Setting
26
+ * `"none"` (or omitting the call) keeps the disabled path active.
27
+ *
28
+ * Precedence (for the CLI hook, not enforced here): `--debug` wins over
29
+ * `--verbose` if both are passed. The decision lives in `program.ts`;
30
+ * this function takes whatever level the caller computed.
31
+ */
32
+ export declare function setDiagnosticLogger(level: DiagnosticLevel): void;
33
+ /**
34
+ * Read the captured diagnostic level. Returns `"none"` when no level
35
+ * has been set (the default).
36
+ */
37
+ export declare function getDiagnosticLogger(): DiagnosticLevel;
38
+ /**
39
+ * Reset to `"none"`. Tests call this in `beforeEach` to keep the
40
+ * module-scoped state isolated. Production code never needs to call
41
+ * this — the CLI's `preAction` hook sets the level once per invocation.
42
+ */
43
+ export declare function resetDiagnosticLogger(): void;
44
+ /**
45
+ * Information about a transport request, captured by the transport
46
+ * layer before the network call. Shape mirrors `TransportRequest` /
47
+ * `MultipartTransportRequest` but is decoupled from those types so
48
+ * future transport additions can log without circular dependencies.
49
+ *
50
+ * `body` is the parsed request envelope (operation name, variables) —
51
+ * NOT the JSON-stringified wire bytes. Redaction is applied by this
52
+ * module on emission.
53
+ */
54
+ export interface RequestLogInfo {
55
+ surface: string;
56
+ endpoint: string;
57
+ transport: "stock" | "impersonated" | "impersonated-multipart";
58
+ method: string;
59
+ operationName: string;
60
+ headers: Record<string, string>;
61
+ body: unknown;
62
+ /**
63
+ * Multipart upload metadata for `impersonated-multipart` requests:
64
+ * the file slot labels and the variable paths they bind to. The
65
+ * binary contents of the files are NOT included (intentionally —
66
+ * binary content is not useful in a diagnostic trace).
67
+ */
68
+ multipart?: {
69
+ files: string[];
70
+ map: Record<string, string[]>;
71
+ };
72
+ }
73
+ /**
74
+ * Information about a transport response, captured AFTER the network
75
+ * call completes. `body` is the parsed response envelope (when JSON)
76
+ * or the raw text (when the response was not JSON). `elapsedMs` is
77
+ * `performance.now()`-derived monotonic elapsed milliseconds from
78
+ * request start, so it stays accurate across wall-clock adjustments
79
+ * during the call.
80
+ */
81
+ export interface ResponseLogInfo {
82
+ surface: string;
83
+ endpoint: string;
84
+ operationName: string;
85
+ status: number;
86
+ headers: Record<string, string>;
87
+ body: unknown;
88
+ elapsedMs: number;
89
+ }
90
+ /**
91
+ * Emit a `--verbose` / `--debug` line for a transport REQUEST.
92
+ *
93
+ * - `"none"`: no-op (single comparison, no allocation).
94
+ * - `"verbose"`: emits one line `POST <endpoint> operation=<op>`.
95
+ * - `"debug"`: emits one JSON-encoded line containing the redacted
96
+ * request envelope: surface, transport, endpoint, method, operation
97
+ * name, redacted headers, redacted body, optional multipart map.
98
+ * Bearer token (`authorization` header) and cookie values are
99
+ * replaced with `***REDACTED***` per the `redact` module BEFORE
100
+ * JSON.stringify, so the serialized line cannot leak any secret.
101
+ *
102
+ * Writes to `process.stderr` only; never touches `process.stdout`.
103
+ */
104
+ export declare function logTransportRequest(info: RequestLogInfo): void;
105
+ /**
106
+ * Emit a `--verbose` / `--debug` line for a transport RESPONSE.
107
+ *
108
+ * - `"none"`: no-op.
109
+ * - `"verbose"`: emits one line `<status> <reasonPhrase> (elapsedMs=<n>)`.
110
+ * `<reasonPhrase>` is derived from {@link HTTP_REASON_PHRASES}; for
111
+ * uncatalogued status codes (rare; non-standard 7xx etc.), the
112
+ * phrase is `"-"`.
113
+ * - `"debug"`: emits one JSON-encoded line containing the redacted
114
+ * response envelope: surface, endpoint, operation name, status,
115
+ * redacted headers, redacted body, elapsed milliseconds. The
116
+ * response body is redacted because Toptal occasionally echoes
117
+ * session-bearing fields back to the caller (per issue #139 spec).
118
+ *
119
+ * Writes to `process.stderr` only.
120
+ */
121
+ export declare function logTransportResponse(info: ResponseLogInfo): void;
122
+ /**
123
+ * Information about a transport retry event, captured when the resilience
124
+ * loop decides to back off and re-issue the request. `reason` discriminates
125
+ * the trigger (429 rate-limit, 5xx transient server error, or a per-attempt
126
+ * timeout). `delayMs` is the wait the loop is about to sleep for; `attempt`
127
+ * is the 1-indexed retry counter (1 = first retry after the initial attempt).
128
+ *
129
+ * `retryAfterMs` is set only when the server's `Retry-After` header was
130
+ * parsed and honored — operators reading the trace can distinguish
131
+ * server-driven backoff from client-side exponential backoff.
132
+ */
133
+ export interface RetryLogInfo {
134
+ surface: string;
135
+ endpoint: string;
136
+ operationName: string;
137
+ attempt: number;
138
+ reason: "rate-limit" | "server-error" | "timeout";
139
+ status?: number;
140
+ delayMs: number;
141
+ retryAfterMs?: number;
142
+ }
143
+ /**
144
+ * Emit a `--verbose` / `--debug` line for a transport RETRY event,
145
+ * fired by the resilience layer (issue #229) when it decides to back off
146
+ * and re-issue a request after a 429, retryable 5xx, or per-attempt
147
+ * timeout.
148
+ *
149
+ * - `"none"`: no-op.
150
+ * - `"verbose"`: emits one line summarising the retry decision.
151
+ * - `"debug"`: emits one JSON-encoded record with full retry context
152
+ * (surface, endpoint, operation, attempt, reason, status, delays).
153
+ *
154
+ * Bearer-absence: this event shape carries NO authorization header and NO
155
+ * body payload — only retry metadata — so there is no redaction path
156
+ * needed.
157
+ */
158
+ export declare function logTransportRetry(info: RetryLogInfo): void;
159
+ //# sourceMappingURL=diagnostic-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostic-log.d.ts","sourceRoot":"","sources":["../../src/lib/diagnostic-log.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC;AAe3D;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,CAEhE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,eAAe,CAErD;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,OAAO,GAAG,cAAc,GAAG,wBAAwB,CAAC;IAC/D,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd;;;;;OAKG;IACH,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;KAAE,CAAC;CAChE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAmB9D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAqBhE;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,GAAG,cAAc,GAAG,SAAS,CAAC;IAClD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAuB1D"}
@@ -0,0 +1,186 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { redactBody, redactHeaders } from "./redact.js";
4
+ /**
5
+ * Module-scoped diagnostic level. Mirrors the `dry-run.ts` /
6
+ * `config-context.ts` pattern: one global holder, set once by the CLI's
7
+ * `preAction` hook, read by transport entry points. Module isolation
8
+ * keeps each call site's signature focused on its domain (no logger
9
+ * parameter threading) while exposing a single place to test the
10
+ * captured value.
11
+ *
12
+ * Tests MUST call {@link resetDiagnosticLogger} in `beforeEach` to
13
+ * avoid state bleeding across cases.
14
+ */
15
+ let currentLevel = "none";
16
+ /**
17
+ * Set the diagnostic level. Called by the CLI's `preAction` hook once
18
+ * per invocation when `--verbose` or `--debug` is present. Setting
19
+ * `"none"` (or omitting the call) keeps the disabled path active.
20
+ *
21
+ * Precedence (for the CLI hook, not enforced here): `--debug` wins over
22
+ * `--verbose` if both are passed. The decision lives in `program.ts`;
23
+ * this function takes whatever level the caller computed.
24
+ */
25
+ export function setDiagnosticLogger(level) {
26
+ currentLevel = level;
27
+ }
28
+ /**
29
+ * Read the captured diagnostic level. Returns `"none"` when no level
30
+ * has been set (the default).
31
+ */
32
+ export function getDiagnosticLogger() {
33
+ return currentLevel;
34
+ }
35
+ /**
36
+ * Reset to `"none"`. Tests call this in `beforeEach` to keep the
37
+ * module-scoped state isolated. Production code never needs to call
38
+ * this — the CLI's `preAction` hook sets the level once per invocation.
39
+ */
40
+ export function resetDiagnosticLogger() {
41
+ currentLevel = "none";
42
+ }
43
+ /**
44
+ * Emit a `--verbose` / `--debug` line for a transport REQUEST.
45
+ *
46
+ * - `"none"`: no-op (single comparison, no allocation).
47
+ * - `"verbose"`: emits one line `POST <endpoint> operation=<op>`.
48
+ * - `"debug"`: emits one JSON-encoded line containing the redacted
49
+ * request envelope: surface, transport, endpoint, method, operation
50
+ * name, redacted headers, redacted body, optional multipart map.
51
+ * Bearer token (`authorization` header) and cookie values are
52
+ * replaced with `***REDACTED***` per the `redact` module BEFORE
53
+ * JSON.stringify, so the serialized line cannot leak any secret.
54
+ *
55
+ * Writes to `process.stderr` only; never touches `process.stdout`.
56
+ */
57
+ export function logTransportRequest(info) {
58
+ if (currentLevel === "none")
59
+ return;
60
+ if (currentLevel === "verbose") {
61
+ process.stderr.write(`${info.method} ${info.endpoint} operation=${info.operationName}\n`);
62
+ return;
63
+ }
64
+ // debug path: full request envelope with redaction
65
+ const record = {
66
+ kind: "request",
67
+ surface: info.surface,
68
+ transport: info.transport,
69
+ endpoint: info.endpoint,
70
+ method: info.method,
71
+ operationName: info.operationName,
72
+ headers: redactHeaders(info.headers),
73
+ body: redactBody(info.body),
74
+ ...(info.multipart !== undefined ? { multipart: info.multipart } : {}),
75
+ };
76
+ process.stderr.write(`${JSON.stringify(record)}\n`);
77
+ }
78
+ /**
79
+ * Emit a `--verbose` / `--debug` line for a transport RESPONSE.
80
+ *
81
+ * - `"none"`: no-op.
82
+ * - `"verbose"`: emits one line `<status> <reasonPhrase> (elapsedMs=<n>)`.
83
+ * `<reasonPhrase>` is derived from {@link HTTP_REASON_PHRASES}; for
84
+ * uncatalogued status codes (rare; non-standard 7xx etc.), the
85
+ * phrase is `"-"`.
86
+ * - `"debug"`: emits one JSON-encoded line containing the redacted
87
+ * response envelope: surface, endpoint, operation name, status,
88
+ * redacted headers, redacted body, elapsed milliseconds. The
89
+ * response body is redacted because Toptal occasionally echoes
90
+ * session-bearing fields back to the caller (per issue #139 spec).
91
+ *
92
+ * Writes to `process.stderr` only.
93
+ */
94
+ export function logTransportResponse(info) {
95
+ if (currentLevel === "none")
96
+ return;
97
+ if (currentLevel === "verbose") {
98
+ const phrase = HTTP_REASON_PHRASES[info.status] ?? "-";
99
+ process.stderr.write(`${info.status.toString()} ${phrase} (elapsedMs=${info.elapsedMs.toFixed(0)}, operation=${info.operationName})\n`);
100
+ return;
101
+ }
102
+ // debug path
103
+ const record = {
104
+ kind: "response",
105
+ surface: info.surface,
106
+ endpoint: info.endpoint,
107
+ operationName: info.operationName,
108
+ status: info.status,
109
+ headers: redactHeaders(info.headers),
110
+ body: redactBody(info.body),
111
+ elapsedMs: Math.round(info.elapsedMs),
112
+ };
113
+ process.stderr.write(`${JSON.stringify(record)}\n`);
114
+ }
115
+ /**
116
+ * Emit a `--verbose` / `--debug` line for a transport RETRY event,
117
+ * fired by the resilience layer (issue #229) when it decides to back off
118
+ * and re-issue a request after a 429, retryable 5xx, or per-attempt
119
+ * timeout.
120
+ *
121
+ * - `"none"`: no-op.
122
+ * - `"verbose"`: emits one line summarising the retry decision.
123
+ * - `"debug"`: emits one JSON-encoded record with full retry context
124
+ * (surface, endpoint, operation, attempt, reason, status, delays).
125
+ *
126
+ * Bearer-absence: this event shape carries NO authorization header and NO
127
+ * body payload — only retry metadata — so there is no redaction path
128
+ * needed.
129
+ */
130
+ export function logTransportRetry(info) {
131
+ if (currentLevel === "none")
132
+ return;
133
+ if (currentLevel === "verbose") {
134
+ const statusPart = info.status !== undefined ? ` status=${info.status.toString()}` : "";
135
+ const retryAfterPart = info.retryAfterMs !== undefined ? ` retryAfterMs=${info.retryAfterMs.toString()}` : "";
136
+ process.stderr.write(`retry attempt=${info.attempt.toString()} reason=${info.reason}${statusPart} ` +
137
+ `delayMs=${info.delayMs.toString()}${retryAfterPart} operation=${info.operationName}\n`);
138
+ return;
139
+ }
140
+ const record = {
141
+ kind: "retry",
142
+ surface: info.surface,
143
+ endpoint: info.endpoint,
144
+ operationName: info.operationName,
145
+ attempt: info.attempt,
146
+ reason: info.reason,
147
+ delayMs: info.delayMs,
148
+ };
149
+ if (info.status !== undefined)
150
+ record["status"] = info.status;
151
+ if (info.retryAfterMs !== undefined)
152
+ record["retryAfterMs"] = info.retryAfterMs;
153
+ process.stderr.write(`${JSON.stringify(record)}\n`);
154
+ }
155
+ /**
156
+ * Minimal table of HTTP reason phrases used by the `"verbose"` log
157
+ * line. Not exhaustive — covers the status codes TTCtl's transport
158
+ * paths plausibly observe in production (mobile gateway, Cloudflare
159
+ * surfaces, multipart upload). Uncatalogued codes render as `"-"`,
160
+ * which is sufficient signal for verbose-mode triage.
161
+ */
162
+ const HTTP_REASON_PHRASES = {
163
+ 200: "OK",
164
+ 201: "Created",
165
+ 204: "No Content",
166
+ 301: "Moved Permanently",
167
+ 302: "Found",
168
+ 304: "Not Modified",
169
+ 400: "Bad Request",
170
+ 401: "Unauthorized",
171
+ 403: "Forbidden",
172
+ 404: "Not Found",
173
+ 405: "Method Not Allowed",
174
+ 408: "Request Timeout",
175
+ 409: "Conflict",
176
+ 410: "Gone",
177
+ 413: "Payload Too Large",
178
+ 415: "Unsupported Media Type",
179
+ 422: "Unprocessable Entity",
180
+ 429: "Too Many Requests",
181
+ 500: "Internal Server Error",
182
+ 502: "Bad Gateway",
183
+ 503: "Service Unavailable",
184
+ 504: "Gateway Timeout",
185
+ };
186
+ //# sourceMappingURL=diagnostic-log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostic-log.js","sourceRoot":"","sources":["../../src/lib/diagnostic-log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Resolve the running package's version by reading the sibling
3
+ * `package.json` of the calling module. Pass `import.meta.url` from the
4
+ * caller; the helper walks from `<dir>/../package.json` (the canonical
5
+ * `dist/<file>.js` → `package.json` layout used by every workspace
6
+ * package in this repo).
7
+ *
8
+ * Falls back to `0.0.0` if the file cannot be read or parsed —
9
+ * defensive against partial installs / chmod weirdness, never throws.
10
+ * `0.0.0` matches the unstamped placeholder used in source today
11
+ * (e.g., `packages/cli/src/program.ts:107`, `packages/mcp/src/server.ts`),
12
+ * so the fallback never surfaces a discontinuity to consumers.
13
+ *
14
+ * Used by the kill-switch wire-up sites (#312) to supply the running
15
+ * version to `checkKillSwitch`, and is available for any future
16
+ * version-aware feature.
17
+ */
18
+ export declare function readPackageVersion(metaUrl: string): string;
19
+ //# sourceMappingURL=package-version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-version.d.ts","sourceRoot":"","sources":["../../src/lib/package-version.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAa1D"}
@@ -0,0 +1,38 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { readFileSync } from "node:fs";
4
+ import { dirname, join } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ /**
7
+ * Resolve the running package's version by reading the sibling
8
+ * `package.json` of the calling module. Pass `import.meta.url` from the
9
+ * caller; the helper walks from `<dir>/../package.json` (the canonical
10
+ * `dist/<file>.js` → `package.json` layout used by every workspace
11
+ * package in this repo).
12
+ *
13
+ * Falls back to `0.0.0` if the file cannot be read or parsed —
14
+ * defensive against partial installs / chmod weirdness, never throws.
15
+ * `0.0.0` matches the unstamped placeholder used in source today
16
+ * (e.g., `packages/cli/src/program.ts:107`, `packages/mcp/src/server.ts`),
17
+ * so the fallback never surfaces a discontinuity to consumers.
18
+ *
19
+ * Used by the kill-switch wire-up sites (#312) to supply the running
20
+ * version to `checkKillSwitch`, and is available for any future
21
+ * version-aware feature.
22
+ */
23
+ export function readPackageVersion(metaUrl) {
24
+ try {
25
+ const dir = dirname(fileURLToPath(metaUrl));
26
+ const candidate = join(dir, "..", "package.json");
27
+ const raw = readFileSync(candidate, "utf-8");
28
+ const parsed = JSON.parse(raw);
29
+ if (typeof parsed.version === "string" && parsed.version.length > 0) {
30
+ return parsed.version;
31
+ }
32
+ }
33
+ catch {
34
+ // Fall through to the placeholder default.
35
+ }
36
+ return "0.0.0";
37
+ }
38
+ //# sourceMappingURL=package-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package-version.js","sourceRoot":"","sources":["../../src/lib/package-version.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,cAAc,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC;QACxD,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpE,OAAO,MAAM,CAAC,OAAO,CAAC;QACxB,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,2CAA2C;IAC7C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}