@tokenfactory/acc-runner 0.47.9 → 0.47.10

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 (40) hide show
  1. package/dist/build-info.generated.d.ts +1 -1
  2. package/dist/build-info.generated.js +2 -2
  3. package/dist/companion-autostart.d.ts.map +1 -1
  4. package/dist/companion-autostart.js +5 -0
  5. package/dist/companion-autostart.js.map +1 -1
  6. package/dist/companion-run.d.ts.map +1 -1
  7. package/dist/companion-run.js +46 -18
  8. package/dist/companion-run.js.map +1 -1
  9. package/dist/doctor.d.ts +20 -0
  10. package/dist/doctor.d.ts.map +1 -1
  11. package/dist/doctor.js +183 -3
  12. package/dist/doctor.js.map +1 -1
  13. package/dist/keychain.d.ts +31 -0
  14. package/dist/keychain.d.ts.map +1 -1
  15. package/dist/keychain.js +70 -1
  16. package/dist/keychain.js.map +1 -1
  17. package/dist/program.d.ts.map +1 -1
  18. package/dist/program.js +16 -1
  19. package/dist/program.js.map +1 -1
  20. package/dist/runtime/auth-lifecycle.d.ts +22 -1
  21. package/dist/runtime/auth-lifecycle.d.ts.map +1 -1
  22. package/dist/runtime/auth-lifecycle.js +28 -1
  23. package/dist/runtime/auth-lifecycle.js.map +1 -1
  24. package/dist/runtime/refresh-lock.d.ts +232 -0
  25. package/dist/runtime/refresh-lock.d.ts.map +1 -0
  26. package/dist/runtime/refresh-lock.js +609 -0
  27. package/dist/runtime/refresh-lock.js.map +1 -0
  28. package/dist/supervisor.d.ts +32 -0
  29. package/dist/supervisor.d.ts.map +1 -1
  30. package/dist/supervisor.js +56 -0
  31. package/dist/supervisor.js.map +1 -1
  32. package/dist/token-provider.d.ts +12 -0
  33. package/dist/token-provider.d.ts.map +1 -1
  34. package/dist/token-provider.js +23 -3
  35. package/dist/token-provider.js.map +1 -1
  36. package/dist/watch.d.ts +4 -2
  37. package/dist/watch.d.ts.map +1 -1
  38. package/dist/watch.js +117 -20
  39. package/dist/watch.js.map +1 -1
  40. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"auth-lifecycle.js","sourceRoot":"","sources":["../../src/runtime/auth-lifecycle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth-lifecycle.js","sourceRoot":"","sources":["../../src/runtime/auth-lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,232 @@
1
+ import type { TerminalRefreshError } from "./auth-lifecycle.js";
2
+ import type { RunnerConfig } from "../config.js";
3
+ import type { StoredSession } from "../types.js";
4
+ import type { TokenProvider } from "../token-provider.js";
5
+ /**
6
+ * RUNNER-REFRESH-ROTATION-LOST: exit status for a TERMINAL refresh refusal
7
+ * (reuse / expired) or an unprovable keychain save. EX_CONFIG from sysexits(3):
8
+ * the config the process was handed is unusable and a restart would only
9
+ * re-present it, so BOTH the `watch` and `companion` supervisor units carry
10
+ * `RestartPreventExitStatus=78` and the process exits this code rather than
11
+ * letting the supervisor loop every minute and burn every token family it can
12
+ * reach. Defined here (not in watch.ts) so the companion can share it without
13
+ * importing the whole watch task-loop module. watch.ts re-exports it.
14
+ */
15
+ export declare const EX_CONFIG = 78;
16
+ /** Which host process hit a refresh refusal — the two rotators on a slot. */
17
+ export type RotatorProcess = "watch" | "companion";
18
+ /** The minimal authenticated-client surface emitRefreshRefused needs. */
19
+ export interface RefreshRefusedLogClient {
20
+ rpc(fn: string, args: Record<string, unknown>): PromiseLike<unknown>;
21
+ }
22
+ export interface EmitRefreshRefusedOpts {
23
+ session: StoredSession;
24
+ /** The instance name this process resolved (null for the unnamed default). */
25
+ instance: string | null;
26
+ /** The keychain account (= instance slot) the refusal was against. */
27
+ account: string;
28
+ error: TerminalRefreshError;
29
+ /** AC3: which rotator died — folded into the board breadcrumb payload. */
30
+ process: RotatorProcess;
31
+ /**
32
+ * Lazily build the authenticated client for the board breadcrumb. Called ONLY
33
+ * when a usable bearer remains, so a refusal reached after the access token
34
+ * itself expired never constructs a client it has no authority to use. Both
35
+ * callers build a short-lived `createRunnerClient`; watch may reuse its own.
36
+ */
37
+ makeClient: () => RefreshRefusedLogClient;
38
+ /** Bound timeout wrapper so the breadcrumb never holds up the terminal exit. */
39
+ withDeadline?: <T>(p: Promise<T>, ms: number) => Promise<T>;
40
+ /** stderr sink (test seam). Defaults to process.stderr.write. */
41
+ write?: (s: string) => void;
42
+ }
43
+ /**
44
+ * RUNNER-REFRESH-ROTATION-LOST (ROTATED): print the operator-actionable banner
45
+ * for a TERMINAL refresh refusal and emit the runner-lane `auth.refresh_refused`
46
+ * board breadcrumb — AC3, carrying the `process` field so the board sees WHICH
47
+ * rotator (watch or companion) died on the shared slot. Shared verbatim by both
48
+ * rotators so the payload shape can never drift between them. Does NOT exit; the
49
+ * caller decides (both exit EX_CONFIG). The breadcrumb is emitted only while a
50
+ * usable bearer remains and is strictly best-effort — it never throws and never
51
+ * blocks the exit.
52
+ */
53
+ export declare function emitRefreshRefused(opts: EmitRefreshRefusedOpts): Promise<void>;
54
+ export interface RefreshLock {
55
+ /** Remove the lock iff we still own it. Safe to call more than once. */
56
+ release(): Promise<void>;
57
+ /** Always true: acquireRefreshLock now fails CLOSED (throws) rather than
58
+ * returning a lockless no-op, so a returned lock is always genuinely held. */
59
+ readonly held: boolean;
60
+ }
61
+ /**
62
+ * Thrown by acquireRefreshLock when the instance-scoped lock could not be taken
63
+ * within the wait budget because a LIVE sibling still holds it. It is NOT a
64
+ * terminal auth error — the caller must treat it as transient (refuse to rotate
65
+ * lockless, then retry), never exit on it.
66
+ */
67
+ /**
68
+ * The keychain slot could not be re-read under the held lock, so the cached
69
+ * refresh token cannot be proven current. No HTTP refresh is made; the caller
70
+ * treats this like a transient refresh failure and retries.
71
+ */
72
+ export declare class RefreshSlotUnreadableError extends Error {
73
+ readonly account: string;
74
+ constructor(account: string, cause: unknown);
75
+ }
76
+ export declare class RefreshLockBusyError extends Error {
77
+ readonly account: string;
78
+ readonly code: "refresh_lock_busy";
79
+ constructor(account: string);
80
+ }
81
+ /**
82
+ * `<cache>/refresh.<hash>.lock`. The hash is the keychain account (the instance
83
+ * slot), so every process resolving the same slot contends on one file while
84
+ * two distinct instances (distinct slots) never do.
85
+ */
86
+ export declare function refreshLockPath(account: string): string;
87
+ /**
88
+ * How long an UNPARSEABLE lock file is presumed to be a live holder's before it
89
+ * may be reclaimed. The lock file is created atomically with its full payload
90
+ * (temp file + hard link, below), so an unreadable or partial file is never a
91
+ * holder mid-write on this build; it is either a crashed older build's leftover
92
+ * or filesystem damage. It is still never reclaimed while fresh: a reader that
93
+ * cannot name the holder's pid has no proof the holder is dead, and unlinking a
94
+ * live holder's lock is exactly the race this lock exists to prevent.
95
+ */
96
+ export declare const UNPARSEABLE_LOCK_STALE_MS = 30000;
97
+ export interface AcquireRefreshLockOptions {
98
+ pid?: number;
99
+ /** Total time to wait for a live holder before failing open. Default 10s. */
100
+ waitMs?: number;
101
+ /** Poll cadence while waiting. Default 100ms. */
102
+ pollMs?: number;
103
+ now?: () => number;
104
+ sleep?: (ms: number) => Promise<void>;
105
+ }
106
+ /**
107
+ * Acquire the instance-scoped advisory refresh lock for `account`. Two layers:
108
+ * an in-process mutex (same-process rotators queue) and an O_EXCL lock file
109
+ * (cross-process rotators contend). Blocks (polling) while a LIVE process holds
110
+ * the file and reclaims a DEAD holder's lock. If the wait budget is exhausted
111
+ * while a live holder still owns it, it fails CLOSED — throwing
112
+ * `RefreshLockBusyError` — because an HTTP refresh must never run without the
113
+ * lock held (a lockless rotator can re-present a superseded token mid-rotation
114
+ * and trip reuse detection). The caller treats the throw as transient and
115
+ * retries. The in-process gate is always released, including on a throw, so a
116
+ * failed acquire never wedges later same-process rotators.
117
+ */
118
+ export declare function acquireRefreshLock(account: string, opts?: AcquireRefreshLockOptions): Promise<RefreshLock>;
119
+ export interface CoordinatedRefreshDeps {
120
+ cfg: RunnerConfig;
121
+ /** The session the caller is currently running on (its in-memory credential). */
122
+ session: StoredSession;
123
+ provider: TokenProvider;
124
+ /** Injectable for tests. Defaults to the real /api/runner/refresh exchange. */
125
+ refresh?: (cfg: RunnerConfig, session: StoredSession) => Promise<StoredSession>;
126
+ /** Injectable for tests. Defaults to the real advisory file lock. */
127
+ acquireLock?: (account: string) => Promise<RefreshLock>;
128
+ /** Injectable for tests. Defaults to keychain.loadSessionFromAccount. */
129
+ loadFromAccount?: (account: string) => Promise<StoredSession | null>;
130
+ }
131
+ export interface CoordinatedRefreshResult {
132
+ session: StoredSession;
133
+ /** True when we took a sibling rotator's already-rotated session (no HTTP). */
134
+ adopted: boolean;
135
+ /** True when we performed the /api/runner/refresh exchange ourselves. */
136
+ refreshed: boolean;
137
+ }
138
+ /**
139
+ * RUNNER-REFRESH-ROTATION-LOST (ROTATED): refresh the session the rotation-safe way.
140
+ *
141
+ * - Env-token providers have no shared keychain slot (boundAccount() === null)
142
+ * so they just refresh in place — there is no sibling to race.
143
+ * - Keychain providers take the instance-scoped lock, then RE-READ the slot. A
144
+ * refresh token in the slot that differs from ours means a sibling rotator
145
+ * already rotated while we held our (now superseded) token — adopt its
146
+ * successor instead of re-presenting ours. Only when the slot still matches
147
+ * do we call /api/runner/refresh ourselves and save the successor.
148
+ */
149
+ export declare function coordinatedRefresh(deps: CoordinatedRefreshDeps): Promise<CoordinatedRefreshResult>;
150
+ export interface RefreshRotator {
151
+ pid: number;
152
+ /** "watch" | "companion" — the sub-command driving the process. */
153
+ kind: string;
154
+ /** The instance NAME parsed from the argv (`--instance <name>`), or null. */
155
+ instance: string | null;
156
+ }
157
+ /** Map an instance name (or null for the unnamed default) to its keychain slot. */
158
+ export declare function rotatorSlot(instance: string | null): string;
159
+ /**
160
+ * pgrep-style scan for other `acc-runner watch` / `acc-runner companion`
161
+ * processes, extracting the `--instance <name>` each was launched with. Offline
162
+ * of any lock file and best-effort (returns [] on any failure). It reads only
163
+ * the command LINE (`ps -axo args`), never a process's environment — reading
164
+ * /proc/<pid>/environ is banned (it would leak secrets per CLAUDE.md).
165
+ *
166
+ * The process scan only sees RUNNING rotators, and only the slot that appears as
167
+ * `--instance` in argv — a stopped/failed unit, or one that carries its slot in
168
+ * `ACC_RUNNER_INSTANCE` rather than argv, is invisible here. `listRefreshRotatorUnits`
169
+ * below covers both gaps from the read-only systemd unit config.
170
+ */
171
+ export declare function listRefreshRotators(selfPid?: number): Promise<RefreshRotator[]>;
172
+ /**
173
+ * A rotator discovered from its systemd --user unit CONFIG (read-only), so it is
174
+ * visible even when stopped or failed. `mainPid` is the unit's MainPID when it
175
+ * is running (0/null otherwise) — used to reconcile a unit with its own process
176
+ * in the process scan so a single supervised rotator is not double-counted.
177
+ */
178
+ export interface RefreshRotatorUnit {
179
+ unit: string;
180
+ kind: string;
181
+ /** Slot NAME resolved from the unit's ACC_RUNNER_INSTANCE env, argv, or name. */
182
+ instance: string | null;
183
+ /** systemd ActiveState: active | failed | inactive | activating | … */
184
+ state: string;
185
+ mainPid: number | null;
186
+ }
187
+ /**
188
+ * Instance name carried in a unit basename: `acc-runner-<name>.service` or the
189
+ * template form `acc-runner@<name>.service` (the impl1–4 lanes). Null for any
190
+ * other name — a companion unit's name (`acc-staging-companion.service`) says
191
+ * nothing about its slot; its environment does.
192
+ */
193
+ export declare function instanceFromUnitName(unit: string): string | null;
194
+ /** What `systemctl show` says about a unit — the subset the census reads. */
195
+ export interface RotatorUnitProps {
196
+ ExecStart?: string;
197
+ Environment?: string;
198
+ ActiveState?: string;
199
+ MainPID?: string;
200
+ }
201
+ /**
202
+ * Classify one systemd unit as a rotator from what it RUNS and what its
203
+ * environment says, never from its name alone. A unit is a rotator when its
204
+ * ExecStart runs the runner binary (`acc-runner` / `acc`) as `watch` or
205
+ * `companion`, or when its environment carries `ACC_RUNNER_INSTANCE` (a unit
206
+ * that pins a slot refreshes it). Anything else — `acc-keyring.service`, a
207
+ * backup timer, an unrelated service that merely has "acc" in its name — is
208
+ * null. This is the rule the reviewer asked for on 91c768ad: the earlier
209
+ * name filter (`/acc-runner/`) skipped `acc-staging-companion.service`, the
210
+ * very unit that burnt the staging-smoke family (ledger 66).
211
+ */
212
+ export declare function classifyRotatorUnit(unit: string, props: RotatorUnitProps): RefreshRotatorUnit | null;
213
+ /**
214
+ * RUNNER-REFRESH-ROTATION-LOST (ROTATED, AC4): enumerate acc-runner rotator
215
+ * units from systemd --user CONFIG, INCLUDING stopped/failed ones, and resolve
216
+ * the keychain slot each targets from its READ-ONLY unit environment rather than
217
+ * a running process's argv. This closes the two gaps in the process scan:
218
+ *
219
+ * - A stopped or failed unit never appears in `ps`, yet it shares the slot it
220
+ * will rotate the instant it (re)starts — so doctor must still count it.
221
+ * - A unit that carries its slot in `Environment=ACC_RUNNER_INSTANCE=<name>`
222
+ * (not in argv) would be misread as the default slot by the argv-only scan.
223
+ * We read it from `systemctl show --property=Environment`, extracting ONLY
224
+ * `ACC_RUNNER_INSTANCE` and discarding the rest of the string, so no other
225
+ * (possibly secret-bearing) unit variable is ever surfaced. This reads the
226
+ * static unit config — NOT a live process's /proc/<pid>/environ, which stays
227
+ * banned per CLAUDE.md.
228
+ *
229
+ * Best-effort: returns [] on any failure (e.g. no systemd, non-Linux).
230
+ */
231
+ export declare function listRefreshRotatorUnits(): Promise<RefreshRotatorUnit[]>;
232
+ //# sourceMappingURL=refresh-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh-lock.d.ts","sourceRoot":"","sources":["../../src/runtime/refresh-lock.ts"],"names":[],"mappings":"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"}