@indigoai-us/hq-cli 5.125.0 → 5.127.0
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/CHANGELOG.md +329 -0
- package/assets/bot-workers/setup/skills/joining-a-team.md +125 -0
- package/assets/bot-workers/setup/skills/your-business.md +270 -0
- package/assets/bot-workers/setup/worker.yaml +189 -58
- package/assets/lanes-hooks/hq-lanes-drain.json +15 -0
- package/assets/lanes-hooks/hq-lanes-drain.mjs +254 -0
- package/assets/lanes-hooks/hq-lanes-drain.sh +21 -0
- package/assets/lanes-reconcile/hq-lanes-reconcile.service +11 -0
- package/assets/lanes-reconcile/hq-lanes-reconcile.timer +12 -0
- package/dist/command-catalog.generated.d.ts +643 -6
- package/dist/command-catalog.generated.js +836 -6
- package/dist/command-registration-plan.d.ts +7 -0
- package/dist/command-registration-plan.js +11 -1
- package/dist/commands/agents.d.ts +12 -0
- package/dist/commands/agents.js +46 -2
- package/dist/commands/bot.d.ts +10 -0
- package/dist/commands/bot.js +6 -0
- package/dist/commands/lanes.d.ts +114 -0
- package/dist/commands/lanes.js +2969 -0
- package/dist/commands/mesh.js +287 -24
- package/dist/commands/onboard-create-identity.d.ts +26 -0
- package/dist/commands/onboard-create-identity.js +23 -0
- package/dist/commands/onboard.js +13 -4
- package/dist/lib/bot/progress.d.ts +6 -0
- package/dist/lib/bot/progress.js +16 -0
- package/dist/lib/bot/runtime/grok.d.ts +30 -7
- package/dist/lib/bot/runtime/grok.js +86 -8
- package/dist/lib/bot/runtime/index.js +15 -8
- package/dist/lib/bot/runtime/messages-stream.d.ts +12 -3
- package/dist/lib/bot/runtime/messages-stream.js +49 -3
- package/dist/lib/lanes/accounts.d.ts +103 -0
- package/dist/lib/lanes/accounts.js +318 -0
- package/dist/lib/lanes/compaction.d.ts +96 -0
- package/dist/lib/lanes/compaction.js +197 -0
- package/dist/lib/lanes/config.d.ts +71 -0
- package/dist/lib/lanes/config.js +408 -0
- package/dist/lib/lanes/delivery.d.ts +151 -0
- package/dist/lib/lanes/delivery.js +354 -0
- package/dist/lib/lanes/dropbox.d.ts +96 -0
- package/dist/lib/lanes/dropbox.js +408 -0
- package/dist/lib/lanes/effort.d.ts +50 -0
- package/dist/lib/lanes/effort.js +109 -0
- package/dist/lib/lanes/errors.d.ts +39 -0
- package/dist/lib/lanes/errors.js +72 -0
- package/dist/lib/lanes/hooks-install.d.ts +81 -0
- package/dist/lib/lanes/hooks-install.js +326 -0
- package/dist/lib/lanes/hq-root.d.ts +19 -0
- package/dist/lib/lanes/hq-root.js +28 -0
- package/dist/lib/lanes/index.d.ts +49 -0
- package/dist/lib/lanes/index.js +27 -0
- package/dist/lib/lanes/liveness.d.ts +95 -0
- package/dist/lib/lanes/liveness.js +332 -0
- package/dist/lib/lanes/machine-identity.d.ts +34 -0
- package/dist/lib/lanes/machine-identity.js +92 -0
- package/dist/lib/lanes/mesh-events.d.ts +109 -0
- package/dist/lib/lanes/mesh-events.js +275 -0
- package/dist/lib/lanes/outpost-dispatch.d.ts +65 -0
- package/dist/lib/lanes/outpost-dispatch.js +90 -0
- package/dist/lib/lanes/questions.d.ts +75 -0
- package/dist/lib/lanes/questions.js +243 -0
- package/dist/lib/lanes/quota.d.ts +95 -0
- package/dist/lib/lanes/quota.js +320 -0
- package/dist/lib/lanes/reconcile-install.d.ts +69 -0
- package/dist/lib/lanes/reconcile-install.js +221 -0
- package/dist/lib/lanes/reconcile.d.ts +102 -0
- package/dist/lib/lanes/reconcile.js +985 -0
- package/dist/lib/lanes/registry.d.ts +116 -0
- package/dist/lib/lanes/registry.js +521 -0
- package/dist/lib/lanes/spawn.d.ts +274 -0
- package/dist/lib/lanes/spawn.js +1363 -0
- package/dist/lib/lanes/store.d.ts +68 -0
- package/dist/lib/lanes/store.js +745 -0
- package/dist/lib/lanes/throttle.d.ts +89 -0
- package/dist/lib/lanes/throttle.js +297 -0
- package/dist/lib/lanes/types.d.ts +535 -0
- package/dist/lib/lanes/types.js +350 -0
- package/dist/lib/lanes/watcher-main.d.ts +9 -0
- package/dist/lib/lanes/watcher-main.js +22 -0
- package/dist/lib/lanes/watcher.d.ts +216 -0
- package/dist/lib/lanes/watcher.js +859 -0
- package/dist/lib/mesh/api.d.ts +71 -7
- package/dist/lib/mesh/api.js +167 -28
- package/dist/lib/mesh/live/backfill-held.d.ts +18 -7
- package/dist/lib/mesh/live/backfill-held.js +66 -21
- package/dist/lib/mesh/live/daemon/config.d.ts +27 -0
- package/dist/lib/mesh/live/daemon/config.js +75 -0
- package/dist/lib/mesh/live/daemon/index.d.ts +4 -3
- package/dist/lib/mesh/live/daemon/index.js +3 -3
- package/dist/lib/mesh/live/daemon/install.d.ts +143 -1
- package/dist/lib/mesh/live/daemon/install.js +444 -2
- package/dist/lib/mesh/live/daemon/paths.d.ts +2 -0
- package/dist/lib/mesh/live/daemon/paths.js +2 -0
- package/dist/lib/mesh/live/daemon/run.d.ts +2 -0
- package/dist/lib/mesh/live/daemon/run.js +111 -54
- package/dist/lib/mesh/live/daemon/state.d.ts +2 -0
- package/dist/lib/mesh/live/daemon/transcript-watch.d.ts +3 -0
- package/dist/lib/mesh/live/daemon/transcript-watch.js +31 -8
- package/dist/lib/scan-packages/index.d.ts +2 -0
- package/dist/lib/scan-packages/index.js +18 -13
- package/dist/lib/work-context/config.d.ts +20 -0
- package/dist/lib/work-context/config.js +26 -5
- package/dist/lib/work-context/reconcile.js +28 -7
- package/dist/lib/work-context/state.d.ts +12 -0
- package/dist/lib/work-context/state.js +131 -3
- package/dist/lib/work-context/windows-acl.d.ts +123 -0
- package/dist/lib/work-context/windows-acl.js +425 -0
- package/dist/utils/pack-contributions.js +5 -4
- package/package.json +3 -1
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* Written only by hq mesh context. Owner 0600. Metadata-only — never prompts/tokens.
|
|
4
4
|
*/
|
|
5
5
|
import * as fs from "node:fs";
|
|
6
|
+
import * as path from "node:path";
|
|
6
7
|
import { WORK_CONTEXT_CONTRACT_VERSION } from "./contract.js";
|
|
7
|
-
import { atomicWriteJson, ensureOwnerDir } from "./atomic.js";
|
|
8
|
-
import { NotTrackingError } from "./errors.js";
|
|
8
|
+
import { atomicWriteJson, ensureOwnerDir, resolveRealTarget } from "./atomic.js";
|
|
9
|
+
import { NotTrackingError, UnsafeConfigPathError } from "./errors.js";
|
|
9
10
|
import { isSafeWorkContextSegment, workContextSessionPath, workContextSessionsDir, } from "./paths.js";
|
|
10
11
|
/** Allowlisted keys that may appear in the durable state projection. */
|
|
11
12
|
export const SESSION_STATE_ALLOWLIST = new Set([
|
|
@@ -30,6 +31,113 @@ export const SESSION_STATE_ALLOWLIST = new Set([
|
|
|
30
31
|
"companyConfidence",
|
|
31
32
|
"updatedAt",
|
|
32
33
|
]);
|
|
34
|
+
const SESSION_STATE_LOCK_TIMEOUT_MS = 5_000;
|
|
35
|
+
const SESSION_STATE_LOCK_RETRY_MS = 10;
|
|
36
|
+
function waitForSessionStateLock(ms) {
|
|
37
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
|
|
38
|
+
}
|
|
39
|
+
function asPersistenceFailure(err) {
|
|
40
|
+
if (err instanceof NotTrackingError || err instanceof UnsafeConfigPathError)
|
|
41
|
+
throw err;
|
|
42
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
43
|
+
throw new NotTrackingError(`Failed to persist session state: ${message}`, "NOT_TRACKING");
|
|
44
|
+
}
|
|
45
|
+
function reclaimStaleSessionStateLock(lockPath) {
|
|
46
|
+
const claim = `${lockPath}.reclaim.${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}`;
|
|
47
|
+
try {
|
|
48
|
+
fs.renameSync(lockPath, claim);
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
if (err.code === "ENOENT")
|
|
52
|
+
return false;
|
|
53
|
+
throw err;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
try {
|
|
60
|
+
fs.unlinkSync(claim);
|
|
61
|
+
}
|
|
62
|
+
catch { /* private claim cannot block writers */ }
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Serialize a session-state read/modify/write with every state writer. Atomic
|
|
67
|
+
* rename protects readers from torn files, but only this shared lock protects
|
|
68
|
+
* a writer that has to verify the current binding before changing it.
|
|
69
|
+
*/
|
|
70
|
+
export function withSessionStateLock(sessionId, root, fn) {
|
|
71
|
+
if (!isSafeWorkContextSegment(sessionId)) {
|
|
72
|
+
throw new NotTrackingError(`Unsafe session id for state file: ${sessionId}`, "NOT_TRACKING");
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
ensureOwnerDir(workContextSessionsDir(root));
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
asPersistenceFailure(err);
|
|
79
|
+
}
|
|
80
|
+
const statePath = resolveRealTarget(workContextSessionPath(sessionId, root));
|
|
81
|
+
const lockPath = `${statePath}.lock`;
|
|
82
|
+
const token = `${process.pid}.${Date.now()}.${Math.random().toString(16).slice(2)}`;
|
|
83
|
+
const deadline = Date.now() + SESSION_STATE_LOCK_TIMEOUT_MS;
|
|
84
|
+
let fd;
|
|
85
|
+
while (fd === undefined) {
|
|
86
|
+
try {
|
|
87
|
+
fd = fs.openSync(lockPath, "wx", 0o600);
|
|
88
|
+
fs.writeSync(fd, JSON.stringify({ pid: process.pid, token }));
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
if (err.code !== "EEXIST")
|
|
92
|
+
asPersistenceFailure(err);
|
|
93
|
+
let ownerPid = 0;
|
|
94
|
+
try {
|
|
95
|
+
const raw = JSON.parse(fs.readFileSync(lockPath, "utf8"));
|
|
96
|
+
ownerPid = typeof raw.pid === "number" && Number.isInteger(raw.pid) ? raw.pid : 0;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// A malformed lock cannot safely protect the state.
|
|
100
|
+
}
|
|
101
|
+
let ownerAlive = false;
|
|
102
|
+
if (ownerPid > 0) {
|
|
103
|
+
try {
|
|
104
|
+
process.kill(ownerPid, 0);
|
|
105
|
+
ownerAlive = true;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
// Dead owners do not retain the lock.
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (!ownerAlive) {
|
|
112
|
+
try {
|
|
113
|
+
reclaimStaleSessionStateLock(lockPath);
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
asPersistenceFailure(err);
|
|
117
|
+
}
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
if (Date.now() >= deadline) {
|
|
121
|
+
throw new NotTrackingError(`Timed out waiting for session state lock: ${path.basename(statePath)}`, "NOT_TRACKING");
|
|
122
|
+
}
|
|
123
|
+
waitForSessionStateLock(SESSION_STATE_LOCK_RETRY_MS);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
return fn();
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
fs.closeSync(fd);
|
|
131
|
+
try {
|
|
132
|
+
const current = JSON.parse(fs.readFileSync(lockPath, "utf8"));
|
|
133
|
+
if (current.token === token)
|
|
134
|
+
fs.unlinkSync(lockPath);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// A stale-lock reclaimer or replacement owner has already retired it.
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
33
141
|
export function readSessionState(sessionId, root) {
|
|
34
142
|
if (!isSafeWorkContextSegment(sessionId))
|
|
35
143
|
return null;
|
|
@@ -50,6 +158,9 @@ export function writeSessionState(state, root) {
|
|
|
50
158
|
if (!isSafeWorkContextSegment(state.sessionId)) {
|
|
51
159
|
throw new NotTrackingError(`Unsafe session id for state file: ${state.sessionId}`, "NOT_TRACKING");
|
|
52
160
|
}
|
|
161
|
+
return withSessionStateLock(state.sessionId, root, () => writeSessionStateUnlocked(state, root));
|
|
162
|
+
}
|
|
163
|
+
function writeSessionStateUnlocked(state, root) {
|
|
53
164
|
const projected = projectSessionState(state);
|
|
54
165
|
try {
|
|
55
166
|
ensureOwnerDir(workContextSessionsDir(root));
|
|
@@ -61,6 +172,20 @@ export function writeSessionState(state, root) {
|
|
|
61
172
|
throw new NotTrackingError(`Failed to persist session state: ${err instanceof Error ? err.message : String(err)}`, "NOT_TRACKING");
|
|
62
173
|
}
|
|
63
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Commit a state change only after inspecting the latest value under the same
|
|
177
|
+
* lock used by ordinary session writers. Returning null declines the write.
|
|
178
|
+
*/
|
|
179
|
+
export function updateSessionState(sessionId, root, update) {
|
|
180
|
+
return withSessionStateLock(sessionId, root, () => {
|
|
181
|
+
const current = readSessionState(sessionId, root);
|
|
182
|
+
const next = update(current);
|
|
183
|
+
if (!next)
|
|
184
|
+
return null;
|
|
185
|
+
writeSessionStateUnlocked(next, root);
|
|
186
|
+
return next;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
64
189
|
/** Strip any non-allowlisted fields before durable write. */
|
|
65
190
|
export function projectSessionState(state) {
|
|
66
191
|
const out = {
|
|
@@ -118,7 +243,10 @@ export function mergeLocalSessionFields(next, prior, options = {}) {
|
|
|
118
243
|
// projected locally; losing it causes held events and repeat registrations.
|
|
119
244
|
// A caller that carries either company field is intentionally changing the
|
|
120
245
|
// binding and remains authoritative.
|
|
121
|
-
if (
|
|
246
|
+
if (options.preserveCompanyBinding !== false &&
|
|
247
|
+
!out.companyUid &&
|
|
248
|
+
!out.companySlug &&
|
|
249
|
+
(prior.companyUid || prior.companySlug)) {
|
|
122
250
|
out.companyUid = prior.companyUid;
|
|
123
251
|
out.companySlug = prior.companySlug;
|
|
124
252
|
out.contextStatus = prior.contextStatus;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows DACL check for the work-context config (US-018).
|
|
3
|
+
*
|
|
4
|
+
* NTFS has no POSIX mode bits: Node reports `mode` 0666 for every regular
|
|
5
|
+
* file on win32, so the POSIX `mode & 0o022` test in config.ts can never pass
|
|
6
|
+
* there. Instead of skipping the check on Windows, this module reads the real
|
|
7
|
+
* DACL and refuses the config when any principal other than the current user,
|
|
8
|
+
* SYSTEM, Administrators, or the owner is granted write/modify/full access.
|
|
9
|
+
*
|
|
10
|
+
* How the DACL is read (no native dependency):
|
|
11
|
+
* `icacls <path> /save <tmpfile>` writes the DACL as an SDDL string
|
|
12
|
+
* (`D:AI(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;FA;;;S-1-5-21-...)`). SDDL carries
|
|
13
|
+
* SIDs or well-known SID abbreviations, never display names, so the check is
|
|
14
|
+
* independent of the OS language (VORDEFINIERT\Administratoren is still BA /
|
|
15
|
+
* S-1-5-32-544). The current user's SID comes from `whoami /user`. Display
|
|
16
|
+
* names are only resolved (via PowerShell) for the error message.
|
|
17
|
+
*
|
|
18
|
+
* Trust is decided by SID: S-1-5-18 (SYSTEM), S-1-5-32-544 (Administrators),
|
|
19
|
+
* S-1-3-0 (CREATOR OWNER), S-1-3-4 (OWNER RIGHTS), the current user's SID and
|
|
20
|
+
* the owner's SID when known.
|
|
21
|
+
*
|
|
22
|
+
* Reduced-guarantee path (explicit, documented): the check does NOT throw and
|
|
23
|
+
* instead emits one stderr diagnostic that the config is unprotected on this
|
|
24
|
+
* platform when, and only when, the DACL cannot be evaluated:
|
|
25
|
+
* - icacls is missing, fails, or its output has no SDDL line (unreadable);
|
|
26
|
+
* - an ACE grants write to a principal whose SID we cannot resolve (an SDDL
|
|
27
|
+
* abbreviation this module does not know), or carries a rights token we
|
|
28
|
+
* cannot decode, or the current user's SID is unknown and the grant is to
|
|
29
|
+
* a non-well-known SID (unresolvable).
|
|
30
|
+
* A DACL that parses and grants write to a resolved SID outside the trusted
|
|
31
|
+
* set always throws UnsafeConfigPathError. Nothing else falls back.
|
|
32
|
+
*/
|
|
33
|
+
export interface SddlAce {
|
|
34
|
+
/** ACE type token, e.g. `A` (allow) or `D` (deny). */
|
|
35
|
+
type: string;
|
|
36
|
+
/** ACE flag string, e.g. `OICIID`. */
|
|
37
|
+
flags: string;
|
|
38
|
+
/** Rights field as written, e.g. `FA`, `0x1200a9`, `CCDCLCSWRPWPRC`. */
|
|
39
|
+
rights: string;
|
|
40
|
+
/** Account field as written: full SID or two-letter abbreviation. */
|
|
41
|
+
account: string;
|
|
42
|
+
}
|
|
43
|
+
export type AclReadResult = {
|
|
44
|
+
readable: true;
|
|
45
|
+
sddl: string;
|
|
46
|
+
} | {
|
|
47
|
+
readable: false;
|
|
48
|
+
reason: string;
|
|
49
|
+
};
|
|
50
|
+
export interface WindowsAclCheckOptions {
|
|
51
|
+
/** Current user SID (defaults to `whoami /user`). `null` = unknown. */
|
|
52
|
+
currentUserSid?: string | null;
|
|
53
|
+
/** Owner SID when known (icacls /save does not include the owner). */
|
|
54
|
+
ownerSid?: string | null;
|
|
55
|
+
/** DACL reader; injectable for tests. Defaults to `icacls <path> /save`. */
|
|
56
|
+
readAcl?: (targetPath: string) => AclReadResult;
|
|
57
|
+
/** SID → display name for error messages; injectable for tests. */
|
|
58
|
+
resolveSidName?: (sid: string) => string | null;
|
|
59
|
+
/** Diagnostic sink for the reduced-guarantee path (defaults to stderr). */
|
|
60
|
+
diagnostic?: (line: string) => void;
|
|
61
|
+
}
|
|
62
|
+
export type AclVerdict = {
|
|
63
|
+
kind: "safe";
|
|
64
|
+
} | {
|
|
65
|
+
kind: "unsafe";
|
|
66
|
+
sid: string;
|
|
67
|
+
rights: string;
|
|
68
|
+
} | {
|
|
69
|
+
kind: "unresolvable";
|
|
70
|
+
reason: string;
|
|
71
|
+
};
|
|
72
|
+
export declare const SID_SYSTEM = "S-1-5-18";
|
|
73
|
+
export declare const SID_ADMINISTRATORS = "S-1-5-32-544";
|
|
74
|
+
export declare const SID_CREATOR_OWNER = "S-1-3-0";
|
|
75
|
+
export declare const SID_OWNER_RIGHTS = "S-1-3-4";
|
|
76
|
+
/** Resolve an SDDL account field to a SID, or null when unknown. */
|
|
77
|
+
export declare function sddlAccountToSid(account: string): string | null;
|
|
78
|
+
/** Any of these bits lets the holder change the file or replace it. */
|
|
79
|
+
export declare const WRITE_MASK: number;
|
|
80
|
+
/** Decode an SDDL rights field to an access mask, or null when undecodable. */
|
|
81
|
+
export declare function sddlRightsToMask(rights: string): number | null;
|
|
82
|
+
/**
|
|
83
|
+
* Parse the DACL portion of an SDDL string into ACEs. Accepts a full security
|
|
84
|
+
* descriptor string (`O:...G:...D:...S:...`) or just the `D:` section.
|
|
85
|
+
* Returns null when no DACL section is present or an ACE is malformed.
|
|
86
|
+
*/
|
|
87
|
+
export declare function parseSddlDacl(sddl: string): SddlAce[] | null;
|
|
88
|
+
/**
|
|
89
|
+
* Parse the file `icacls <path> /save <file>` writes: UTF-16LE (optional BOM),
|
|
90
|
+
* CRLF, alternating `<name>` / `<sddl>` lines. Returns the SDDL of the first
|
|
91
|
+
* entry (the target itself), or an unreadable result.
|
|
92
|
+
*/
|
|
93
|
+
export declare function parseIcaclsSaveOutput(raw: string | Buffer): AclReadResult;
|
|
94
|
+
/**
|
|
95
|
+
* Absolute path of a System32 tool. PATH lookup is not safe here: Git Bash and
|
|
96
|
+
* MSYS environments put a coreutils `whoami` ahead of Windows' `whoami.exe`,
|
|
97
|
+
* which does not understand `/user` and would make the current user SID look
|
|
98
|
+
* unknown on every run.
|
|
99
|
+
*/
|
|
100
|
+
export declare function system32Tool(exe: string): string;
|
|
101
|
+
export declare function readAclWithIcaclsSave(targetPath: string): AclReadResult;
|
|
102
|
+
/** Current user's SID via `whoami /user /fo csv /nh`; null when unavailable. */
|
|
103
|
+
export declare function readCurrentUserSid(): string | null;
|
|
104
|
+
/** Best-effort SID → account name (only used to build error messages). */
|
|
105
|
+
export declare function resolveSidNameWithPowerShell(sid: string): string | null;
|
|
106
|
+
/**
|
|
107
|
+
* Evaluate parsed ACEs against the trusted SID set.
|
|
108
|
+
* - `unsafe`: an allow ACE grants a write bit to a resolved, untrusted SID.
|
|
109
|
+
* - `unresolvable`: a write-granting ACE whose SID or rights cannot be decoded,
|
|
110
|
+
* or whose SID is a per-machine/domain SID while the current user is unknown.
|
|
111
|
+
* - `safe`: everything else (deny ACEs and read-only grants are ignored).
|
|
112
|
+
*/
|
|
113
|
+
export declare function evaluateDacl(aces: SddlAce[], opts: Pick<WindowsAclCheckOptions, "currentUserSid" | "ownerSid">): AclVerdict;
|
|
114
|
+
/**
|
|
115
|
+
* Assert the Windows DACL of `targetPath` grants write only to trusted
|
|
116
|
+
* principals. Throws UnsafeConfigPathError naming the offending principal.
|
|
117
|
+
* Unreadable or unresolvable DACL → reduced-guarantee diagnostic (once per
|
|
118
|
+
* path), no throw. See the module header for the exact conditions.
|
|
119
|
+
*/
|
|
120
|
+
export declare function assertWindowsOwnerOnlyAcl(targetPath: string, kind: "file" | "directory", opts?: WindowsAclCheckOptions): void;
|
|
121
|
+
/** Test hook: forget which paths already emitted the reduced-guarantee line. */
|
|
122
|
+
export declare function resetWindowsAclDiagnostics(): void;
|
|
123
|
+
//# sourceMappingURL=windows-acl.d.ts.map
|