@songsid/agend 2.1.12 → 2.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/README.zh-TW.md +2 -2
- package/dist/auth/one-time-code.d.ts +19 -0
- package/dist/auth/one-time-code.js +49 -0
- package/dist/auth/one-time-code.js.map +1 -0
- package/dist/auth-api.d.ts +52 -0
- package/dist/auth-api.js +346 -0
- package/dist/auth-api.js.map +1 -0
- package/dist/backend/claude-code.d.ts +4 -0
- package/dist/backend/claude-code.js +97 -0
- package/dist/backend/claude-code.js.map +1 -1
- package/dist/backend/codex.js +59 -30
- package/dist/backend/codex.js.map +1 -1
- package/dist/backend/kiro-agent.d.ts +66 -0
- package/dist/backend/kiro-agent.js +302 -0
- package/dist/backend/kiro-agent.js.map +1 -0
- package/dist/backend/kiro-identity.d.ts +80 -0
- package/dist/backend/kiro-identity.js +537 -0
- package/dist/backend/kiro-identity.js.map +1 -0
- package/dist/backend/kiro-v2-store-worker.d.ts +1 -0
- package/dist/backend/kiro-v2-store-worker.js +87 -0
- package/dist/backend/kiro-v2-store-worker.js.map +1 -0
- package/dist/backend/kiro-v2-store.d.ts +54 -0
- package/dist/backend/kiro-v2-store.js +131 -0
- package/dist/backend/kiro-v2-store.js.map +1 -0
- package/dist/backend/kiro-v3-identity.d.ts +5 -0
- package/dist/backend/kiro-v3-identity.js +22 -0
- package/dist/backend/kiro-v3-identity.js.map +1 -1
- package/dist/backend/kiro.d.ts +83 -7
- package/dist/backend/kiro.js +418 -91
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/types.d.ts +45 -3
- package/dist/backend/types.js.map +1 -1
- package/dist/channel/adapters/discord.d.ts +1 -0
- package/dist/channel/adapters/discord.js +29 -10
- package/dist/channel/adapters/discord.js.map +1 -1
- package/dist/channel/adapters/telegram.d.ts +1 -0
- package/dist/channel/adapters/telegram.js +13 -1
- package/dist/channel/adapters/telegram.js.map +1 -1
- package/dist/channel/types.d.ts +9 -1
- package/dist/classic-channel-manager.d.ts +18 -10
- package/dist/classic-channel-manager.js +45 -18
- package/dist/classic-channel-manager.js.map +1 -1
- package/dist/cli.js +225 -127
- package/dist/cli.js.map +1 -1
- package/dist/command-table.d.ts +5 -3
- package/dist/command-table.js +29 -27
- package/dist/command-table.js.map +1 -1
- package/dist/config-validator.js +46 -0
- package/dist/config-validator.js.map +1 -1
- package/dist/config.js +12 -0
- package/dist/config.js.map +1 -1
- package/dist/connection-secrets.d.ts +6 -0
- package/dist/connection-secrets.js +4 -0
- package/dist/connection-secrets.js.map +1 -1
- package/dist/daemon.d.ts +89 -4
- package/dist/daemon.js +661 -77
- package/dist/daemon.js.map +1 -1
- package/dist/darwin-memory.d.ts +6 -1
- package/dist/darwin-memory.js +17 -6
- package/dist/darwin-memory.js.map +1 -1
- package/dist/delivery-consumed-watch.d.ts +85 -0
- package/dist/delivery-consumed-watch.js +244 -0
- package/dist/delivery-consumed-watch.js.map +1 -0
- package/dist/delivery-outbox.d.ts +61 -0
- package/dist/delivery-outbox.js +120 -2
- package/dist/delivery-outbox.js.map +1 -1
- package/dist/delivery-reconciliation.d.ts +14 -5
- package/dist/delivery-reconciliation.js +27 -4
- package/dist/delivery-reconciliation.js.map +1 -1
- package/dist/delivery-reconciliation.test.js +35 -1
- package/dist/delivery-reconciliation.test.js.map +1 -1
- package/dist/event-loop-watch.d.ts +28 -0
- package/dist/event-loop-watch.js +75 -3
- package/dist/event-loop-watch.js.map +1 -1
- package/dist/fleet-context.d.ts +22 -2
- package/dist/fleet-level-config.d.ts +2 -2
- package/dist/fleet-level-config.js +6 -1
- package/dist/fleet-level-config.js.map +1 -1
- package/dist/fleet-manager.d.ts +293 -12
- package/dist/fleet-manager.js +2364 -449
- package/dist/fleet-manager.js.map +1 -1
- package/dist/host-memory.d.ts +4 -0
- package/dist/host-memory.js.map +1 -1
- package/dist/instance-config-impact.js +5 -0
- package/dist/instance-config-impact.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +10 -5
- package/dist/instance-lifecycle.js +162 -53
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/locale.js +150 -16
- package/dist/locale.js.map +1 -1
- package/dist/login-controller.d.ts +2 -0
- package/dist/login-controller.js +17 -5
- package/dist/login-controller.js.map +1 -1
- package/dist/memory-pressure.d.ts +7 -8
- package/dist/memory-pressure.js +76 -15
- package/dist/memory-pressure.js.map +1 -1
- package/dist/monotonic-budget.d.ts +2 -0
- package/dist/monotonic-budget.js +28 -0
- package/dist/monotonic-budget.js.map +1 -0
- package/dist/needs-you-hub.d.ts +114 -0
- package/dist/needs-you-hub.js +370 -0
- package/dist/needs-you-hub.js.map +1 -0
- package/dist/needs-you-live.d.ts +116 -0
- package/dist/needs-you-live.js +228 -0
- package/dist/needs-you-live.js.map +1 -0
- package/dist/needs-you.d.ts +132 -0
- package/dist/needs-you.js +164 -0
- package/dist/needs-you.js.map +1 -0
- package/dist/node-version-guard.d.ts +30 -0
- package/dist/node-version-guard.js +50 -0
- package/dist/node-version-guard.js.map +1 -0
- package/dist/operator-control-paths.d.ts +4 -0
- package/dist/operator-control-paths.js +24 -0
- package/dist/operator-control-paths.js.map +1 -0
- package/dist/outbound-handlers.d.ts +2 -0
- package/dist/outbound-handlers.js +9 -2
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/outbound-schemas.d.ts +5 -5
- package/dist/profile-control.js +4 -20
- package/dist/profile-control.js.map +1 -1
- package/dist/public-web-gateway.d.ts +18 -0
- package/dist/public-web-gateway.js +141 -0
- package/dist/public-web-gateway.js.map +1 -0
- package/dist/public-web-link.d.ts +53 -0
- package/dist/public-web-link.js +175 -0
- package/dist/public-web-link.js.map +1 -0
- package/dist/quickstart-api.d.ts +8 -1
- package/dist/quickstart-api.js +86 -48
- package/dist/quickstart-api.js.map +1 -1
- package/dist/quickstart.d.ts +1 -0
- package/dist/quickstart.js +6 -2
- package/dist/quickstart.js.map +1 -1
- package/dist/scheduler/db.d.ts +7 -1
- package/dist/scheduler/db.js +38 -0
- package/dist/scheduler/db.js.map +1 -1
- package/dist/scheduler/index.d.ts +1 -1
- package/dist/scheduler/retry-label.d.ts +11 -0
- package/dist/scheduler/retry-label.js +24 -0
- package/dist/scheduler/retry-label.js.map +1 -0
- package/dist/scheduler/scheduler.d.ts +55 -2
- package/dist/scheduler/scheduler.js +220 -8
- package/dist/scheduler/scheduler.js.map +1 -1
- package/dist/scheduler/types.d.ts +22 -0
- package/dist/scheduler/types.js.map +1 -1
- package/dist/secret-store.d.ts +5 -0
- package/dist/secret-store.js +20 -0
- package/dist/secret-store.js.map +1 -1
- package/dist/service-activation.d.ts +110 -0
- package/dist/service-activation.js +302 -0
- package/dist/service-activation.js.map +1 -0
- package/dist/service-installer.d.ts +7 -0
- package/dist/service-installer.js +7 -4
- package/dist/service-installer.js.map +1 -1
- package/dist/service-restart-selection.d.ts +6 -5
- package/dist/service-restart-selection.js +6 -5
- package/dist/service-restart-selection.js.map +1 -1
- package/dist/settings-api.d.ts +10 -2
- package/dist/settings-api.js +175 -72
- package/dist/settings-api.js.map +1 -1
- package/dist/settings-baseline.d.ts +20 -0
- package/dist/settings-baseline.js +104 -0
- package/dist/settings-baseline.js.map +1 -0
- package/dist/settings-change.d.ts +21 -0
- package/dist/settings-change.js +133 -0
- package/dist/settings-change.js.map +1 -0
- package/dist/settings-confirmation.d.ts +105 -0
- package/dist/settings-confirmation.js +232 -0
- package/dist/settings-confirmation.js.map +1 -0
- package/dist/settings-control.d.ts +41 -0
- package/dist/settings-control.js +294 -0
- package/dist/settings-control.js.map +1 -0
- package/dist/settings-effect.d.ts +24 -0
- package/dist/settings-effect.js +169 -0
- package/dist/settings-effect.js.map +1 -0
- package/dist/settings-http-confirmation.d.ts +29 -0
- package/dist/settings-http-confirmation.js +123 -0
- package/dist/settings-http-confirmation.js.map +1 -0
- package/dist/settings-instance-patch.d.ts +4 -0
- package/dist/settings-instance-patch.js +26 -0
- package/dist/settings-instance-patch.js.map +1 -0
- package/dist/settings-request-capability.d.ts +16 -0
- package/dist/settings-request-capability.js +32 -0
- package/dist/settings-request-capability.js.map +1 -0
- package/dist/settings-transaction.d.ts +65 -0
- package/dist/settings-transaction.js +223 -0
- package/dist/settings-transaction.js.map +1 -0
- package/dist/setup-auth.d.ts +10 -18
- package/dist/setup-auth.js +14 -38
- package/dist/setup-auth.js.map +1 -1
- package/dist/setup-form.d.ts +1 -1
- package/dist/setup-form.js +75 -18
- package/dist/setup-form.js.map +1 -1
- package/dist/setup-guide.d.ts +13 -0
- package/dist/setup-guide.js +25 -0
- package/dist/setup-guide.js.map +1 -0
- package/dist/setup-host.d.ts +16 -0
- package/dist/setup-host.js +197 -32
- package/dist/setup-host.js.map +1 -1
- package/dist/setup-wizard.js +3 -0
- package/dist/setup-wizard.js.map +1 -1
- package/dist/slash-authz.d.ts +17 -3
- package/dist/slash-authz.js +5 -0
- package/dist/slash-authz.js.map +1 -1
- package/dist/spawn-gate.js +3 -3
- package/dist/spawn-gate.js.map +1 -1
- package/dist/statusline-watcher.d.ts +5 -0
- package/dist/statusline-watcher.js +2 -0
- package/dist/statusline-watcher.js.map +1 -1
- package/dist/steer-capability.d.ts +6 -0
- package/dist/steer-capability.js +8 -0
- package/dist/steer-capability.js.map +1 -1
- package/dist/sync-work-attribution.d.ts +14 -0
- package/dist/sync-work-attribution.js +43 -8
- package/dist/sync-work-attribution.js.map +1 -1
- package/dist/tips.js +10 -5
- package/dist/tips.js.map +1 -1
- package/dist/tmux-control.d.ts +35 -5
- package/dist/tmux-control.js +291 -57
- package/dist/tmux-control.js.map +1 -1
- package/dist/tmux-manager.d.ts +20 -6
- package/dist/tmux-manager.js +90 -47
- package/dist/tmux-manager.js.map +1 -1
- package/dist/tmux-read.d.ts +59 -0
- package/dist/tmux-read.js +213 -0
- package/dist/tmux-read.js.map +1 -0
- package/dist/topic-commands.d.ts +21 -10
- package/dist/topic-commands.js +191 -58
- package/dist/topic-commands.js.map +1 -1
- package/dist/transcript-delta-reader.js +2 -1
- package/dist/transcript-delta-reader.js.map +1 -1
- package/dist/tunnel/cloudflared-install.d.ts +2 -0
- package/dist/tunnel/cloudflared-install.js +1 -1
- package/dist/tunnel/cloudflared-install.js.map +1 -1
- package/dist/tunnel/purpose-lane.d.ts +14 -0
- package/dist/tunnel/purpose-lane.js +43 -0
- package/dist/tunnel/purpose-lane.js.map +1 -0
- package/dist/turn-reply-guard.d.ts +2 -0
- package/dist/turn-reply-guard.js +10 -1
- package/dist/turn-reply-guard.js.map +1 -1
- package/dist/types.d.ts +33 -0
- package/dist/ui/app.html +18 -0
- package/dist/ui/chat-render.js +478 -0
- package/dist/ui/chat-store.js +289 -0
- package/dist/ui/chat-strings.js +69 -0
- package/dist/ui/chat-thread.js +209 -0
- package/dist/ui/chat-tour.js +116 -0
- package/dist/ui/fleet-org.js +142 -0
- package/dist/ui/panel-chat.js +418 -0
- package/dist/ui/panel-fleet.js +413 -0
- package/dist/ui/panel-needs.js +202 -0
- package/dist/ui/panel-settings.js +750 -0
- package/dist/ui/preview.js +266 -0
- package/dist/ui/settings-apply.js +239 -0
- package/dist/ui/settings-confirm.js +186 -0
- package/dist/ui/settings-dialogs.js +546 -0
- package/dist/ui/settings-model.js +277 -0
- package/dist/ui/settings-strings.js +652 -0
- package/dist/ui/settings-wizard.js +140 -0
- package/dist/ui/shared/agend-auth.js +93 -0
- package/dist/ui/shared/app-ctx.js +80 -0
- package/dist/ui/shared/app-html.js +9 -0
- package/dist/ui/shared/app-i18n.js +95 -0
- package/dist/ui/shared/app-nav.js +73 -0
- package/dist/ui/shared/app-needs.js +114 -0
- package/dist/ui/shared/app-route.js +73 -0
- package/dist/ui/shared/app-session.js +66 -0
- package/dist/ui/shared/app-shell.js +344 -0
- package/dist/ui/shared/app-store.js +51 -0
- package/dist/ui/shared/app-stream.js +201 -0
- package/dist/ui/shared/app.css +676 -0
- package/dist/ui/shared/app.js +88 -0
- package/dist/ui/shared/fonts/OFL.txt +92 -0
- package/dist/ui/shared/fonts/README.md +21 -0
- package/dist/ui/shared/fonts/inter.woff2 +0 -0
- package/dist/ui/shared/htm.module.js +1 -0
- package/dist/ui/shared/panel-view.js +655 -0
- package/dist/ui/shared/preact-hooks.module.js +2 -0
- package/dist/ui/shared/preact.module.js +2 -0
- package/dist/ui/shared/signin.js +130 -0
- package/dist/ui/shared/theme.js +29 -0
- package/dist/ui/shared/tokens.css +153 -0
- package/dist/ui/shared/ui-confirm.js +43 -0
- package/dist/ui/shared/ui-dialog.js +45 -0
- package/dist/ui/shared/ui-icons.js +61 -0
- package/dist/ui/shared/ui-menu.js +39 -0
- package/dist/ui/shared/ui-states.js +20 -0
- package/dist/ui/shared/ui-toast.js +18 -0
- package/dist/ui/shared/vendor/htm.LICENSE +202 -0
- package/dist/ui/shared/vendor/preact.LICENSE +21 -0
- package/dist/ui/shared/vendor/vendor.json +39 -0
- package/dist/ui/shared/view-strings.js +309 -0
- package/dist/ui/signin.html +51 -0
- package/dist/update-check.d.ts +6 -2
- package/dist/update-check.js +12 -3
- package/dist/update-check.js.map +1 -1
- package/dist/update-install.d.ts +71 -0
- package/dist/update-install.js +162 -0
- package/dist/update-install.js.map +1 -0
- package/dist/upgrade-notices.d.ts +17 -0
- package/dist/upgrade-notices.js +93 -0
- package/dist/upgrade-notices.js.map +1 -0
- package/dist/usage/statusline-usage.d.ts +2 -0
- package/dist/usage/statusline-usage.js +14 -10
- package/dist/usage/statusline-usage.js.map +1 -1
- package/dist/view-api.d.ts +6 -1
- package/dist/view-api.js +62 -51
- package/dist/view-api.js.map +1 -1
- package/dist/web-api.d.ts +71 -14
- package/dist/web-api.js +492 -77
- package/dist/web-api.js.map +1 -1
- package/dist/web-auth.d.ts +71 -27
- package/dist/web-auth.js +169 -69
- package/dist/web-auth.js.map +1 -1
- package/dist/web-body.d.ts +3 -0
- package/dist/web-body.js +55 -0
- package/dist/web-body.js.map +1 -0
- package/dist/web-channel-echo.d.ts +9 -0
- package/dist/web-channel-echo.js +55 -0
- package/dist/web-channel-echo.js.map +1 -0
- package/dist/web-chat-history.d.ts +125 -0
- package/dist/web-chat-history.js +184 -0
- package/dist/web-chat-history.js.map +1 -0
- package/dist/web-continuation.d.ts +7 -0
- package/dist/web-continuation.js +22 -0
- package/dist/web-continuation.js.map +1 -0
- package/dist/web-host-guard.d.ts +34 -0
- package/dist/web-host-guard.js +57 -1
- package/dist/web-host-guard.js.map +1 -1
- package/dist/web-login.d.ts +72 -0
- package/dist/web-login.js +132 -0
- package/dist/web-login.js.map +1 -0
- package/dist/web-org.d.ts +55 -0
- package/dist/web-org.js +67 -0
- package/dist/web-org.js.map +1 -0
- package/dist/web-preview.d.ts +77 -0
- package/dist/web-preview.js +240 -0
- package/dist/web-preview.js.map +1 -0
- package/dist/web-request-context.d.ts +10 -0
- package/dist/web-request-context.js +13 -0
- package/dist/web-request-context.js.map +1 -0
- package/dist/web-session.d.ts +167 -0
- package/dist/web-session.js +389 -0
- package/dist/web-session.js.map +1 -0
- package/dist/web-shell-routes.d.ts +59 -0
- package/dist/web-shell-routes.js +96 -0
- package/dist/web-shell-routes.js.map +1 -0
- package/dist/web-upload.d.ts +183 -0
- package/dist/web-upload.js +468 -0
- package/dist/web-upload.js.map +1 -0
- package/dist/website-tips-renderer.d.ts +2 -2
- package/dist/website-tips-renderer.js +3 -3
- package/dist/website-tips-renderer.js.map +1 -1
- package/package.json +8 -5
- package/scripts/preinstall-guard.cjs +36 -0
- package/dist/ui/dashboard.html +0 -774
- package/dist/ui/settings.html +0 -2165
- package/dist/ui/view.html +0 -1139
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<a href="https://songsid.github.io/AgEnD"><img src="https://img.shields.io/badge/Website-songsid.github.io/AgEnD-blue" alt="Website"></a>
|
|
8
8
|
<a href="https://www.npmjs.com/package/@songsid/agend"><img src="https://img.shields.io/npm/v/@songsid/agend" alt="npm"></a>
|
|
9
9
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
|
|
10
|
-
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-%3E%3D%
|
|
10
|
+
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-%3E%3D%2022.14.0-green.svg" alt="Node.js >= 22.14.0"></a>
|
|
11
11
|
</p>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
@@ -150,7 +150,7 @@ graph LR
|
|
|
150
150
|
|
|
151
151
|
## Requirements
|
|
152
152
|
|
|
153
|
-
- Node.js >=
|
|
153
|
+
- Node.js ^22.14.0 || ^23.6.0 || >=24
|
|
154
154
|
- tmux
|
|
155
155
|
- One of the supported AI coding CLIs (installed and authenticated)
|
|
156
156
|
- Telegram bot token ([@BotFather](https://t.me/BotFather)) or Discord bot token
|
package/README.zh-TW.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<a href="https://songsid.github.io/AgEnD"><img src="https://img.shields.io/badge/Website-songsid.github.io/AgEnD-blue" alt="Website"></a>
|
|
8
8
|
<a href="https://www.npmjs.com/package/@songsid/agend"><img src="https://img.shields.io/npm/v/@songsid/agend" alt="npm"></a>
|
|
9
9
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
|
|
10
|
-
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-%3E%3D%
|
|
10
|
+
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-%3E%3D%2022.14.0-green.svg" alt="Node.js >= 22.14.0"></a>
|
|
11
11
|
</p>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
@@ -150,7 +150,7 @@ graph LR
|
|
|
150
150
|
|
|
151
151
|
## 系統需求
|
|
152
152
|
|
|
153
|
-
- Node.js >=
|
|
153
|
+
- Node.js ^22.14.0 || ^23.6.0 || >=24
|
|
154
154
|
- tmux
|
|
155
155
|
- 以下任一 AI coding CLI(需安裝並完成認證)
|
|
156
156
|
- Telegram bot token([@BotFather](https://t.me/BotFather))或 Discord bot token
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const ONE_TIME_CODE_LENGTH = 8;
|
|
2
|
+
export declare function generateOneTimeCode(): string;
|
|
3
|
+
/** `ABCD-EFGH` — a shape that survives being read aloud and retyped. */
|
|
4
|
+
export declare function formatOneTimeCode(code: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* What the person typed, as the code it was meant to be.
|
|
7
|
+
*
|
|
8
|
+
* Case and the dash are presentation. Rejecting `abcd efgh` would be rejecting
|
|
9
|
+
* a correct answer, and the person retyping it has no idea which detail was
|
|
10
|
+
* wrong — so they spend attempts on formatting.
|
|
11
|
+
*/
|
|
12
|
+
export declare function normalizeOneTimeCode(input: string): string;
|
|
13
|
+
/**
|
|
14
|
+
* Fixed-length constant-time compare.
|
|
15
|
+
*
|
|
16
|
+
* Both sides are padded to the same length first: `timingSafeEqual` throws on a
|
|
17
|
+
* mismatch, and returning early on one leaks the length through timing.
|
|
18
|
+
*/
|
|
19
|
+
export declare function constantTimeMatches(provided: string, expected: string): boolean;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The typed one-time code, as a primitive.
|
|
3
|
+
*
|
|
4
|
+
* Shared by the pre-fleet setup page (`setup-auth.ts`) and the dashboard login
|
|
5
|
+
* (`web-login.ts`). What is shared is only what has no policy in it: the
|
|
6
|
+
* alphabet, how a code is generated, shown and read back, and how two strings
|
|
7
|
+
* are compared. Attempt budgets, lifetimes and what a redeemed code is *worth*
|
|
8
|
+
* differ between the two and stay with their owners — the setup page burns
|
|
9
|
+
* itself on the fifth failure, a long-lived fleet must not.
|
|
10
|
+
*/
|
|
11
|
+
import { randomInt, timingSafeEqual } from "node:crypto";
|
|
12
|
+
/** RFC 4648 base32, minus nothing: the digits 0/1 are absent from it already. */
|
|
13
|
+
const CODE_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
14
|
+
export const ONE_TIME_CODE_LENGTH = 8;
|
|
15
|
+
export function generateOneTimeCode() {
|
|
16
|
+
let code = "";
|
|
17
|
+
for (let i = 0; i < ONE_TIME_CODE_LENGTH; i++)
|
|
18
|
+
code += CODE_ALPHABET[randomInt(CODE_ALPHABET.length)];
|
|
19
|
+
return code;
|
|
20
|
+
}
|
|
21
|
+
/** `ABCD-EFGH` — a shape that survives being read aloud and retyped. */
|
|
22
|
+
export function formatOneTimeCode(code) {
|
|
23
|
+
return `${code.slice(0, 4)}-${code.slice(4)}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* What the person typed, as the code it was meant to be.
|
|
27
|
+
*
|
|
28
|
+
* Case and the dash are presentation. Rejecting `abcd efgh` would be rejecting
|
|
29
|
+
* a correct answer, and the person retyping it has no idea which detail was
|
|
30
|
+
* wrong — so they spend attempts on formatting.
|
|
31
|
+
*/
|
|
32
|
+
export function normalizeOneTimeCode(input) {
|
|
33
|
+
return input.replace(/[^0-9A-Za-z]/g, "").toUpperCase();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Fixed-length constant-time compare.
|
|
37
|
+
*
|
|
38
|
+
* Both sides are padded to the same length first: `timingSafeEqual` throws on a
|
|
39
|
+
* mismatch, and returning early on one leaks the length through timing.
|
|
40
|
+
*/
|
|
41
|
+
export function constantTimeMatches(provided, expected) {
|
|
42
|
+
const width = Math.max(provided.length, expected.length, 1);
|
|
43
|
+
const a = Buffer.alloc(width);
|
|
44
|
+
const b = Buffer.alloc(width);
|
|
45
|
+
a.write(provided, "utf8");
|
|
46
|
+
b.write(expected, "utf8");
|
|
47
|
+
return timingSafeEqual(a, b) && provided.length === expected.length;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=one-time-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"one-time-code.js","sourceRoot":"","sources":["../../src/auth/one-time-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEzD,iFAAiF;AACjF,MAAM,aAAa,GAAG,kCAAkC,CAAC;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAEtC,MAAM,UAAU,mBAAmB;IACjC,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,oBAAoB,EAAE,CAAC,EAAE;QAAE,IAAI,IAAI,aAAa,CAAC,SAAS,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;IACtG,OAAO,IAAI,CAAC;AACd,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AAChD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,OAAO,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AAC1D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,QAAgB;IACpE,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC5D,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC1B,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC1B,OAAO,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
import type { Logger } from "./logger.js";
|
|
3
|
+
import { type SessionTier, type WebSessionStore } from "./web-session.js";
|
|
4
|
+
import type { LoginCodeOwner, WebLoginCodes } from "./web-login.js";
|
|
5
|
+
export declare const LOGIN_REFUSED_MESSAGE = "That code did not work \u2014 it may be wrong, expired or already used. Ask for a new one with /dashboard.";
|
|
6
|
+
export declare const LOGIN_PAUSED_MESSAGE = "Too many wrong codes \u2014 sign-in is paused for a few minutes.";
|
|
7
|
+
export interface AuthApiContext {
|
|
8
|
+
readonly webToken: string | null;
|
|
9
|
+
readonly webSessions: WebSessionStore | null;
|
|
10
|
+
readonly webLoginCodes: WebLoginCodes | null;
|
|
11
|
+
readonly logger: Logger;
|
|
12
|
+
/** Told after every successful sign-in, so the operator can be shown one they did not make. */
|
|
13
|
+
confirmPublicWebLogin?(info: {
|
|
14
|
+
label: string;
|
|
15
|
+
handle: string;
|
|
16
|
+
owner: LoginCodeOwner;
|
|
17
|
+
}, isCurrent: () => boolean): Promise<void>;
|
|
18
|
+
onWebLogin?(info: {
|
|
19
|
+
label: string;
|
|
20
|
+
surface: "local" | "gateway";
|
|
21
|
+
tier: SessionTier;
|
|
22
|
+
handle: string;
|
|
23
|
+
}): void;
|
|
24
|
+
}
|
|
25
|
+
/** True for a name `/assets/` serves. The public link's manifest asks this too: one list, not two. */
|
|
26
|
+
export declare function isServedAsset(name: string): boolean;
|
|
27
|
+
export declare function isAuthPath(path: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Whether a request skips the global gate. Everything not named here goes
|
|
30
|
+
* through `decideWebGate`.
|
|
31
|
+
*
|
|
32
|
+
* - `/health` (GET) is the monitor's probe; `/agent` (POST) authenticates itself
|
|
33
|
+
* with an instance token.
|
|
34
|
+
* - The sign-in page and its endpoints are the way *through* the gate; each route
|
|
35
|
+
* in this file does its own checks.
|
|
36
|
+
* - `/view`'s reads and `/api/ai-usage` are open by default, and only reads: a
|
|
37
|
+
* write to any of them is gated like everything else, so it needs a session
|
|
38
|
+
* (with the cookie-write checks) or the header token, never a `?token=`.
|
|
39
|
+
* `web.view_access: session` closes the reads too.
|
|
40
|
+
*/
|
|
41
|
+
export declare function bypassesWebGate(req: {
|
|
42
|
+
method?: string | undefined;
|
|
43
|
+
url?: string | undefined;
|
|
44
|
+
}, path: string, config: {
|
|
45
|
+
web?: {
|
|
46
|
+
view_access?: string;
|
|
47
|
+
} | undefined;
|
|
48
|
+
} | null | undefined, isViewRead: (path: string) => boolean): boolean;
|
|
49
|
+
/** The sign-in page. Also what a browser navigation gets from a gated page it has no cookie for. */
|
|
50
|
+
export declare function serveSigninPage(res: ServerResponse, status?: number): void;
|
|
51
|
+
export declare function handleAuthRequest(req: IncomingMessage, res: ServerResponse, url: URL, ctx: AuthApiContext): boolean;
|
|
52
|
+
export declare const REVOCATION_NOT_DURABLE_MESSAGE = "Signed out for now, but the change could not be saved: the session file could not be updated or removed, so a fleet restart may bring the session back. Fix the permissions on ~/.agend/web-sessions.json and sign out again, or rotate the token (agend web-token rotate).";
|
package/dist/auth-api.js
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import { readBoundedWebBody } from "./web-body.js";
|
|
2
|
+
import { performance } from "node:perf_hooks";
|
|
3
|
+
import { withinBudget } from "./monotonic-budget.js";
|
|
4
|
+
import { gatewayRequestContext, isWebRequestCurrent } from "./web-request-context.js";
|
|
5
|
+
/**
|
|
6
|
+
* The sign-in surface: the page, the exchange, and session management.
|
|
7
|
+
*
|
|
8
|
+
* GET /signin static page — no side effects, no secret
|
|
9
|
+
* GET /assets/<file> the two scripts the page and the panels load
|
|
10
|
+
* POST /auth/login {code} → session cookie
|
|
11
|
+
* GET /auth/session who am I (+ the CSRF value this session must send)
|
|
12
|
+
* POST /auth/logout end this session
|
|
13
|
+
* GET /auth/sessions this operator's signed-in devices
|
|
14
|
+
* DELETE /auth/sessions/<handle> end one of them
|
|
15
|
+
* DELETE /auth/sessions end all of them
|
|
16
|
+
* POST /auth/issue-code X-Agend-Token only — how `agend web --code` asks for a code
|
|
17
|
+
*
|
|
18
|
+
* Every GET here is free of side effects: a chat client that previews a link
|
|
19
|
+
* cannot spend a code, mint a session, or move a counter. The only thing that
|
|
20
|
+
* consumes a code is a POST from the page's own origin.
|
|
21
|
+
*
|
|
22
|
+
* Nothing here is behind the global gate — this *is* the way through it — so each
|
|
23
|
+
* route does its own checks, with the same primitives the gate uses.
|
|
24
|
+
*
|
|
25
|
+
* See `docs/design/web-unification-secure-login.zh-TW.md` §3.
|
|
26
|
+
*/
|
|
27
|
+
import { sendPanelHtml } from "./web-host-guard.js";
|
|
28
|
+
import { readFileSync } from "node:fs";
|
|
29
|
+
import { dirname, join } from "node:path";
|
|
30
|
+
import { fileURLToPath } from "node:url";
|
|
31
|
+
import { authorizeSession, buildClearedSessionCookies, buildSessionCookie, hasValidHeaderToken, isSameOriginRequest, isSecureRequest, readSessionCookie, WEB_CSRF_MESSAGE, } from "./web-auth.js";
|
|
32
|
+
import { csrfTokenFor, labelFromUserAgent, sessionIdHash, tokenEpoch } from "./web-session.js";
|
|
33
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
34
|
+
export const LOGIN_REFUSED_MESSAGE = "That code did not work — it may be wrong, expired or already used. Ask for a new one with /dashboard.";
|
|
35
|
+
export const LOGIN_PAUSED_MESSAGE = "Too many wrong codes — sign-in is paused for a few minutes.";
|
|
36
|
+
const MAX_LOGIN_BODY = 1024;
|
|
37
|
+
/** The only files `/assets/` will serve. A map, not a directory: nothing else can be named into it. */
|
|
38
|
+
const ASSETS = {
|
|
39
|
+
"agend-auth.js": { file: join("shared", "agend-auth.js"), type: "text/javascript; charset=utf-8" },
|
|
40
|
+
"signin.js": { file: join("shared", "signin.js"), type: "text/javascript; charset=utf-8" },
|
|
41
|
+
"theme.js": { file: join("shared", "theme.js"), type: "text/javascript; charset=utf-8" },
|
|
42
|
+
// #1408: the design tokens every panel shares, and the font they name (Inter, SIL OFL 1.1: shared/fonts/OFL.txt).
|
|
43
|
+
"tokens.css": { file: join("shared", "tokens.css"), type: "text/css; charset=utf-8" },
|
|
44
|
+
"inter.woff2": { file: join("shared", "fonts", "inter.woff2"), type: "font/woff2" },
|
|
45
|
+
// #1408: the app shell's public closure — the entry module, everything it imports statically, and the vendored
|
|
46
|
+
// Preact + htm (shared/vendor/vendor.json, byte-checked). Static code with no data, like signin.js; the panels that
|
|
47
|
+
// need a session stay behind the gate under /ui/js/ and are reached only by a dynamic import.
|
|
48
|
+
...Object.fromEntries([
|
|
49
|
+
"app.js", "app-html.js", "app-i18n.js", "app-route.js", "app-nav.js", "app-ctx.js", "app-stream.js", "app-store.js",
|
|
50
|
+
"app-shell.js", "app-session.js", "app-needs.js", "ui-confirm.js", "ui-dialog.js", "ui-menu.js", "ui-states.js", "ui-icons.js", "ui-toast.js",
|
|
51
|
+
// #1408 step 2: View is public (an anonymous reader opens it under web.view_access: open), loaded on demand.
|
|
52
|
+
"panel-view.js", "view-strings.js",
|
|
53
|
+
"preact.module.js", "preact-hooks.module.js", "htm.module.js",
|
|
54
|
+
].map(name => [name, { file: join("shared", name), type: "text/javascript; charset=utf-8" }])),
|
|
55
|
+
"app.css": { file: join("shared", "app.css"), type: "text/css; charset=utf-8" },
|
|
56
|
+
};
|
|
57
|
+
/** True for a name `/assets/` serves. The public link's manifest asks this too: one list, not two. */
|
|
58
|
+
export function isServedAsset(name) {
|
|
59
|
+
return Object.prototype.hasOwnProperty.call(ASSETS, name);
|
|
60
|
+
}
|
|
61
|
+
export function isAuthPath(path) {
|
|
62
|
+
return path === "/" || path === "/signin" || path.startsWith("/auth/") || path.startsWith("/assets/");
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Whether a request skips the global gate. Everything not named here goes
|
|
66
|
+
* through `decideWebGate`.
|
|
67
|
+
*
|
|
68
|
+
* - `/health` (GET) is the monitor's probe; `/agent` (POST) authenticates itself
|
|
69
|
+
* with an instance token.
|
|
70
|
+
* - The sign-in page and its endpoints are the way *through* the gate; each route
|
|
71
|
+
* in this file does its own checks.
|
|
72
|
+
* - `/view`'s reads and `/api/ai-usage` are open by default, and only reads: a
|
|
73
|
+
* write to any of them is gated like everything else, so it needs a session
|
|
74
|
+
* (with the cookie-write checks) or the header token, never a `?token=`.
|
|
75
|
+
* `web.view_access: session` closes the reads too.
|
|
76
|
+
*/
|
|
77
|
+
export function bypassesWebGate(req, path, config, isViewRead) {
|
|
78
|
+
const method = req.method ?? "GET";
|
|
79
|
+
if (method === "GET" && req.url === "/health")
|
|
80
|
+
return true;
|
|
81
|
+
if (method === "POST" && req.url === "/agent")
|
|
82
|
+
return true;
|
|
83
|
+
if (isAuthPath(path))
|
|
84
|
+
return true;
|
|
85
|
+
return (method === "GET" || method === "HEAD") && config?.web?.view_access !== "session" && isViewRead(path);
|
|
86
|
+
}
|
|
87
|
+
function json(res, code, body, headers = {}) {
|
|
88
|
+
res.writeHead(code, { "Content-Type": "application/json", ...headers });
|
|
89
|
+
res.end(JSON.stringify(body));
|
|
90
|
+
}
|
|
91
|
+
/** The sign-in page. Also what a browser navigation gets from a gated page it has no cookie for. */
|
|
92
|
+
export function serveSigninPage(res, status = 200) {
|
|
93
|
+
try {
|
|
94
|
+
const html = readFileSync(join(__dirname, "ui", "signin.html"), "utf-8");
|
|
95
|
+
sendPanelHtml(res, html, status, { "Cache-Control": "no-store" });
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
json(res, 500, { error: "signin.html not found" });
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
async function readJsonBody(req) {
|
|
102
|
+
try {
|
|
103
|
+
const parsed = JSON.parse((await readBoundedWebBody(req, MAX_LOGIN_BODY)).toString("utf8") || "{}");
|
|
104
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function isJsonRequest(req) {
|
|
111
|
+
return String(req.headers["content-type"] ?? "").toLowerCase().startsWith("application/json");
|
|
112
|
+
}
|
|
113
|
+
export function handleAuthRequest(req, res, url, ctx) {
|
|
114
|
+
const path = url.pathname;
|
|
115
|
+
if (!isAuthPath(path))
|
|
116
|
+
return false;
|
|
117
|
+
const method = req.method ?? "GET";
|
|
118
|
+
const gateReq = req;
|
|
119
|
+
// ── `/` is a door, not a page: everything about who may enter is decided at /ui ──
|
|
120
|
+
if (path === "/") {
|
|
121
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
122
|
+
json(res, 405, { error: "method not allowed" });
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
res.writeHead(302, { Location: "/ui", "Cache-Control": "no-store" });
|
|
126
|
+
res.end();
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
// ── The page and its scripts: public, inert ──
|
|
130
|
+
if (path === "/signin") {
|
|
131
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
132
|
+
json(res, 405, { error: "method not allowed" });
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
135
|
+
serveSigninPage(res);
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
if (path.startsWith("/assets/")) {
|
|
139
|
+
const asset = method === "GET" ? ASSETS[path.slice("/assets/".length)] : undefined;
|
|
140
|
+
if (!asset) {
|
|
141
|
+
json(res, 404, { error: "not found" });
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const body = readFileSync(join(__dirname, "ui", asset.file));
|
|
146
|
+
res.writeHead(200, { "Content-Type": asset.type });
|
|
147
|
+
res.end(body);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
json(res, 404, { error: "not found" });
|
|
151
|
+
}
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
// ── POST /auth/login ──
|
|
155
|
+
if (path === "/auth/login") {
|
|
156
|
+
if (method !== "POST") {
|
|
157
|
+
json(res, 405, { error: "method not allowed" });
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
// Origin is required, not merely checked: the sign-in page is always same-origin,
|
|
161
|
+
// and a login POST with no Origin is nobody's legitimate request.
|
|
162
|
+
if (!req.headers.origin || !isSameOriginRequest(gateReq)) {
|
|
163
|
+
json(res, 403, { error: "Cross-site request rejected" });
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
if (!isJsonRequest(req)) {
|
|
167
|
+
json(res, 415, { error: "expected application/json" });
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
const token = ctx.webToken;
|
|
171
|
+
if (!token || !ctx.webSessions || !ctx.webLoginCodes) {
|
|
172
|
+
json(res, 401, { error: LOGIN_REFUSED_MESSAGE });
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
const sessions = ctx.webSessions;
|
|
176
|
+
const codes = ctx.webLoginCodes;
|
|
177
|
+
// A notice ACK cannot create an orphan credential after the browser has
|
|
178
|
+
// disconnected. Normal completed request-body close is not an abort.
|
|
179
|
+
const publicRequest = !!gatewayRequestContext(req);
|
|
180
|
+
let disconnected = false;
|
|
181
|
+
let candidateId;
|
|
182
|
+
const disconnect = () => {
|
|
183
|
+
disconnected = true;
|
|
184
|
+
if (candidateId)
|
|
185
|
+
sessions.revokeById(candidateId);
|
|
186
|
+
};
|
|
187
|
+
if (publicRequest) {
|
|
188
|
+
req.once("aborted", disconnect);
|
|
189
|
+
res.once?.("close", disconnect);
|
|
190
|
+
}
|
|
191
|
+
void readJsonBody(req).then(async (body) => {
|
|
192
|
+
if (!body || typeof body.code !== "string") {
|
|
193
|
+
json(res, 400, { error: "expected {\"code\": \"XXXX-XXXX\"}" });
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const gateway = gatewayRequestContext(req);
|
|
197
|
+
const current = () => isWebRequestCurrent(req) && ctx.webToken === token
|
|
198
|
+
&& (!publicRequest || (!disconnected && !req.aborted && !(req.destroyed && !req.complete) && !res.destroyed && !res.writableEnded));
|
|
199
|
+
if (!current()) {
|
|
200
|
+
json(res, 401, { error: LOGIN_REFUSED_MESSAGE });
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const result = codes.redeem(body.code, tokenEpoch(token), gateway?.exposureId ?? "local");
|
|
204
|
+
if (result.kind === "paused") {
|
|
205
|
+
json(res, 429, { error: LOGIN_PAUSED_MESSAGE }, { "Retry-After": String(Math.ceil(result.retryAfterMs / 1000)) });
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
if (result.kind === "invalid") {
|
|
209
|
+
ctx.logger.debug("web sign-in refused");
|
|
210
|
+
json(res, 401, { error: LOGIN_REFUSED_MESSAGE });
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// A new id every time, whatever the request carried: the browser never
|
|
214
|
+
// gets to choose the value it will be authenticated by, and a cookie it
|
|
215
|
+
// already had is retired rather than upgraded.
|
|
216
|
+
const previous = readSessionCookie(gateReq);
|
|
217
|
+
if (previous && sessions.authenticate(previous, tokenEpoch(token), { touch: false, surface: gateway?.surface, exposureId: gateway?.exposureId }))
|
|
218
|
+
sessions.revokeById(previous);
|
|
219
|
+
const label = labelFromUserAgent(typeof req.headers["user-agent"] === "string" ? req.headers["user-agent"] : undefined);
|
|
220
|
+
const { sessionId, record } = sessions.create({ tier: result.tier, surface: gateway?.surface ?? "local", label, tokenEpoch: tokenEpoch(token), exposureId: gateway?.exposureId, pending: !!gateway });
|
|
221
|
+
if (gateway)
|
|
222
|
+
candidateId = sessionId;
|
|
223
|
+
if (gateway) {
|
|
224
|
+
try {
|
|
225
|
+
if (!result.owner || !ctx.confirmPublicWebLogin)
|
|
226
|
+
throw new Error("public notice unavailable");
|
|
227
|
+
await withinBudget(ctx.confirmPublicWebLogin({ label, handle: record.handle, owner: result.owner }, current), performance.now() + 5_000);
|
|
228
|
+
if (!current() || !sessions.activate(sessionId))
|
|
229
|
+
throw new Error("public login closed");
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
sessions.revokeById(sessionId);
|
|
233
|
+
ctx.logger.debug("Public sign-in could not be confirmed");
|
|
234
|
+
if (!res.destroyed)
|
|
235
|
+
json(res, 503, { error: "Sign-in could not be confirmed. Ask for a new code and try again." });
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
ctx.logger.info({ handle: record.handle, label, tier: record.tier, surface: record.surface }, "Web sign-in");
|
|
240
|
+
try {
|
|
241
|
+
if (!gateway)
|
|
242
|
+
ctx.onWebLogin?.({ label, surface: record.surface, tier: record.tier, handle: record.handle });
|
|
243
|
+
}
|
|
244
|
+
catch (err) {
|
|
245
|
+
ctx.logger.debug({ err }, "web sign-in notice failed");
|
|
246
|
+
}
|
|
247
|
+
json(res, 200, { ok: true, csrf: csrfTokenFor(sessionId), tier: record.tier, expiresAt: record.absoluteExpiry }, {
|
|
248
|
+
"Set-Cookie": buildSessionCookie(sessionId, isSecureRequest(gateReq), (record.absoluteExpiry - record.created) / 1000),
|
|
249
|
+
});
|
|
250
|
+
}).catch(() => { if (!res.destroyed && !res.headersSent)
|
|
251
|
+
json(res, 500, { error: "sign-in failed" }); })
|
|
252
|
+
.finally(() => { req.removeListener("aborted", disconnect); res.removeListener?.("close", disconnect); });
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
// ── POST /auth/issue-code — a local script's way to ask for a code ──
|
|
256
|
+
if (path === "/auth/issue-code") {
|
|
257
|
+
if (method !== "POST") {
|
|
258
|
+
json(res, 405, { error: "method not allowed" });
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
261
|
+
const token = ctx.webToken;
|
|
262
|
+
if (gatewayRequestContext(req) || !token || !ctx.webLoginCodes || !isSameOriginRequest(gateReq) || !hasValidHeaderToken(gateReq, token)) {
|
|
263
|
+
json(res, 401, { error: "X-Agend-Token required" });
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
const issued = ctx.webLoginCodes.issue({ tier: "admin", epoch: tokenEpoch(token) });
|
|
267
|
+
ctx.logger.info({ source: "cli" }, "Web login code issued");
|
|
268
|
+
json(res, 200, { code: issued.display, expiresAt: issued.expiresAt });
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
// ── The session's own endpoints: a session, and nothing else, is the credential ──
|
|
272
|
+
if (path === "/auth/session" || path === "/auth/logout" || path === "/auth/sessions" || path.startsWith("/auth/sessions/")) {
|
|
273
|
+
const auth = authorizeSession(gateReq, ctx.webToken, ctx.webSessions, { touch: path === "/auth/session" });
|
|
274
|
+
if (auth.kind === "reject") {
|
|
275
|
+
json(res, auth.status, auth.message === WEB_CSRF_MESSAGE ? { error: auth.message } : { ok: false, error: auth.message });
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
const sessions = ctx.webSessions;
|
|
279
|
+
const { session, sessionId } = auth;
|
|
280
|
+
if (path === "/auth/session" && method === "GET") {
|
|
281
|
+
json(res, 200, {
|
|
282
|
+
ok: true,
|
|
283
|
+
csrf: csrfTokenFor(sessionId),
|
|
284
|
+
handle: session.handle,
|
|
285
|
+
tier: session.tier,
|
|
286
|
+
surface: session.surface,
|
|
287
|
+
label: session.label,
|
|
288
|
+
created: session.created,
|
|
289
|
+
expiresAt: session.absoluteExpiry,
|
|
290
|
+
idleExpiresAt: session.idleExpiry,
|
|
291
|
+
idleMs: sessions.idleWindowMs(session.surface),
|
|
292
|
+
});
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
if (path === "/auth/logout" && method === "POST") {
|
|
296
|
+
const { durable } = sessions.revokeById(sessionId);
|
|
297
|
+
if (!durable)
|
|
298
|
+
return notDurable(res, ctx, { handle: session.handle }, "Web sign-out not saved");
|
|
299
|
+
ctx.logger.info({ handle: session.handle }, "Web sign-out");
|
|
300
|
+
json(res, 200, { ok: true }, { "Set-Cookie": buildClearedSessionCookies() });
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
if (path === "/auth/sessions" && method === "GET") {
|
|
304
|
+
json(res, 200, { sessions: sessions.list(sessionIdHash(sessionId)) });
|
|
305
|
+
return true;
|
|
306
|
+
}
|
|
307
|
+
if (path === "/auth/sessions" && method === "DELETE") {
|
|
308
|
+
const { count, durable } = sessions.revokeAll();
|
|
309
|
+
if (!durable)
|
|
310
|
+
return notDurable(res, ctx, { count }, "Web sessions revoked in memory only");
|
|
311
|
+
ctx.logger.info({ count }, "Web sessions revoked (all)");
|
|
312
|
+
json(res, 200, { ok: true, revoked: count }, { "Set-Cookie": buildClearedSessionCookies() });
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
if (path.startsWith("/auth/sessions/") && method === "DELETE") {
|
|
316
|
+
const handle = path.slice("/auth/sessions/".length);
|
|
317
|
+
const wasCurrent = handle === session.handle;
|
|
318
|
+
const { found, durable } = sessions.revokeByHandle(handle);
|
|
319
|
+
if (!found) {
|
|
320
|
+
json(res, 404, { error: "no such session" });
|
|
321
|
+
return true;
|
|
322
|
+
}
|
|
323
|
+
if (!durable)
|
|
324
|
+
return notDurable(res, ctx, { handle }, "Web session revoked in memory only", wasCurrent);
|
|
325
|
+
ctx.logger.info({ handle }, "Web session revoked");
|
|
326
|
+
json(res, 200, { ok: true, current: wasCurrent }, wasCurrent ? { "Set-Cookie": buildClearedSessionCookies() } : {});
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
json(res, 405, { error: "method not allowed" });
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
json(res, 404, { error: "not found" });
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
export const REVOCATION_NOT_DURABLE_MESSAGE = "Signed out for now, but the change could not be saved: the session file could not be updated or removed, so a fleet restart may bring the session back. Fix the permissions on ~/.agend/web-sessions.json and sign out again, or rotate the token (agend web-token rotate).";
|
|
336
|
+
/**
|
|
337
|
+
* A revocation that holds only in memory is reported as a failure (500), never as "ok": the browser is
|
|
338
|
+
* still told to drop its cookie (it is signed out here), but whoever asked must not believe a session is
|
|
339
|
+
* dead that the next start revives.
|
|
340
|
+
*/
|
|
341
|
+
function notDurable(res, ctx, detail, msg, clearCookie = true) {
|
|
342
|
+
ctx.logger.warn({ ...detail, durable: false }, msg);
|
|
343
|
+
json(res, 500, { ok: false, durable: false, error: REVOCATION_NOT_DURABLE_MESSAGE }, clearCookie ? { "Set-Cookie": buildClearedSessionCookies() } : {});
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=auth-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-api.js","sourceRoot":"","sources":["../src/auth-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -50,6 +50,10 @@ export declare function claudeResumeMenuState(pane: string): {
|
|
|
50
50
|
active: boolean;
|
|
51
51
|
defaultCursor: boolean;
|
|
52
52
|
};
|
|
53
|
+
export declare function claudeColdResumePromptState(pane: string): {
|
|
54
|
+
titled: boolean;
|
|
55
|
+
exact: boolean;
|
|
56
|
+
};
|
|
53
57
|
/**
|
|
54
58
|
* Claude Code's live input box, read as a region (#1200). Captured live from 2.1.293 under the production launch
|
|
55
59
|
* (tests/fixtures/claude-2.1.293-*.pane.txt):
|