@raidiant/notifai 8.0.0 → 9.1.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 (168) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +20 -13
  3. package/dist/atomic-file.d.ts +14 -0
  4. package/dist/atomic-file.js +27 -2
  5. package/dist/atomic-file.js.map +1 -1
  6. package/dist/cli-bin.d.ts +4 -0
  7. package/dist/cli-bin.js +62 -0
  8. package/dist/cli-bin.js.map +1 -0
  9. package/dist/cli-release.d.ts +10 -0
  10. package/dist/cli-release.js +75 -0
  11. package/dist/cli-release.js.map +1 -0
  12. package/dist/client.d.ts +1 -0
  13. package/dist/client.js +13 -3
  14. package/dist/client.js.map +1 -1
  15. package/dist/command-session.d.ts +14 -0
  16. package/dist/command-session.js +30 -0
  17. package/dist/command-session.js.map +1 -0
  18. package/dist/commands-auth.d.ts +6 -0
  19. package/dist/commands-auth.js +28 -3
  20. package/dist/commands-auth.js.map +1 -1
  21. package/dist/commands-config.js +22 -3
  22. package/dist/commands-config.js.map +1 -1
  23. package/dist/commands-core.d.ts +12 -0
  24. package/dist/commands-core.js +27 -3
  25. package/dist/commands-core.js.map +1 -1
  26. package/dist/commands-doctor.d.ts +1 -0
  27. package/dist/commands-doctor.js +87 -29
  28. package/dist/commands-doctor.js.map +1 -1
  29. package/dist/commands-guidance.d.ts +7 -3
  30. package/dist/commands-guidance.js +40 -31
  31. package/dist/commands-guidance.js.map +1 -1
  32. package/dist/commands-harness-context.js +21 -1
  33. package/dist/commands-harness-context.js.map +1 -1
  34. package/dist/commands-hooks.d.ts +20 -5
  35. package/dist/commands-hooks.js +509 -155
  36. package/dist/commands-hooks.js.map +1 -1
  37. package/dist/commands-init.d.ts +12 -18
  38. package/dist/commands-init.js +149 -47
  39. package/dist/commands-init.js.map +1 -1
  40. package/dist/commands-send-support.d.ts +17 -2
  41. package/dist/commands-send-support.js +61 -5
  42. package/dist/commands-send-support.js.map +1 -1
  43. package/dist/commands-send.d.ts +1 -0
  44. package/dist/commands-send.js +114 -17
  45. package/dist/commands-send.js.map +1 -1
  46. package/dist/commands-setup-proof.d.ts +12 -3
  47. package/dist/commands-setup-proof.js +60 -16
  48. package/dist/commands-setup-proof.js.map +1 -1
  49. package/dist/commands-skill.d.ts +11 -1
  50. package/dist/commands-skill.js +61 -11
  51. package/dist/commands-skill.js.map +1 -1
  52. package/dist/commands.d.ts +2 -2
  53. package/dist/commands.js +1 -1
  54. package/dist/commands.js.map +1 -1
  55. package/dist/config-schema.d.ts +1 -1
  56. package/dist/config-schema.js +25 -0
  57. package/dist/config-schema.js.map +1 -1
  58. package/dist/config.d.ts +24 -3
  59. package/dist/config.js +37 -5
  60. package/dist/config.js.map +1 -1
  61. package/dist/credentials.d.ts +10 -1
  62. package/dist/credentials.js +25 -12
  63. package/dist/credentials.js.map +1 -1
  64. package/dist/guidance-content.d.ts +20 -0
  65. package/dist/guidance-content.js +73 -8
  66. package/dist/guidance-content.js.map +1 -1
  67. package/dist/guidance-render.d.ts +20 -0
  68. package/dist/guidance-render.js +42 -0
  69. package/dist/guidance-render.js.map +1 -0
  70. package/dist/guidance.d.ts +21 -0
  71. package/dist/guidance.js +73 -18
  72. package/dist/guidance.js.map +1 -1
  73. package/dist/hook-adapter.js +37 -3
  74. package/dist/hook-adapter.js.map +1 -1
  75. package/dist/hooks.d.ts +83 -7
  76. package/dist/hooks.js +288 -90
  77. package/dist/hooks.js.map +1 -1
  78. package/dist/install-hooks.d.ts +10 -18
  79. package/dist/install-hooks.js +110 -23
  80. package/dist/install-hooks.js.map +1 -1
  81. package/dist/interactive.d.ts +1 -1
  82. package/dist/interactive.js +1 -1
  83. package/dist/interactive.js.map +1 -1
  84. package/dist/logging.d.ts +8 -1
  85. package/dist/logging.js +43 -2
  86. package/dist/logging.js.map +1 -1
  87. package/dist/main.js +2 -13
  88. package/dist/main.js.map +1 -1
  89. package/dist/native-skills.d.ts +19 -0
  90. package/dist/native-skills.js +30 -8
  91. package/dist/native-skills.js.map +1 -1
  92. package/dist/opencode-plugin.js +25 -1
  93. package/dist/opencode-plugin.js.map +1 -1
  94. package/dist/program.js +34 -20
  95. package/dist/program.js.map +1 -1
  96. package/dist/readiness.d.ts +6 -0
  97. package/dist/readiness.js +37 -0
  98. package/dist/readiness.js.map +1 -1
  99. package/dist/send-attempts.d.ts +26 -0
  100. package/dist/send-attempts.js +139 -0
  101. package/dist/send-attempts.js.map +1 -0
  102. package/dist/send.d.ts +8 -1
  103. package/dist/send.js +17 -1
  104. package/dist/send.js.map +1 -1
  105. package/dist/session-activation.d.ts +11 -0
  106. package/dist/session-activation.js +46 -0
  107. package/dist/session-activation.js.map +1 -0
  108. package/dist/url-policy.d.ts +85 -0
  109. package/dist/url-policy.js +369 -0
  110. package/dist/url-policy.js.map +1 -0
  111. package/package.json +3 -3
  112. package/src/atomic-file.ts +36 -2
  113. package/src/cli-bin.test.ts +38 -0
  114. package/src/cli-bin.ts +67 -0
  115. package/src/cli-release.test.ts +46 -0
  116. package/src/cli-release.ts +78 -0
  117. package/src/client.test.ts +95 -0
  118. package/src/client.ts +16 -3
  119. package/src/command-session.ts +38 -0
  120. package/src/commands-auth.ts +32 -3
  121. package/src/commands-config.ts +25 -2
  122. package/src/commands-core.ts +38 -3
  123. package/src/commands-doctor.ts +117 -41
  124. package/src/commands-guidance.ts +43 -32
  125. package/src/commands-harness-context.ts +24 -1
  126. package/src/commands-hooks.ts +704 -188
  127. package/src/commands-init.ts +180 -57
  128. package/src/commands-send-support.test.ts +156 -0
  129. package/src/commands-send-support.ts +67 -5
  130. package/src/commands-send.ts +135 -16
  131. package/src/commands-setup-proof.test.ts +72 -0
  132. package/src/commands-setup-proof.ts +69 -16
  133. package/src/commands-skill.ts +78 -15
  134. package/src/commands.test.ts +1281 -157
  135. package/src/commands.ts +2 -0
  136. package/src/config-schema.ts +28 -1
  137. package/src/config.test.ts +1 -1
  138. package/src/config.ts +49 -5
  139. package/src/credentials.test.ts +71 -3
  140. package/src/credentials.ts +29 -15
  141. package/src/guidance-content.ts +74 -8
  142. package/src/guidance-render.ts +56 -0
  143. package/src/guidance.test.ts +70 -11
  144. package/src/guidance.ts +100 -18
  145. package/src/hook-adapter.test.ts +113 -1
  146. package/src/hook-adapter.ts +37 -3
  147. package/src/hooks.test.ts +778 -166
  148. package/src/hooks.ts +368 -129
  149. package/src/install-hooks.test.ts +135 -16
  150. package/src/install-hooks.ts +113 -25
  151. package/src/interactive.ts +1 -1
  152. package/src/logging.test.ts +66 -3
  153. package/src/logging.ts +45 -2
  154. package/src/main.ts +2 -14
  155. package/src/native-skills.test.ts +41 -1
  156. package/src/native-skills.ts +40 -6
  157. package/src/opencode-plugin.ts +25 -1
  158. package/src/program.test.ts +37 -2
  159. package/src/program.ts +62 -24
  160. package/src/readiness.ts +44 -0
  161. package/src/send-attempts.test.ts +143 -0
  162. package/src/send-attempts.ts +188 -0
  163. package/src/send.test.ts +28 -0
  164. package/src/send.ts +28 -2
  165. package/src/session-activation.ts +62 -0
  166. package/src/skill.test.ts +125 -11
  167. package/src/trust-policy.test.ts +701 -0
  168. package/src/url-policy.ts +399 -0
package/CHANGELOG.md CHANGED
@@ -8,6 +8,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8
8
  This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
9
9
  and [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
10
10
 
11
+ ## [9.1.0](https://github.com/Raidiant-io/notifai/compare/v9.0.0...v9.1.0) (2026-08-26)
12
+
13
+
14
+ ### Features
15
+
16
+ * **cli:** remove mechanical agent ceremony ([#73](https://github.com/Raidiant-io/notifai/issues/73)) ([989f0d0](https://github.com/Raidiant-io/notifai/commit/989f0d05634605d7b411819050a743a19a25b1d8))
17
+
18
+ ## [9.0.0](https://github.com/Raidiant-io/notifai/compare/v8.0.0...v9.0.0) (2026-08-25)
19
+
20
+
21
+ ### ⚠ BREAKING CHANGES
22
+
23
+ * **cli:** publishing now requires a verified protocol release before the CLI is published, and npm >= 11.5.1.
24
+ * **cli:** `notifai send --event` is removed.
25
+ * remote media and approval URLs must satisfy the stated trust policy; hosts outside it require an explicit User-owned origins exception.
26
+ * **protocol:** begin-pairing requests must include confirmation_hash, and dashboard pairing actions require the full code and confirmation secret.
27
+ * notification drafts and evidence snapshots no longer carry an `event` field.
28
+
29
+ ### Features
30
+
31
+ * **cli:** ask one project-or-machine setup scope ([#66](https://github.com/Raidiant-io/notifai/issues/66)) ([bedc0ea](https://github.com/Raidiant-io/notifai/commit/bedc0ea82aa428b2fe63dd03cf8092d0d813bc6d))
32
+ * hold hostile repository input to a stated trust policy ([#70](https://github.com/Raidiant-io/notifai/issues/70)) ([1568768](https://github.com/Raidiant-io/notifai/commit/15687686eed3f74f5f0f6d4d8a9e49b50de4bebc))
33
+ * **protocol:** require proof for pairing actions ([#69](https://github.com/Raidiant-io/notifai/issues/69)) ([ad3d5dc](https://github.com/Raidiant-io/notifai/commit/ad3d5dc593ae7248abb487a0574b5af9ada99506))
34
+ * remove send --event and the protocol event field ([#67](https://github.com/Raidiant-io/notifai/issues/67)) ([7dde05f](https://github.com/Raidiant-io/notifai/commit/7dde05f6161fc3474a637c71abe47d54aacf50a9))
35
+
36
+
37
+ ### Bug Fixes
38
+
39
+ * **cli:** default the service origin to https://api.notifai.sh ([#60](https://github.com/Raidiant-io/notifai/issues/60)) ([8063d20](https://github.com/Raidiant-io/notifai/commit/8063d2040caaa1c09fe7cdb2f5f7302f86221bad))
40
+ * **cli:** drop the terminal-timing rule from when-to-notify guidance ([0c1ed8e](https://github.com/Raidiant-io/notifai/commit/0c1ed8e40fe4470ebcab49d13663c704cf6056ed))
41
+ * **cli:** keep machine credentials out of argv and harden trusted publishing ([#71](https://github.com/Raidiant-io/notifai/issues/71)) ([a03d85c](https://github.com/Raidiant-io/notifai/commit/a03d85ccba6fc36d378168feeb5297103065e62e))
42
+ * **cli:** keep the bin runnable and harden doctor, send, and Codex hooks ([#64](https://github.com/Raidiant-io/notifai/issues/64)) ([d7f2d7b](https://github.com/Raidiant-io/notifai/commit/d7f2d7b612d27e426c328284e2f72d0723b0ae43))
43
+ * **cli:** pin signed-in origin and redact sensitive local logs ([#59](https://github.com/Raidiant-io/notifai/issues/59)) ([7dffafb](https://github.com/Raidiant-io/notifai/commit/7dffafb1e2ebbc307adb99ab9638e8ad3787e776))
44
+ * **cli:** restore question pushes after a spent Stop waiter ([89f6d76](https://github.com/Raidiant-io/notifai/commit/89f6d76e6569190cbd04120f922ecf284a89798c))
45
+ * harden proactive Notifai activation ([#63](https://github.com/Raidiant-io/notifai/issues/63)) ([e486d22](https://github.com/Raidiant-io/notifai/commit/e486d224a5261ba039ba26494a9fdf8b74711817))
46
+ * **hooks:** retire questions without reserved client events ([#65](https://github.com/Raidiant-io/notifai/issues/65)) ([154fd11](https://github.com/Raidiant-io/notifai/commit/154fd1116d7a5b79aeabc8cb1b897262e6953d9c))
47
+ * **hooks:** survive a node upgrade that moves the pinned runtime ([#61](https://github.com/Raidiant-io/notifai/issues/61)) ([0c19acb](https://github.com/Raidiant-io/notifai/commit/0c19acb62d42d3ae95ebe489e56839a5a3ad4ec4))
48
+ * make user-resumable blockers answerable ([#62](https://github.com/Raidiant-io/notifai/issues/62)) ([22e78b5](https://github.com/Raidiant-io/notifai/commit/22e78b5b66c7a1eb2a39ca78675e21a1e82459a9))
49
+ * name press-and-hold on closed-choice iPhone banners ([#68](https://github.com/Raidiant-io/notifai/issues/68)) ([419c7f8](https://github.com/Raidiant-io/notifai/commit/419c7f8d389889662fad45f516fd0cef33c3e344))
50
+ * trigger Notifai guidance consistently ([#58](https://github.com/Raidiant-io/notifai/issues/58)) ([ddf1f94](https://github.com/Raidiant-io/notifai/commit/ddf1f94db6a282b081302e03cd17b204d0231ed1))
51
+
52
+
53
+ ### Dependencies
54
+
55
+ * The following workspace dependencies were updated
56
+ * dependencies
57
+ * @raidiant/notifai-protocol bumped from 4.1.0 to 5.0.0
58
+
11
59
  ## [8.0.0](https://github.com/Raidiant-io/notifai/compare/v7.0.2...v8.0.0) (2026-08-24)
12
60
 
13
61
 
package/README.md CHANGED
@@ -5,26 +5,30 @@ Send native phone notifications from agents and local programs.
5
5
  An agent working while you are away has no way to reach you, so it either
6
6
  guesses or sits blocked in a terminal nobody is watching. `notifai` gives
7
7
  it a way to tell you something finished, and a way to ask you a question
8
- and get your answer back — as a banner on your phone, with buttons.
8
+ and get your answer back as a banner on your phone.
9
9
 
10
10
  ```sh
11
11
  npm install -g @raidiant/notifai
12
12
  notifai init
13
13
  ```
14
14
 
15
- If you do not want a global bin, `npx --yes @raidiant/notifai@<version>` is
16
- supported. Pin the version. `hooks install` then writes that same pinned npx
17
- invocation into the harness adapter. This is slower than a real install and
18
- is not the default path.
15
+ The `notifai` command is always a machine-wide install. Setup scope (this
16
+ project vs this machine) does not change that. If you do not want a global
17
+ bin, `npx --yes @raidiant/notifai@<version>` is supported. Pin the version.
18
+ `hooks install` then writes that same pinned npx invocation into the harness
19
+ adapter. This is slower than a real install and is not the default path.
19
20
 
20
21
  `init` walks the setup one step at a time and tells you the single next
21
22
  thing to do. Run it again after each step; it works out what remains.
22
23
 
23
- When `--skills` is selected at a human terminal, `init` runs the native
24
- `npx skills` flow so that flow can ask whether the skill belongs to the
25
- project or the machine. An unattended caller must select one explicitly:
26
- `notifai init --skills --skills-scope project` or
27
- `notifai init --skills --skills-scope global`.
24
+ At a human terminal, `init` asks once whether this setup is for this project
25
+ or for every project on this machine. That answer is skill, hooks, and
26
+ config together. Pairing, devices, and credentials stay on this machine
27
+ either way. An unattended caller passes the same choice as a flag:
28
+ `notifai init --setup-scope project` or `notifai init --setup-scope global`.
29
+ `--skills-scope` is an alias of that flag when `--skills` is set. Shared
30
+ project config may live in the repo; personal project preferences live under
31
+ the user config directory and never require a `.gitignore` edit.
28
32
 
29
33
  ## Telling you something happened
30
34
 
@@ -47,8 +51,8 @@ notifai ask "Deploy the migration to production?" --choice Yes --choice No
47
51
  ```
48
52
 
49
53
  The agent registers the question, ends its turn, and your answer comes
50
- back on its next turn. On iPhone the choices are buttons on the banner
51
- itself.
54
+ back on its next turn. On iPhone, press and hold the collapsed banner to
55
+ answer; the choices appear on the expanded card, not on the lock screen.
52
56
 
53
57
  By default a question reaches your devices when the agent turn ends, whether or
54
58
  not you are at the keyboard (`ask_grace_seconds = 0`). Set a positive grace
@@ -117,7 +121,10 @@ do not. `--json` emits the same result with an explicit `exit_code`.
117
121
  Everything useful is possible non-interactively, so an agent never
118
122
  reaches a prompt and hangs.
119
123
 
120
- Source, issues and the security policy:
124
+ Source, issues and the public/private boundary policy:
121
125
  <https://github.com/Raidiant-io/notifai>
122
126
 
127
+ The URL, self-host exception, guidance-authority and non-exfiltration policy is
128
+ documented in [`docs/TRUST.md`](https://github.com/Raidiant-io/notifai/blob/main/docs/TRUST.md).
129
+
123
130
  Apache-2.0.
@@ -5,6 +5,12 @@ export interface AtomicWriteOptions {
5
5
  preserveMode?: boolean;
6
6
  /** Reject a target owned by another user instead of replacing it. */
7
7
  requireCurrentUserOwner?: boolean;
8
+ /**
9
+ * POSIX directory mode applied to the parent. Defaults to 0o700 when
10
+ * `requireCurrentUserOwner` is set so credential and config dirs match the
11
+ * hook-adapter and log directories.
12
+ */
13
+ directoryMode?: number;
8
14
  }
9
15
  /**
10
16
  * Replace one regular file without exposing a truncated intermediate state.
@@ -14,3 +20,11 @@ export interface AtomicWriteOptions {
14
20
  * symlink target is refused instead of silently writing through it.
15
21
  */
16
22
  export declare function atomicWriteFileSync(file: string, contents: string, options?: AtomicWriteOptions): void;
23
+ /**
24
+ * Create (or tighten) a directory that must not be world-readable.
25
+ *
26
+ * `mkdir` mode applies only to a newly created leaf, so an existing 0755
27
+ * credential directory would otherwise stay world-listable. POSIX chmod of
28
+ * the leaf is the matching repair; Windows has no equivalent mode bits.
29
+ */
30
+ export declare function ensurePrivateDirectory(directory: string): void;
@@ -10,8 +10,12 @@ import path from 'node:path';
10
10
  */
11
11
  export function atomicWriteFileSync(file, contents, options = {}) {
12
12
  const directory = path.dirname(file);
13
- mkdirSync(directory, { recursive: true });
14
- const parent = safeDirectory(directory, options.requireCurrentUserOwner ?? false);
13
+ const requireCurrentUserOwner = options.requireCurrentUserOwner ?? false;
14
+ const directoryMode = options.directoryMode ?? (requireCurrentUserOwner ? 0o700 : undefined);
15
+ const parent = ensureDirectory(directory, {
16
+ requireCurrentUserOwner,
17
+ ...(directoryMode === undefined ? {} : { mode: directoryMode }),
18
+ });
15
19
  const target = targetMetadata(file, options.mode ?? 0o600, options.preserveMode ?? true, options.requireCurrentUserOwner ?? false);
16
20
  const temp = path.join(directory, `.${path.basename(file)}.notifai-${process.pid}-${randomBytes(6).toString('hex')}.tmp`);
17
21
  let handle;
@@ -39,6 +43,27 @@ export function atomicWriteFileSync(file, contents, options = {}) {
39
43
  throw err;
40
44
  }
41
45
  }
46
+ /**
47
+ * Create (or tighten) a directory that must not be world-readable.
48
+ *
49
+ * `mkdir` mode applies only to a newly created leaf, so an existing 0755
50
+ * credential directory would otherwise stay world-listable. POSIX chmod of
51
+ * the leaf is the matching repair; Windows has no equivalent mode bits.
52
+ */
53
+ export function ensurePrivateDirectory(directory) {
54
+ ensureDirectory(directory, { mode: 0o700, requireCurrentUserOwner: false });
55
+ }
56
+ function ensureDirectory(directory, options) {
57
+ if (options.mode === undefined)
58
+ mkdirSync(directory, { recursive: true });
59
+ else
60
+ mkdirSync(directory, { recursive: true, mode: options.mode });
61
+ const parent = safeDirectory(directory, options.requireCurrentUserOwner);
62
+ if (options.mode !== undefined && process.platform !== 'win32') {
63
+ chmodSync(directory, options.mode);
64
+ }
65
+ return parent;
66
+ }
42
67
  /** Persist the published directory entry where the host supports directory fsync. */
43
68
  function syncDirectory(directory) {
44
69
  if (process.platform === 'win32')
@@ -1 +1 @@
1
- {"version":3,"file":"atomic-file.js","sourceRoot":"","sources":["../src/atomic-file.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"atomic-file.js","sourceRoot":"","sources":["../src/atomic-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ReadinessState } from './readiness.js';
2
+ export declare function pathNotifaiEntries(env: NodeJS.ProcessEnv, platform?: NodeJS.Platform): string[];
3
+ export declare function isExecutablePath(file: string, platform?: NodeJS.Platform): boolean;
4
+ export declare function cliBinReadiness(env: NodeJS.ProcessEnv, platform?: NodeJS.Platform): ReadinessState;
@@ -0,0 +1,62 @@
1
+ import { accessSync, constants, existsSync, lstatSync, realpathSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ const POSIX_NAMES = ['notifai'];
4
+ const WINDOWS_NAMES = ['notifai.cmd', 'notifai.exe', 'notifai'];
5
+ export function pathNotifaiEntries(env, platform = process.platform) {
6
+ const raw = platform === 'win32' ? (env['Path'] ?? env['PATH'] ?? '') : (env['PATH'] ?? '');
7
+ const delimiter = platform === 'win32' ? ';' : ':';
8
+ const names = platform === 'win32' ? WINDOWS_NAMES : POSIX_NAMES;
9
+ const found = [];
10
+ for (const directory of raw.split(delimiter)) {
11
+ if (directory === '')
12
+ continue;
13
+ for (const name of names) {
14
+ const candidate = path.join(directory, name);
15
+ if (!existsSync(candidate))
16
+ continue;
17
+ if (!found.includes(candidate))
18
+ found.push(candidate);
19
+ }
20
+ }
21
+ return found;
22
+ }
23
+ export function isExecutablePath(file, platform = process.platform) {
24
+ if (!existsSync(file))
25
+ return false;
26
+ if (platform === 'win32')
27
+ return true;
28
+ try {
29
+ const target = lstatSync(file).isSymbolicLink() ? realpathSync(file) : file;
30
+ accessSync(target, constants.X_OK);
31
+ return true;
32
+ }
33
+ catch {
34
+ return false;
35
+ }
36
+ }
37
+ export function cliBinReadiness(env, platform = process.platform) {
38
+ const entries = pathNotifaiEntries(env, platform);
39
+ const broken = entries.find((file) => !isExecutablePath(file, platform));
40
+ if (broken !== undefined) {
41
+ return {
42
+ id: 'cli-bin',
43
+ title: 'notifai command',
44
+ status: 'gap',
45
+ detail: `${broken} is on PATH but is not executable`,
46
+ remedy: {
47
+ by: 'user-here',
48
+ summary: 'repair the global notifai command so it can run',
49
+ command: 'npm install -g @raidiant/notifai',
50
+ },
51
+ };
52
+ }
53
+ return {
54
+ id: 'cli-bin',
55
+ title: 'notifai command',
56
+ status: 'ready',
57
+ detail: entries[0] === undefined
58
+ ? 'this process can run; no notifai binary was on PATH'
59
+ : `${entries[0]} is executable`,
60
+ };
61
+ }
62
+ //# sourceMappingURL=cli-bin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-bin.js","sourceRoot":"","sources":["../src/cli-bin.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export declare function compareCliSemVer(left: string, right: string): number | null;
2
+ export declare function shouldConsultCliRegistry(input: {
3
+ interactive?: boolean;
4
+ json?: boolean;
5
+ env?: NodeJS.ProcessEnv;
6
+ }): boolean;
7
+ export declare function latestPublishedCliVersion(fetchImpl?: typeof fetch): Promise<string | null>;
8
+ export declare function newerPublishedCli(local: string | null, latest: string | null): string | null;
9
+ export declare function thisCliVersion(): string | null;
10
+ export declare function resetLatestPublishedCliVersionForTest(): void;
@@ -0,0 +1,75 @@
1
+ import { packageVersion } from './release.js';
2
+ /**
3
+ * The newest published CLI, read from the registry that publishes it.
4
+ *
5
+ * Which version is newest is a registry fact. Doctor consults it as a
6
+ * best-effort, cached, short-timeout hint: never fatal, and never on a
7
+ * non-interactive or CI invocation — those callers already get structured
8
+ * support state from the server when they are signed in.
9
+ */
10
+ const DIST_TAGS_URL = 'https://registry.npmjs.org/-/package/@raidiant/notifai/dist-tags';
11
+ const REQUEST_TIMEOUT_MS = 2_000;
12
+ const CACHE_TTL_MS = 60 * 60 * 1000;
13
+ let cached = null;
14
+ export function compareCliSemVer(left, right) {
15
+ const parse = (value) => {
16
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(value);
17
+ if (!match)
18
+ return null;
19
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
20
+ };
21
+ const a = parse(left);
22
+ const b = parse(right);
23
+ if (a === null || b === null)
24
+ return null;
25
+ for (let index = 0; index < 3; index += 1) {
26
+ if (a[index] !== b[index])
27
+ return a[index] - b[index];
28
+ }
29
+ return 0;
30
+ }
31
+ export function shouldConsultCliRegistry(input) {
32
+ if (input.json === true)
33
+ return false;
34
+ if (input.interactive !== true)
35
+ return false;
36
+ const ci = input.env?.['CI'];
37
+ return ci !== '1' && ci !== 'true';
38
+ }
39
+ export async function latestPublishedCliVersion(fetchImpl = fetch) {
40
+ if (cached !== null && Date.now() - cached.at < CACHE_TTL_MS)
41
+ return cached.value;
42
+ try {
43
+ const response = await fetchImpl(DIST_TAGS_URL, {
44
+ headers: { accept: 'application/json' },
45
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
46
+ });
47
+ if (!response.ok)
48
+ return cached?.value ?? null;
49
+ const body = await response.json();
50
+ if (typeof body !== 'object' || body === null)
51
+ return cached?.value ?? null;
52
+ const latest = body.latest;
53
+ if (typeof latest !== 'string' || compareCliSemVer(latest, '0.0.0') === null) {
54
+ return cached?.value ?? null;
55
+ }
56
+ cached = { value: latest, at: Date.now() };
57
+ return latest;
58
+ }
59
+ catch {
60
+ return cached?.value ?? null;
61
+ }
62
+ }
63
+ export function newerPublishedCli(local, latest) {
64
+ if (local === null || latest === null)
65
+ return null;
66
+ const comparison = compareCliSemVer(latest, local);
67
+ return comparison !== null && comparison > 0 ? latest : null;
68
+ }
69
+ export function thisCliVersion() {
70
+ return packageVersion();
71
+ }
72
+ export function resetLatestPublishedCliVersionForTest() {
73
+ cached = null;
74
+ }
75
+ //# sourceMappingURL=cli-release.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-release.js","sourceRoot":"","sources":["../src/cli-release.ts"],"names":[],"mappings":"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"}
package/dist/client.d.ts CHANGED
@@ -22,6 +22,7 @@ export interface ApiClient {
22
22
  machine_name: string;
23
23
  credential_hash: string;
24
24
  poll_verifier_hash: string;
25
+ confirmation_hash: string;
25
26
  }): Promise<BeginPairingResponse>;
26
27
  pollPairing(pairingId: string, pollVerifier: string): Promise<PollPairingResponse>;
27
28
  accessStatus(): Promise<AccountAccessResponse>;
package/dist/client.js CHANGED
@@ -104,6 +104,7 @@ export function createClient(baseUrl, bearer, options = {}) {
104
104
  ...clientHeaders,
105
105
  },
106
106
  signal,
107
+ ...(bearer ? { redirect: 'error' } : {}),
107
108
  ...(body !== undefined ? { body: JSON.stringify(body) } : {}),
108
109
  });
109
110
  }
@@ -133,7 +134,9 @@ export function createClient(baseUrl, bearer, options = {}) {
133
134
  }
134
135
  return {
135
136
  beginPairing: (body) => call('POST', '/api/v1/pairings', body),
136
- pollPairing: (pairingId, pollVerifier) => call('POST', `/api/v1/pairings/${pairingId}/poll`, { poll_verifier: pollVerifier }),
137
+ pollPairing: (pairingId, pollVerifier) => call('POST', `/api/v1/pairings/${encodeURIComponent(pairingId)}/poll`, {
138
+ poll_verifier: pollVerifier,
139
+ }),
137
140
  accessStatus: () => call('GET', '/api/v1/account/access'),
138
141
  listDevices: () => call('GET', '/api/v1/devices'),
139
142
  capabilities: (platform = 'ios', appVersion, appBuild) => {
@@ -143,11 +146,11 @@ export function createClient(baseUrl, bearer, options = {}) {
143
146
  if (appBuild !== undefined)
144
147
  query.set('app_build', appBuild);
145
148
  const suffix = query.size > 0 ? `?${query.toString()}` : '';
146
- return call('GET', `/api/v1/capabilities/${platform}${suffix}`);
149
+ return call('GET', `/api/v1/capabilities/${encodeURIComponent(platform)}${suffix}`);
147
150
  },
148
151
  compatibility: () => call('GET', '/api/v1/compatibility'),
149
152
  submit: (body, waitSeconds) => call('POST', `/api/v1/notifications?wait_seconds=${waitSeconds}`, body, waitSeconds),
150
- evidence: (requestId) => call('GET', `/api/v1/notifications/${requestId}`),
153
+ evidence: (requestId) => call('GET', `/api/v1/notifications/${encodeURIComponent(requestId)}`),
151
154
  replies: (requestId, { waitSeconds, afterSeq }) => call('GET', `/api/v1/notifications/${encodeURIComponent(requestId)}/replies?wait_seconds=${waitSeconds}&after_seq=${afterSeq}`, undefined, waitSeconds),
152
155
  closeReplies: (requestId) => call('POST', `/api/v1/notifications/${encodeURIComponent(requestId)}/replies/close`),
153
156
  putAgentAcknowledgement: (requestId, body) => call('PUT', `/api/v1/notifications/${encodeURIComponent(requestId)}/agent-acknowledgement`, body),
@@ -166,11 +169,18 @@ export function createClient(baseUrl, bearer, options = {}) {
166
169
  // Media can be large, so this gets its own allowance rather than the
167
170
  // per-request budget — but still a finite one.
168
171
  signal: AbortSignal.timeout(Math.max(budgetMs, 60_000)),
172
+ // The grant names one exact destination and carries signed headers.
173
+ // A redirect would replay both against an origin the server never
174
+ // granted, so it is refused rather than followed.
175
+ redirect: 'manual',
169
176
  });
170
177
  }
171
178
  catch (err) {
172
179
  throw new NetworkError(`Upload failed: ${String(err)}`);
173
180
  }
181
+ if (response.status >= 300 && response.status < 400) {
182
+ throw new NetworkError(`Upload redirect is refused, not followed: the grant's headers are signed for one exact destination`);
183
+ }
174
184
  if (!response.ok) {
175
185
  throw new NetworkError(`Upload rejected with status ${response.status}`);
176
186
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { CommandDeps } from './commands-core.js';
2
+ export interface ResolvedCommandSession {
3
+ sessionId: string;
4
+ source: 'exact-harness' | 'stable-id' | 'project-pointer';
5
+ }
6
+ /**
7
+ * Resolve only Question Routing lifecycle ownership.
8
+ *
9
+ * Exact harness identity wins across checkouts. A stable question/request id
10
+ * wins next. The cwd pointer remains a compatibility fallback for shells that
11
+ * genuinely have no exact harness identity; it never owns Project or config
12
+ * scope, which stay with the command's invocation directory.
13
+ */
14
+ export declare function resolveCommandSession(deps: CommandDeps, stableId?: string): ResolvedCommandSession | null;
@@ -0,0 +1,30 @@
1
+ import { resolveActiveHarness } from './commands-harness-context.js';
2
+ import { findOwningSession, readProjectSession } from './hooks.js';
3
+ /**
4
+ * Resolve only Question Routing lifecycle ownership.
5
+ *
6
+ * Exact harness identity wins across checkouts. A stable question/request id
7
+ * wins next. The cwd pointer remains a compatibility fallback for shells that
8
+ * genuinely have no exact harness identity; it never owns Project or config
9
+ * scope, which stay with the command's invocation directory.
10
+ */
11
+ export function resolveCommandSession(deps, stableId) {
12
+ if (stableId !== undefined) {
13
+ const owner = findOwningSession(stableId, deps.env);
14
+ if (owner.ambiguous)
15
+ return null;
16
+ if (owner.sessionId !== null)
17
+ return { sessionId: owner.sessionId, source: 'stable-id' };
18
+ }
19
+ const now = (deps.now ?? Date.now)();
20
+ const resolution = resolveActiveHarness(deps.env, deps.cwd, now);
21
+ if (resolution.contested.length > 0)
22
+ return null;
23
+ if (resolution.active?.sessionId !== undefined &&
24
+ resolution.contested.length === 0) {
25
+ return { sessionId: resolution.active.sessionId, source: 'exact-harness' };
26
+ }
27
+ const pointer = readProjectSession(deps.cwd, deps.env, now);
28
+ return pointer === null ? null : { sessionId: pointer, source: 'project-pointer' };
29
+ }
30
+ //# sourceMappingURL=command-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-session.js","sourceRoot":"","sources":["../src/command-session.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAOlE;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAiB,EACjB,QAAiB;IAEjB,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;QACnD,IAAI,KAAK,CAAC,SAAS;YAAE,OAAO,IAAI,CAAA;QAChC,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI;YAAE,OAAO,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;IAC1F,CAAC;IACD,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAA;IACpC,MAAM,UAAU,GAAG,oBAAoB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IAChE,IAAI,UAAU,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAA;IAChD,IACE,UAAU,CAAC,MAAM,EAAE,SAAS,KAAK,SAAS;QAC1C,UAAU,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EACjC,CAAC;QACD,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,EAAE,CAAA;IAC5E,CAAC;IACD,MAAM,OAAO,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IAC3D,OAAO,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAA;AACpF,CAAC"}
@@ -1,4 +1,10 @@
1
1
  import { type CommandDeps } from './commands-core.js';
2
+ /**
3
+ * Keep the one-time confirmation secret out of the HTTP request that opens
4
+ * the dashboard. URL fragments are browser-local and are not sent by GET,
5
+ * prefetchers, referrers, or link scanners.
6
+ */
7
+ export declare function pairingApprovalUrl(approveUrl: string, confirmationSecret: string): string;
2
8
  export declare function loginCommand(deps: CommandDeps, flags: {
3
9
  name?: string;
4
10
  baseUrl?: string;
@@ -4,16 +4,28 @@ import { randomBytes } from 'node:crypto';
4
4
  import os from 'node:os';
5
5
  import { NetworkError } from './client.js';
6
6
  import {} from './config.js';
7
+ import { checkApproveUrl } from './url-policy.js';
7
8
  import { EXIT, authedClient, loadLoggedConfig, makeClient, reportError, } from './commands-core.js';
8
9
  // ---------------------------------------------------------------------------
9
10
  // login / logout / auth status
10
11
  // ---------------------------------------------------------------------------
12
+ /**
13
+ * Keep the one-time confirmation secret out of the HTTP request that opens
14
+ * the dashboard. URL fragments are browser-local and are not sent by GET,
15
+ * prefetchers, referrers, or link scanners.
16
+ */
17
+ export function pairingApprovalUrl(approveUrl, confirmationSecret) {
18
+ const url = new URL(approveUrl);
19
+ url.hash = new URLSearchParams({ confirmation_secret: confirmationSecret }).toString();
20
+ return url.toString();
21
+ }
11
22
  export async function loginCommand(deps, flags) {
12
23
  const config = loadLoggedConfig(deps, { cwd: deps.cwd, env: deps.env, flags: { base_url: flags.baseUrl } });
13
24
  const baseUrl = config.base_url.value;
14
25
  const machineName = flags.name ?? os.hostname();
15
26
  const secret = randomBytes(32).toString('base64url');
16
27
  const pollVerifier = randomBytes(24).toString('base64url');
28
+ const confirmationSecret = randomBytes(32).toString('base64url');
17
29
  const client = makeClient(deps, baseUrl, null);
18
30
  let begin;
19
31
  try {
@@ -21,23 +33,36 @@ export async function loginCommand(deps, flags) {
21
33
  machine_name: machineName,
22
34
  credential_hash: sha256Hex(secret),
23
35
  poll_verifier_hash: sha256Hex(pollVerifier),
36
+ confirmation_hash: sha256Hex(confirmationSecret),
24
37
  });
25
38
  }
26
39
  catch (err) {
27
40
  return reportError(deps, err);
28
41
  }
42
+ const approveUrl = pairingApprovalUrl(begin.approve_url, confirmationSecret);
43
+ // The approval URL is the server's choice, and this machine is about to put
44
+ // it in front of the user's browser. A compromised or misconfigured service
45
+ // must not be able to aim that anywhere it likes, so the pairing stops here
46
+ // rather than showing a link the user would reasonably trust.
47
+ const approvable = checkApproveUrl(begin.approve_url, baseUrl, config.approve_origins.value);
48
+ if (!approvable.ok) {
49
+ deps.io.err(`Pairing stopped: ${approvable.reason}`);
50
+ deps.io.err('next: If you self-host with the dashboard on its own origin, allow it with ' +
51
+ '`notifai config set approve_origins <origin>` and run `notifai login` again.');
52
+ return EXIT.auth;
53
+ }
29
54
  const interactive = deps.io.interactive === true;
30
55
  if (interactive) {
31
56
  await deps.io.intro?.('Notifai sign in');
32
- await deps.io.note?.(`Code: ${begin.code}\n${begin.approve_url}`, 'Approve this machine');
57
+ await deps.io.note?.(`Code: ${begin.code}\n${approveUrl}`, 'Approve this machine');
33
58
  }
34
59
  else {
35
60
  deps.io.out(`Pairing code: ${begin.code}`);
36
- deps.io.out(`Approve this machine at: ${begin.approve_url}`);
61
+ deps.io.out(`Approve this machine at: ${approveUrl}`);
37
62
  deps.io.out('Waiting for approval…');
38
63
  }
39
64
  if (flags.open !== false)
40
- deps.io.openUrl(begin.approve_url);
65
+ deps.io.openUrl(approveUrl);
41
66
  const expiresAt = new Date(begin.expires_at).getTime();
42
67
  const intervalMs = Math.max(begin.poll_interval_seconds, 1) * 1000;
43
68
  const now = deps.now ?? Date.now;