@indigoai-us/hq-cloud 6.15.4 → 6.15.6

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 (150) hide show
  1. package/dist/cli/push-scan-exclusions.test.d.ts +2 -0
  2. package/dist/cli/push-scan-exclusions.test.d.ts.map +1 -0
  3. package/dist/cli/push-scan-exclusions.test.js +87 -0
  4. package/dist/cli/push-scan-exclusions.test.js.map +1 -0
  5. package/dist/cli/rescue-exec-bit-preserve.test.js +8 -0
  6. package/dist/cli/rescue-exec-bit-preserve.test.js.map +1 -1
  7. package/dist/cli/share.d.ts.map +1 -1
  8. package/dist/cli/share.js +21 -1
  9. package/dist/cli/share.js.map +1 -1
  10. package/dist/cli/share.test.js +82 -0
  11. package/dist/cli/share.test.js.map +1 -1
  12. package/dist/cli/sync.d.ts +23 -0
  13. package/dist/cli/sync.d.ts.map +1 -1
  14. package/dist/cli/sync.js +9 -0
  15. package/dist/cli/sync.js.map +1 -1
  16. package/dist/lib/net-errors.d.ts.map +1 -1
  17. package/dist/lib/net-errors.js +4 -0
  18. package/dist/lib/net-errors.js.map +1 -1
  19. package/dist/machine-auth.test.js +7 -1
  20. package/dist/machine-auth.test.js.map +1 -1
  21. package/dist/object-io.d.ts +21 -0
  22. package/dist/object-io.d.ts.map +1 -1
  23. package/dist/object-io.js +229 -77
  24. package/dist/object-io.js.map +1 -1
  25. package/dist/object-io.test.js +211 -1
  26. package/dist/object-io.test.js.map +1 -1
  27. package/dist/outposts/billing.d.ts +41 -0
  28. package/dist/outposts/billing.d.ts.map +1 -0
  29. package/dist/outposts/billing.js +53 -0
  30. package/dist/outposts/billing.js.map +1 -0
  31. package/dist/outposts/cli-billing.d.ts +59 -0
  32. package/dist/outposts/cli-billing.d.ts.map +1 -0
  33. package/dist/outposts/cli-billing.js +93 -0
  34. package/dist/outposts/cli-billing.js.map +1 -0
  35. package/dist/outposts/cli.d.ts +13 -0
  36. package/dist/outposts/cli.d.ts.map +1 -0
  37. package/dist/outposts/cli.js +13 -0
  38. package/dist/outposts/cli.js.map +1 -0
  39. package/dist/outposts/client.d.ts +140 -0
  40. package/dist/outposts/client.d.ts.map +1 -0
  41. package/dist/outposts/client.js +271 -0
  42. package/dist/outposts/client.js.map +1 -0
  43. package/dist/outposts/client.test.d.ts +9 -0
  44. package/dist/outposts/client.test.d.ts.map +1 -0
  45. package/dist/outposts/client.test.js +226 -0
  46. package/dist/outposts/client.test.js.map +1 -0
  47. package/dist/outposts/command.d.ts +74 -0
  48. package/dist/outposts/command.d.ts.map +1 -0
  49. package/dist/outposts/command.js +661 -0
  50. package/dist/outposts/command.js.map +1 -0
  51. package/dist/outposts/command.test.d.ts +18 -0
  52. package/dist/outposts/command.test.d.ts.map +1 -0
  53. package/dist/outposts/command.test.js +933 -0
  54. package/dist/outposts/command.test.js.map +1 -0
  55. package/dist/outposts/errors.d.ts +32 -0
  56. package/dist/outposts/errors.d.ts.map +1 -0
  57. package/dist/outposts/errors.js +72 -0
  58. package/dist/outposts/errors.js.map +1 -0
  59. package/dist/outposts/heartbeat-command.d.ts +106 -0
  60. package/dist/outposts/heartbeat-command.d.ts.map +1 -0
  61. package/dist/outposts/heartbeat-command.js +186 -0
  62. package/dist/outposts/heartbeat-command.js.map +1 -0
  63. package/dist/outposts/host-deps.d.ts +49 -0
  64. package/dist/outposts/host-deps.d.ts.map +1 -0
  65. package/dist/outposts/host-deps.js +93 -0
  66. package/dist/outposts/host-deps.js.map +1 -0
  67. package/dist/outposts/index.d.ts +36 -0
  68. package/dist/outposts/index.d.ts.map +1 -0
  69. package/dist/outposts/index.js +32 -0
  70. package/dist/outposts/index.js.map +1 -0
  71. package/dist/outposts/node.d.ts +23 -0
  72. package/dist/outposts/node.d.ts.map +1 -0
  73. package/dist/outposts/node.js +22 -0
  74. package/dist/outposts/node.js.map +1 -0
  75. package/dist/outposts/remote-command.d.ts +30 -0
  76. package/dist/outposts/remote-command.d.ts.map +1 -0
  77. package/dist/outposts/remote-command.js +39 -0
  78. package/dist/outposts/remote-command.js.map +1 -0
  79. package/dist/outposts/replica-sync.d.ts +40 -0
  80. package/dist/outposts/replica-sync.d.ts.map +1 -0
  81. package/dist/outposts/replica-sync.js +188 -0
  82. package/dist/outposts/replica-sync.js.map +1 -0
  83. package/dist/outposts/replica-sync.test.d.ts +2 -0
  84. package/dist/outposts/replica-sync.test.d.ts.map +1 -0
  85. package/dist/outposts/replica-sync.test.js +224 -0
  86. package/dist/outposts/replica-sync.test.js.map +1 -0
  87. package/dist/outposts/self-deploy.d.ts +47 -0
  88. package/dist/outposts/self-deploy.d.ts.map +1 -0
  89. package/dist/outposts/self-deploy.js +188 -0
  90. package/dist/outposts/self-deploy.js.map +1 -0
  91. package/dist/outposts/self-deploy.test.d.ts +2 -0
  92. package/dist/outposts/self-deploy.test.d.ts.map +1 -0
  93. package/dist/outposts/self-deploy.test.js +186 -0
  94. package/dist/outposts/self-deploy.test.js.map +1 -0
  95. package/dist/outposts/session-heartbeat-bounds.test.d.ts +25 -0
  96. package/dist/outposts/session-heartbeat-bounds.test.d.ts.map +1 -0
  97. package/dist/outposts/session-heartbeat-bounds.test.js +156 -0
  98. package/dist/outposts/session-heartbeat-bounds.test.js.map +1 -0
  99. package/dist/outposts/session-heartbeat-guard.test.d.ts +16 -0
  100. package/dist/outposts/session-heartbeat-guard.test.d.ts.map +1 -0
  101. package/dist/outposts/session-heartbeat-guard.test.js +88 -0
  102. package/dist/outposts/session-heartbeat-guard.test.js.map +1 -0
  103. package/dist/outposts/session-heartbeat-publisher.d.ts +76 -0
  104. package/dist/outposts/session-heartbeat-publisher.d.ts.map +1 -0
  105. package/dist/outposts/session-heartbeat-publisher.js +117 -0
  106. package/dist/outposts/session-heartbeat-publisher.js.map +1 -0
  107. package/dist/outposts/session-heartbeat-publisher.test.d.ts +10 -0
  108. package/dist/outposts/session-heartbeat-publisher.test.d.ts.map +1 -0
  109. package/dist/outposts/session-heartbeat-publisher.test.js +153 -0
  110. package/dist/outposts/session-heartbeat-publisher.test.js.map +1 -0
  111. package/dist/outposts/session-heartbeat-retain-guard.test.d.ts +18 -0
  112. package/dist/outposts/session-heartbeat-retain-guard.test.d.ts.map +1 -0
  113. package/dist/outposts/session-heartbeat-retain-guard.test.js +106 -0
  114. package/dist/outposts/session-heartbeat-retain-guard.test.js.map +1 -0
  115. package/dist/outposts/session-heartbeat.d.ts +210 -0
  116. package/dist/outposts/session-heartbeat.d.ts.map +1 -0
  117. package/dist/outposts/session-heartbeat.js +657 -0
  118. package/dist/outposts/session-heartbeat.js.map +1 -0
  119. package/dist/outposts/session-heartbeat.test.d.ts +11 -0
  120. package/dist/outposts/session-heartbeat.test.d.ts.map +1 -0
  121. package/dist/outposts/session-heartbeat.test.js +370 -0
  122. package/dist/outposts/session-heartbeat.test.js.map +1 -0
  123. package/dist/outposts/ssh.d.ts +29 -0
  124. package/dist/outposts/ssh.d.ts.map +1 -0
  125. package/dist/outposts/ssh.js +66 -0
  126. package/dist/outposts/ssh.js.map +1 -0
  127. package/dist/outposts/transport.d.ts +76 -0
  128. package/dist/outposts/transport.d.ts.map +1 -0
  129. package/dist/outposts/transport.js +91 -0
  130. package/dist/outposts/transport.js.map +1 -0
  131. package/dist/outposts/transport.test.d.ts +10 -0
  132. package/dist/outposts/transport.test.d.ts.map +1 -0
  133. package/dist/outposts/transport.test.js +116 -0
  134. package/dist/outposts/transport.test.js.map +1 -0
  135. package/dist/outposts/types.d.ts +125 -0
  136. package/dist/outposts/types.d.ts.map +1 -0
  137. package/dist/outposts/types.js +13 -0
  138. package/dist/outposts/types.js.map +1 -0
  139. package/dist/personal-vault.d.ts +69 -0
  140. package/dist/personal-vault.d.ts.map +1 -1
  141. package/dist/personal-vault.js +100 -0
  142. package/dist/personal-vault.js.map +1 -1
  143. package/dist/personal-vault.test.js +140 -1
  144. package/dist/personal-vault.test.js.map +1 -1
  145. package/dist/s3.d.ts.map +1 -1
  146. package/dist/s3.js +62 -0
  147. package/dist/s3.js.map +1 -1
  148. package/dist/s3.test.js +126 -0
  149. package/dist/s3.test.js.map +1 -1
  150. package/package.json +39 -3
@@ -0,0 +1,93 @@
1
+ /**
2
+ * The small local-environment surface the box-side commands touch, injected so
3
+ * they are testable without an actual EC2 host.
4
+ *
5
+ * Node-only. `self-deploy` needs the base set; `replica-sync` extends it with two
6
+ * filesystem probes for the repo clone, kept as an extension so the self-deploy
7
+ * surface stays minimal.
8
+ */
9
+ import { spawnSync } from "node:child_process";
10
+ import * as fs from "node:fs";
11
+ import * as os from "node:os";
12
+ import * as path from "node:path";
13
+ import * as readline from "node:readline";
14
+ import { loadCachedTokens } from "../cognito-auth.js";
15
+ export const defaultSelfDeployDependencies = {
16
+ spawnSync: (command, args, options) => spawnSync(command, args, options),
17
+ readTextFile: (file) => fs.readFileSync(file, "utf8"),
18
+ loadCachedTokens: () => loadCachedTokens() ?? undefined,
19
+ getUid: () => process.getuid?.(),
20
+ isStdinTty: () => process.stdin.isTTY === true,
21
+ confirm: async () => {
22
+ const rl = readline.createInterface({
23
+ input: process.stdin,
24
+ output: process.stdout,
25
+ });
26
+ return new Promise((resolve) => {
27
+ rl.question("", (answer) => {
28
+ rl.close();
29
+ resolve(/^y(es)?$/i.test(answer.trim()));
30
+ });
31
+ });
32
+ },
33
+ defaultHqRoot: () => process.env.HQ_ROOT ?? path.join(os.homedir(), "hq"),
34
+ invokingUser: () => process.env.SUDO_USER ?? process.env.USER ?? os.userInfo().username,
35
+ };
36
+ export const defaultReplicaSyncDependencies = {
37
+ ...defaultSelfDeployDependencies,
38
+ pathExists: (p) => fs.existsSync(p),
39
+ mkdirp: (p) => {
40
+ fs.mkdirSync(p, { recursive: true });
41
+ },
42
+ };
43
+ /**
44
+ * Run a child and throw a plain description on any failure.
45
+ *
46
+ * Child output is deliberately excluded from the thrown message: even though
47
+ * these callers never pass credentials in argv, several of them stream secrets
48
+ * through a child's stdin or environment, so the error path stays secret-safe by
49
+ * construction rather than by review.
50
+ */
51
+ export function runChecked(deps, command, args, description, options) {
52
+ let result;
53
+ try {
54
+ result = deps.spawnSync(command, args, options);
55
+ }
56
+ catch {
57
+ throw new Error(`${description} could not be started.`);
58
+ }
59
+ if (!result || result.error || result.status !== 0) {
60
+ throw new Error(`${description} failed. Resolve the error and try again.`);
61
+ }
62
+ }
63
+ /** `runChecked` under `sudo` unless already root. */
64
+ export function runPrivileged(deps, command, args, description, options) {
65
+ if (deps.getUid() === 0) {
66
+ runChecked(deps, command, args, description, options);
67
+ return;
68
+ }
69
+ runChecked(deps, "sudo", [command, ...args], description, options);
70
+ }
71
+ /** True when `command args` exits 0. Never throws. */
72
+ export function commandSucceeded(deps, command, args) {
73
+ try {
74
+ const result = deps.spawnSync(command, args, { encoding: "utf8" });
75
+ return !!result && !result.error && result.status === 0;
76
+ }
77
+ catch {
78
+ return false;
79
+ }
80
+ }
81
+ /** Trimmed stdout of `command args`, or undefined when it failed. Never throws. */
82
+ export function commandOutput(deps, command, args) {
83
+ try {
84
+ const result = deps.spawnSync(command, args, { encoding: "utf8" });
85
+ if (!result || result.error || result.status !== 0)
86
+ return undefined;
87
+ return String(result.stdout ?? "").trim();
88
+ }
89
+ catch {
90
+ return undefined;
91
+ }
92
+ }
93
+ //# sourceMappingURL=host-deps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-deps.js","sourceRoot":"","sources":["../../src/outposts/host-deps.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * `@indigoai-us/hq-cloud/outposts` — the portable Outpost control-plane client.
3
+ *
4
+ * This entry point is deliberately free of Node built-ins, CLI dependencies, and
5
+ * module-level side effects, so it can be imported straight into a Next.js server
6
+ * action, a route handler, or an edge function. It is also why the subpath exists
7
+ * at all: the package root (`@indigoai-us/hq-cloud`) pulls in the AWS SDK,
8
+ * `chokidar`, and `pino`, none of which belong in a web app's module graph.
9
+ *
10
+ * Server-side only. Every call carries a bearer token, so none of this may run in
11
+ * a client component.
12
+ *
13
+ * ```ts
14
+ * // app/lib/outposts.ts
15
+ * import { OutpostsClient, createOutpostTransport } from "@indigoai-us/hq-cloud/outposts";
16
+ *
17
+ * export const outposts = new OutpostsClient({
18
+ * transport: createOutpostTransport(),
19
+ * token: async () => (await auth())!.idToken,
20
+ * });
21
+ * ```
22
+ *
23
+ * Node-only helpers (SSH exec, the self-hosting installer, the box-side
24
+ * heartbeat) live at `@indigoai-us/hq-cloud/outposts/node`. The `hq outposts`
25
+ * command tree lives at `@indigoai-us/hq-cloud/outposts/cli`.
26
+ */
27
+ export { OutpostsClient, EXEC_MAX_TIMEOUT_SECONDS } from "./client.js";
28
+ export type { OutpostsClientOptions, OutpostTokenSource, WaitForExecOptions, } from "./client.js";
29
+ export { createOutpostTransport, defaultOutpostApiUrl, } from "./transport.js";
30
+ export type { FetchLike, OutpostRequest, OutpostTransport, } from "./transport.js";
31
+ export { OutpostHttpError, parseCappedPayload, parseBillingPayload, isBillingSetupAction, } from "./errors.js";
32
+ export { joinCommandParts, withRemoteHqDir, REMOTE_HQ_DIR_PREFIX, } from "./remote-command.js";
33
+ export { AGENT_PRICE_CENTS, OUTPOST_PRICE_CENTS, formatUsd, mintPaymentLink, } from "./billing.js";
34
+ export type { PaidResource } from "./billing.js";
35
+ export type { BillingErrorPayload, BillingSetupAction, OutpostAgentRuntime, OutpostCappedPayload, OutpostExecAsyncResult, OutpostExecResult, OutpostExecStage, OutpostExecSubmission, OutpostSshAccess, OutpostSummary, ProvisionOutpostInput, } from "./types.js";
36
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/outposts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AACvE,YAAY,EACV,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,SAAS,EACT,cAAc,EACd,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * `@indigoai-us/hq-cloud/outposts` — the portable Outpost control-plane client.
3
+ *
4
+ * This entry point is deliberately free of Node built-ins, CLI dependencies, and
5
+ * module-level side effects, so it can be imported straight into a Next.js server
6
+ * action, a route handler, or an edge function. It is also why the subpath exists
7
+ * at all: the package root (`@indigoai-us/hq-cloud`) pulls in the AWS SDK,
8
+ * `chokidar`, and `pino`, none of which belong in a web app's module graph.
9
+ *
10
+ * Server-side only. Every call carries a bearer token, so none of this may run in
11
+ * a client component.
12
+ *
13
+ * ```ts
14
+ * // app/lib/outposts.ts
15
+ * import { OutpostsClient, createOutpostTransport } from "@indigoai-us/hq-cloud/outposts";
16
+ *
17
+ * export const outposts = new OutpostsClient({
18
+ * transport: createOutpostTransport(),
19
+ * token: async () => (await auth())!.idToken,
20
+ * });
21
+ * ```
22
+ *
23
+ * Node-only helpers (SSH exec, the self-hosting installer, the box-side
24
+ * heartbeat) live at `@indigoai-us/hq-cloud/outposts/node`. The `hq outposts`
25
+ * command tree lives at `@indigoai-us/hq-cloud/outposts/cli`.
26
+ */
27
+ export { OutpostsClient, EXEC_MAX_TIMEOUT_SECONDS } from "./client.js";
28
+ export { createOutpostTransport, defaultOutpostApiUrl, } from "./transport.js";
29
+ export { OutpostHttpError, parseCappedPayload, parseBillingPayload, isBillingSetupAction, } from "./errors.js";
30
+ export { joinCommandParts, withRemoteHqDir, REMOTE_HQ_DIR_PREFIX, } from "./remote-command.js";
31
+ export { AGENT_PRICE_CENTS, OUTPOST_PRICE_CENTS, formatUsd, mintPaymentLink, } from "./billing.js";
32
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/outposts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAOvE,OAAO,EACL,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,gBAAgB,CAAC;AAOxB,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,oBAAoB,GACrB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,eAAe,GAChB,MAAM,cAAc,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `@indigoai-us/hq-cloud/outposts/node` — Node-only Outpost helpers.
3
+ *
4
+ * Everything here touches the filesystem, spawns processes, or talks to AWS IoT,
5
+ * so it cannot run on an edge runtime and is kept out of the portable
6
+ * `@indigoai-us/hq-cloud/outposts` entry point. A Next.js app running on the Node
7
+ * runtime *can* import this, but almost certainly wants the portable client
8
+ * instead — these are host-side and box-side operations.
9
+ */
10
+ export { execViaSsh } from "./ssh.js";
11
+ export type { SshExecResult } from "./ssh.js";
12
+ export { defaultSelfDeployDependencies, defaultReplicaSyncDependencies, runChecked, runPrivileged, commandSucceeded, commandOutput, } from "./host-deps.js";
13
+ export type { SelfDeployDependencies, ReplicaSyncDependencies, } from "./host-deps.js";
14
+ export { selfDeployOutpost, selfDeployPreflight, hqIdentityFromSession, renderSelfDeploySyncScript, renderSelfDeployService, } from "./self-deploy.js";
15
+ export { replicaSyncOutpost, parseReposManifest } from "./replica-sync.js";
16
+ export type { ReplicaRepo } from "./replica-sync.js";
17
+ export { runHeartbeatLoop, resolveIntervalSeconds, writeHeartbeatState, DEFAULT_HEARTBEAT_STATE_FILE, } from "./heartbeat-command.js";
18
+ export type { HeartbeatLoopDeps, HeartbeatLoopOptions, HeartbeatCommandDeps, } from "./heartbeat-command.js";
19
+ export { DEFAULT_HEARTBEAT_INTERVAL_SECONDS, collectSessions, nodeFileSystem, sessionsTopicForPerson, assertNoSecretsInPayload, } from "./session-heartbeat.js";
20
+ export type { FileSystemPort, PublishPort, SessionsHeartbeatPayload, } from "./session-heartbeat.js";
21
+ export { createIotPublishPort, defaultRealtimeCredentialsFetcher, } from "./session-heartbeat-publisher.js";
22
+ export type { RealtimeCredentialsResponse } from "./session-heartbeat-publisher.js";
23
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/outposts/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,EAC9B,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,aAAa,GACd,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACnB,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,kCAAkC,EAClC,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EACV,cAAc,EACd,WAAW,EACX,wBAAwB,GACzB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,oBAAoB,EACpB,iCAAiC,GAClC,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `@indigoai-us/hq-cloud/outposts/node` — Node-only Outpost helpers.
3
+ *
4
+ * Everything here touches the filesystem, spawns processes, or talks to AWS IoT,
5
+ * so it cannot run on an edge runtime and is kept out of the portable
6
+ * `@indigoai-us/hq-cloud/outposts` entry point. A Next.js app running on the Node
7
+ * runtime *can* import this, but almost certainly wants the portable client
8
+ * instead — these are host-side and box-side operations.
9
+ */
10
+ // SSH fallback for boxes without an SSM agent (Lightsail).
11
+ export { execViaSsh } from "./ssh.js";
12
+ // Injected host-environment surface shared by the box-side commands.
13
+ export { defaultSelfDeployDependencies, defaultReplicaSyncDependencies, runChecked, runPrivileged, commandSucceeded, commandOutput, } from "./host-deps.js";
14
+ // Turn the current host into an unmanaged, self-hosted outpost.
15
+ export { selfDeployOutpost, selfDeployPreflight, hqIdentityFromSession, renderSelfDeploySyncScript, renderSelfDeployService, } from "./self-deploy.js";
16
+ // Make a managed box a full replica of the operator's HQ.
17
+ export { replicaSyncOutpost, parseReposManifest } from "./replica-sync.js";
18
+ // Box-side agent-session heartbeat.
19
+ export { runHeartbeatLoop, resolveIntervalSeconds, writeHeartbeatState, DEFAULT_HEARTBEAT_STATE_FILE, } from "./heartbeat-command.js";
20
+ export { DEFAULT_HEARTBEAT_INTERVAL_SECONDS, collectSessions, nodeFileSystem, sessionsTopicForPerson, assertNoSecretsInPayload, } from "./session-heartbeat.js";
21
+ export { createIotPublishPort, defaultRealtimeCredentialsFetcher, } from "./session-heartbeat-publisher.js";
22
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/outposts/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,2DAA2D;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,qEAAqE;AACrE,OAAO,EACL,6BAA6B,EAC7B,8BAA8B,EAC9B,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,aAAa,GACd,MAAM,gBAAgB,CAAC;AAMxB,gEAAgE;AAChE,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,0BAA0B,EAC1B,uBAAuB,GACxB,MAAM,kBAAkB,CAAC;AAE1B,0DAA0D;AAC1D,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAG3E,oCAAoC;AACpC,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACnB,4BAA4B,GAC7B,MAAM,wBAAwB,CAAC;AAOhC,OAAO,EACL,kCAAkC,EAClC,eAAe,EACf,cAAc,EACd,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,wBAAwB,CAAC;AAOhC,OAAO,EACL,oBAAoB,EACpB,iCAAiC,GAClC,MAAM,kCAAkC,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Pure string helpers for shaping a command before it is handed to a box.
3
+ *
4
+ * No imports, no I/O — these are shared verbatim between the CLI and any other
5
+ * caller that needs to build the same remote command line.
6
+ */
7
+ /**
8
+ * Preserve a single command string; safely join argv when an arg parser split it.
9
+ *
10
+ * A single element is passed through untouched so an already-quoted command
11
+ * survives intact; multiple elements are individually quoted and joined, which
12
+ * is what makes `outposts exec -- ls "my dir"` behave.
13
+ */
14
+ export declare function joinCommandParts(commandParts: string[]): string;
15
+ /**
16
+ * Prefix that best-effort `cd`s into the box's HQ checkout before running the
17
+ * caller's command. `exec` runs over two transports with two different default
18
+ * working directories — SSM runs as root with no `$HOME` (cwd `/usr/bin`) and
19
+ * SSH lands in the login user's home — so without this, `exec -- pwd` printed an
20
+ * unhelpful, transport-dependent directory. Initialize a real root home for the
21
+ * SSM case before resolving the HQ folder: tools run by the caller (notably
22
+ * `gh`) otherwise treat the HQ checkout as their home and can create root-owned
23
+ * machine state inside it. The trailing `|| true` keeps the command running from
24
+ * the default directory when no HQ checkout is present, so exec never fails
25
+ * merely because the box has no HQ folder.
26
+ */
27
+ export declare const REMOTE_HQ_DIR_PREFIX = "export HOME=\"${HOME:-/root}\"; cd \"$HOME/hq\" 2>/dev/null || cd ~ec2-user/hq 2>/dev/null || true";
28
+ /** Wrap `command` so it runs from the box's HQ folder (see {@link REMOTE_HQ_DIR_PREFIX}). */
29
+ export declare function withRemoteHqDir(command: string): string;
30
+ //# sourceMappingURL=remote-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-command.d.ts","sourceRoot":"","sources":["../../src/outposts/remote-command.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,CAG/D;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,uGACiE,CAAC;AAEnG,6FAA6F;AAC7F,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Pure string helpers for shaping a command before it is handed to a box.
3
+ *
4
+ * No imports, no I/O — these are shared verbatim between the CLI and any other
5
+ * caller that needs to build the same remote command line.
6
+ */
7
+ function shellQuote(part) {
8
+ return `'${part.replace(/'/g, `'\\''`)}'`;
9
+ }
10
+ /**
11
+ * Preserve a single command string; safely join argv when an arg parser split it.
12
+ *
13
+ * A single element is passed through untouched so an already-quoted command
14
+ * survives intact; multiple elements are individually quoted and joined, which
15
+ * is what makes `outposts exec -- ls "my dir"` behave.
16
+ */
17
+ export function joinCommandParts(commandParts) {
18
+ if (commandParts.length === 1)
19
+ return commandParts[0];
20
+ return commandParts.map(shellQuote).join(" ");
21
+ }
22
+ /**
23
+ * Prefix that best-effort `cd`s into the box's HQ checkout before running the
24
+ * caller's command. `exec` runs over two transports with two different default
25
+ * working directories — SSM runs as root with no `$HOME` (cwd `/usr/bin`) and
26
+ * SSH lands in the login user's home — so without this, `exec -- pwd` printed an
27
+ * unhelpful, transport-dependent directory. Initialize a real root home for the
28
+ * SSM case before resolving the HQ folder: tools run by the caller (notably
29
+ * `gh`) otherwise treat the HQ checkout as their home and can create root-owned
30
+ * machine state inside it. The trailing `|| true` keeps the command running from
31
+ * the default directory when no HQ checkout is present, so exec never fails
32
+ * merely because the box has no HQ folder.
33
+ */
34
+ export const REMOTE_HQ_DIR_PREFIX = 'export HOME="${HOME:-/root}"; cd "$HOME/hq" 2>/dev/null || cd ~ec2-user/hq 2>/dev/null || true';
35
+ /** Wrap `command` so it runs from the box's HQ folder (see {@link REMOTE_HQ_DIR_PREFIX}). */
36
+ export function withRemoteHqDir(command) {
37
+ return `${REMOTE_HQ_DIR_PREFIX}; ${command}`;
38
+ }
39
+ //# sourceMappingURL=remote-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-command.js","sourceRoot":"","sources":["../../src/outposts/remote-command.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC5C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAAC,YAAsB;IACrD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;IACtD,OAAO,YAAY,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAC/B,gGAAgG,CAAC;AAEnG,6FAA6F;AAC7F,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,OAAO,GAAG,oBAAoB,KAAK,OAAO,EAAE,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * `outposts replica-sync` — make a MANAGED box a full replica of the operator's HQ.
3
+ *
4
+ * A box provisioned via `outposts provision` runs this on a systemd timer:
5
+ * 1. `hq auth refresh` — freshen the seeded Cognito session
6
+ * 2. `hq sync pull --personal` — the personal vault (repos.yaml, policies, …)
7
+ * 3. `hq rescue` — re-lay the core kernel (needs `companies/`)
8
+ * 4. clone `repos.yaml` — the operator's OWN repos, gh-authed via vault
9
+ *
10
+ * Unlike `self-deploy` (a manual, unmanaged, all-company watcher on a box you
11
+ * own), replica-sync is GENERIC: it works for every HQ user off their own personal
12
+ * vault, with no per-operator setup script.
13
+ *
14
+ * It is deliberately best-effort end to end. A repeating timer must never leave
15
+ * the systemd unit in `failed` just because one transient step — a mirror blip, a
16
+ * not-yet-signed-in box — didn't complete this cycle. Every step logs its outcome
17
+ * and the run continues.
18
+ *
19
+ * Node-only: shells out to `hq`, `git`, and `gh`, and probes the filesystem.
20
+ */
21
+ import type { ReplicaSyncDependencies } from "./host-deps.js";
22
+ /** One repo entry resolved from `personal/data/repos.yaml`. */
23
+ export interface ReplicaRepo {
24
+ url: string;
25
+ visibility: "public" | "private";
26
+ name: string;
27
+ }
28
+ /**
29
+ * Parse `personal/data/repos.yaml` into a clone list.
30
+ *
31
+ * Mirrors `setup.sh`'s `clone_repos`: `visibility` defaults to public, `name`
32
+ * defaults to the URL basename. Malformed entries are skipped rather than thrown,
33
+ * so one bad row cannot stop the replica cycle.
34
+ */
35
+ export declare function parseReposManifest(yamlText: string): ReplicaRepo[];
36
+ /** Run one replica cycle. Best-effort throughout — see the module doc comment. */
37
+ export declare function replicaSyncOutpost(opts: {
38
+ hqRoot?: string;
39
+ }, deps: ReplicaSyncDependencies): Promise<void>;
40
+ //# sourceMappingURL=replica-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replica-sync.d.ts","sourceRoot":"","sources":["../../src/outposts/replica-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAG9D,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd;AAsBD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,EAAE,CAyBlE;AAiHD,kFAAkF;AAClF,wBAAsB,kBAAkB,CACtC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EACzB,IAAI,EAAE,uBAAuB,GAC5B,OAAO,CAAC,IAAI,CAAC,CAgDf"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * `outposts replica-sync` — make a MANAGED box a full replica of the operator's HQ.
3
+ *
4
+ * A box provisioned via `outposts provision` runs this on a systemd timer:
5
+ * 1. `hq auth refresh` — freshen the seeded Cognito session
6
+ * 2. `hq sync pull --personal` — the personal vault (repos.yaml, policies, …)
7
+ * 3. `hq rescue` — re-lay the core kernel (needs `companies/`)
8
+ * 4. clone `repos.yaml` — the operator's OWN repos, gh-authed via vault
9
+ *
10
+ * Unlike `self-deploy` (a manual, unmanaged, all-company watcher on a box you
11
+ * own), replica-sync is GENERIC: it works for every HQ user off their own personal
12
+ * vault, with no per-operator setup script.
13
+ *
14
+ * It is deliberately best-effort end to end. A repeating timer must never leave
15
+ * the systemd unit in `failed` just because one transient step — a mirror blip, a
16
+ * not-yet-signed-in box — didn't complete this cycle. Every step logs its outcome
17
+ * and the run continues.
18
+ *
19
+ * Node-only: shells out to `hq`, `git`, and `gh`, and probes the filesystem.
20
+ */
21
+ import * as path from "node:path";
22
+ import * as yaml from "js-yaml";
23
+ function repoNameFromUrl(url) {
24
+ const tail = url.split("/").pop() ?? "";
25
+ return tail.replace(/\.git$/, "").trim();
26
+ }
27
+ /**
28
+ * A repo `name` becomes a path segment under `repos/<visibility>/`. A synced
29
+ * repos.yaml is operator data, but a malformed or hostile name must never escape
30
+ * that directory, so constrain it to a single, non-traversal component.
31
+ */
32
+ function isSafePathComponent(value) {
33
+ return (value.length > 0 &&
34
+ !value.includes("/") &&
35
+ !value.includes("\\") &&
36
+ value !== "." &&
37
+ value !== "..");
38
+ }
39
+ /**
40
+ * Parse `personal/data/repos.yaml` into a clone list.
41
+ *
42
+ * Mirrors `setup.sh`'s `clone_repos`: `visibility` defaults to public, `name`
43
+ * defaults to the URL basename. Malformed entries are skipped rather than thrown,
44
+ * so one bad row cannot stop the replica cycle.
45
+ */
46
+ export function parseReposManifest(yamlText) {
47
+ let doc;
48
+ try {
49
+ doc = yaml.load(yamlText);
50
+ }
51
+ catch {
52
+ return [];
53
+ }
54
+ const rawRepos = doc?.repos;
55
+ if (!Array.isArray(rawRepos))
56
+ return [];
57
+ const out = [];
58
+ for (const entry of rawRepos) {
59
+ if (!entry || typeof entry !== "object")
60
+ continue;
61
+ const e = entry;
62
+ const url = typeof e.url === "string" ? e.url.trim() : "";
63
+ if (!url)
64
+ continue;
65
+ const visibility = e.visibility === "private" ? "private" : "public";
66
+ const name = typeof e.name === "string" && e.name.trim()
67
+ ? e.name.trim()
68
+ : repoNameFromUrl(url);
69
+ if (!isSafePathComponent(name))
70
+ continue;
71
+ out.push({ url, visibility, name });
72
+ }
73
+ return out;
74
+ }
75
+ /**
76
+ * Best-effort spawn: log a one-line outcome and carry on. NEVER throws and NEVER
77
+ * echoes child output — the same secret-safety stance as `runChecked`, since these
78
+ * children (auth refresh, secrets exec) touch credentials.
79
+ */
80
+ function runBestEffort(deps, command, args, description, options) {
81
+ let result;
82
+ try {
83
+ result = deps.spawnSync(command, args, options ?? { stdio: "inherit" });
84
+ }
85
+ catch {
86
+ console.warn(`replica-sync: ${description} could not run — continuing.`);
87
+ return false;
88
+ }
89
+ if (!result || result.error || result.status !== 0) {
90
+ console.warn(`replica-sync: ${description} did not complete cleanly — continuing.`);
91
+ return false;
92
+ }
93
+ return true;
94
+ }
95
+ /**
96
+ * Authenticate `gh` for private clones by streaming GITHUB_TOKEN through the vault
97
+ * into the child's ENV ONLY, unsetting it in-shell, and piping it to
98
+ * `gh auth login --with-token` over stdin. The token never touches argv or this
99
+ * process's logs. Mirrors `personal/scripts/setup.sh`'s `configure_gh`.
100
+ */
101
+ function authGitHubViaVault(deps) {
102
+ const ghLogin = [
103
+ 'TOKEN="$GITHUB_TOKEN"',
104
+ "unset GITHUB_TOKEN",
105
+ 'printf "%s" "$TOKEN" | gh auth login --with-token',
106
+ ].join("\n");
107
+ const authed = runBestEffort(deps, "hq", [
108
+ "secrets",
109
+ "--personal",
110
+ "exec",
111
+ "--only",
112
+ "GITHUB_TOKEN",
113
+ "--",
114
+ "bash",
115
+ "-c",
116
+ ghLogin,
117
+ ], "GitHub auth via vault");
118
+ if (authed) {
119
+ // Let plain `git clone https://github.com/...` reuse gh's token so private
120
+ // repos don't prompt for a username/password.
121
+ runBestEffort(deps, "gh", ["auth", "setup-git"], "gh auth setup-git");
122
+ }
123
+ }
124
+ /** Clone any repos from `personal/data/repos.yaml` that aren't on disk yet. */
125
+ function replicateRepos(deps, hqRoot) {
126
+ const manifestPath = path.join(hqRoot, "personal", "data", "repos.yaml");
127
+ let manifestText;
128
+ try {
129
+ manifestText = deps.readTextFile(manifestPath);
130
+ }
131
+ catch {
132
+ console.log("replica-sync: no personal/data/repos.yaml — skipping repo clone.");
133
+ return;
134
+ }
135
+ const repos = parseReposManifest(manifestText);
136
+ if (repos.length === 0) {
137
+ console.log("replica-sync: repos.yaml lists no repos — skipping.");
138
+ return;
139
+ }
140
+ const missing = repos.filter((repo) => !deps.pathExists(path.join(hqRoot, "repos", repo.visibility, repo.name, ".git")));
141
+ if (missing.length === 0) {
142
+ console.log("replica-sync: all repos already present.");
143
+ return;
144
+ }
145
+ // Private repos need gh auth first; public-only manifests skip the vault call.
146
+ if (missing.some((repo) => repo.visibility === "private")) {
147
+ authGitHubViaVault(deps);
148
+ }
149
+ for (const repo of missing) {
150
+ deps.mkdirp(path.join(hqRoot, "repos", repo.visibility));
151
+ const dest = path.join(hqRoot, "repos", repo.visibility, repo.name);
152
+ console.log(`replica-sync: cloning ${repo.visibility}/${repo.name}…`);
153
+ runBestEffort(deps, "git", ["clone", "--recurse-submodules", repo.url, dest], `clone ${repo.visibility}/${repo.name}`);
154
+ }
155
+ }
156
+ /** Run one replica cycle. Best-effort throughout — see the module doc comment. */
157
+ export async function replicaSyncOutpost(opts, deps) {
158
+ const hqRoot = opts.hqRoot ?? deps.defaultHqRoot();
159
+ // Gate: only replicate on a box that has an HQ session. A box that was never
160
+ // signed in has nothing to pull — exit cleanly so the timer stays green.
161
+ const session = deps.loadCachedTokens();
162
+ if (!session?.refreshToken) {
163
+ console.log("replica-sync: no HQ session on this box yet — nothing to replicate.");
164
+ return;
165
+ }
166
+ // Auth refresh gates the run: if the seeded refresh token is dead, every
167
+ // authenticated step below (pull, secrets exec) would just cascade 401s. Stop
168
+ // the cycle cleanly instead — the timer retries next tick.
169
+ if (!runBestEffort(deps, "hq", ["auth", "refresh"], "HQ auth refresh")) {
170
+ console.warn("replica-sync: auth refresh failed — skipping this cycle (token likely expired).");
171
+ return;
172
+ }
173
+ runBestEffort(deps, "hq", [
174
+ "sync",
175
+ "pull",
176
+ "--personal",
177
+ "--hq-root",
178
+ hqRoot,
179
+ "--on-conflict",
180
+ "keep",
181
+ ], "personal vault pull");
182
+ // rescue lays down the core kernel and expects companies/ to exist.
183
+ deps.mkdirp(path.join(hqRoot, "companies"));
184
+ runBestEffort(deps, "hq", ["rescue", "--hq-root", hqRoot, "--yes"], "HQ kernel rescue");
185
+ replicateRepos(deps, hqRoot);
186
+ console.log("replica-sync: complete.");
187
+ }
188
+ //# sourceMappingURL=replica-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replica-sync.js","sourceRoot":"","sources":["../../src/outposts/replica-sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=replica-sync.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replica-sync.test.d.ts","sourceRoot":"","sources":["../../src/outposts/replica-sync.test.ts"],"names":[],"mappings":""}