@indigoai-us/hq-cli 5.108.25 → 5.109.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/dist/commands/__fixtures__/access-vault.d.ts +93 -0
  3. package/dist/commands/__fixtures__/access-vault.js +166 -0
  4. package/dist/commands/access.d.ts +158 -0
  5. package/dist/commands/access.js +783 -0
  6. package/dist/commands/cloud.js +11 -1
  7. package/dist/commands/files-browse.d.ts +25 -1
  8. package/dist/commands/files-browse.js +81 -17
  9. package/dist/commands/files.js +15 -5
  10. package/dist/commands/integrations-api.d.ts +15 -0
  11. package/dist/commands/integrations-connect.js +84 -3
  12. package/dist/commands/integrations-oauth.js +62 -3
  13. package/dist/commands/mcp-registration.d.ts +17 -7
  14. package/dist/commands/mcp-registration.js +16 -27
  15. package/dist/commands/mesh.js +174 -50
  16. package/dist/commands/pack-install.js +5 -5
  17. package/dist/commands/secrets.d.ts +7 -0
  18. package/dist/commands/secrets.js +26 -2
  19. package/dist/commands/sync-mode.js +12 -1
  20. package/dist/commands/sync-narrow.js +12 -1
  21. package/dist/lib/mesh/live/backfill-held.d.ts +42 -1
  22. package/dist/lib/mesh/live/backfill-held.js +95 -13
  23. package/dist/lib/mesh/live/daemon/doctor.d.ts +15 -0
  24. package/dist/lib/mesh/live/daemon/doctor.js +41 -10
  25. package/dist/lib/mesh/live/daemon/mode.d.ts +37 -0
  26. package/dist/lib/mesh/live/daemon/mode.js +88 -0
  27. package/dist/lib/mesh/live/daemon/run.d.ts +8 -0
  28. package/dist/lib/mesh/live/daemon/run.js +39 -28
  29. package/dist/lib/mesh/live/daemon/state.d.ts +2 -0
  30. package/dist/lib/mesh/live/emit-client.d.ts +99 -0
  31. package/dist/lib/mesh/live/emit-client.js +193 -0
  32. package/dist/lib/mesh/live/emit-evidence.d.ts +49 -0
  33. package/dist/lib/mesh/live/emit-evidence.js +77 -0
  34. package/dist/lib/mesh/live/emit-replay.d.ts +26 -0
  35. package/dist/lib/mesh/live/emit-replay.js +157 -0
  36. package/dist/lib/mesh/live/emit-retry.d.ts +25 -0
  37. package/dist/lib/mesh/live/emit-retry.js +79 -0
  38. package/dist/lib/mesh/live/emit.d.ts +54 -0
  39. package/dist/lib/mesh/live/emit.js +153 -0
  40. package/dist/lib/narrow-hint-banner.d.ts +3 -7
  41. package/dist/lib/narrow-hint-banner.js +13 -34
  42. package/dist/lib/plan-limit-nag.d.ts +0 -3
  43. package/dist/lib/plan-limit-nag.js +10 -20
  44. package/dist/register-all.js +3 -0
  45. package/dist/utils/access-denied-hint.d.ts +32 -0
  46. package/dist/utils/access-denied-hint.js +139 -0
  47. package/dist/utils/access-requests.d.ts +28 -0
  48. package/dist/utils/access-requests.js +98 -0
  49. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,94 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [5.109.0] — 2026-09-08
6
+
7
+ ### Added
8
+
9
+ - `hq access <path-or-query>` — one command for "I can't find or open this
10
+ file". Resolves an exact key or a fuzzy name (never auto-picks between
11
+ several hits), then reports exactly one of `never-existed`, `local`,
12
+ `not-synced`, or `no-access` (exit 0/2/3, 4 for ambiguous). When the file
13
+ exists and you can read it but it is not on disk, it fetches and pins it the
14
+ same way `hq files get` does, and if that fails it runs `hq sync status`,
15
+ `hq sync doctor`, and retries once. When you lack access it names the
16
+ grantor (ACL creator, then company owner/admin), shows their email, asks one
17
+ yes/no question, and sends them a DM whose Copy-prompt is the exact
18
+ `hq files share … --permission read` command. Repeat requests for the same
19
+ prefix are deduped for 24h via `.hq/access-requests.json`. `--json` without
20
+ `--yes` never sends; `--no-fix` diagnoses only.
21
+ - Every access-denied (403) error from `hq files …` and `hq sync …` now ends
22
+ with `Run: hq access <path>`; in a TTY it offers to run it for you.
23
+ Existing messages and exit codes are unchanged.
24
+
25
+ ## [5.108.26] — 2026-09-08
26
+
27
+ ### Added
28
+
29
+ - **Daemon receive-only mode** (owner decision 2026-09-08; contract
30
+ direct-emit-v1 §6.3). `hq mesh mode <get|legacy|direct|check>` selects the
31
+ daemon's emit mode, resolved from `HQ_MESH_MODE` then `~/.hq/work-mesh/config.json`
32
+ (`emitMode`), defaulting to **legacy**. In `legacy` the daemon runs the spool
33
+ watch + flush + held + outbox replay + transcript-watch emit path (unchanged).
34
+ In `direct` it runs **receive-only** — the presence subscriber keeps the cache
35
+ the desktop app reads warm on `hq/{personUid}/mesh`, with no spool/held/outbox/
36
+ flush/transcript-watch — because sessions POST events directly. `hq mesh mode
37
+ check` probes whether `/v1/mesh/events` is live so the flag can flip after the
38
+ server route lands. `hq mesh daemon doctor` reports `mode` + `subscription`
39
+ state and omits the spool/held/outbox lines in direct mode.
40
+ - **Direct-emit path** (owner decision 2026-09-08 "retire the client daemon";
41
+ contract `direct-emit-v1`). `hq mesh session <kind>` now POSTs each Work Mesh
42
+ event straight to `POST /v1/mesh/events` with the caller's normal HQ bearer
43
+ token instead of appending to the local spool; the server attributes the event
44
+ to a company server-side and fans it out over MQTT. Evidence for attribution
45
+ travels in an `evidence` object gathered client-side: `companySlug` (from the
46
+ session meta), `cwd`, `hqRoot`, `touchedPaths` (`--touched-path`, repeatable),
47
+ `repoPath` (derived from the enclosing git work-tree), `project`, `task`. On a
48
+ network/5xx/429 failure the batch is written to a tiny local retry file that the
49
+ next invocation drains — no long-lived process. `--enqueue` is retained as a
50
+ no-op for hook back-compat (it now emits directly).
51
+ - `hq mesh emit` — drains the retry file; `--replay-legacy` also replays the
52
+ legacy `spool.jsonl` + `held.jsonl` backlog through the new endpoint, lifting
53
+ each event's local-only fields into `evidence` and reusing its `eventId` so the
54
+ server dedupes.
55
+ - `hq mesh daemon doctor` now reports the direct-emit path: `emit last post`
56
+ (lastPostAt), per-status counts from the last attempt, and `emit retry depth`.
57
+ - `hq integrations connect --scopes "<list>"` sends an explicit permissions list
58
+ on the OAuth start request, for a vendor whose requirements HQ does not yet
59
+ know. Space- or comma-separated; order preserved, duplicates dropped. Omitting
60
+ the flag is unchanged — the request carries no `scopes` field at all and
61
+ hq-pro keeps choosing, because an empty list would ask a vendor for no access
62
+ rather than for its default. Refused up front where it could never be honoured
63
+ (alongside `--token`, or against an app whose auth mode is known to be `key`
64
+ or `none`), and carried through the printed bring-your-own-client command. A
65
+ console hand-off cannot carry it, and now says so.
66
+
67
+ ### Changed
68
+
69
+ - The loopback sign-in callback page — the one HQ surface a person sees in a
70
+ browser during `hq integrations connect` — now carries the hq-console visual
71
+ language instead of an unstyled white page: near-black ground, hairline-bordered
72
+ card, one 13px size, grey heading over bright body, and a dim `HQ` mark.
73
+ Deliberately ships no webfont: the page is served by a local port and is often
74
+ the browser's first paint after a redirect, where a blocking font request would
75
+ delay it and would fail outright offline — exactly when a loopback callback
76
+ still works.
77
+
78
+ ### Fixed
79
+
80
+ - `hq secrets set` now attributes its writes to a `cli_secrets_set` telemetry
81
+ surface, so CLI-created secrets are no longer recorded as generic `api` traffic.
82
+ - `hq mesh context backfill-held` now forwards the company evidence each held
83
+ event recorded at enqueue time (`cwd`, `hqRoot`, the session's bound
84
+ `companySlug`, and any `project`/`task`) into the synthesized reconcile
85
+ observation, so an ended session attributes to the company it was actually
86
+ bound to (or its `companies/{slug}/` cwd) instead of resolving to
87
+ `needs_company` and staying held forever. `--dry-run` now predicts with the
88
+ same evidence + shared resolver the write path uses, so its `reconciled`/
89
+ `unresolved` counts match a real run — previously `--dry-run` reported every
90
+ unattributed session as would-reconcile while the write run, given no
91
+ evidence in its observation, resolved none.
92
+
5
93
  ## [5.108.25] — 2026-09-08
6
94
 
7
95
  ## [5.108.24] — 2026-09-08
@@ -0,0 +1,93 @@
1
+ /**
2
+ * In-memory vault / ACL / DM harness for the `hq access` command.
3
+ * No network I/O — listings, GetObject, STS vend, and DMs stay in process
4
+ * (or under a tmp hqRoot the caller supplies).
5
+ */
6
+ import { vi } from "vitest";
7
+ import type { CompanyBrowseClientFactory, FilesBrowseVaultClient } from "../files-browse.js";
8
+ export type AccessVaultState = "missing" | "present-local" | "present-not-local" | "present-denied";
9
+ export interface FakeDmMessage {
10
+ recipient: string;
11
+ message: string;
12
+ prompt?: string;
13
+ details?: string;
14
+ }
15
+ export interface FakeDmTransport {
16
+ sent: FakeDmMessage[];
17
+ send(msg: FakeDmMessage): Promise<{
18
+ eventId: string;
19
+ }>;
20
+ }
21
+ export declare function makeFakeDmTransport(): FakeDmTransport;
22
+ export interface AclEntry {
23
+ granteeType: string;
24
+ granteeId: string;
25
+ permission: string;
26
+ grantedBy: string;
27
+ grantedAt: string;
28
+ }
29
+ export interface AccessAclTree {
30
+ prefix: string;
31
+ direct: AclEntry[];
32
+ inherited: Array<AclEntry & {
33
+ sourcePrefix: string;
34
+ }>;
35
+ children: Array<AclEntry & {
36
+ sourcePrefix: string;
37
+ }>;
38
+ directRow: {
39
+ creatorUid: string;
40
+ open: boolean;
41
+ createdAt: string;
42
+ updatedAt: string;
43
+ } | null;
44
+ effectivePermission: string | null;
45
+ }
46
+ export interface AccessMember {
47
+ personUid: string;
48
+ personEmail: string;
49
+ personName?: string;
50
+ role: "owner" | "admin" | "member" | "guest";
51
+ }
52
+ export interface AccessVaultFixture {
53
+ state: AccessVaultState;
54
+ hqRoot: string;
55
+ companySlug: string;
56
+ companyUid: string;
57
+ /** Company-anchored e.g. companies/acme/knowledge/report.md */
58
+ key: string;
59
+ /** Company-relative e.g. knowledge/report.md */
60
+ bucketKey: string;
61
+ vaultClient: FilesBrowseVaultClient;
62
+ companyClient: CompanyBrowseClientFactory;
63
+ vend: ReturnType<typeof vi.fn>;
64
+ acl: AccessAclTree | null;
65
+ members: AccessMember[];
66
+ dm: FakeDmTransport;
67
+ listedKeys: string[];
68
+ region: string;
69
+ }
70
+ export interface MakeAccessFixtureOptions {
71
+ state: AccessVaultState;
72
+ hqRoot: string;
73
+ companySlug?: string;
74
+ key?: string;
75
+ extraKeys?: string[];
76
+ acl?: AccessAclTree | null;
77
+ members?: AccessMember[];
78
+ content?: string;
79
+ /**
80
+ * `present-denied` only: make the LIST call itself fail with 403 (the
81
+ * `/v1/files/list` shape) instead of returning the key. Models a caller
82
+ * without read on the prefix — the server refuses to enumerate.
83
+ */
84
+ listDenied?: boolean;
85
+ /** Deny only the ROOT (prefix "") list — the caller can read the prefix but not enumerate the bucket. */
86
+ rootListDenied?: boolean;
87
+ }
88
+ export declare function vendStatusForState(state: AccessVaultState): {
89
+ status: number;
90
+ message?: string;
91
+ };
92
+ export declare function makeAccessFixture(opts: MakeAccessFixtureOptions): AccessVaultFixture;
93
+ //# sourceMappingURL=access-vault.d.ts.map
@@ -0,0 +1,166 @@
1
+ /**
2
+ * In-memory vault / ACL / DM harness for the `hq access` command.
3
+ * No network I/O — listings, GetObject, STS vend, and DMs stay in process
4
+ * (or under a tmp hqRoot the caller supplies).
5
+ */
6
+ import * as fs from "node:fs";
7
+ import * as path from "node:path";
8
+ import { Readable } from "node:stream";
9
+ import { vi } from "vitest";
10
+ import { ListObjectsV2Command, GetObjectCommand, } from "@aws-sdk/client-s3";
11
+ export function makeFakeDmTransport() {
12
+ const sent = [];
13
+ let n = 0;
14
+ return {
15
+ sent,
16
+ async send(msg) {
17
+ sent.push(msg);
18
+ n += 1;
19
+ return { eventId: `evt_${n}` };
20
+ },
21
+ };
22
+ }
23
+ const FAKE_VEND = {
24
+ credentials: {
25
+ accessKeyId: "ASIA-test",
26
+ secretAccessKey: "secret-test",
27
+ sessionToken: "session-test",
28
+ },
29
+ };
30
+ const DEFAULT_MEMBERS = [
31
+ {
32
+ personUid: "prs_owner",
33
+ personEmail: "owner@example.com",
34
+ personName: "Olive Owner",
35
+ role: "owner",
36
+ },
37
+ {
38
+ personUid: "prs_admin",
39
+ personEmail: "admin@example.com",
40
+ personName: "Adam Admin",
41
+ role: "admin",
42
+ },
43
+ {
44
+ personUid: "prs_me",
45
+ personEmail: "me@example.com",
46
+ personName: "Mia Member",
47
+ role: "member",
48
+ },
49
+ ];
50
+ export function vendStatusForState(state) {
51
+ if (state === "missing")
52
+ return { status: 404 };
53
+ if (state === "present-denied") {
54
+ return { status: 403, message: "caller lacks read on this prefix" };
55
+ }
56
+ return { status: 200 };
57
+ }
58
+ function attachStatus(err, status) {
59
+ const tagged = err;
60
+ tagged.status = status;
61
+ return tagged;
62
+ }
63
+ function attachHttpStatus(err, httpStatusCode) {
64
+ const tagged = err;
65
+ tagged.$metadata = { httpStatusCode };
66
+ return tagged;
67
+ }
68
+ function toBucketKey(key, slug) {
69
+ const prefix = `companies/${slug}/`;
70
+ const trimmed = key.replace(/^\/+/, "");
71
+ if (trimmed.startsWith(prefix))
72
+ return trimmed.slice(prefix.length);
73
+ return trimmed;
74
+ }
75
+ export function makeAccessFixture(opts) {
76
+ const companySlug = opts.companySlug ?? "acme";
77
+ const key = opts.key ?? `companies/${companySlug}/knowledge/report.md`;
78
+ const bucketKey = toBucketKey(key, companySlug);
79
+ const companyUid = `cmp_${companySlug}`;
80
+ const content = opts.content ?? "hello";
81
+ const extraKeys = opts.extraKeys ?? [];
82
+ const listedKeys = opts.state === "missing" ? [...extraKeys] : [...extraKeys, bucketKey];
83
+ const members = opts.members ?? DEFAULT_MEMBERS;
84
+ const acl = opts.acl === undefined ? null : opts.acl;
85
+ const region = "us-east-1";
86
+ const dm = makeFakeDmTransport();
87
+ if (opts.state === "present-local") {
88
+ const dest = path.join(opts.hqRoot, key);
89
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
90
+ fs.writeFileSync(dest, content, "utf-8");
91
+ }
92
+ const vend = vi.fn(async () => {
93
+ if (opts.state === "missing") {
94
+ throw attachStatus(new Error("not found (404)"), 404);
95
+ }
96
+ if (opts.state === "present-denied") {
97
+ throw attachStatus(new Error("caller lacks read on this prefix (403)"), 403);
98
+ }
99
+ return FAKE_VEND;
100
+ });
101
+ const vendSelf = vi.fn(async () => FAKE_VEND);
102
+ const listMyExplicitGrants = vi.fn(async () => []);
103
+ const entityShape = {
104
+ uid: companyUid,
105
+ slug: companySlug,
106
+ name: companySlug,
107
+ bucketName: `hq-vault-cmp-${companySlug}`,
108
+ };
109
+ const findInMyNamespace = vi.fn(async () => entityShape);
110
+ const get = vi.fn(async () => entityShape);
111
+ const vaultClient = {
112
+ sts: { vend, vendSelf },
113
+ listMyExplicitGrants,
114
+ entity: { get, findInMyNamespace },
115
+ };
116
+ const listDenied = opts.state === "present-denied" && opts.listDenied === true;
117
+ const send = vi.fn(async (cmd) => {
118
+ if (cmd instanceof ListObjectsV2Command) {
119
+ const prefix = cmd.input.Prefix ?? "";
120
+ if (listDenied || (opts.rootListDenied === true && prefix === "")) {
121
+ throw Object.assign(new Error("files list failed (403)"), {
122
+ status: 403,
123
+ key: prefix,
124
+ company: companySlug,
125
+ });
126
+ }
127
+ const Contents = listedKeys
128
+ .filter((k) => (prefix === "" ? true : k.startsWith(prefix)))
129
+ .map((Key) => ({
130
+ Key,
131
+ Size: content.length,
132
+ LastModified: new Date(),
133
+ }));
134
+ return { Contents };
135
+ }
136
+ if (cmd instanceof GetObjectCommand) {
137
+ const requested = cmd.input.Key ?? "";
138
+ if (opts.state === "missing" || requested !== bucketKey) {
139
+ throw attachHttpStatus(new Error("Not found (404)"), 404);
140
+ }
141
+ if (opts.state === "present-denied") {
142
+ throw attachHttpStatus(new Error("caller lacks read on this prefix"), 403);
143
+ }
144
+ return { Body: Readable.from([content]) };
145
+ }
146
+ throw new Error(`unexpected command: ${cmd}`);
147
+ });
148
+ const companyClient = vi.fn(() => ({ send }));
149
+ return {
150
+ state: opts.state,
151
+ hqRoot: opts.hqRoot,
152
+ companySlug,
153
+ companyUid,
154
+ key,
155
+ bucketKey,
156
+ vaultClient,
157
+ companyClient,
158
+ vend,
159
+ acl,
160
+ members,
161
+ dm,
162
+ listedKeys,
163
+ region,
164
+ };
165
+ }
166
+ //# sourceMappingURL=access-vault.js.map
@@ -0,0 +1,158 @@
1
+ /**
2
+ * `hq access <path-or-query>` — existence + ACL probe with a self-healing
3
+ * ladder: resolve, list, probe ACL, then (with --fix) download / pin / repair
4
+ * sync or request access from the grantor.
5
+ *
6
+ * Tells a teammate whether a vault file exists and whether they can read it,
7
+ * so they never see a bare not-found.
8
+ *
9
+ * Vending uses the multi-tenant STS route `vaultClient.sts.vend({ companyUid })`
10
+ * (`/sts/vend`). The legacy `POST /vend` is never used — it assumes a single
11
+ * static BUCKET_ARN that is unset in multi-tenant prod.
12
+ *
13
+ * Company vault keys are company-relative; the CLI speaks the anchored form
14
+ * `companies/<slug>/...` for display.
15
+ */
16
+ import { Command } from "commander";
17
+ import { type CompanyBrowseClientFactory, type FilesBrowseVaultClient, type RunGetResult } from "./files-browse.js";
18
+ export type AccessOutcome = "never-existed" | "local" | "not-synced" | "no-access" | "ambiguous" | "pending-confirmation";
19
+ export interface AccessAclTree {
20
+ prefix: string;
21
+ direct: Array<{
22
+ granteeType: string;
23
+ granteeId: string;
24
+ permission: string;
25
+ grantedBy: string;
26
+ grantedAt: string;
27
+ }>;
28
+ inherited: Array<{
29
+ granteeType: string;
30
+ granteeId: string;
31
+ permission: string;
32
+ grantedBy: string;
33
+ grantedAt: string;
34
+ sourcePrefix: string;
35
+ }>;
36
+ children: Array<{
37
+ granteeType: string;
38
+ granteeId: string;
39
+ permission: string;
40
+ grantedBy: string;
41
+ grantedAt: string;
42
+ sourcePrefix: string;
43
+ }>;
44
+ directRow: {
45
+ creatorUid: string;
46
+ open: boolean;
47
+ createdAt: string;
48
+ updatedAt: string;
49
+ } | null;
50
+ effectivePermission: string | null;
51
+ }
52
+ export interface AccessMember {
53
+ personUid: string;
54
+ personEmail: string;
55
+ personName?: string;
56
+ role: "owner" | "admin" | "member" | "guest";
57
+ }
58
+ export interface AccessGrantor {
59
+ personUid: string;
60
+ email: string;
61
+ name?: string;
62
+ source: "acl-creator" | "owner" | "admin";
63
+ }
64
+ export interface AccessDeps {
65
+ hqRoot: string;
66
+ companySlug: string;
67
+ companyUid: string;
68
+ vaultClient: FilesBrowseVaultClient;
69
+ companyClient: CompanyBrowseClientFactory;
70
+ region: string;
71
+ /** GET acl/tree for the exact company-relative prefix; null = no ACL record. */
72
+ fetchAclTree: (prefix: string) => Promise<AccessAclTree | null>;
73
+ /** Active members (owner/admin/member/guest) — used for grantor resolution. */
74
+ listMembers: () => Promise<AccessMember[]>;
75
+ requester: {
76
+ email: string;
77
+ name?: string;
78
+ };
79
+ dm?: {
80
+ send(msg: {
81
+ recipient: string;
82
+ message: string;
83
+ prompt?: string;
84
+ details?: string;
85
+ }): Promise<{
86
+ eventId: string;
87
+ }>;
88
+ };
89
+ confirm?: (question: string) => Promise<boolean>;
90
+ now?: () => number;
91
+ /** Multi-hit chooser. Absent or returning null ⇒ outcome "ambiguous". Never auto-pick. */
92
+ pick?: (candidates: string[]) => Promise<string | null>;
93
+ /** Plain-text sink (default console.log). Tests capture it. */
94
+ log?: (line: string) => void;
95
+ /**
96
+ * Diagnostic sink (default console.error). Carries the recipient line before
97
+ * a DM is sent so it is visible even under --json, whose stdout must stay
98
+ * a single JSON object.
99
+ */
100
+ stderr?: (line: string) => void;
101
+ /** Materialize + pin one path. Default: runGet from ./files-browse.js. */
102
+ get?: (anchoredPath: string) => Promise<RunGetResult>;
103
+ /** Summarise local sync journal state for the company. */
104
+ syncStatus?: () => Promise<string>;
105
+ /** Sync doctor. Default wraps hq-cloud syncDoctor(reconcileConflicts). */
106
+ syncDoctor?: (apply: boolean) => Promise<SyncDoctorOutcome>;
107
+ }
108
+ export interface SyncDoctorOutcome {
109
+ twins: number;
110
+ summary: string;
111
+ bulkRefused?: boolean;
112
+ breakerMessage?: string;
113
+ }
114
+ export interface RunAccessInput {
115
+ target: string;
116
+ fix: boolean;
117
+ json: boolean;
118
+ yes?: boolean;
119
+ deps: AccessDeps;
120
+ }
121
+ export interface RunAccessResult {
122
+ outcome: AccessOutcome;
123
+ path: string;
124
+ company: string;
125
+ exists: boolean;
126
+ grantor?: AccessGrantor;
127
+ candidates?: string[];
128
+ steps: string[];
129
+ exitCode: 0 | 2 | 3 | 4;
130
+ /** True when the self-heal get rung materialized the file. Omitted when not fixed. */
131
+ fixed?: boolean;
132
+ localPath?: string;
133
+ requestSentAt?: string;
134
+ alreadyAskedAt?: string;
135
+ requestNote?: string;
136
+ }
137
+ export declare function outcomeExitCode(outcome: AccessOutcome): 0 | 2 | 3 | 4;
138
+ export declare function formatAccessOutcome(result: RunAccessResult): string;
139
+ export declare function resolveGrantor(tree: AccessAclTree | null, members: AccessMember[]): AccessGrantor | null;
140
+ export declare function runAccess(input: RunAccessInput): Promise<RunAccessResult>;
141
+ export declare function registerAccessCommand(program: Command): void;
142
+ /**
143
+ * Resolve the company `hq access` runs against: explicit `company` (the
144
+ * ladder forwards the slug stamped on a 403), else the slug anchored in the
145
+ * target path, else the active company in `<hqRoot>/.hq/config.json`.
146
+ */
147
+ export declare function resolveAccessCompany(target: string, opts?: {
148
+ company?: string;
149
+ hqRoot?: string;
150
+ }): string | undefined;
151
+ export declare function runAccessForPath(path: string, opts?: {
152
+ company?: string;
153
+ hqRoot?: string;
154
+ json?: boolean;
155
+ yes?: boolean;
156
+ fix?: boolean;
157
+ }): Promise<RunAccessResult>;
158
+ //# sourceMappingURL=access.d.ts.map