agent-relay 1.2.3 → 1.3.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 (200) hide show
  1. package/.trajectories/agent-relay-322-324.md +17 -0
  2. package/.trajectories/completed/2026-01/traj_03zupyv1s7b9.json +49 -0
  3. package/.trajectories/completed/2026-01/traj_03zupyv1s7b9.md +31 -0
  4. package/.trajectories/completed/2026-01/traj_0zacdjl1g4ht.json +125 -0
  5. package/.trajectories/completed/2026-01/traj_0zacdjl1g4ht.md +62 -0
  6. package/.trajectories/completed/2026-01/traj_33iuy72sezbk.json +49 -0
  7. package/.trajectories/completed/2026-01/traj_33iuy72sezbk.md +31 -0
  8. package/.trajectories/completed/2026-01/traj_5ammh5qtvklq.json +77 -0
  9. package/.trajectories/completed/2026-01/traj_5ammh5qtvklq.md +42 -0
  10. package/.trajectories/completed/2026-01/traj_6mieijqyvaag.json +77 -0
  11. package/.trajectories/completed/2026-01/traj_6mieijqyvaag.md +42 -0
  12. package/.trajectories/completed/2026-01/traj_78ffm31jn3uk.json +77 -0
  13. package/.trajectories/completed/2026-01/traj_78ffm31jn3uk.md +42 -0
  14. package/.trajectories/completed/2026-01/traj_94gnp3k30goq.json +66 -0
  15. package/.trajectories/completed/2026-01/traj_94gnp3k30goq.md +36 -0
  16. package/.trajectories/completed/2026-01/traj_avqeghu6pz5a.json +40 -0
  17. package/.trajectories/completed/2026-01/traj_avqeghu6pz5a.md +22 -0
  18. package/.trajectories/completed/2026-01/traj_dcsp9s8y01ra.json +121 -0
  19. package/.trajectories/completed/2026-01/traj_dcsp9s8y01ra.md +29 -0
  20. package/.trajectories/completed/2026-01/traj_fhx9irlckht6.json +53 -0
  21. package/.trajectories/completed/2026-01/traj_fhx9irlckht6.md +32 -0
  22. package/.trajectories/completed/2026-01/traj_fqduidx3xbtp.json +101 -0
  23. package/.trajectories/completed/2026-01/traj_fqduidx3xbtp.md +52 -0
  24. package/.trajectories/completed/2026-01/traj_hf81ey93uz6t.json +49 -0
  25. package/.trajectories/completed/2026-01/traj_hf81ey93uz6t.md +31 -0
  26. package/.trajectories/completed/2026-01/traj_hfmki2jr9d4r.json +65 -0
  27. package/.trajectories/completed/2026-01/traj_hfmki2jr9d4r.md +37 -0
  28. package/.trajectories/completed/2026-01/traj_lq450ly148uw.json +49 -0
  29. package/.trajectories/completed/2026-01/traj_lq450ly148uw.md +31 -0
  30. package/.trajectories/completed/2026-01/traj_multi_server_arch.md +101 -0
  31. package/.trajectories/completed/2026-01/traj_psd9ob0j2ru3.json +27 -0
  32. package/.trajectories/completed/2026-01/traj_psd9ob0j2ru3.md +14 -0
  33. package/.trajectories/completed/2026-01/traj_ub8csuv3lcv4.json +53 -0
  34. package/.trajectories/completed/2026-01/traj_ub8csuv3lcv4.md +32 -0
  35. package/.trajectories/completed/2026-01/traj_uc29tlso8i9s.json +186 -0
  36. package/.trajectories/completed/2026-01/traj_uc29tlso8i9s.md +86 -0
  37. package/.trajectories/completed/2026-01/traj_ui9b4tqxoa7j.json +77 -0
  38. package/.trajectories/completed/2026-01/traj_ui9b4tqxoa7j.md +42 -0
  39. package/.trajectories/completed/2026-01/traj_v9dkdoxylyid.json +89 -0
  40. package/.trajectories/completed/2026-01/traj_v9dkdoxylyid.md +47 -0
  41. package/.trajectories/completed/2026-01/traj_xy9vifpqet80.json +65 -0
  42. package/.trajectories/completed/2026-01/traj_xy9vifpqet80.md +37 -0
  43. package/.trajectories/completed/2026-01/traj_y7aiwijyfmmv.json +49 -0
  44. package/.trajectories/completed/2026-01/traj_y7aiwijyfmmv.md +31 -0
  45. package/.trajectories/consolidate-settings-panel.md +24 -0
  46. package/.trajectories/gh-cli-user-token.md +26 -0
  47. package/.trajectories/index.json +155 -1
  48. package/deploy/workspace/codex.config.toml +15 -0
  49. package/deploy/workspace/entrypoint.sh +167 -7
  50. package/deploy/workspace/git-credential-relay +17 -2
  51. package/dist/bridge/spawner.d.ts +7 -0
  52. package/dist/bridge/spawner.js +40 -9
  53. package/dist/bridge/types.d.ts +2 -0
  54. package/dist/cli/index.js +210 -168
  55. package/dist/cloud/api/admin.d.ts +8 -0
  56. package/dist/cloud/api/admin.js +212 -0
  57. package/dist/cloud/api/auth.js +8 -0
  58. package/dist/cloud/api/billing.d.ts +0 -10
  59. package/dist/cloud/api/billing.js +248 -58
  60. package/dist/cloud/api/codex-auth-helper.d.ts +10 -4
  61. package/dist/cloud/api/codex-auth-helper.js +215 -8
  62. package/dist/cloud/api/coordinators.js +402 -0
  63. package/dist/cloud/api/daemons.js +15 -11
  64. package/dist/cloud/api/git.js +104 -17
  65. package/dist/cloud/api/github-app.js +42 -8
  66. package/dist/cloud/api/nango-auth.js +297 -16
  67. package/dist/cloud/api/onboarding.js +97 -33
  68. package/dist/cloud/api/providers.js +12 -16
  69. package/dist/cloud/api/repos.js +200 -124
  70. package/dist/cloud/api/test-helpers.js +40 -0
  71. package/dist/cloud/api/usage.js +13 -0
  72. package/dist/cloud/api/webhooks.js +1 -1
  73. package/dist/cloud/api/workspaces.d.ts +18 -0
  74. package/dist/cloud/api/workspaces.js +945 -15
  75. package/dist/cloud/config.d.ts +8 -0
  76. package/dist/cloud/config.js +15 -0
  77. package/dist/cloud/db/drizzle.d.ts +5 -2
  78. package/dist/cloud/db/drizzle.js +27 -20
  79. package/dist/cloud/db/schema.d.ts +19 -51
  80. package/dist/cloud/db/schema.js +5 -4
  81. package/dist/cloud/index.d.ts +0 -1
  82. package/dist/cloud/index.js +0 -1
  83. package/dist/cloud/provisioner/index.d.ts +93 -1
  84. package/dist/cloud/provisioner/index.js +608 -63
  85. package/dist/cloud/server.js +156 -16
  86. package/dist/cloud/services/compute-enforcement.d.ts +57 -0
  87. package/dist/cloud/services/compute-enforcement.js +175 -0
  88. package/dist/cloud/services/index.d.ts +2 -0
  89. package/dist/cloud/services/index.js +4 -0
  90. package/dist/cloud/services/intro-expiration.d.ts +55 -0
  91. package/dist/cloud/services/intro-expiration.js +211 -0
  92. package/dist/cloud/services/nango.d.ts +14 -0
  93. package/dist/cloud/services/nango.js +74 -14
  94. package/dist/cloud/services/ssh-security.d.ts +31 -0
  95. package/dist/cloud/services/ssh-security.js +63 -0
  96. package/dist/continuity/manager.d.ts +5 -0
  97. package/dist/continuity/manager.js +56 -2
  98. package/dist/daemon/api.d.ts +2 -0
  99. package/dist/daemon/api.js +214 -5
  100. package/dist/daemon/cli-auth.d.ts +13 -1
  101. package/dist/daemon/cli-auth.js +166 -47
  102. package/dist/daemon/connection.d.ts +7 -1
  103. package/dist/daemon/connection.js +15 -0
  104. package/dist/daemon/orchestrator.d.ts +2 -0
  105. package/dist/daemon/orchestrator.js +26 -0
  106. package/dist/daemon/repo-manager.d.ts +116 -0
  107. package/dist/daemon/repo-manager.js +384 -0
  108. package/dist/daemon/router.d.ts +60 -1
  109. package/dist/daemon/router.js +281 -20
  110. package/dist/daemon/user-directory.d.ts +111 -0
  111. package/dist/daemon/user-directory.js +233 -0
  112. package/dist/dashboard/out/404.html +1 -1
  113. package/dist/dashboard/out/_next/static/T1tgCqVWHFIkV7ClEtzD7/_ssgManifest.js +1 -0
  114. package/dist/dashboard/out/_next/static/chunks/532-bace199897eeab37.js +9 -0
  115. package/dist/dashboard/out/_next/static/chunks/766-b54f0853794b78c3.js +1 -0
  116. package/dist/dashboard/out/_next/static/chunks/83-b51836037078006c.js +1 -0
  117. package/dist/dashboard/out/_next/static/chunks/891-6cd50de1224f70bb.js +1 -0
  118. package/dist/dashboard/out/_next/static/chunks/899-bb19a9b3d9b39ea6.js +1 -0
  119. package/dist/dashboard/out/_next/static/chunks/app/app/onboarding/page-8939b0fc700f7eca.js +1 -0
  120. package/dist/dashboard/out/_next/static/chunks/app/app/page-5af1b6b439858aa6.js +1 -0
  121. package/dist/dashboard/out/_next/static/chunks/app/connect-repos/page-f45ecbc3e06134fc.js +1 -0
  122. package/dist/dashboard/out/_next/static/chunks/app/history/{page-abb9ab2d329f56e9.js → page-8c8bed33beb2bf1c.js} +1 -1
  123. package/dist/dashboard/out/_next/static/chunks/app/layout-2433bb48965f4333.js +1 -0
  124. package/dist/dashboard/out/_next/static/chunks/app/login/{page-c22d080201cbd9fb.js → page-16f3b49e55b1e0ed.js} +1 -1
  125. package/dist/dashboard/out/_next/static/chunks/app/metrics/page-ac39dc0cc3c26fa7.js +1 -0
  126. package/dist/dashboard/out/_next/static/chunks/app/{page-77e9c65420a06cfb.js → page-4a5938c18a11a654.js} +1 -1
  127. package/dist/dashboard/out/_next/static/chunks/app/pricing/page-982a7000fee44014.js +1 -0
  128. package/dist/dashboard/out/_next/static/chunks/app/providers/page-ac3a6ac433fd6001.js +1 -0
  129. package/dist/dashboard/out/_next/static/chunks/app/providers/setup/[provider]/page-09f9caae98a18c09.js +1 -0
  130. package/dist/dashboard/out/_next/static/chunks/app/signup/{page-68d34f50baa8ab6b.js → page-547dd0ca55ecd0ba.js} +1 -1
  131. package/dist/dashboard/out/_next/static/chunks/{main-ed4e1fb6f29c34cf.js → main-2ee6beb2ae96d210.js} +1 -1
  132. package/dist/dashboard/out/_next/static/chunks/{main-app-6e8e8d3ef4e0192a.js → main-app-5d692157a8eb1fd9.js} +1 -1
  133. package/dist/dashboard/out/_next/static/css/85d2af9c7ac74d62.css +1 -0
  134. package/dist/dashboard/out/_next/static/css/fe4b28883eeff359.css +1 -0
  135. package/dist/dashboard/out/app/onboarding.html +1 -1
  136. package/dist/dashboard/out/app/onboarding.txt +3 -3
  137. package/dist/dashboard/out/app.html +1 -1
  138. package/dist/dashboard/out/app.txt +3 -3
  139. package/dist/dashboard/out/apple-icon.png +0 -0
  140. package/dist/dashboard/out/connect-repos.html +1 -1
  141. package/dist/dashboard/out/connect-repos.txt +3 -3
  142. package/dist/dashboard/out/history.html +1 -1
  143. package/dist/dashboard/out/history.txt +3 -3
  144. package/dist/dashboard/out/index.html +1 -1
  145. package/dist/dashboard/out/index.txt +3 -3
  146. package/dist/dashboard/out/login.html +2 -2
  147. package/dist/dashboard/out/login.txt +3 -3
  148. package/dist/dashboard/out/metrics.html +1 -1
  149. package/dist/dashboard/out/metrics.txt +3 -3
  150. package/dist/dashboard/out/pricing.html +2 -2
  151. package/dist/dashboard/out/pricing.txt +3 -3
  152. package/dist/dashboard/out/providers/setup/claude.html +1 -0
  153. package/dist/dashboard/out/providers/setup/claude.txt +8 -0
  154. package/dist/dashboard/out/providers/setup/codex.html +1 -0
  155. package/dist/dashboard/out/providers/setup/codex.txt +8 -0
  156. package/dist/dashboard/out/providers.html +1 -1
  157. package/dist/dashboard/out/providers.txt +3 -3
  158. package/dist/dashboard/out/signup.html +2 -2
  159. package/dist/dashboard/out/signup.txt +3 -3
  160. package/dist/dashboard-server/server.js +316 -12
  161. package/dist/dashboard-server/user-bridge.d.ts +103 -0
  162. package/dist/dashboard-server/user-bridge.js +189 -0
  163. package/dist/protocol/channels.d.ts +205 -0
  164. package/dist/protocol/channels.js +154 -0
  165. package/dist/protocol/types.d.ts +13 -1
  166. package/dist/resiliency/provider-context.js +2 -0
  167. package/dist/shared/cli-auth-config.d.ts +19 -0
  168. package/dist/shared/cli-auth-config.js +58 -2
  169. package/dist/utils/agent-config.js +1 -1
  170. package/dist/wrapper/auth-detection.d.ts +49 -0
  171. package/dist/wrapper/auth-detection.js +192 -0
  172. package/dist/wrapper/base-wrapper.d.ts +153 -0
  173. package/dist/wrapper/base-wrapper.js +393 -0
  174. package/dist/wrapper/client.d.ts +7 -1
  175. package/dist/wrapper/client.js +3 -0
  176. package/dist/wrapper/index.d.ts +1 -0
  177. package/dist/wrapper/index.js +4 -3
  178. package/dist/wrapper/pty-wrapper.d.ts +62 -84
  179. package/dist/wrapper/pty-wrapper.js +154 -180
  180. package/dist/wrapper/tmux-wrapper.d.ts +41 -66
  181. package/dist/wrapper/tmux-wrapper.js +90 -134
  182. package/package.json +4 -2
  183. package/scripts/postinstall.js +11 -155
  184. package/scripts/test-interactive-terminal.sh +248 -0
  185. package/dist/cloud/vault/index.d.ts +0 -76
  186. package/dist/cloud/vault/index.js +0 -219
  187. package/dist/dashboard/out/_next/static/chunks/699-3b1cd6618a45d259.js +0 -1
  188. package/dist/dashboard/out/_next/static/chunks/724-2dae7627550ab88f.js +0 -9
  189. package/dist/dashboard/out/_next/static/chunks/766-1f2dd8cb7f766b0b.js +0 -1
  190. package/dist/dashboard/out/_next/static/chunks/app/app/onboarding/page-3fdfa60e53f2810d.js +0 -1
  191. package/dist/dashboard/out/_next/static/chunks/app/app/page-e6381e5a6e1fbcfd.js +0 -1
  192. package/dist/dashboard/out/_next/static/chunks/app/connect-repos/page-3538dfe0ffe984b8.js +0 -1
  193. package/dist/dashboard/out/_next/static/chunks/app/layout-c0d118c0f92d969c.js +0 -1
  194. package/dist/dashboard/out/_next/static/chunks/app/metrics/page-67a3e98d9a43a6ed.js +0 -1
  195. package/dist/dashboard/out/_next/static/chunks/app/pricing/page-b08ed1c34d14434a.js +0 -1
  196. package/dist/dashboard/out/_next/static/chunks/app/providers/page-e88bc117ef7671c3.js +0 -1
  197. package/dist/dashboard/out/_next/static/css/29852f26181969a0.css +0 -1
  198. package/dist/dashboard/out/_next/static/css/7c3ae9e8617d42a5.css +0 -1
  199. package/dist/dashboard/out/_next/static/wPgKJtcOmTFLpUncDg16A/_ssgManifest.js +0 -1
  200. /package/dist/dashboard/out/_next/static/{wPgKJtcOmTFLpUncDg16A → T1tgCqVWHFIkV7ClEtzD7}/_buildManifest.js +0 -0
@@ -0,0 +1,186 @@
1
+ {
2
+ "id": "traj_uc29tlso8i9s",
3
+ "version": 1,
4
+ "task": {
5
+ "title": "Production-ready SSH tunneling for Codex OAuth with security hardening"
6
+ },
7
+ "status": "completed",
8
+ "startedAt": "2026-01-07T10:08:04.299Z",
9
+ "agents": [
10
+ {
11
+ "name": "khaliqgant",
12
+ "role": "lead",
13
+ "joinedAt": "2026-01-07T10:08:04.300Z"
14
+ },
15
+ {
16
+ "name": "default",
17
+ "role": "contributor",
18
+ "joinedAt": "2026-01-07T10:08:04.710Z"
19
+ }
20
+ ],
21
+ "chapters": [
22
+ {
23
+ "id": "chap_8omowh9k21wa",
24
+ "title": "Work",
25
+ "agentName": "default",
26
+ "startedAt": "2026-01-07T10:08:04.710Z",
27
+ "events": [
28
+ {
29
+ "ts": 1767780484710,
30
+ "type": "decision",
31
+ "content": "Changed UsageBanner intro bonus from purple to cyan: Changed UsageBanner intro bonus from purple to cyan",
32
+ "raw": {
33
+ "question": "Changed UsageBanner intro bonus from purple to cyan",
34
+ "chosen": "Changed UsageBanner intro bonus from purple to cyan",
35
+ "alternatives": [],
36
+ "reasoning": "Brand consistency - cyan is primary accent color, purple was off-brand"
37
+ },
38
+ "significance": "high"
39
+ },
40
+ {
41
+ "ts": 1767780493469,
42
+ "type": "decision",
43
+ "content": "Added landing page auth check - shows Go to App when logged in: Added landing page auth check - shows Go to App when logged in",
44
+ "raw": {
45
+ "question": "Added landing page auth check - shows Go to App when logged in",
46
+ "chosen": "Added landing page auth check - shows Go to App when logged in",
47
+ "alternatives": [],
48
+ "reasoning": "Better UX for returning users who shouldn't see Sign In buttons"
49
+ },
50
+ "significance": "high"
51
+ },
52
+ {
53
+ "ts": 1767780494224,
54
+ "type": "decision",
55
+ "content": "Expose SSH port 2222 publicly on Fly.io via TCP service: Expose SSH port 2222 publicly on Fly.io via TCP service",
56
+ "raw": {
57
+ "question": "Expose SSH port 2222 publicly on Fly.io via TCP service",
58
+ "chosen": "Expose SSH port 2222 publicly on Fly.io via TCP service",
59
+ "alternatives": [],
60
+ "reasoning": "Internal .internal hostnames aren't routable from user machines. Public SSH with unique passwords per workspace is secure enough for production."
61
+ },
62
+ "significance": "high"
63
+ },
64
+ {
65
+ "ts": 1767780500783,
66
+ "type": "decision",
67
+ "content": "Updated CTA terminal to show realistic CLI flow (cloud link + send): Updated CTA terminal to show realistic CLI flow (cloud link + send)",
68
+ "raw": {
69
+ "question": "Updated CTA terminal to show realistic CLI flow (cloud link + send)",
70
+ "chosen": "Updated CTA terminal to show realistic CLI flow (cloud link + send)",
71
+ "alternatives": [],
72
+ "reasoning": "Previous mock commands were inaccurate. Now shows actual agent-relay cloud commands"
73
+ },
74
+ "significance": "high"
75
+ },
76
+ {
77
+ "ts": 1767780501007,
78
+ "type": "decision",
79
+ "content": "Use deterministic password derivation instead of storage: Use deterministic password derivation instead of storage",
80
+ "raw": {
81
+ "question": "Use deterministic password derivation instead of storage",
82
+ "chosen": "Use deterministic password derivation instead of storage",
83
+ "alternatives": [],
84
+ "reasoning": "SHA-256(workspaceId + salt) produces unique passwords without database storage. Both cloud server and container can derive the same password independently. 96 bits of entropy is sufficient."
85
+ },
86
+ "significance": "high"
87
+ },
88
+ {
89
+ "ts": 1767780508469,
90
+ "type": "decision",
91
+ "content": "Create shared ssh-security.ts utility: Create shared ssh-security.ts utility",
92
+ "raw": {
93
+ "question": "Create shared ssh-security.ts utility",
94
+ "chosen": "Create shared ssh-security.ts utility",
95
+ "alternatives": [],
96
+ "reasoning": "Password derivation was duplicated in provisioner and codex-auth-helper. Single source of truth prevents bugs if algorithm changes. Also adds startup validation."
97
+ },
98
+ "significance": "high"
99
+ },
100
+ {
101
+ "ts": 1767780510961,
102
+ "type": "decision",
103
+ "content": "Fixed TypeScript error: Promise<never> to Promise<void>: Fixed TypeScript error: Promise<never> to Promise<void>",
104
+ "raw": {
105
+ "question": "Fixed TypeScript error: Promise<never> to Promise<void>",
106
+ "chosen": "Fixed TypeScript error: Promise<never> to Promise<void>",
107
+ "alternatives": [],
108
+ "reasoning": "Promise<never> caused control flow analysis to mark subsequent code as unreachable"
109
+ },
110
+ "significance": "high"
111
+ },
112
+ {
113
+ "ts": 1767780517965,
114
+ "type": "decision",
115
+ "content": "Keep password-based SSH for now, defer key-based auth: Keep password-based SSH for now, defer key-based auth",
116
+ "raw": {
117
+ "question": "Keep password-based SSH for now, defer key-based auth",
118
+ "chosen": "Keep password-based SSH for now, defer key-based auth",
119
+ "alternatives": [],
120
+ "reasoning": "Password-based is simpler to implement and per-workspace unique passwords provide reasonable security. Key-based auth would require container-side authorized_keys management - tracked as future improvement in agent-relay-476."
121
+ },
122
+ "significance": "high"
123
+ },
124
+ {
125
+ "ts": 1767780523070,
126
+ "type": "decision",
127
+ "content": "Settings page: replaced sidebar with always-visible horizontal tabs: Settings page: replaced sidebar with always-visible horizontal tabs",
128
+ "raw": {
129
+ "question": "Settings page: replaced sidebar with always-visible horizontal tabs",
130
+ "chosen": "Settings page: replaced sidebar with always-visible horizontal tabs",
131
+ "alternatives": [],
132
+ "reasoning": "Desktop sidebar wasn't rendering for user. Horizontal tabs provide consistent navigation on all screen sizes"
133
+ },
134
+ "significance": "high"
135
+ },
136
+ {
137
+ "ts": 1767780530293,
138
+ "type": "decision",
139
+ "content": "Billing API: respect database user.plan when no Stripe subscription: Billing API: respect database user.plan when no Stripe subscription",
140
+ "raw": {
141
+ "question": "Billing API: respect database user.plan when no Stripe subscription",
142
+ "chosen": "Billing API: respect database user.plan when no Stripe subscription",
143
+ "alternatives": [],
144
+ "reasoning": "Allows manual plan overrides in database to take effect without Stripe subscription"
145
+ },
146
+ "significance": "high"
147
+ },
148
+ {
149
+ "ts": 1767780538628,
150
+ "type": "decision",
151
+ "content": "Billing panel: dynamic tier descriptions and smart plan recommendations: Billing panel: dynamic tier descriptions and smart plan recommendations",
152
+ "raw": {
153
+ "question": "Billing panel: dynamic tier descriptions and smart plan recommendations",
154
+ "chosen": "Billing panel: dynamic tier descriptions and smart plan recommendations",
155
+ "alternatives": [],
156
+ "reasoning": "Fixed hardcoded Free tier text. Only highlight upgrades, not downgrades (no Pro promotion to Team users)"
157
+ },
158
+ "significance": "high"
159
+ },
160
+ {
161
+ "ts": 1767780548294,
162
+ "type": "decision",
163
+ "content": "Aligned workspace Codex auth with /app onboarding: Aligned workspace Codex auth with /app onboarding",
164
+ "raw": {
165
+ "question": "Aligned workspace Codex auth with /app onboarding",
166
+ "chosen": "Aligned workspace Codex auth with /app onboarding",
167
+ "alternatives": [],
168
+ "reasoning": "Added supportsDeviceFlow prop to ProviderAuthFlow to match /app page props"
169
+ },
170
+ "significance": "high"
171
+ }
172
+ ],
173
+ "endedAt": "2026-01-07T10:09:10.870Z"
174
+ }
175
+ ],
176
+ "commits": [],
177
+ "filesChanged": [],
178
+ "projectId": "/Users/khaliqgant/Projects/agent-workforce/relay",
179
+ "tags": [],
180
+ "completedAt": "2026-01-07T10:09:10.870Z",
181
+ "retrospective": {
182
+ "summary": "Implemented production-ready SSH tunneling for Codex OAuth. Key changes: (1) Exposed SSH port 2222 publicly on Fly.io via TCP service, (2) Changed from .internal to .fly.dev hostname for public routing, (3) Created shared ssh-security.ts with deterministic password derivation (SHA-256 of workspaceId + salt), (4) Added startup validation for SSH_PASSWORD_SALT env var, (5) Created beads for future improvements: rate limiting, key-based auth, time-limited access.",
183
+ "approach": "Standard approach",
184
+ "confidence": 0.85
185
+ }
186
+ }
@@ -0,0 +1,86 @@
1
+ # Trajectory: Production-ready SSH tunneling for Codex OAuth with security hardening
2
+
3
+ > **Status:** ✅ Completed
4
+ > **Confidence:** 85%
5
+ > **Started:** January 7, 2026 at 11:08 AM
6
+ > **Completed:** January 7, 2026 at 11:09 AM
7
+
8
+ ---
9
+
10
+ ## Summary
11
+
12
+ Implemented production-ready SSH tunneling for Codex OAuth. Key changes: (1) Exposed SSH port 2222 publicly on Fly.io via TCP service, (2) Changed from .internal to .fly.dev hostname for public routing, (3) Created shared ssh-security.ts with deterministic password derivation (SHA-256 of workspaceId + salt), (4) Added startup validation for SSH_PASSWORD_SALT env var, (5) Created beads for future improvements: rate limiting, key-based auth, time-limited access.
13
+
14
+ **Approach:** Standard approach
15
+
16
+ ---
17
+
18
+ ## Key Decisions
19
+
20
+ ### Changed UsageBanner intro bonus from purple to cyan
21
+ - **Chose:** Changed UsageBanner intro bonus from purple to cyan
22
+ - **Reasoning:** Brand consistency - cyan is primary accent color, purple was off-brand
23
+
24
+ ### Added landing page auth check - shows Go to App when logged in
25
+ - **Chose:** Added landing page auth check - shows Go to App when logged in
26
+ - **Reasoning:** Better UX for returning users who shouldn't see Sign In buttons
27
+
28
+ ### Expose SSH port 2222 publicly on Fly.io via TCP service
29
+ - **Chose:** Expose SSH port 2222 publicly on Fly.io via TCP service
30
+ - **Reasoning:** Internal .internal hostnames aren't routable from user machines. Public SSH with unique passwords per workspace is secure enough for production.
31
+
32
+ ### Updated CTA terminal to show realistic CLI flow (cloud link + send)
33
+ - **Chose:** Updated CTA terminal to show realistic CLI flow (cloud link + send)
34
+ - **Reasoning:** Previous mock commands were inaccurate. Now shows actual agent-relay cloud commands
35
+
36
+ ### Use deterministic password derivation instead of storage
37
+ - **Chose:** Use deterministic password derivation instead of storage
38
+ - **Reasoning:** SHA-256(workspaceId + salt) produces unique passwords without database storage. Both cloud server and container can derive the same password independently. 96 bits of entropy is sufficient.
39
+
40
+ ### Create shared ssh-security.ts utility
41
+ - **Chose:** Create shared ssh-security.ts utility
42
+ - **Reasoning:** Password derivation was duplicated in provisioner and codex-auth-helper. Single source of truth prevents bugs if algorithm changes. Also adds startup validation.
43
+
44
+ ### Fixed TypeScript error: Promise<never> to Promise<void>
45
+ - **Chose:** Fixed TypeScript error: Promise<never> to Promise<void>
46
+ - **Reasoning:** Promise<never> caused control flow analysis to mark subsequent code as unreachable
47
+
48
+ ### Keep password-based SSH for now, defer key-based auth
49
+ - **Chose:** Keep password-based SSH for now, defer key-based auth
50
+ - **Reasoning:** Password-based is simpler to implement and per-workspace unique passwords provide reasonable security. Key-based auth would require container-side authorized_keys management - tracked as future improvement in agent-relay-476.
51
+
52
+ ### Settings page: replaced sidebar with always-visible horizontal tabs
53
+ - **Chose:** Settings page: replaced sidebar with always-visible horizontal tabs
54
+ - **Reasoning:** Desktop sidebar wasn't rendering for user. Horizontal tabs provide consistent navigation on all screen sizes
55
+
56
+ ### Billing API: respect database user.plan when no Stripe subscription
57
+ - **Chose:** Billing API: respect database user.plan when no Stripe subscription
58
+ - **Reasoning:** Allows manual plan overrides in database to take effect without Stripe subscription
59
+
60
+ ### Billing panel: dynamic tier descriptions and smart plan recommendations
61
+ - **Chose:** Billing panel: dynamic tier descriptions and smart plan recommendations
62
+ - **Reasoning:** Fixed hardcoded Free tier text. Only highlight upgrades, not downgrades (no Pro promotion to Team users)
63
+
64
+ ### Aligned workspace Codex auth with /app onboarding
65
+ - **Chose:** Aligned workspace Codex auth with /app onboarding
66
+ - **Reasoning:** Added supportsDeviceFlow prop to ProviderAuthFlow to match /app page props
67
+
68
+ ---
69
+
70
+ ## Chapters
71
+
72
+ ### 1. Work
73
+ *Agent: default*
74
+
75
+ - Changed UsageBanner intro bonus from purple to cyan: Changed UsageBanner intro bonus from purple to cyan
76
+ - Added landing page auth check - shows Go to App when logged in: Added landing page auth check - shows Go to App when logged in
77
+ - Expose SSH port 2222 publicly on Fly.io via TCP service: Expose SSH port 2222 publicly on Fly.io via TCP service
78
+ - Updated CTA terminal to show realistic CLI flow (cloud link + send): Updated CTA terminal to show realistic CLI flow (cloud link + send)
79
+ - Use deterministic password derivation instead of storage: Use deterministic password derivation instead of storage
80
+ - Create shared ssh-security.ts utility: Create shared ssh-security.ts utility
81
+ - Fixed TypeScript error: Promise<never> to Promise<void>: Fixed TypeScript error: Promise<never> to Promise<void>
82
+ - Keep password-based SSH for now, defer key-based auth: Keep password-based SSH for now, defer key-based auth
83
+ - Settings page: replaced sidebar with always-visible horizontal tabs: Settings page: replaced sidebar with always-visible horizontal tabs
84
+ - Billing API: respect database user.plan when no Stripe subscription: Billing API: respect database user.plan when no Stripe subscription
85
+ - Billing panel: dynamic tier descriptions and smart plan recommendations: Billing panel: dynamic tier descriptions and smart plan recommendations
86
+ - Aligned workspace Codex auth with /app onboarding: Aligned workspace Codex auth with /app onboarding
@@ -0,0 +1,77 @@
1
+ {
2
+ "id": "traj_ui9b4tqxoa7j",
3
+ "version": 1,
4
+ "task": {
5
+ "title": "Fix agent token fetch with improved error handling",
6
+ "source": {
7
+ "system": "plain",
8
+ "id": "fix-agent-token-fetch-sW7v5"
9
+ }
10
+ },
11
+ "status": "completed",
12
+ "startedAt": "2026-01-06T08:24:36.222Z",
13
+ "agents": [
14
+ {
15
+ "name": "default",
16
+ "role": "lead",
17
+ "joinedAt": "2026-01-06T08:24:48.653Z"
18
+ }
19
+ ],
20
+ "chapters": [
21
+ {
22
+ "id": "chap_8510b2gli7tq",
23
+ "title": "Work",
24
+ "agentName": "default",
25
+ "startedAt": "2026-01-06T08:24:48.653Z",
26
+ "events": [
27
+ {
28
+ "ts": 1767687888655,
29
+ "type": "decision",
30
+ "content": "Enhanced verifyWorkspaceToken to return detailed failure reasons: Enhanced verifyWorkspaceToken to return detailed failure reasons",
31
+ "raw": {
32
+ "question": "Enhanced verifyWorkspaceToken to return detailed failure reasons",
33
+ "chosen": "Enhanced verifyWorkspaceToken to return detailed failure reasons",
34
+ "alternatives": [],
35
+ "reasoning": "Helps diagnose whether issue is missing token, wrong format, or mismatch"
36
+ },
37
+ "significance": "high"
38
+ },
39
+ {
40
+ "ts": 1767687904489,
41
+ "type": "decision",
42
+ "content": "Added error codes and actionable hints to all error responses: Added error codes and actionable hints to all error responses",
43
+ "raw": {
44
+ "question": "Added error codes and actionable hints to all error responses",
45
+ "chosen": "Added error codes and actionable hints to all error responses",
46
+ "alternatives": [],
47
+ "reasoning": "Enables git-credential-relay to show specific guidance to users"
48
+ },
49
+ "significance": "high"
50
+ },
51
+ {
52
+ "ts": 1767687910382,
53
+ "type": "decision",
54
+ "content": "Wrapped Nango token fetch in try-catch with specific error handling: Wrapped Nango token fetch in try-catch with specific error handling",
55
+ "raw": {
56
+ "question": "Wrapped Nango token fetch in try-catch with specific error handling",
57
+ "chosen": "Wrapped Nango token fetch in try-catch with specific error handling",
58
+ "alternatives": [],
59
+ "reasoning": "Distinguishes between expired connections and temporary failures"
60
+ },
61
+ "significance": "high"
62
+ }
63
+ ],
64
+ "endedAt": "2026-01-06T08:25:20.777Z"
65
+ }
66
+ ],
67
+ "commits": [],
68
+ "filesChanged": [],
69
+ "projectId": "/home/user/relay",
70
+ "tags": [],
71
+ "completedAt": "2026-01-06T08:25:20.777Z",
72
+ "retrospective": {
73
+ "summary": "Added comprehensive error handling and diagnostics to git token API and credential helper",
74
+ "approach": "Standard approach",
75
+ "confidence": 0.85
76
+ }
77
+ }
@@ -0,0 +1,42 @@
1
+ # Trajectory: Fix agent token fetch with improved error handling
2
+
3
+ > **Status:** ✅ Completed
4
+ > **Task:** fix-agent-token-fetch-sW7v5
5
+ > **Confidence:** 85%
6
+ > **Started:** January 6, 2026 at 08:24 AM
7
+ > **Completed:** January 6, 2026 at 08:25 AM
8
+
9
+ ---
10
+
11
+ ## Summary
12
+
13
+ Added comprehensive error handling and diagnostics to git token API and credential helper
14
+
15
+ **Approach:** Standard approach
16
+
17
+ ---
18
+
19
+ ## Key Decisions
20
+
21
+ ### Enhanced verifyWorkspaceToken to return detailed failure reasons
22
+ - **Chose:** Enhanced verifyWorkspaceToken to return detailed failure reasons
23
+ - **Reasoning:** Helps diagnose whether issue is missing token, wrong format, or mismatch
24
+
25
+ ### Added error codes and actionable hints to all error responses
26
+ - **Chose:** Added error codes and actionable hints to all error responses
27
+ - **Reasoning:** Enables git-credential-relay to show specific guidance to users
28
+
29
+ ### Wrapped Nango token fetch in try-catch with specific error handling
30
+ - **Chose:** Wrapped Nango token fetch in try-catch with specific error handling
31
+ - **Reasoning:** Distinguishes between expired connections and temporary failures
32
+
33
+ ---
34
+
35
+ ## Chapters
36
+
37
+ ### 1. Work
38
+ *Agent: default*
39
+
40
+ - Enhanced verifyWorkspaceToken to return detailed failure reasons: Enhanced verifyWorkspaceToken to return detailed failure reasons
41
+ - Added error codes and actionable hints to all error responses: Added error codes and actionable hints to all error responses
42
+ - Wrapped Nango token fetch in try-catch with specific error handling: Wrapped Nango token fetch in try-catch with specific error handling
@@ -0,0 +1,89 @@
1
+ {
2
+ "id": "traj_v9dkdoxylyid",
3
+ "version": 1,
4
+ "task": {
5
+ "title": "Implement first-class user messaging with channels and DMs",
6
+ "source": {
7
+ "system": "plain",
8
+ "id": "user-messaging-feature"
9
+ }
10
+ },
11
+ "status": "completed",
12
+ "startedAt": "2026-01-06T17:11:57.504Z",
13
+ "agents": [
14
+ {
15
+ "name": "default",
16
+ "role": "lead",
17
+ "joinedAt": "2026-01-06T17:12:09.617Z"
18
+ }
19
+ ],
20
+ "chapters": [
21
+ {
22
+ "id": "chap_u095g4higo8q",
23
+ "title": "Work",
24
+ "agentName": "default",
25
+ "startedAt": "2026-01-06T17:12:09.617Z",
26
+ "events": [
27
+ {
28
+ "ts": 1767719529619,
29
+ "type": "decision",
30
+ "content": "Chose unified relay daemon approach over WebSocket-only: Chose unified relay daemon approach over WebSocket-only",
31
+ "raw": {
32
+ "question": "Chose unified relay daemon approach over WebSocket-only",
33
+ "chosen": "Chose unified relay daemon approach over WebSocket-only",
34
+ "alternatives": [],
35
+ "reasoning": "Enables consistent message routing for both users and agents, supports future features like message persistence and cross-project messaging"
36
+ },
37
+ "significance": "high"
38
+ },
39
+ {
40
+ "ts": 1767719541811,
41
+ "type": "decision",
42
+ "content": "Added EntityType to protocol: Added EntityType to protocol",
43
+ "raw": {
44
+ "question": "Added EntityType to protocol",
45
+ "chosen": "Added EntityType to protocol",
46
+ "alternatives": [],
47
+ "reasoning": "Distinguishes 'user' (human) from 'agent' (AI) entities for proper routing and UI display"
48
+ },
49
+ "significance": "high"
50
+ },
51
+ {
52
+ "ts": 1767719549146,
53
+ "type": "decision",
54
+ "content": "DM channels use 'dm:alice:bob' naming convention with sorted names: DM channels use 'dm:alice:bob' naming convention with sorted names",
55
+ "raw": {
56
+ "question": "DM channels use 'dm:alice:bob' naming convention with sorted names",
57
+ "chosen": "DM channels use 'dm:alice:bob' naming convention with sorted names",
58
+ "alternatives": [],
59
+ "reasoning": "Ensures consistent channel naming regardless of who initiates the DM"
60
+ },
61
+ "significance": "high"
62
+ },
63
+ {
64
+ "ts": 1767719563124,
65
+ "type": "decision",
66
+ "content": "Created UserBridge to bridge WebSocket users to relay daemon: Created UserBridge to bridge WebSocket users to relay daemon",
67
+ "raw": {
68
+ "question": "Created UserBridge to bridge WebSocket users to relay daemon",
69
+ "chosen": "Created UserBridge to bridge WebSocket users to relay daemon",
70
+ "alternatives": [],
71
+ "reasoning": "Clean separation of concerns - dashboard server handles WebSocket, UserBridge creates relay client per user for unified messaging"
72
+ },
73
+ "significance": "high"
74
+ }
75
+ ],
76
+ "endedAt": "2026-01-06T17:12:56.919Z"
77
+ }
78
+ ],
79
+ "commits": [],
80
+ "filesChanged": [],
81
+ "projectId": "/home/user/relay",
82
+ "tags": [],
83
+ "completedAt": "2026-01-06T17:12:56.919Z",
84
+ "retrospective": {
85
+ "summary": "Implemented first-class user messaging: EntityType protocol extension, channel join/leave/message routing in daemon, UserBridge for dashboard-relay integration, REST API endpoints, and React components (useChannels hook, ChannelSidebar, ChannelChat). All 1030 tests passing.",
86
+ "approach": "Standard approach",
87
+ "confidence": 0.85
88
+ }
89
+ }
@@ -0,0 +1,47 @@
1
+ # Trajectory: Implement first-class user messaging with channels and DMs
2
+
3
+ > **Status:** ✅ Completed
4
+ > **Task:** user-messaging-feature
5
+ > **Confidence:** 85%
6
+ > **Started:** January 6, 2026 at 05:11 PM
7
+ > **Completed:** January 6, 2026 at 05:12 PM
8
+
9
+ ---
10
+
11
+ ## Summary
12
+
13
+ Implemented first-class user messaging: EntityType protocol extension, channel join/leave/message routing in daemon, UserBridge for dashboard-relay integration, REST API endpoints, and React components (useChannels hook, ChannelSidebar, ChannelChat). All 1030 tests passing.
14
+
15
+ **Approach:** Standard approach
16
+
17
+ ---
18
+
19
+ ## Key Decisions
20
+
21
+ ### Chose unified relay daemon approach over WebSocket-only
22
+ - **Chose:** Chose unified relay daemon approach over WebSocket-only
23
+ - **Reasoning:** Enables consistent message routing for both users and agents, supports future features like message persistence and cross-project messaging
24
+
25
+ ### Added EntityType to protocol
26
+ - **Chose:** Added EntityType to protocol
27
+ - **Reasoning:** Distinguishes 'user' (human) from 'agent' (AI) entities for proper routing and UI display
28
+
29
+ ### DM channels use 'dm:alice:bob' naming convention with sorted names
30
+ - **Chose:** DM channels use 'dm:alice:bob' naming convention with sorted names
31
+ - **Reasoning:** Ensures consistent channel naming regardless of who initiates the DM
32
+
33
+ ### Created UserBridge to bridge WebSocket users to relay daemon
34
+ - **Chose:** Created UserBridge to bridge WebSocket users to relay daemon
35
+ - **Reasoning:** Clean separation of concerns - dashboard server handles WebSocket, UserBridge creates relay client per user for unified messaging
36
+
37
+ ---
38
+
39
+ ## Chapters
40
+
41
+ ### 1. Work
42
+ *Agent: default*
43
+
44
+ - Chose unified relay daemon approach over WebSocket-only: Chose unified relay daemon approach over WebSocket-only
45
+ - Added EntityType to protocol: Added EntityType to protocol
46
+ - DM channels use 'dm:alice:bob' naming convention with sorted names: DM channels use 'dm:alice:bob' naming convention with sorted names
47
+ - Created UserBridge to bridge WebSocket users to relay daemon: Created UserBridge to bridge WebSocket users to relay daemon
@@ -0,0 +1,65 @@
1
+ {
2
+ "id": "traj_xy9vifpqet80",
3
+ "version": 1,
4
+ "task": {
5
+ "title": "Extract BaseWrapper from PtyWrapper and TmuxWrapper",
6
+ "source": {
7
+ "system": "plain",
8
+ "id": "agent-relay-wrap1"
9
+ }
10
+ },
11
+ "status": "completed",
12
+ "startedAt": "2026-01-06T12:27:13.004Z",
13
+ "agents": [
14
+ {
15
+ "name": "khaliqgant",
16
+ "role": "lead",
17
+ "joinedAt": "2026-01-06T12:27:13.007Z"
18
+ }
19
+ ],
20
+ "chapters": [
21
+ {
22
+ "id": "chap_8t7vbaqwiz3f",
23
+ "title": "Work",
24
+ "agentName": "default",
25
+ "startedAt": "2026-01-06T12:27:45.698Z",
26
+ "events": [
27
+ {
28
+ "ts": 1767702465699,
29
+ "type": "decision",
30
+ "content": "Using abstract class with protected methods for shared implementation: Using abstract class with protected methods for shared implementation",
31
+ "raw": {
32
+ "question": "Using abstract class with protected methods for shared implementation",
33
+ "chosen": "Using abstract class with protected methods for shared implementation",
34
+ "alternatives": [],
35
+ "reasoning": "Allows subclasses to override while providing default behavior"
36
+ },
37
+ "significance": "high"
38
+ },
39
+ {
40
+ "ts": 1767703025592,
41
+ "type": "decision",
42
+ "content": "Created BaseWrapper abstract class with comprehensive tests: Created BaseWrapper abstract class with comprehensive tests",
43
+ "raw": {
44
+ "question": "Created BaseWrapper abstract class with comprehensive tests",
45
+ "chosen": "Created BaseWrapper abstract class with comprehensive tests",
46
+ "alternatives": [],
47
+ "reasoning": "Extracted shared functionality from PtyWrapper/TmuxWrapper into base class. Tests cover message queue, spawn/release, continuity, and relay command handling."
48
+ },
49
+ "significance": "high"
50
+ }
51
+ ],
52
+ "endedAt": "2026-01-06T12:58:24.003Z"
53
+ }
54
+ ],
55
+ "commits": [],
56
+ "filesChanged": [],
57
+ "projectId": "/Users/khaliqgant/Projects/agent-workforce/relay",
58
+ "tags": [],
59
+ "completedAt": "2026-01-06T12:58:24.003Z",
60
+ "retrospective": {
61
+ "summary": "Extracted BaseWrapper abstract class from PtyWrapper and TmuxWrapper using TDD approach. Created 29 new tests, removed ~900 lines of duplicate code, both wrappers now inherit shared functionality.",
62
+ "approach": "Standard approach",
63
+ "confidence": 0.9
64
+ }
65
+ }
@@ -0,0 +1,37 @@
1
+ # Trajectory: Extract BaseWrapper from PtyWrapper and TmuxWrapper
2
+
3
+ > **Status:** ✅ Completed
4
+ > **Task:** agent-relay-wrap1
5
+ > **Confidence:** 90%
6
+ > **Started:** January 6, 2026 at 01:27 PM
7
+ > **Completed:** January 6, 2026 at 01:58 PM
8
+
9
+ ---
10
+
11
+ ## Summary
12
+
13
+ Extracted BaseWrapper abstract class from PtyWrapper and TmuxWrapper using TDD approach. Created 29 new tests, removed ~900 lines of duplicate code, both wrappers now inherit shared functionality.
14
+
15
+ **Approach:** Standard approach
16
+
17
+ ---
18
+
19
+ ## Key Decisions
20
+
21
+ ### Using abstract class with protected methods for shared implementation
22
+ - **Chose:** Using abstract class with protected methods for shared implementation
23
+ - **Reasoning:** Allows subclasses to override while providing default behavior
24
+
25
+ ### Created BaseWrapper abstract class with comprehensive tests
26
+ - **Chose:** Created BaseWrapper abstract class with comprehensive tests
27
+ - **Reasoning:** Extracted shared functionality from PtyWrapper/TmuxWrapper into base class. Tests cover message queue, spawn/release, continuity, and relay command handling.
28
+
29
+ ---
30
+
31
+ ## Chapters
32
+
33
+ ### 1. Work
34
+ *Agent: default*
35
+
36
+ - Using abstract class with protected methods for shared implementation: Using abstract class with protected methods for shared implementation
37
+ - Created BaseWrapper abstract class with comprehensive tests: Created BaseWrapper abstract class with comprehensive tests