@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,153 @@
1
+ /**
2
+ * Centralized redaction primitives for diagnostic logging and pattern-leak
3
+ * detection.
4
+ *
5
+ * This module is the **single source of truth** for "what is a secret" across
6
+ * the project — both the runtime debug-log path (issue #139) and the static
7
+ * `check-secret-leakage` script consume the constants defined here. Any
8
+ * future addition to either redaction (runtime) or detection (lint) MUST
9
+ * extend these exports rather than redefining them locally.
10
+ *
11
+ * Consumers:
12
+ *
13
+ * - `packages/core/src/lib/diagnostic-log.ts` calls {@link redactHeaders} /
14
+ * {@link redactBody} before emitting any `--verbose` / `--debug` line
15
+ * to stderr.
16
+ * - `scripts/check-secret-leakage.ts` consumes {@link BEARER_PATTERN_SOURCE}
17
+ * to scan tracked source for accidentally committed Toptal session
18
+ * bearers.
19
+ *
20
+ * Wire shape is stable; downstream tools and tests identify redaction sites
21
+ * by exact match against {@link REDACTED}. Patterns are append-only — never
22
+ * remove an entry, only add. Tests assert that no `authToken` value or
23
+ * cookie value can appear verbatim in the output of either consumer.
24
+ */
25
+ /**
26
+ * Replacement marker for redacted scalar values. Stable wire-shape so
27
+ * downstream tools and tests can identify redaction sites by exact match.
28
+ */
29
+ export declare const REDACTED: "***REDACTED***";
30
+ /**
31
+ * Source pattern for Toptal Talent's session bearer token, exported as a
32
+ * STRING (not a `RegExp`) so non-TypeScript consumers (the
33
+ * `scripts/check-secret-leakage.ts` lint script before its own
34
+ * `new RegExp(..., "g")` construction) can adopt the canonical pattern
35
+ * without paying for any module-load-time `g`-flag state. The TS-side
36
+ * {@link BEARER_PATTERN} below wraps this source in a fresh `RegExp` per
37
+ * import so callers do not share the `lastIndex` cursor (`/g` flag is
38
+ * stateful per-instance).
39
+ *
40
+ * The bearer shape is `user_<24hex>_<20alnum>` — the canonical output of
41
+ * Toptal's `EmailPasswordSignIn` mutation (per
42
+ * `hq/engineering/adr/ADR-005-auth-model.md`). Anchored to character
43
+ * class boundaries: the `user_` literal prefix is TTCtl-specific (no false
44
+ * positives against unrelated `user_` strings in test data), the 24-hex +
45
+ * 20-alphanumeric pair is the empirically observed shape.
46
+ */
47
+ export declare const BEARER_PATTERN_SOURCE: "user_[0-9a-f]{24}_[A-Za-z0-9]{20}";
48
+ /**
49
+ * Compiled bearer-shape regex with the `g` (global) flag. A fresh `RegExp`
50
+ * instance constructed at module-load time so callers in this package can
51
+ * use `.test()` / `.exec()` against multiline strings without resetting
52
+ * `lastIndex` between unrelated callers.
53
+ *
54
+ * **Stateful flag warning**: the `g` flag makes `exec` / `test` advance an
55
+ * internal cursor. Callers iterating over multiple inputs must either
56
+ * reset `BEARER_PATTERN.lastIndex = 0` before each input, or construct a
57
+ * fresh instance via `new RegExp(BEARER_PATTERN_SOURCE, "g")`.
58
+ */
59
+ export declare const BEARER_PATTERN: RegExp;
60
+ /**
61
+ * Header names whose VALUES carry session-bearing or otherwise
62
+ * authentication-sensitive material. Lowercased for case-insensitive
63
+ * matching — runtime code paths normalise the header key to lowercase
64
+ * before lookup. Includes both standard auth headers (`authorization`,
65
+ * `cookie`, `proxy-authorization`) and a small set of vendor-specific
66
+ * variants that historically carry session tokens.
67
+ *
68
+ * `set-cookie` is included because GraphQL responses occasionally echo
69
+ * session-bearing cookies on the response side; redacting it on the
70
+ * response trace keeps the symmetric request/response wire shape clean.
71
+ */
72
+ export declare const SECRET_HEADER_NAMES: ReadonlySet<string>;
73
+ /**
74
+ * Field names (case-insensitive) whose VALUES carry secrets when they
75
+ * appear inside request or response bodies — GraphQL `variables`, JSON
76
+ * payloads, REST request bodies, error envelopes, etc. Runtime code
77
+ * paths normalise the field key to lowercase before lookup.
78
+ *
79
+ * Conservative on purpose: the cost of redacting a field that turns out
80
+ * to be benign is zero (one fewer scalar visible in debug output); the
81
+ * cost of NOT redacting an actual secret is a credential leak. Add new
82
+ * field names freely.
83
+ */
84
+ export declare const SECRET_BODY_FIELD_NAMES: ReadonlySet<string>;
85
+ /**
86
+ * Return a redacted copy of `headers`. Keys are preserved verbatim; values
87
+ * for keys whose lowercase form is in {@link SECRET_HEADER_NAMES} are
88
+ * replaced with {@link REDACTED}. Non-secret headers pass through unchanged.
89
+ *
90
+ * For the `cookie` and `set-cookie` headers, the entire header value is
91
+ * replaced. TTCtl is bearer-only (no cookie jar is configured in either
92
+ * transport — see ADR-005), but a server may still emit `Set-Cookie` on
93
+ * responses (Cloudflare bot-management cookies, Toptal session hints
94
+ * TTCtl ignores). Whole-value redaction is the safe default for that
95
+ * case; cookie names carry no operational signal here because TTCtl
96
+ * never sends them back.
97
+ *
98
+ * Pure — does not mutate the input.
99
+ */
100
+ export declare function redactHeaders(headers: Record<string, string>): Record<string, string>;
101
+ /**
102
+ * Deep-walk `body` and replace values of any field whose key (lowercased)
103
+ * is in {@link SECRET_BODY_FIELD_NAMES} with {@link REDACTED}. Returns a
104
+ * structurally cloned copy — does NOT mutate the input. Non-object inputs
105
+ * pass through unchanged (scalars, null, undefined).
106
+ *
107
+ * Walks both plain objects and arrays. Arrays inherit the parent's
108
+ * redaction rules — e.g., `{credentials: [{password: "..."}]}` redacts
109
+ * the `password` field inside the array element.
110
+ *
111
+ * Designed for GraphQL `variables` payloads (which are arbitrary JSON
112
+ * trees) and REST request bodies. Cycle detection is NOT implemented —
113
+ * GraphQL request/response payloads are tree-shaped by spec, so cycles
114
+ * cannot occur in valid inputs; defensive callers (e.g.,
115
+ * `diagnostic-log.ts`) parse JSON before invoking and pass the parsed
116
+ * tree.
117
+ *
118
+ * The implementation walks keys via `Object.entries` which preserves
119
+ * insertion order in V8 — useful for tests that snapshot the redacted
120
+ * output as JSON.
121
+ */
122
+ export declare function redactBody(body: unknown): unknown;
123
+ /**
124
+ * True when `text` contains a Toptal Talent session bearer match per
125
+ * {@link BEARER_PATTERN_SOURCE}. Convenience wrapper that constructs a
126
+ * fresh `RegExp` per call so `lastIndex` state on the shared
127
+ * {@link BEARER_PATTERN} cannot leak into the test.
128
+ *
129
+ * Used by `scripts/check-secret-leakage.ts` as the authoritative
130
+ * "contains-bearer" check, replacing the previous in-script regex.
131
+ */
132
+ export declare function containsBearerToken(text: string): boolean;
133
+ /**
134
+ * Replace every Toptal Talent session bearer match in `text` with the
135
+ * canonical {@link REDACTED} marker. Returns the input unchanged when no
136
+ * match is present.
137
+ *
138
+ * Free-text counterpart to the structural {@link redactBody} /
139
+ * {@link redactHeaders} pair — designed for diagnostic output whose
140
+ * shape is a single string (error messages, stack traces, crash logs)
141
+ * rather than a parsed object graph. The bearer regex is the only
142
+ * pattern this scrubs; password and other unstructured secrets cannot
143
+ * be detected without a runtime registry of known values (out of scope
144
+ * for this module — see SECURITY.md § Crash-output secret invariant).
145
+ *
146
+ * Constructs a fresh `RegExp` per call so the shared
147
+ * {@link BEARER_PATTERN}'s `lastIndex` cursor cannot be advanced by
148
+ * unrelated callers.
149
+ *
150
+ * Pure — does not mutate the input string.
151
+ */
152
+ export declare function redactString(text: string): string;
153
+ //# sourceMappingURL=redact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/lib/redact.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;GAGG;AACH,eAAO,MAAM,QAAQ,EAAG,gBAAyB,CAAC;AAElD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,qBAAqB,EAAG,mCAA4C,CAAC;AAElF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc,EAAE,MAA+C,CAAC;AAE7E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CASlD,CAAC;AAEH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,uBAAuB,EAAE,WAAW,CAAC,MAAM,CAetD,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMrF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAcjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD"}
@@ -0,0 +1,207 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ /**
4
+ * Centralized redaction primitives for diagnostic logging and pattern-leak
5
+ * detection.
6
+ *
7
+ * This module is the **single source of truth** for "what is a secret" across
8
+ * the project — both the runtime debug-log path (issue #139) and the static
9
+ * `check-secret-leakage` script consume the constants defined here. Any
10
+ * future addition to either redaction (runtime) or detection (lint) MUST
11
+ * extend these exports rather than redefining them locally.
12
+ *
13
+ * Consumers:
14
+ *
15
+ * - `packages/core/src/lib/diagnostic-log.ts` calls {@link redactHeaders} /
16
+ * {@link redactBody} before emitting any `--verbose` / `--debug` line
17
+ * to stderr.
18
+ * - `scripts/check-secret-leakage.ts` consumes {@link BEARER_PATTERN_SOURCE}
19
+ * to scan tracked source for accidentally committed Toptal session
20
+ * bearers.
21
+ *
22
+ * Wire shape is stable; downstream tools and tests identify redaction sites
23
+ * by exact match against {@link REDACTED}. Patterns are append-only — never
24
+ * remove an entry, only add. Tests assert that no `authToken` value or
25
+ * cookie value can appear verbatim in the output of either consumer.
26
+ */
27
+ /**
28
+ * Replacement marker for redacted scalar values. Stable wire-shape so
29
+ * downstream tools and tests can identify redaction sites by exact match.
30
+ */
31
+ export const REDACTED = "***REDACTED***";
32
+ /**
33
+ * Source pattern for Toptal Talent's session bearer token, exported as a
34
+ * STRING (not a `RegExp`) so non-TypeScript consumers (the
35
+ * `scripts/check-secret-leakage.ts` lint script before its own
36
+ * `new RegExp(..., "g")` construction) can adopt the canonical pattern
37
+ * without paying for any module-load-time `g`-flag state. The TS-side
38
+ * {@link BEARER_PATTERN} below wraps this source in a fresh `RegExp` per
39
+ * import so callers do not share the `lastIndex` cursor (`/g` flag is
40
+ * stateful per-instance).
41
+ *
42
+ * The bearer shape is `user_<24hex>_<20alnum>` — the canonical output of
43
+ * Toptal's `EmailPasswordSignIn` mutation (per
44
+ * `hq/engineering/adr/ADR-005-auth-model.md`). Anchored to character
45
+ * class boundaries: the `user_` literal prefix is TTCtl-specific (no false
46
+ * positives against unrelated `user_` strings in test data), the 24-hex +
47
+ * 20-alphanumeric pair is the empirically observed shape.
48
+ */
49
+ export const BEARER_PATTERN_SOURCE = "user_[0-9a-f]{24}_[A-Za-z0-9]{20}";
50
+ /**
51
+ * Compiled bearer-shape regex with the `g` (global) flag. A fresh `RegExp`
52
+ * instance constructed at module-load time so callers in this package can
53
+ * use `.test()` / `.exec()` against multiline strings without resetting
54
+ * `lastIndex` between unrelated callers.
55
+ *
56
+ * **Stateful flag warning**: the `g` flag makes `exec` / `test` advance an
57
+ * internal cursor. Callers iterating over multiple inputs must either
58
+ * reset `BEARER_PATTERN.lastIndex = 0` before each input, or construct a
59
+ * fresh instance via `new RegExp(BEARER_PATTERN_SOURCE, "g")`.
60
+ */
61
+ export const BEARER_PATTERN = new RegExp(BEARER_PATTERN_SOURCE, "g");
62
+ /**
63
+ * Header names whose VALUES carry session-bearing or otherwise
64
+ * authentication-sensitive material. Lowercased for case-insensitive
65
+ * matching — runtime code paths normalise the header key to lowercase
66
+ * before lookup. Includes both standard auth headers (`authorization`,
67
+ * `cookie`, `proxy-authorization`) and a small set of vendor-specific
68
+ * variants that historically carry session tokens.
69
+ *
70
+ * `set-cookie` is included because GraphQL responses occasionally echo
71
+ * session-bearing cookies on the response side; redacting it on the
72
+ * response trace keeps the symmetric request/response wire shape clean.
73
+ */
74
+ export const SECRET_HEADER_NAMES = new Set([
75
+ "authorization",
76
+ "cookie",
77
+ "set-cookie",
78
+ "proxy-authorization",
79
+ "x-auth-token",
80
+ "x-csrf-token",
81
+ "x-session-token",
82
+ "x-toptal-session",
83
+ ]);
84
+ /**
85
+ * Field names (case-insensitive) whose VALUES carry secrets when they
86
+ * appear inside request or response bodies — GraphQL `variables`, JSON
87
+ * payloads, REST request bodies, error envelopes, etc. Runtime code
88
+ * paths normalise the field key to lowercase before lookup.
89
+ *
90
+ * Conservative on purpose: the cost of redacting a field that turns out
91
+ * to be benign is zero (one fewer scalar visible in debug output); the
92
+ * cost of NOT redacting an actual secret is a credential leak. Add new
93
+ * field names freely.
94
+ */
95
+ export const SECRET_BODY_FIELD_NAMES = new Set([
96
+ "password",
97
+ "passwd",
98
+ "token",
99
+ "secret",
100
+ "apikey",
101
+ "api_key",
102
+ "authtoken",
103
+ "auth_token",
104
+ "accesstoken",
105
+ "access_token",
106
+ "refreshtoken",
107
+ "refresh_token",
108
+ "authorization",
109
+ "email",
110
+ ]);
111
+ /**
112
+ * Return a redacted copy of `headers`. Keys are preserved verbatim; values
113
+ * for keys whose lowercase form is in {@link SECRET_HEADER_NAMES} are
114
+ * replaced with {@link REDACTED}. Non-secret headers pass through unchanged.
115
+ *
116
+ * For the `cookie` and `set-cookie` headers, the entire header value is
117
+ * replaced. TTCtl is bearer-only (no cookie jar is configured in either
118
+ * transport — see ADR-005), but a server may still emit `Set-Cookie` on
119
+ * responses (Cloudflare bot-management cookies, Toptal session hints
120
+ * TTCtl ignores). Whole-value redaction is the safe default for that
121
+ * case; cookie names carry no operational signal here because TTCtl
122
+ * never sends them back.
123
+ *
124
+ * Pure — does not mutate the input.
125
+ */
126
+ export function redactHeaders(headers) {
127
+ const out = {};
128
+ for (const [key, value] of Object.entries(headers)) {
129
+ out[key] = SECRET_HEADER_NAMES.has(key.toLowerCase()) ? REDACTED : value;
130
+ }
131
+ return out;
132
+ }
133
+ /**
134
+ * Deep-walk `body` and replace values of any field whose key (lowercased)
135
+ * is in {@link SECRET_BODY_FIELD_NAMES} with {@link REDACTED}. Returns a
136
+ * structurally cloned copy — does NOT mutate the input. Non-object inputs
137
+ * pass through unchanged (scalars, null, undefined).
138
+ *
139
+ * Walks both plain objects and arrays. Arrays inherit the parent's
140
+ * redaction rules — e.g., `{credentials: [{password: "..."}]}` redacts
141
+ * the `password` field inside the array element.
142
+ *
143
+ * Designed for GraphQL `variables` payloads (which are arbitrary JSON
144
+ * trees) and REST request bodies. Cycle detection is NOT implemented —
145
+ * GraphQL request/response payloads are tree-shaped by spec, so cycles
146
+ * cannot occur in valid inputs; defensive callers (e.g.,
147
+ * `diagnostic-log.ts`) parse JSON before invoking and pass the parsed
148
+ * tree.
149
+ *
150
+ * The implementation walks keys via `Object.entries` which preserves
151
+ * insertion order in V8 — useful for tests that snapshot the redacted
152
+ * output as JSON.
153
+ */
154
+ export function redactBody(body) {
155
+ if (body === null || body === undefined)
156
+ return body;
157
+ if (Array.isArray(body))
158
+ return body.map((item) => redactBody(item));
159
+ if (typeof body !== "object")
160
+ return body;
161
+ const input = body;
162
+ const out = {};
163
+ for (const [key, value] of Object.entries(input)) {
164
+ if (SECRET_BODY_FIELD_NAMES.has(key.toLowerCase())) {
165
+ out[key] = REDACTED;
166
+ }
167
+ else {
168
+ out[key] = redactBody(value);
169
+ }
170
+ }
171
+ return out;
172
+ }
173
+ /**
174
+ * True when `text` contains a Toptal Talent session bearer match per
175
+ * {@link BEARER_PATTERN_SOURCE}. Convenience wrapper that constructs a
176
+ * fresh `RegExp` per call so `lastIndex` state on the shared
177
+ * {@link BEARER_PATTERN} cannot leak into the test.
178
+ *
179
+ * Used by `scripts/check-secret-leakage.ts` as the authoritative
180
+ * "contains-bearer" check, replacing the previous in-script regex.
181
+ */
182
+ export function containsBearerToken(text) {
183
+ return new RegExp(BEARER_PATTERN_SOURCE).test(text);
184
+ }
185
+ /**
186
+ * Replace every Toptal Talent session bearer match in `text` with the
187
+ * canonical {@link REDACTED} marker. Returns the input unchanged when no
188
+ * match is present.
189
+ *
190
+ * Free-text counterpart to the structural {@link redactBody} /
191
+ * {@link redactHeaders} pair — designed for diagnostic output whose
192
+ * shape is a single string (error messages, stack traces, crash logs)
193
+ * rather than a parsed object graph. The bearer regex is the only
194
+ * pattern this scrubs; password and other unstructured secrets cannot
195
+ * be detected without a runtime registry of known values (out of scope
196
+ * for this module — see SECURITY.md § Crash-output secret invariant).
197
+ *
198
+ * Constructs a fresh `RegExp` per call so the shared
199
+ * {@link BEARER_PATTERN}'s `lastIndex` cursor cannot be advanced by
200
+ * unrelated callers.
201
+ *
202
+ * Pure — does not mutate the input string.
203
+ */
204
+ export function redactString(text) {
205
+ return text.replace(new RegExp(BEARER_PATTERN_SOURCE, "g"), REDACTED);
206
+ }
207
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/lib/redact.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,gBAAyB,CAAC;AAElD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,mCAA4C,CAAC;AAElF;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GAAW,IAAI,MAAM,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;AAE7E;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IAC9D,eAAe;IACf,QAAQ;IACR,YAAY;IACZ,qBAAqB;IACrB,cAAc;IACd,cAAc;IACd,iBAAiB;IACjB,kBAAkB;CACnB,CAAC,CAAC;AAEH;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAwB,IAAI,GAAG,CAAC;IAClE,UAAU;IACV,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,QAAQ;IACR,SAAS;IACT,WAAW;IACX,YAAY;IACZ,aAAa;IACb,cAAc;IACd,cAAc;IACd,eAAe;IACf,eAAe;IACf,OAAO;CACR,CAAC,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,aAAa,CAAC,OAA+B;IAC3D,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,GAAG,CAAC,GAAG,mBAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3E,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,UAAU,CAAC,IAAa;IACtC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACrD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACrE,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC1C,MAAM,KAAK,GAAG,IAA+B,CAAC;IAC9C,MAAM,GAAG,GAA4B,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,IAAI,uBAAuB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YACnD,GAAG,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC;QACtB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI,MAAM,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,qBAAqB,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Split a multi-paragraph string on blank lines into an array of trimmed
3
+ * paragraphs (drops empties). Mirrors the wire shape used by sub-domains
4
+ * whose mutation inputs accept paragraph arrays (e.g. `experienceItems`
5
+ * on `UpdateEmploymentInput` per
6
+ * `research/captures/web/inputs/UpdateEmploymentInput.json`).
7
+ *
8
+ * Pure — no I/O — so it's directly unit-testable.
9
+ *
10
+ * @param text - source string with paragraphs separated by blank lines
11
+ * @returns array of trimmed paragraphs (empty paragraphs dropped)
12
+ */
13
+ export declare function splitParagraphs(text: string): string[];
14
+ //# sourceMappingURL=text.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../../src/lib/text.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAKtD"}
@@ -0,0 +1,21 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ /**
4
+ * Split a multi-paragraph string on blank lines into an array of trimmed
5
+ * paragraphs (drops empties). Mirrors the wire shape used by sub-domains
6
+ * whose mutation inputs accept paragraph arrays (e.g. `experienceItems`
7
+ * on `UpdateEmploymentInput` per
8
+ * `research/captures/web/inputs/UpdateEmploymentInput.json`).
9
+ *
10
+ * Pure — no I/O — so it's directly unit-testable.
11
+ *
12
+ * @param text - source string with paragraphs separated by blank lines
13
+ * @returns array of trimmed paragraphs (empty paragraphs dropped)
14
+ */
15
+ export function splitParagraphs(text) {
16
+ return text
17
+ .split(/\r?\n\s*\r?\n/)
18
+ .map((p) => p.trim())
19
+ .filter((p) => p.length > 0);
20
+ }
21
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text.js","sourceRoot":"","sources":["../../src/lib/text.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI;SACR,KAAK,CAAC,eAAe,CAAC;SACtB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Shared wire-shape validation helper for the hybrid runtime
3
+ * field-level validation model (ADR-006). Used by every per-service
4
+ * `callGateway` / `callTalentProfile` helper to convert a
5
+ * {@link z.ZodError} from a failed `schema.parse(body.data)` call into
6
+ * the structured payload required by the project's `WIRE_SHAPE_ERROR`
7
+ * UX (see `docs/wire-validation-error-format.md`, M2 / #281).
8
+ *
9
+ * Operationally a `WIRE_SHAPE_ERROR` means Toptal changed the wire
10
+ * shape (the schemas were synthesized from APK decompilation + live
11
+ * captures and lag behind server-side updates). The CLI / MCP surfaces
12
+ * render the diff so an operator can file an actionable bug.
13
+ *
14
+ * Z-3 (#286) wires this helper through the call path. No production op
15
+ * has `schema` wired yet — that's Z-4 (#288)'s beachhead.
16
+ *
17
+ * Zod v4 note: in v4 the public `error.issues[]` does NOT carry the
18
+ * raw input value (`input` is stripped from the user-facing
19
+ * {@link z.core.$ZodIssue} despite being present on the internal
20
+ * {@link z.core.$ZodRawIssue}). To recover the wire value for the
21
+ * `actual` and `value` slots of a {@link WireShapeDiffEntry}, the
22
+ * caller passes the original wire data (`body.data`) as the second
23
+ * argument to {@link buildWireShapeError} / {@link projectZodErrorToDiff};
24
+ * we walk the issue's `path` against that snapshot. When the wire
25
+ * value can't be resolved (e.g., the schema rejected the entire
26
+ * top-level shape), the entry falls back to a path-only render.
27
+ */
28
+ import type { z } from "zod";
29
+ /**
30
+ * One field-level diff entry in a {@link WireShapeErrorPayload}. Wire
31
+ * shape matches the JSON contract in `docs/wire-validation-error-format.md`:
32
+ *
33
+ * - `op` — `"+"` schema-unknown wire field (strict mode unrecognized
34
+ * keys) / `"-"` schema-required missing on wire / `"~"` type
35
+ * mismatch.
36
+ * - `path` — JSON path from operation root with zero-indexed bracket
37
+ * notation for arrays (`billingCycle.records[0].duration`) so it
38
+ * matches `jq` semantics.
39
+ * - `expected` — schema type as a short string (`"number"`,
40
+ * `"string"`, `"undefined"`, …).
41
+ * - `actual` — wire value type as a short string.
42
+ * - `value?` — raw wire value rendered to a string, truncated to
43
+ * {@link MAX_VALUE_LENGTH} chars with `…` on overflow. Omitted for
44
+ * `+` (key absent from schema, value undefined) and `-` (field
45
+ * absent from wire, value undefined). `body.data` never contains
46
+ * the bearer, so no redaction is needed.
47
+ */
48
+ export interface WireShapeDiffEntry {
49
+ op: "+" | "-" | "~";
50
+ path: string;
51
+ expected: string;
52
+ actual: string;
53
+ value?: string;
54
+ }
55
+ /**
56
+ * Structured payload returned by {@link buildWireShapeError}. Each
57
+ * service-level `WIRE_SHAPE_ERROR` carries this payload through its
58
+ * own domain-error class via the `cause` field. The CLI / MCP layers
59
+ * lift `message`, `hint`, and `diff` into the user-visible envelope.
60
+ */
61
+ export interface WireShapeErrorPayload {
62
+ message: string;
63
+ hint: string;
64
+ diff: WireShapeDiffEntry[];
65
+ }
66
+ /**
67
+ * Maximum rendered length of a {@link WireShapeDiffEntry.value} field
68
+ * (per `docs/wire-validation-error-format.md` § Diff entries).
69
+ * Truncation appends `…` (a single ellipsis character, not three
70
+ * dots) to mark overflow.
71
+ */
72
+ export declare const MAX_VALUE_LENGTH = 32;
73
+ /**
74
+ * Verbatim hint string emitted alongside every `WIRE_SHAPE_ERROR`.
75
+ * Lifted into the CLI envelope's `hint` slot and the MCP error-text
76
+ * `Hint:` block; identical across all surfaces so an operator pattern-
77
+ * matches the message regardless of where it's encountered. The text
78
+ * comes directly from `docs/wire-validation-error-format.md` § Code +
79
+ * base fields (M2 / #281).
80
+ */
81
+ export declare const WIRE_SHAPE_HINT = "wire shape doesn't match expected \u2014 this typically means Toptal changed the API; please file an issue at https://github.com/alexey-pelykh/ttctl/issues with the operation name and timestamp.";
82
+ /**
83
+ * Build the field-level diff from a {@link z.ZodError}. Issues are
84
+ * projected per {@link issueToDiffEntries} and sorted deterministically
85
+ * per {@link compareDiffEntries} so two runs against the same drifted
86
+ * wire response produce byte-identical output (load-bearing for
87
+ * snapshot tests and CI grep-fu).
88
+ *
89
+ * `wireData` is the original `body.data` snapshot that failed
90
+ * validation — walking it against each issue's `path` recovers the
91
+ * actual wire value (Zod v4 strips `input` from public issues; see
92
+ * file header). Pass `undefined` only in tests / migration paths
93
+ * where the snapshot is unavailable; entries will degrade to path-
94
+ * only render in that case.
95
+ *
96
+ * Exported for unit tests; callers should prefer
97
+ * {@link buildWireShapeError} which composes the full payload.
98
+ */
99
+ export declare function projectZodErrorToDiff(error: z.ZodError, wireData?: unknown): WireShapeDiffEntry[];
100
+ /**
101
+ * Compose the `message` line of a `WIRE_SHAPE_ERROR` per
102
+ * `docs/wire-validation-error-format.md` § Code + base fields. The
103
+ * pluralisation is wire-stable (`1 field issue` vs `2 field issues`)
104
+ * so snapshot tests don't need locale-aware matchers.
105
+ *
106
+ * Exported for unit tests; callers should prefer
107
+ * {@link buildWireShapeError} which composes the full payload.
108
+ */
109
+ export declare function buildWireShapeMessage(operationName: string, diffEntryCount: number): string;
110
+ /**
111
+ * Convert a {@link z.ZodError} from a failed `schema.parse(body.data)`
112
+ * call into the full {@link WireShapeErrorPayload}. The payload is
113
+ * stable across surfaces (CLI envelope, MCP error text) and round-
114
+ * trips through JSON without redaction (body.data never carries the
115
+ * bearer).
116
+ *
117
+ * Each service's `callGateway` / `callTalentProfile` helper wraps the
118
+ * payload's `message` into its own domain-error class with
119
+ * `code: "WIRE_SHAPE_ERROR"` and `cause: zodError`; the CLI / MCP
120
+ * layers reconstruct the diff from `cause` when rendering.
121
+ *
122
+ * Pass `wireData` (the original `body.data` snapshot) so the diff
123
+ * can recover actual wire values via path walk — Zod v4 strips the
124
+ * `input` field from public issues, so the snapshot is the only way
125
+ * to render `actual` / `value` for non-`unrecognized_keys` entries.
126
+ *
127
+ * Z-3 (#286) wires the mechanism; no production op has `schema`
128
+ * passed in yet (Z-4 / #288 ships the first beachhead).
129
+ */
130
+ export declare function buildWireShapeError(operationName: string, error: z.ZodError, wireData?: unknown): WireShapeErrorPayload;
131
+ //# sourceMappingURL=wire-shape.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-shape.d.ts","sourceRoot":"","sources":["../../src/lib/wire-shape.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,kBAAkB,EAAE,CAAC;CAC5B;AAED;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,KAAK,CAAC;AAEnC;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,uMACqK,CAAC;AAqRlM;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,OAAO,GAAG,kBAAkB,EAAE,CAOjG;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAG3F;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,KAAK,EAAE,CAAC,CAAC,QAAQ,EACjB,QAAQ,CAAC,EAAE,OAAO,GACjB,qBAAqB,CAOvB"}