@tokenfactory/acc-runner 0.47.9 → 0.47.11
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/dist/build-info.generated.d.ts +1 -1
- package/dist/build-info.generated.js +2 -2
- package/dist/companion-autostart.d.ts.map +1 -1
- package/dist/companion-autostart.js +5 -0
- package/dist/companion-autostart.js.map +1 -1
- package/dist/companion-run.d.ts.map +1 -1
- package/dist/companion-run.js +46 -18
- package/dist/companion-run.js.map +1 -1
- package/dist/doctor.d.ts +20 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +187 -3
- package/dist/doctor.js.map +1 -1
- package/dist/keychain.d.ts +31 -0
- package/dist/keychain.d.ts.map +1 -1
- package/dist/keychain.js +70 -1
- package/dist/keychain.js.map +1 -1
- package/dist/program.d.ts.map +1 -1
- package/dist/program.js +23 -1
- package/dist/program.js.map +1 -1
- package/dist/runtime/auth-lifecycle.d.ts +22 -1
- package/dist/runtime/auth-lifecycle.d.ts.map +1 -1
- package/dist/runtime/auth-lifecycle.js +28 -1
- package/dist/runtime/auth-lifecycle.js.map +1 -1
- package/dist/runtime/refresh-lock.d.ts +232 -0
- package/dist/runtime/refresh-lock.d.ts.map +1 -0
- package/dist/runtime/refresh-lock.js +609 -0
- package/dist/runtime/refresh-lock.js.map +1 -0
- package/dist/supervisor.d.ts +46 -0
- package/dist/supervisor.d.ts.map +1 -1
- package/dist/supervisor.js +65 -0
- package/dist/supervisor.js.map +1 -1
- package/dist/task-runner.d.ts.map +1 -1
- package/dist/task-runner.js +16 -0
- package/dist/task-runner.js.map +1 -1
- package/dist/token-provider.d.ts +12 -0
- package/dist/token-provider.d.ts.map +1 -1
- package/dist/token-provider.js +23 -3
- package/dist/token-provider.js.map +1 -1
- package/dist/watch.d.ts +31 -13
- package/dist/watch.d.ts.map +1 -1
- package/dist/watch.js +180 -37
- package/dist/watch.js.map +1 -1
- package/package.json +1 -1
- package/scripts/setup-dedicated-runner-linux.sh +17 -35
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-lifecycle.js","sourceRoot":"","sources":["../../src/runtime/auth-lifecycle.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE1C
|
|
1
|
+
{"version":3,"file":"auth-lifecycle.js","sourceRoot":"","sources":["../../src/runtime/auth-lifecycle.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAE1C;;;;;;;;GAQG;AACH,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IACzC,IAAI,GAAuB,wBAAwB,CAAC;IAC7D,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAC;IAC1C,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IACnC,IAAI,GAAuB,iBAAiB,CAAC;IACtD,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAKD,iFAAiF;AACjF,MAAM,UAAU,sBAAsB,CAAC,GAAY;IACjD,OAAO,GAAG,YAAY,yBAAyB,IAAI,GAAG,YAAY,mBAAmB,CAAC;AACxF,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,WAAW,CAAC,OAAsB,EAAE,MAAM,GAAG,WAAW;IACtE,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3C,OAAO,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC;AACvC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,GAAiB,EACjB,OAAsB;IAEtB,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,qBAAqB,EAAE;QACjF,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,YAAY,EAAE,cAAc,gBAAgB,EAAE;SAC/C;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC;KAC/D,CAAC,CAAC;IACH,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAA4B,CAAC;QAC7E,IAAI,IAAI,CAAC,KAAK,KAAK,wBAAwB,EAAE,CAAC;YAC5C,MAAM,IAAI,yBAAyB,CACjC,IAAI,CAAC,IAAI;gBACP,2GAA2G,CAC9G,CAAC;QACJ,CAAC;QACD,yEAAyE;QACzE,4EAA4E;QAC5E,wDAAwD;QACxD,MAAM,IAAI,mBAAmB,CAAC,IAAI,CAAC,IAAI,IAAI,+CAA+C,CAAC,CAAC;IAC9F,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,CAAC,MAAM,IAAI,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAmB,CAAC;IAClD,OAAO;QACL,GAAG,OAAO;QACV,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,iBAAiB,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;QACjE,aAAa,EAAE,IAAI,CAAC,aAAa,IAAI,OAAO,CAAC,aAAa;KAC3D,CAAC;AACJ,CAAC;AAWD;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CACpC,GAAyE;IAEzE,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC9C,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,IACE,IAAI,KAAK,UAAU;QACnB,IAAI,KAAK,KAAK;QACd,IAAI,KAAK,KAAK;QACd,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnB,GAAG,CAAC,QAAQ,CAAC,eAAe,CAAC;QAC7B,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACjC,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC;QAC5B,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,EACzB,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QAC1F,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACnE,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,IACE,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC3B,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC3B,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC;QAC3B,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnB,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,EACnB,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACzD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IACE,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC;QAC5B,GAAG,CAAC,QAAQ,CAAC,cAAc,CAAC;QAC5B,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC;QACvB,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAC9B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAU,CAAC;AAEpF;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,mBAA2B,EAAE,MAAc;IAC9E,IAAI,mBAAmB,IAAI,CAAC;QAAE,OAAO,MAAM,CAAC;IAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,mBAAmB,GAAG,CAAC,EAAE,oBAAoB,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/E,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -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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"}
|