@ttctl/core 0.0.0 → 0.1.0-rc.2

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 +200 -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 +238 -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 +214 -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 +52 -0
  47. package/dist/configLock.d.ts.map +1 -0
  48. package/dist/configLock.js +109 -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 +688 -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 +425 -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 +132 -0
  135. package/dist/services/profile/employment/index.d.ts.map +1 -0
  136. package/dist/services/profile/employment/index.js +262 -0
  137. package/dist/services/profile/employment/index.js.map +1 -0
  138. package/dist/services/profile/external/index.d.ts +278 -0
  139. package/dist/services/profile/external/index.d.ts.map +1 -0
  140. package/dist/services/profile/external/index.js +640 -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 +337 -0
  175. package/dist/services/timesheet/index.d.ts.map +1 -0
  176. package/dist/services/timesheet/index.js +336 -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,109 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import lockfile from "proper-lockfile";
4
+ import { ConfigError } from "./config.js";
5
+ /**
6
+ * Wall-clock budget for `acquireConfigLock` contention timeout. The macOS /
7
+ * Linux baseline configuration produces ≤1.0s total wait: 5 retries × max
8
+ * 250ms backoff = 1250ms ceiling, but with `factor: 1` the backoff stays
9
+ * flat at `minTimeout`-`maxTimeout` so the practical envelope is closer to
10
+ * 5×100ms to 5×250ms = 500ms-1250ms with jitter. Tightens the upper bound
11
+ * below NFR-LOCK-1's 1.0s plan on the OSes the NFR was authored against.
12
+ * Windows operates on a 3x carve-out — see the Windows section below.
13
+ *
14
+ * Windows carve-out (#362): on Windows CI runners (Azure-hosted, shared,
15
+ * higher scheduler variance than Linux/macOS), the 1.0s envelope is too
16
+ * tight for the cross-process serialization test pair in
17
+ * `configLock-cross-process.test.ts` — both `staged race` and the 2-worker
18
+ * `serialize cleanly` variant have flaked when the second worker loses its
19
+ * scheduling slice long enough for its mkdir contention budget to expire
20
+ * before the first worker releases. Sibling prior art: #171, #180, #270
21
+ * (all Windows-specific timing fixes for the same `persistAuthToken`
22
+ * cross-process write path). Extending Windows to ~3.0s (15 retries × 100-
23
+ * 250ms = 1500-3750ms practical envelope) absorbs the variance without
24
+ * changing the NFR-LOCK-1 invariant on the OSes where it applies.
25
+ *
26
+ * Production impact: a real LOCKED contention surfaces in ~3s on Windows
27
+ * (vs ~1s elsewhere). The user-facing message already says "typically ≤2s"
28
+ * — the 3s ceiling does not contradict it, and contended writes are rare
29
+ * (CLI signin + concurrent MCP tool call on the same config).
30
+ */
31
+ const WINDOWS_BUDGET_MULTIPLIER = process.platform === "win32" ? 3 : 1;
32
+ const LOCK_RETRY_OPTIONS = {
33
+ retries: 5 * WINDOWS_BUDGET_MULTIPLIER,
34
+ factor: 1,
35
+ minTimeout: 100,
36
+ maxTimeout: 250,
37
+ };
38
+ /**
39
+ * Stale-lock threshold. If a lockfile is older than this without a refresh,
40
+ * `proper-lockfile` treats it as abandoned and overrides it. Defends against
41
+ * a crashed CLI/MCP that didn't release its lock on exit. The exit-handler
42
+ * via `signal-exit` is best-effort; the stale threshold is the second line.
43
+ *
44
+ * Set to 10s — long enough that a slow signin (network-bound ~2-5s) won't
45
+ * trip the threshold, short enough that a stranded lock from a SIGKILL'd
46
+ * process clears within a single user-perceptible retry window.
47
+ */
48
+ const LOCK_STALE_MS = 10_000;
49
+ /**
50
+ * Acquire an advisory exclusive lock for `configPath`.
51
+ *
52
+ * Implementation: `proper-lockfile` creates `<configPath>.lock` as a
53
+ * sibling DIRECTORY via atomic `mkdir(2)`. The `mkdir` syscall is atomic on
54
+ * ext4, APFS, NTFS, and any other filesystem with POSIX-equivalent
55
+ * semantics — `EEXIST` is the contention signal.
56
+ *
57
+ * Why sibling-lockfile and NOT self-lock: the atomic-rename pattern in
58
+ * `performYamlMutation` swaps the inode at `<configPath>` mid-operation. A
59
+ * `flock(fd)` on the original inode does NOT survive the rename and a
60
+ * concurrent locker on the post-rename inode sees no contention. The
61
+ * sibling pattern sidesteps this — the `.lock` directory's existence is the
62
+ * lock signal, independent of the config file's inode.
63
+ *
64
+ * Cross-platform: works identically on Linux/macOS/Windows — `mkdir`-based
65
+ * atomic creation is portable. No Windows no-op needed (in contrast to the
66
+ * existing POSIX-mode logic in `loadConfigFile` and `performYamlMutation`,
67
+ * which IS Windows-skipped because mode bits aren't meaningful).
68
+ *
69
+ * Contention: ≤1.0s wall-clock budget per `LOCK_RETRY_OPTIONS` on macOS /
70
+ * Linux, ≤3.0s on Windows (Windows scheduler-variance carve-out — see
71
+ * `LOCK_RETRY_OPTIONS` JSDoc + #362). On timeout, throws
72
+ * `ConfigError(LOCKED)` naming the path and suggesting retry — never blocks
73
+ * indefinitely.
74
+ *
75
+ * `realpath: false` skips proper-lockfile's pre-flight `realpath()` check.
76
+ * The caller has already resolved `configPath` to an absolute, symlink-free
77
+ * path via `assertSafePath`, AND the config file may not exist yet (e.g.,
78
+ * the lock is acquired BEFORE the stat baseline that throws ENOENT). With
79
+ * `realpath: true` (the library default), a missing file would surface as
80
+ * an opaque proper-lockfile error before our own ENOENT path runs.
81
+ */
82
+ export async function acquireConfigLock(configPath) {
83
+ let release;
84
+ try {
85
+ release = await lockfile.lock(configPath, {
86
+ stale: LOCK_STALE_MS,
87
+ retries: LOCK_RETRY_OPTIONS,
88
+ realpath: false,
89
+ });
90
+ }
91
+ catch (err) {
92
+ // proper-lockfile throws an Error with a `code` property of "ELOCKED"
93
+ // when contention exhausts retries. Surface as ConfigError(LOCKED) so
94
+ // CLI/MCP error renderers can branch on the code rather than the
95
+ // library-specific marker.
96
+ const code = err.code;
97
+ if (code === "ELOCKED") {
98
+ throw new ConfigError(`Refusing to acquire config lock at ${configPath}.lock: another ttctl process holds it. ` +
99
+ `Wait for it to finish (CLI signin / MCP tool call typically ≤2s) and retry.`, "LOCKED", configPath);
100
+ }
101
+ // Any other error (EACCES on the parent dir, EROFS, etc.) — surface as
102
+ // PERMISSION so the caller can branch on it. Lock acquisition is
103
+ // mechanically a write to the parent directory, so permission errors
104
+ // are the natural failure mode.
105
+ throw new ConfigError(`Cannot acquire config lock at ${configPath}.lock: ${err.message}`, "PERMISSION", configPath);
106
+ }
107
+ return { release };
108
+ }
109
+ //# sourceMappingURL=configLock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configLock.js","sourceRoot":"","sources":["../src/configLock.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AAEvC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAoB1C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,yBAAyB,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvE,MAAM,kBAAkB,GAAG;IACzB,OAAO,EAAE,CAAC,GAAG,yBAAyB;IACtC,MAAM,EAAE,CAAC;IACT,UAAU,EAAE,GAAG;IACf,UAAU,EAAE,GAAG;CAChB,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,aAAa,GAAG,MAAM,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,UAAkB;IACxD,IAAI,OAA4B,CAAC;IACjC,IAAI,CAAC;QACH,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE;YACxC,KAAK,EAAE,aAAa;YACpB,OAAO,EAAE,kBAAkB;YAC3B,QAAQ,EAAE,KAAK;SAChB,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,sEAAsE;QACtE,sEAAsE;QACtE,iEAAiE;QACjE,2BAA2B;QAC3B,MAAM,IAAI,GAAI,GAA6B,CAAC,IAAI,CAAC;QACjD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,MAAM,IAAI,WAAW,CACnB,sCAAsC,UAAU,yCAAyC;gBACvF,6EAA6E,EAC/E,QAAQ,EACR,UAAU,CACX,CAAC;QACJ,CAAC;QACD,uEAAuE;QACvE,iEAAiE;QACjE,qEAAqE;QACrE,gCAAgC;QAChC,MAAM,IAAI,WAAW,CACnB,iCAAiC,UAAU,UAAW,GAAa,CAAC,OAAO,EAAE,EAC7E,YAAY,EACZ,UAAU,CACX,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC;AACrB,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Failure surface for `persistAuthToken` and `clearAuthToken`. Carries the
3
+ * YAML config path AND, for persist-failures-after-signin, the captured
4
+ * bearer token verbatim as a "rescue line" so the operator can manually
5
+ * write it to disk before re-running signin.
6
+ *
7
+ * The bearer is INTENTIONALLY in the message — without it, a write-back
8
+ * failure (read-only filesystem, full disk, kernel I/O error) silently
9
+ * loses the just-acquired session and forces a full re-signin. The cost of
10
+ * a bearer in stderr is bounded: the user sees it in their own terminal,
11
+ * the persist failure is rare, and the recovery is "save this manually".
12
+ */
13
+ export declare class AuthTokenPersistError extends Error {
14
+ readonly configPath: string;
15
+ readonly cause?: NodeJS.ErrnoException | undefined;
16
+ readonly bearerRescue?: string | undefined;
17
+ readonly name = "AuthTokenPersistError";
18
+ constructor(message: string, configPath: string, cause?: NodeJS.ErrnoException | undefined, bearerRescue?: string | undefined);
19
+ }
20
+ /**
21
+ * Persist a captured bearer token to the SAME YAML config file the user
22
+ * authored. Surgically mutates `auth.token` via `yaml.parseDocument` +
23
+ * `setIn` to preserve comments, key order, and scalar styles. Atomic on
24
+ * POSIX (temp + rename + fsync).
25
+ *
26
+ * Path safety gates fire BEFORE the read: symlinks and sync-root paths are
27
+ * refused with `ConfigError(PERMISSION)` (not `AuthTokenPersistError`)
28
+ * because they reflect static filesystem state, not a transient I/O
29
+ * failure. Callers route both error classes through the same user-visible
30
+ * "signin couldn't persist the token" message.
31
+ *
32
+ * On any I/O failure after the bearer was captured, the error message
33
+ * carries the bearer verbatim as a "rescue line" — the operator can copy
34
+ * it into the config manually rather than redoing signin.
35
+ *
36
+ * Cross-process write-back is serialized by an advisory sibling lockfile
37
+ * (`<configPath>.lock`, atomic-mkdir-based via `proper-lockfile`). Two
38
+ * concurrent ttctl processes (e.g., CLI signin AND a long-running MCP
39
+ * tool call) cannot interleave their write-paths — one waits up to 1s and
40
+ * sees the other's committed file, then proceeds with its own
41
+ * read/parse/mutate/write cycle on the up-to-date contents. On contention
42
+ * timeout, throws `ConfigError(LOCKED)` — never blocks indefinitely.
43
+ *
44
+ * The mtime-drift check inside the locked region is the second line of
45
+ * defense for lock-disregarding writers (manual editor save during a
46
+ * persist window) — those still get caught and refused.
47
+ */
48
+ export declare function persistAuthToken(configPath: string, token: string): Promise<void>;
49
+ /**
50
+ * Remove the `auth.token` field from the YAML config file. Distinct from
51
+ * "set token to empty string" — `deleteIn` removes the field entirely so
52
+ * the next load sees Form A/B (credentials only) or Form C/Empty
53
+ * depending on what remains.
54
+ *
55
+ * Per security-architect's Stage 2 input: post-signout state must NEVER
56
+ * be `auth: { token: "" }` — empty-string is data and could be replayed
57
+ * as a (malformed) bearer. Removal is the only safe shape.
58
+ */
59
+ export declare function clearAuthToken(configPath: string): Promise<void>;
60
+ /**
61
+ * Write a freshly-authored config file to `configPath`.
62
+ *
63
+ * Sibling primitive to `performYamlMutation` for the bootstrap case
64
+ * (`ttctl auth init`): no pre-existing file is read or mutated — the YAML
65
+ * content is supplied verbatim by the caller from interactive prompts. The
66
+ * same atomic / safety invariants apply:
67
+ *
68
+ * - Path safety gate (`assertSafePath`) — refuses sync-roots and
69
+ * pre-existing symlinks at `configPath`. A non-existent path is
70
+ * accepted (the whole point of init).
71
+ * - Pre-existence gate — refuses unless `opts.force` is true. The
72
+ * refusal is `ConfigError(PERMISSION)` so CLI/MCP error renderers
73
+ * route it through the same exit-code + message contract as the
74
+ * other write-path failures.
75
+ * - Schema validation — the supplied content is parsed and validated
76
+ * against `ConfigLoadSchema` BEFORE we touch disk. The strict load
77
+ * schema catches malformed YAML composed by an interactive flow
78
+ * (e.g. quoting bug) before we lock it in place.
79
+ * - Atomic write — temp at `0o600`, fsync, defensive chmod, rename,
80
+ * fsync(parent dir). Same dance as `persistAuthToken`'s temp path so
81
+ * a crashed init never leaves a partial config.
82
+ *
83
+ * On `force` overwrite: the existing file is replaced atomically; the
84
+ * mtime-drift guard from `performYamlMutation` does NOT apply here because
85
+ * the bootstrap operation explicitly asks for replacement. Symlink and
86
+ * sync-root refusals still fire.
87
+ *
88
+ * Parent directories are created with `mkdir -p` semantics (the bootstrap
89
+ * is allowed to create its own `~/.ttctl.yaml` even if that means creating
90
+ * a fresh home — though in practice the parent is always `homedir()` which
91
+ * already exists; the recursive flag is for `--config <path>` cases that
92
+ * specify a not-yet-existing project dir).
93
+ */
94
+ export declare function writeNewConfig(configPath: string, content: string, opts: {
95
+ force: boolean;
96
+ }): Promise<void>;
97
+ //# sourceMappingURL=configWriter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configWriter.d.ts","sourceRoot":"","sources":["../src/configWriter.ts"],"names":[],"mappings":"AA2GA;;;;;;;;;;;GAWG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;aAI5B,UAAU,EAAE,MAAM;aAClB,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc;aAC7B,YAAY,CAAC,EAAE,MAAM;IALvC,SAAkB,IAAI,2BAA2B;gBAE/C,OAAO,EAAE,MAAM,EACC,UAAU,EAAE,MAAM,EAClB,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,YAAA,EAC7B,YAAY,CAAC,EAAE,MAAM,YAAA;CAIxC;AAglBD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAevF;AAED;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOtE;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,cAAc,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE;IAAE,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAoEjH"}