@ttctl/core 0.0.0 → 0.1.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -9
- package/dist/__generated__/gateway.d.ts +4546 -0
- package/dist/__generated__/gateway.d.ts.map +1 -0
- package/dist/__generated__/gateway.js +9 -0
- package/dist/__generated__/gateway.js.map +1 -0
- package/dist/__generated__/talent-profile-zod-schemas.d.ts +1187 -0
- package/dist/__generated__/talent-profile-zod-schemas.d.ts.map +1 -0
- package/dist/__generated__/talent-profile-zod-schemas.js +1136 -0
- package/dist/__generated__/talent-profile-zod-schemas.js.map +1 -0
- package/dist/__generated__/talent-profile.d.ts +1397 -0
- package/dist/__generated__/talent-profile.d.ts.map +1 -0
- package/dist/__generated__/talent-profile.js +9 -0
- package/dist/__generated__/talent-profile.js.map +1 -0
- package/dist/__generated__/zod-schemas.d.ts +2895 -0
- package/dist/__generated__/zod-schemas.d.ts.map +1 -0
- package/dist/__generated__/zod-schemas.js +3121 -0
- package/dist/__generated__/zod-schemas.js.map +1 -0
- package/dist/__tests__/fixtures/profile/builders.d.ts +74 -0
- package/dist/__tests__/fixtures/profile/builders.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/builders.js +196 -0
- package/dist/__tests__/fixtures/profile/builders.js.map +1 -0
- package/dist/__tests__/fixtures/profile/data.d.ts +39 -0
- package/dist/__tests__/fixtures/profile/data.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/data.js +230 -0
- package/dist/__tests__/fixtures/profile/data.js.map +1 -0
- package/dist/__tests__/fixtures/profile/index.d.ts +9 -0
- package/dist/__tests__/fixtures/profile/index.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/index.js +10 -0
- package/dist/__tests__/fixtures/profile/index.js.map +1 -0
- package/dist/__tests__/fixtures/profile/types.d.ts +53 -0
- package/dist/__tests__/fixtures/profile/types.d.ts.map +1 -0
- package/dist/__tests__/fixtures/profile/types.js +4 -0
- package/dist/__tests__/fixtures/profile/types.js.map +1 -0
- package/dist/auth/errors.d.ts +82 -0
- package/dist/auth/errors.d.ts.map +1 -0
- package/dist/auth/errors.js +68 -0
- package/dist/auth/errors.js.map +1 -0
- package/dist/auth.d.ts +192 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +294 -0
- package/dist/auth.js.map +1 -0
- package/dist/config.d.ts +212 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +349 -0
- package/dist/config.js.map +1 -0
- package/dist/configLock.d.ts +50 -0
- package/dist/configLock.d.ts.map +1 -0
- package/dist/configLock.js +88 -0
- package/dist/configLock.js.map +1 -0
- package/dist/configWriter.d.ts +97 -0
- package/dist/configWriter.d.ts.map +1 -0
- package/dist/configWriter.js +687 -0
- package/dist/configWriter.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/kill-switch.d.ts +161 -0
- package/dist/kill-switch.d.ts.map +1 -0
- package/dist/kill-switch.js +235 -0
- package/dist/kill-switch.js.map +1 -0
- package/dist/lib/date.d.ts +58 -0
- package/dist/lib/date.d.ts.map +1 -0
- package/dist/lib/date.js +104 -0
- package/dist/lib/date.js.map +1 -0
- package/dist/lib/diagnostic-log.d.ts +159 -0
- package/dist/lib/diagnostic-log.d.ts.map +1 -0
- package/dist/lib/diagnostic-log.js +186 -0
- package/dist/lib/diagnostic-log.js.map +1 -0
- package/dist/lib/package-version.d.ts +19 -0
- package/dist/lib/package-version.d.ts.map +1 -0
- package/dist/lib/package-version.js +38 -0
- package/dist/lib/package-version.js.map +1 -0
- package/dist/lib/redact.d.ts +153 -0
- package/dist/lib/redact.d.ts.map +1 -0
- package/dist/lib/redact.js +207 -0
- package/dist/lib/redact.js.map +1 -0
- package/dist/lib/text.d.ts +14 -0
- package/dist/lib/text.d.ts.map +1 -0
- package/dist/lib/text.js +21 -0
- package/dist/lib/text.js.map +1 -0
- package/dist/lib/wire-shape.d.ts +131 -0
- package/dist/lib/wire-shape.d.ts.map +1 -0
- package/dist/lib/wire-shape.js +376 -0
- package/dist/lib/wire-shape.js.map +1 -0
- package/dist/onepassword.d.ts +29 -0
- package/dist/onepassword.d.ts.map +1 -0
- package/dist/onepassword.js +112 -0
- package/dist/onepassword.js.map +1 -0
- package/dist/services/_shared/transport.d.ts +148 -0
- package/dist/services/_shared/transport.d.ts.map +1 -0
- package/dist/services/_shared/transport.js +102 -0
- package/dist/services/_shared/transport.js.map +1 -0
- package/dist/services/applications/index.d.ts +210 -0
- package/dist/services/applications/index.d.ts.map +1 -0
- package/dist/services/applications/index.js +240 -0
- package/dist/services/applications/index.js.map +1 -0
- package/dist/services/availability/index.d.ts +254 -0
- package/dist/services/availability/index.d.ts.map +1 -0
- package/dist/services/availability/index.js +310 -0
- package/dist/services/availability/index.js.map +1 -0
- package/dist/services/contracts/index.d.ts +132 -0
- package/dist/services/contracts/index.d.ts.map +1 -0
- package/dist/services/contracts/index.js +211 -0
- package/dist/services/contracts/index.js.map +1 -0
- package/dist/services/engagements/index.d.ts +504 -0
- package/dist/services/engagements/index.d.ts.map +1 -0
- package/dist/services/engagements/index.js +613 -0
- package/dist/services/engagements/index.js.map +1 -0
- package/dist/services/jobs/index.d.ts +490 -0
- package/dist/services/jobs/index.d.ts.map +1 -0
- package/dist/services/jobs/index.js +753 -0
- package/dist/services/jobs/index.js.map +1 -0
- package/dist/services/payments/index.d.ts +415 -0
- package/dist/services/payments/index.d.ts.map +1 -0
- package/dist/services/payments/index.js +636 -0
- package/dist/services/payments/index.js.map +1 -0
- package/dist/services/profile/__tests__/fixtures.d.ts +214 -0
- package/dist/services/profile/__tests__/fixtures.d.ts.map +1 -0
- package/dist/services/profile/__tests__/fixtures.js +176 -0
- package/dist/services/profile/__tests__/fixtures.js.map +1 -0
- package/dist/services/profile/basic/index.d.ts +390 -0
- package/dist/services/profile/basic/index.d.ts.map +1 -0
- package/dist/services/profile/basic/index.js +1007 -0
- package/dist/services/profile/basic/index.js.map +1 -0
- package/dist/services/profile/certifications/index.d.ts +74 -0
- package/dist/services/profile/certifications/index.d.ts.map +1 -0
- package/dist/services/profile/certifications/index.js +169 -0
- package/dist/services/profile/certifications/index.js.map +1 -0
- package/dist/services/profile/education/index.d.ts +73 -0
- package/dist/services/profile/education/index.d.ts.map +1 -0
- package/dist/services/profile/education/index.js +168 -0
- package/dist/services/profile/education/index.js.map +1 -0
- package/dist/services/profile/employment/index.d.ts +111 -0
- package/dist/services/profile/employment/index.d.ts.map +1 -0
- package/dist/services/profile/employment/index.js +202 -0
- package/dist/services/profile/employment/index.js.map +1 -0
- package/dist/services/profile/external/index.d.ts +219 -0
- package/dist/services/profile/external/index.d.ts.map +1 -0
- package/dist/services/profile/external/index.js +560 -0
- package/dist/services/profile/external/index.js.map +1 -0
- package/dist/services/profile/index.d.ts +24 -0
- package/dist/services/profile/index.d.ts.map +1 -0
- package/dist/services/profile/index.js +26 -0
- package/dist/services/profile/index.js.map +1 -0
- package/dist/services/profile/industries/index.d.ts +130 -0
- package/dist/services/profile/industries/index.d.ts.map +1 -0
- package/dist/services/profile/industries/index.js +292 -0
- package/dist/services/profile/industries/index.js.map +1 -0
- package/dist/services/profile/portfolio/index.d.ts +352 -0
- package/dist/services/profile/portfolio/index.d.ts.map +1 -0
- package/dist/services/profile/portfolio/index.js +833 -0
- package/dist/services/profile/portfolio/index.js.map +1 -0
- package/dist/services/profile/resume/index.d.ts +60 -0
- package/dist/services/profile/resume/index.d.ts.map +1 -0
- package/dist/services/profile/resume/index.js +212 -0
- package/dist/services/profile/resume/index.js.map +1 -0
- package/dist/services/profile/reviews/index.d.ts +137 -0
- package/dist/services/profile/reviews/index.d.ts.map +1 -0
- package/dist/services/profile/reviews/index.js +431 -0
- package/dist/services/profile/reviews/index.js.map +1 -0
- package/dist/services/profile/shared.d.ts +127 -0
- package/dist/services/profile/shared.d.ts.map +1 -0
- package/dist/services/profile/shared.js +155 -0
- package/dist/services/profile/shared.js.map +1 -0
- package/dist/services/profile/skills/index.d.ts +212 -0
- package/dist/services/profile/skills/index.d.ts.map +1 -0
- package/dist/services/profile/skills/index.js +461 -0
- package/dist/services/profile/skills/index.js.map +1 -0
- package/dist/services/profile/visas/index.d.ts +74 -0
- package/dist/services/profile/visas/index.d.ts.map +1 -0
- package/dist/services/profile/visas/index.js +306 -0
- package/dist/services/profile/visas/index.js.map +1 -0
- package/dist/services/timesheet/index.d.ts +326 -0
- package/dist/services/timesheet/index.d.ts.map +1 -0
- package/dist/services/timesheet/index.js +324 -0
- package/dist/services/timesheet/index.js.map +1 -0
- package/dist/services/translations.d.ts +79 -0
- package/dist/services/translations.d.ts.map +1 -0
- package/dist/services/translations.js +136 -0
- package/dist/services/translations.js.map +1 -0
- package/dist/transport-resilience.d.ts +136 -0
- package/dist/transport-resilience.d.ts.map +1 -0
- package/dist/transport-resilience.js +247 -0
- package/dist/transport-resilience.js.map +1 -0
- package/dist/transport.d.ts +408 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +691 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +41 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +18 -0
- package/dist/types.js.map +1 -0
- package/package.json +40 -12
- package/index.js +0 -7
|
@@ -0,0 +1,88 @@
|
|
|
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 chosen
|
|
7
|
+
* configuration produces ≤1.0s total wait: 5 retries × max 250ms backoff =
|
|
8
|
+
* 1250ms ceiling, but with `factor: 1` the backoff stays flat at
|
|
9
|
+
* `minTimeout`-`maxTimeout` so the practical envelope is closer to 5×100ms
|
|
10
|
+
* to 5×250ms = 500ms-1250ms with jitter. Tightens the upper bound below
|
|
11
|
+
* NFR-LOCK-1's 1.0s plan.
|
|
12
|
+
*/
|
|
13
|
+
const LOCK_RETRY_OPTIONS = {
|
|
14
|
+
retries: 5,
|
|
15
|
+
factor: 1,
|
|
16
|
+
minTimeout: 100,
|
|
17
|
+
maxTimeout: 250,
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Stale-lock threshold. If a lockfile is older than this without a refresh,
|
|
21
|
+
* `proper-lockfile` treats it as abandoned and overrides it. Defends against
|
|
22
|
+
* a crashed CLI/MCP that didn't release its lock on exit. The exit-handler
|
|
23
|
+
* via `signal-exit` is best-effort; the stale threshold is the second line.
|
|
24
|
+
*
|
|
25
|
+
* Set to 10s — long enough that a slow signin (network-bound ~2-5s) won't
|
|
26
|
+
* trip the threshold, short enough that a stranded lock from a SIGKILL'd
|
|
27
|
+
* process clears within a single user-perceptible retry window.
|
|
28
|
+
*/
|
|
29
|
+
const LOCK_STALE_MS = 10_000;
|
|
30
|
+
/**
|
|
31
|
+
* Acquire an advisory exclusive lock for `configPath`.
|
|
32
|
+
*
|
|
33
|
+
* Implementation: `proper-lockfile` creates `<configPath>.lock` as a
|
|
34
|
+
* sibling DIRECTORY via atomic `mkdir(2)`. The `mkdir` syscall is atomic on
|
|
35
|
+
* ext4, APFS, NTFS, and any other filesystem with POSIX-equivalent
|
|
36
|
+
* semantics — `EEXIST` is the contention signal.
|
|
37
|
+
*
|
|
38
|
+
* Why sibling-lockfile and NOT self-lock: the atomic-rename pattern in
|
|
39
|
+
* `performYamlMutation` swaps the inode at `<configPath>` mid-operation. A
|
|
40
|
+
* `flock(fd)` on the original inode does NOT survive the rename and a
|
|
41
|
+
* concurrent locker on the post-rename inode sees no contention. The
|
|
42
|
+
* sibling pattern sidesteps this — the `.lock` directory's existence is the
|
|
43
|
+
* lock signal, independent of the config file's inode.
|
|
44
|
+
*
|
|
45
|
+
* Cross-platform: works identically on Linux/macOS/Windows — `mkdir`-based
|
|
46
|
+
* atomic creation is portable. No Windows no-op needed (in contrast to the
|
|
47
|
+
* existing POSIX-mode logic in `loadConfigFile` and `performYamlMutation`,
|
|
48
|
+
* which IS Windows-skipped because mode bits aren't meaningful).
|
|
49
|
+
*
|
|
50
|
+
* Contention: ≤1.0s wall-clock budget per `LOCK_RETRY_OPTIONS`. On timeout,
|
|
51
|
+
* throws `ConfigError(LOCKED)` naming the path and suggesting retry — never
|
|
52
|
+
* blocks indefinitely.
|
|
53
|
+
*
|
|
54
|
+
* `realpath: false` skips proper-lockfile's pre-flight `realpath()` check.
|
|
55
|
+
* The caller has already resolved `configPath` to an absolute, symlink-free
|
|
56
|
+
* path via `assertSafePath`, AND the config file may not exist yet (e.g.,
|
|
57
|
+
* the lock is acquired BEFORE the stat baseline that throws ENOENT). With
|
|
58
|
+
* `realpath: true` (the library default), a missing file would surface as
|
|
59
|
+
* an opaque proper-lockfile error before our own ENOENT path runs.
|
|
60
|
+
*/
|
|
61
|
+
export async function acquireConfigLock(configPath) {
|
|
62
|
+
let release;
|
|
63
|
+
try {
|
|
64
|
+
release = await lockfile.lock(configPath, {
|
|
65
|
+
stale: LOCK_STALE_MS,
|
|
66
|
+
retries: LOCK_RETRY_OPTIONS,
|
|
67
|
+
realpath: false,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
// proper-lockfile throws an Error with a `code` property of "ELOCKED"
|
|
72
|
+
// when contention exhausts retries. Surface as ConfigError(LOCKED) so
|
|
73
|
+
// CLI/MCP error renderers can branch on the code rather than the
|
|
74
|
+
// library-specific marker.
|
|
75
|
+
const code = err.code;
|
|
76
|
+
if (code === "ELOCKED") {
|
|
77
|
+
throw new ConfigError(`Refusing to acquire config lock at ${configPath}.lock: another ttctl process holds it. ` +
|
|
78
|
+
`Wait for it to finish (CLI signin / MCP tool call typically ≤2s) and retry.`, "LOCKED", configPath);
|
|
79
|
+
}
|
|
80
|
+
// Any other error (EACCES on the parent dir, EROFS, etc.) — surface as
|
|
81
|
+
// PERMISSION so the caller can branch on it. Lock acquisition is
|
|
82
|
+
// mechanically a write to the parent directory, so permission errors
|
|
83
|
+
// are the natural failure mode.
|
|
84
|
+
throw new ConfigError(`Cannot acquire config lock at ${configPath}.lock: ${err.message}`, "PERMISSION", configPath);
|
|
85
|
+
}
|
|
86
|
+
return { release };
|
|
87
|
+
}
|
|
88
|
+
//# 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;;;;;;;GAOG;AACH,MAAM,kBAAkB,GAAG;IACzB,OAAO,EAAE,CAAC;IACV,MAAM,EAAE,CAAC;IACT,UAAU,EAAE,GAAG;IACf,UAAU,EAAE,GAAG;CAChB,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,aAAa,GAAG,MAAM,CAAC;AAE7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;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;AA+kBD;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
|