@intentic/sandbox-contract 1.307.0 → 1.308.2

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 (260) hide show
  1. package/README.md +12 -0
  2. package/dist/contracts/accounts.contract.d.ts +6 -6
  3. package/dist/contracts/accounts.contract.js +7 -7
  4. package/dist/contracts/accounts.contract.js.map +1 -1
  5. package/dist/contracts/activity.contract.d.ts +2 -2
  6. package/dist/contracts/activity.contract.js +3 -3
  7. package/dist/contracts/activity.contract.js.map +1 -1
  8. package/dist/contracts/agent.contract.d.ts +10 -10
  9. package/dist/contracts/agent.contract.d.ts.map +1 -1
  10. package/dist/contracts/agent.contract.js +21 -11
  11. package/dist/contracts/agent.contract.js.map +1 -1
  12. package/dist/contracts/agents.contract.d.ts +41 -27
  13. package/dist/contracts/agents.contract.d.ts.map +1 -1
  14. package/dist/contracts/agents.contract.js +44 -28
  15. package/dist/contracts/agents.contract.js.map +1 -1
  16. package/dist/contracts/approvals.contract.d.ts +3 -3
  17. package/dist/contracts/approvals.contract.js +4 -4
  18. package/dist/contracts/approvals.contract.js.map +1 -1
  19. package/dist/contracts/areas.contract.d.ts +3 -3
  20. package/dist/contracts/areas.contract.d.ts.map +1 -1
  21. package/dist/contracts/areas.contract.js +5 -4
  22. package/dist/contracts/areas.contract.js.map +1 -1
  23. package/dist/contracts/automations.contract.d.ts +11 -11
  24. package/dist/contracts/automations.contract.js +12 -12
  25. package/dist/contracts/automations.contract.js.map +1 -1
  26. package/dist/contracts/capabilities.contract.d.ts +13 -13
  27. package/dist/contracts/capabilities.contract.d.ts.map +1 -1
  28. package/dist/contracts/capabilities.contract.js +18 -14
  29. package/dist/contracts/capabilities.contract.js.map +1 -1
  30. package/dist/contracts/chores.contract.d.ts +3 -3
  31. package/dist/contracts/chores.contract.js +4 -4
  32. package/dist/contracts/chores.contract.js.map +1 -1
  33. package/dist/contracts/ci.contract.d.ts +5 -5
  34. package/dist/contracts/ci.contract.js +6 -6
  35. package/dist/contracts/ci.contract.js.map +1 -1
  36. package/dist/contracts/diff.contract.d.ts +1 -1
  37. package/dist/contracts/diff.contract.js +2 -2
  38. package/dist/contracts/diff.contract.js.map +1 -1
  39. package/dist/contracts/endpoints.contract.d.ts +4 -4
  40. package/dist/contracts/endpoints.contract.js +5 -5
  41. package/dist/contracts/endpoints.contract.js.map +1 -1
  42. package/dist/contracts/exit.contract.d.ts +7 -7
  43. package/dist/contracts/exit.contract.d.ts.map +1 -1
  44. package/dist/contracts/exit.contract.js +9 -8
  45. package/dist/contracts/exit.contract.js.map +1 -1
  46. package/dist/contracts/extensions.contract.d.ts +17 -17
  47. package/dist/contracts/extensions.contract.js +18 -18
  48. package/dist/contracts/extensions.contract.js.map +1 -1
  49. package/dist/contracts/git.contract.d.ts +47 -45
  50. package/dist/contracts/git.contract.d.ts.map +1 -1
  51. package/dist/contracts/git.contract.js +46 -46
  52. package/dist/contracts/git.contract.js.map +1 -1
  53. package/dist/contracts/history.contract.d.ts +4 -4
  54. package/dist/contracts/history.contract.js +5 -5
  55. package/dist/contracts/history.contract.js.map +1 -1
  56. package/dist/contracts/intentic.contract.d.ts +3 -3
  57. package/dist/contracts/intentic.contract.d.ts.map +1 -1
  58. package/dist/contracts/intentic.contract.js +5 -4
  59. package/dist/contracts/intentic.contract.js.map +1 -1
  60. package/dist/contracts/inventory.contract.d.ts +3 -3
  61. package/dist/contracts/inventory.contract.js +4 -4
  62. package/dist/contracts/inventory.contract.js.map +1 -1
  63. package/dist/contracts/issues.contract.d.ts +5 -5
  64. package/dist/contracts/issues.contract.js +6 -6
  65. package/dist/contracts/issues.contract.js.map +1 -1
  66. package/dist/contracts/logs.contract.d.ts +3 -3
  67. package/dist/contracts/logs.contract.d.ts.map +1 -1
  68. package/dist/contracts/logs.contract.js +6 -4
  69. package/dist/contracts/logs.contract.js.map +1 -1
  70. package/dist/contracts/loops.contract.d.ts +6 -6
  71. package/dist/contracts/loops.contract.js +7 -7
  72. package/dist/contracts/loops.contract.js.map +1 -1
  73. package/dist/contracts/netdisk.contract.d.ts +3 -3
  74. package/dist/contracts/netdisk.contract.d.ts.map +1 -1
  75. package/dist/contracts/netdisk.contract.js +5 -4
  76. package/dist/contracts/netdisk.contract.js.map +1 -1
  77. package/dist/contracts/panels.contract.d.ts +3 -3
  78. package/dist/contracts/panels.contract.js +4 -4
  79. package/dist/contracts/panels.contract.js.map +1 -1
  80. package/dist/contracts/personas.contract.d.ts +8 -8
  81. package/dist/contracts/personas.contract.d.ts.map +1 -1
  82. package/dist/contracts/personas.contract.js +10 -9
  83. package/dist/contracts/personas.contract.js.map +1 -1
  84. package/dist/contracts/ports.contract.d.ts +3 -3
  85. package/dist/contracts/ports.contract.d.ts.map +1 -1
  86. package/dist/contracts/ports.contract.js +5 -4
  87. package/dist/contracts/ports.contract.js.map +1 -1
  88. package/dist/contracts/prepush.contract.d.ts +3 -3
  89. package/dist/contracts/prepush.contract.js +4 -4
  90. package/dist/contracts/prepush.contract.js.map +1 -1
  91. package/dist/contracts/providers.contract.d.ts +2 -2
  92. package/dist/contracts/providers.contract.d.ts.map +1 -1
  93. package/dist/contracts/providers.contract.js +5 -3
  94. package/dist/contracts/providers.contract.js.map +1 -1
  95. package/dist/contracts/public.contract.d.ts +3 -3
  96. package/dist/contracts/public.contract.js +4 -4
  97. package/dist/contracts/public.contract.js.map +1 -1
  98. package/dist/contracts/push.contract.d.ts +4 -4
  99. package/dist/contracts/push.contract.d.ts.map +1 -1
  100. package/dist/contracts/push.contract.js +9 -5
  101. package/dist/contracts/push.contract.js.map +1 -1
  102. package/dist/contracts/safety.contract.d.ts +3 -3
  103. package/dist/contracts/safety.contract.js +4 -4
  104. package/dist/contracts/safety.contract.js.map +1 -1
  105. package/dist/contracts/secrets.contract.d.ts +9 -9
  106. package/dist/contracts/secrets.contract.d.ts.map +1 -1
  107. package/dist/contracts/secrets.contract.js +13 -10
  108. package/dist/contracts/secrets.contract.js.map +1 -1
  109. package/dist/contracts/sessions.contract.d.ts +2 -2
  110. package/dist/contracts/sessions.contract.d.ts.map +1 -1
  111. package/dist/contracts/sessions.contract.js +5 -3
  112. package/dist/contracts/sessions.contract.js.map +1 -1
  113. package/dist/contracts/settings.contract.d.ts +11 -9
  114. package/dist/contracts/settings.contract.d.ts.map +1 -1
  115. package/dist/contracts/settings.contract.js +11 -10
  116. package/dist/contracts/settings.contract.js.map +1 -1
  117. package/dist/contracts/share.contract.d.ts +4 -4
  118. package/dist/contracts/share.contract.js +5 -5
  119. package/dist/contracts/share.contract.js.map +1 -1
  120. package/dist/contracts/skills.contract.d.ts +5 -5
  121. package/dist/contracts/skills.contract.js +6 -6
  122. package/dist/contracts/skills.contract.js.map +1 -1
  123. package/dist/contracts/system.contract.d.ts +22 -19
  124. package/dist/contracts/system.contract.d.ts.map +1 -1
  125. package/dist/contracts/system.contract.js +27 -20
  126. package/dist/contracts/system.contract.js.map +1 -1
  127. package/dist/contracts/translator.contract.d.ts +5 -5
  128. package/dist/contracts/translator.contract.js +6 -6
  129. package/dist/contracts/translator.contract.js.map +1 -1
  130. package/dist/contracts/usage.contract.d.ts +4 -4
  131. package/dist/contracts/usage.contract.js +5 -5
  132. package/dist/contracts/usage.contract.js.map +1 -1
  133. package/dist/contracts/vpn.contract.d.ts +4 -4
  134. package/dist/contracts/vpn.contract.d.ts.map +1 -1
  135. package/dist/contracts/vpn.contract.js +6 -5
  136. package/dist/contracts/vpn.contract.js.map +1 -1
  137. package/dist/contracts/workflows.contract.d.ts +9 -9
  138. package/dist/contracts/workflows.contract.js +10 -10
  139. package/dist/contracts/workflows.contract.js.map +1 -1
  140. package/dist/contracts/workspace.contract.d.ts +30 -30
  141. package/dist/contracts/workspace.contract.d.ts.map +1 -1
  142. package/dist/contracts/workspace.contract.js +46 -31
  143. package/dist/contracts/workspace.contract.js.map +1 -1
  144. package/dist/events/land-breakage.d.ts +4 -0
  145. package/dist/events/land-breakage.d.ts.map +1 -0
  146. package/dist/events/land-breakage.js +4 -0
  147. package/dist/events/land-breakage.js.map +1 -0
  148. package/dist/events/system-events.d.ts +2 -0
  149. package/dist/events/system-events.d.ts.map +1 -1
  150. package/dist/index.d.ts +9379 -9350
  151. package/dist/index.d.ts.map +1 -1
  152. package/dist/index.js +13 -1
  153. package/dist/index.js.map +1 -1
  154. package/dist/protocol/procedure-types.d.ts +10 -0
  155. package/dist/protocol/procedure-types.d.ts.map +1 -0
  156. package/dist/protocol/procedure-types.js +2 -0
  157. package/dist/protocol/procedure-types.js.map +1 -0
  158. package/dist/protocol/raw-routes.d.ts +417 -0
  159. package/dist/protocol/raw-routes.d.ts.map +1 -0
  160. package/dist/protocol/raw-routes.js +140 -0
  161. package/dist/protocol/raw-routes.js.map +1 -0
  162. package/dist/protocol/route-meta.d.ts +18 -0
  163. package/dist/protocol/route-meta.d.ts.map +1 -0
  164. package/dist/protocol/route-meta.js +3 -0
  165. package/dist/protocol/route-meta.js.map +1 -0
  166. package/dist/protocol/routes.d.ts +3 -0
  167. package/dist/protocol/routes.d.ts.map +1 -1
  168. package/dist/protocol/routes.js +47 -14
  169. package/dist/protocol/routes.js.map +1 -1
  170. package/dist/schemas/agent.d.ts +33 -0
  171. package/dist/schemas/agent.d.ts.map +1 -1
  172. package/dist/schemas/agent.js +22 -3
  173. package/dist/schemas/agent.js.map +1 -1
  174. package/dist/schemas/agents.d.ts +4 -0
  175. package/dist/schemas/agents.d.ts.map +1 -1
  176. package/dist/schemas/agents.js +4 -0
  177. package/dist/schemas/agents.js.map +1 -1
  178. package/dist/schemas/automations.d.ts +1 -0
  179. package/dist/schemas/automations.d.ts.map +1 -1
  180. package/dist/schemas/devices.d.ts.map +1 -1
  181. package/dist/schemas/devices.js +2 -2
  182. package/dist/schemas/devices.js.map +1 -1
  183. package/dist/schemas/git/git.d.ts +3 -0
  184. package/dist/schemas/git/git.d.ts.map +1 -1
  185. package/dist/schemas/hosts.d.ts +1 -0
  186. package/dist/schemas/hosts.d.ts.map +1 -1
  187. package/dist/schemas/hosts.js +1 -0
  188. package/dist/schemas/hosts.js.map +1 -1
  189. package/dist/schemas/settings.d.ts +1 -0
  190. package/dist/schemas/settings.d.ts.map +1 -1
  191. package/dist/schemas/settings.js +4 -0
  192. package/dist/schemas/settings.js.map +1 -1
  193. package/dist/state/definition.d.ts +4 -0
  194. package/dist/state/definition.d.ts.map +1 -1
  195. package/dist/state/history-state.d.ts.map +1 -1
  196. package/dist/state/history-state.js +2 -12
  197. package/dist/state/history-state.js.map +1 -1
  198. package/dist/state/landed-commit.d.ts +4 -0
  199. package/dist/state/landed-commit.d.ts.map +1 -0
  200. package/dist/state/landed-commit.js +12 -0
  201. package/dist/state/landed-commit.js.map +1 -0
  202. package/package.json +5 -5
  203. package/src/contracts/accounts.contract.ts +7 -7
  204. package/src/contracts/activity.contract.ts +3 -3
  205. package/src/contracts/agent.contract.ts +25 -11
  206. package/src/contracts/agents.contract.ts +48 -30
  207. package/src/contracts/approvals.contract.ts +4 -4
  208. package/src/contracts/areas.contract.ts +5 -4
  209. package/src/contracts/automations.contract.ts +12 -12
  210. package/src/contracts/capabilities.contract.ts +23 -14
  211. package/src/contracts/chores.contract.ts +4 -4
  212. package/src/contracts/ci.contract.ts +6 -6
  213. package/src/contracts/diff.contract.ts +2 -2
  214. package/src/contracts/endpoints.contract.ts +5 -5
  215. package/src/contracts/exit.contract.ts +11 -8
  216. package/src/contracts/extensions.contract.ts +18 -18
  217. package/src/contracts/git.contract.ts +46 -46
  218. package/src/contracts/history.contract.ts +5 -5
  219. package/src/contracts/intentic.contract.ts +5 -4
  220. package/src/contracts/inventory.contract.ts +4 -4
  221. package/src/contracts/issues.contract.ts +6 -6
  222. package/src/contracts/logs.contract.ts +8 -4
  223. package/src/contracts/loops.contract.ts +7 -7
  224. package/src/contracts/netdisk.contract.ts +7 -4
  225. package/src/contracts/panels.contract.ts +4 -4
  226. package/src/contracts/personas.contract.ts +10 -9
  227. package/src/contracts/ports.contract.ts +6 -4
  228. package/src/contracts/prepush.contract.ts +4 -4
  229. package/src/contracts/providers.contract.ts +5 -3
  230. package/src/contracts/public.contract.ts +4 -4
  231. package/src/contracts/push.contract.ts +12 -5
  232. package/src/contracts/safety.contract.ts +4 -4
  233. package/src/contracts/secrets.contract.ts +16 -10
  234. package/src/contracts/sessions.contract.ts +6 -3
  235. package/src/contracts/settings.contract.ts +11 -10
  236. package/src/contracts/share.contract.ts +5 -5
  237. package/src/contracts/skills.contract.ts +6 -6
  238. package/src/contracts/system.contract.ts +32 -20
  239. package/src/contracts/translator.contract.ts +6 -6
  240. package/src/contracts/usage.contract.ts +5 -5
  241. package/src/contracts/vpn.contract.ts +8 -5
  242. package/src/contracts/workflows.contract.ts +10 -10
  243. package/src/contracts/workspace.contract.ts +49 -31
  244. package/src/events/land-breakage.ts +11 -0
  245. package/src/index.ts +23 -1
  246. package/src/models/capability-ledger.test.ts +1 -1
  247. package/src/protocol/procedure-types.ts +24 -0
  248. package/src/protocol/raw-routes.ts +191 -0
  249. package/src/protocol/route-meta.ts +39 -0
  250. package/src/protocol/routes.test.ts +65 -2
  251. package/src/protocol/routes.ts +88 -27
  252. package/src/schemas/agent.test.ts +66 -0
  253. package/src/schemas/agent.ts +184 -154
  254. package/src/schemas/agents.ts +6 -0
  255. package/src/schemas/devices.ts +2 -2
  256. package/src/schemas/hosts.ts +4 -0
  257. package/src/schemas/settings.ts +9 -0
  258. package/src/state/history-state.ts +14 -29
  259. package/src/state/landed-commit.test.ts +18 -0
  260. package/src/state/landed-commit.ts +17 -0
@@ -1,15 +1,18 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { streamOf } from "../protocol/routes.js";
3
3
  import { IntenticLineSchema } from "../events/system-events.js";
4
4
  import { NetdiskIdParamSchema, NetdiskListSchema } from "../schemas/netdisk.js";
5
5
  import { OkSchema } from "../schemas/shared.js";
6
6
 
7
+ // The agent's `netdisk` CLI mounts and unmounts these on the agent token.
8
+ const netdiskRoute = procedure.meta({ agent: true });
9
+
7
10
  // A network disk is added as a `netdisk` capability; mounting and unmounting it happen through the routes here, called
8
11
  // by both the operator UI and the agent's `netdisk` CLI.
9
12
  // Every route reads mount state from the kernel, not daemon memory, so a disk unmounted from a shell and one unmounted
10
13
  // from a screen are the same event across a restart.
11
14
  export const netdiskContract = {
12
- list: oc
15
+ list: netdiskRoute
13
16
  .route({
14
17
  method: "GET",
15
18
  path: "/netdisk",
@@ -20,7 +23,7 @@ export const netdiskContract = {
20
23
  .output(NetdiskListSchema),
21
24
  // Streamed: a mount can take seconds against a slow server and can fail with something a person has to read (a
22
25
  // refused password, an unreachable server behind a tunnel that is down).
23
- mount: oc
26
+ mount: netdiskRoute
24
27
  .route({
25
28
  method: "POST",
26
29
  path: "/netdisk/{id}/mount",
@@ -30,7 +33,7 @@ export const netdiskContract = {
30
33
  })
31
34
  .input(NetdiskIdParamSchema)
32
35
  .output(streamOf(IntenticLineSchema)),
33
- unmount: oc
36
+ unmount: netdiskRoute
34
37
  .route({
35
38
  method: "POST",
36
39
  path: "/netdisk/{id}/unmount",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { PanelRepoParamSchema, PanelsListSchema } from "../schemas/panels.js";
3
3
  import { OkSchema } from "../schemas/shared.js";
4
4
 
@@ -7,7 +7,7 @@ import { OkSchema } from "../schemas/shared.js";
7
7
  // on the global GET /system/terminals (the web app's one terminal panel); the interactive I/O is the
8
8
  // /system/terminal WebSocket.
9
9
  export const panelsContract = {
10
- list: oc
10
+ list: procedure
11
11
  .route({
12
12
  method: "GET",
13
13
  path: "/panels",
@@ -15,7 +15,7 @@ export const panelsContract = {
15
15
  description: "Every repo with whether its dev server is up and what the sandbox worked out about its contents.",
16
16
  })
17
17
  .output(PanelsListSchema),
18
- start: oc
18
+ start: procedure
19
19
  .route({
20
20
  method: "POST",
21
21
  path: "/panels/{repo}/start",
@@ -24,7 +24,7 @@ export const panelsContract = {
24
24
  })
25
25
  .input(PanelRepoParamSchema)
26
26
  .output(OkSchema),
27
- stop: oc
27
+ stop: procedure
28
28
  .route({
29
29
  method: "POST",
30
30
  path: "/panels/{repo}/stop",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import {
3
3
  PersonaIdParamSchema,
4
4
  PersonaKitSchema,
@@ -15,7 +15,7 @@ import { OkSchema } from "../schemas/shared.js";
15
15
  // nothing, only a decision about existing accounts. The kit routes below edit its files (prompt, skills only its turns
16
16
  // reach) per verb, not one whole-kit PUT, so one skill's edit cannot delete another.
17
17
  export const personasContract = {
18
- list: oc
18
+ list: procedure
19
19
  .route({
20
20
  method: "GET",
21
21
  path: "/personas",
@@ -23,9 +23,10 @@ export const personasContract = {
23
23
  description:
24
24
  "Each persona with the connected accounts it speaks for, what a conversation wearing it is allowed to do, and where it works.",
25
25
  })
26
+ .meta({ guest: true })
26
27
  .output(PersonasListSchema),
27
28
  // Upsert by id, re-saving the same id edits that card.
28
- save: oc
29
+ save: procedure
29
30
  .route({
30
31
  method: "POST",
31
32
  path: "/personas",
@@ -37,7 +38,7 @@ export const personasContract = {
37
38
  .output(OkSchema),
38
39
  // Never removes the account; an automation pinned to this id resolves as no accounts, and goes quiet.
39
40
  // Also deletes the persona's kit folder (prompt + skills), rather than leaving it orphaned on disk.
40
- remove: oc
41
+ remove: procedure
41
42
  .route({
42
43
  method: "DELETE",
43
44
  path: "/personas/{id}",
@@ -52,7 +53,7 @@ export const personasContract = {
52
53
 
53
54
  // The kit: what this card is told, and the skills only it reaches.
54
55
 
55
- kit: oc
56
+ kit: procedure
56
57
  .route({
57
58
  method: "GET",
58
59
  path: "/personas/{id}/kit",
@@ -63,7 +64,7 @@ export const personasContract = {
63
64
  .input(PersonaIdParamSchema)
64
65
  .output(PersonaKitSchema),
65
66
  // An empty prompt deletes the file rather than storing a blank; it then falls back to the sandbox's own prompt.
66
- savePrompt: oc
67
+ savePrompt: procedure
67
68
  .route({
68
69
  method: "POST",
69
70
  path: "/personas/{id}/prompt",
@@ -73,7 +74,7 @@ export const personasContract = {
73
74
  })
74
75
  .input(PersonaPromptSchema)
75
76
  .output(OkSchema),
76
- readSkill: oc
77
+ readSkill: procedure
77
78
  .route({
78
79
  method: "GET",
79
80
  path: "/personas/{id}/skills/read",
@@ -83,7 +84,7 @@ export const personasContract = {
83
84
  .input(PersonaSkillNameSchema)
84
85
  .output(PersonaSkillBodySchema),
85
86
  // Upsert by name, no enabled list to write: a kit skill is on exactly when its persona is worn.
86
- saveSkill: oc
87
+ saveSkill: procedure
87
88
  .route({
88
89
  method: "POST",
89
90
  path: "/personas/{id}/skills",
@@ -93,7 +94,7 @@ export const personasContract = {
93
94
  })
94
95
  .input(PersonaSkillSchema)
95
96
  .output(OkSchema),
96
- removeSkill: oc
97
+ removeSkill: procedure
97
98
  .route({
98
99
  method: "POST",
99
100
  path: "/personas/{id}/skills/remove",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { PortForwardResultSchema, PortParamSchema, PortsListSchema } from "../schemas/ports.js";
3
3
  import { OkSchema } from "../schemas/shared.js";
4
4
 
@@ -6,15 +6,17 @@ import { OkSchema } from "../schemas/shared.js";
6
6
  // schemas/ports.ts). `forward` is idempotent, re-forwarding a port returns its existing slot's URL; `unforward`
7
7
  // frees the slot immediately (the hostname keeps resolving, the proxy just stops mapping it).
8
8
  export const portsContract = {
9
- list: oc
9
+ list: procedure
10
10
  .route({
11
11
  method: "GET",
12
12
  path: "/ports",
13
13
  summary: "What is listening inside the sandbox",
14
14
  description: "Every port something is answering on, and whether each one is reachable from outside.",
15
15
  })
16
+ // The desktop-sync watcher's poll, and the machine's check-in.
17
+ .meta({ sync: "poll" })
16
18
  .output(PortsListSchema),
17
- forward: oc
19
+ forward: procedure
18
20
  .route({
19
21
  method: "POST",
20
22
  path: "/ports/forward",
@@ -24,7 +26,7 @@ export const portsContract = {
24
26
  })
25
27
  .input(PortParamSchema)
26
28
  .output(PortForwardResultSchema),
27
- unforward: oc
29
+ unforward: procedure
28
30
  .route({
29
31
  method: "POST",
30
32
  path: "/ports/unforward",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { z } from "zod";
3
3
  import { CommandRunSchema } from "../schemas/ci.js";
4
4
  import { OkSchema } from "../schemas/shared.js";
@@ -28,7 +28,7 @@ export const PrepushRunSchema = z
28
28
  // tmux window, so watching it is the terminal's job. `cancel` kills that window; the run settles as `cancelled`
29
29
  // and the push it was gating does not go.
30
30
  export const prepushContract = {
31
- state: oc
31
+ state: procedure
32
32
  .route({
33
33
  method: "GET",
34
34
  path: "/prepush/state",
@@ -37,7 +37,7 @@ export const prepushContract = {
37
37
  "The verdict, or the progress so far. Nothing is addressed by id here, because there is one working tree and so exactly one check.",
38
38
  })
39
39
  .output(CommandRunSchema),
40
- run: oc
40
+ run: procedure
41
41
  .route({
42
42
  method: "POST",
43
43
  path: "/prepush/run",
@@ -47,7 +47,7 @@ export const prepushContract = {
47
47
  })
48
48
  .input(PrepushRunSchema)
49
49
  .output(OkSchema),
50
- cancel: oc
50
+ cancel: procedure
51
51
  .route({
52
52
  method: "POST",
53
53
  path: "/prepush/cancel",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { z } from "zod";
3
3
  import { NativeProviderParamSchema } from "../schemas/agent.js";
4
4
  import { ModelsSchema } from "../schemas/providers/provider-oauth.js";
@@ -33,7 +33,7 @@ export type RunnableProviders = z.infer<typeof RunnableProvidersSchema>;
33
33
  // their own route (endpoints.contract.ts): they are user-created and unbounded, and a missing one is NOT_FOUND, not an
34
34
  // empty catalog.
35
35
  export const providersContract = {
36
- list: oc
36
+ list: procedure
37
37
  .route({
38
38
  method: "GET",
39
39
  path: "/providers",
@@ -41,9 +41,10 @@ export const providersContract = {
41
41
  description:
42
42
  "The installed ACP agents and model endpoints, which are the providers this sandbox adds to the fixed native list. A read for anyone who may watch or drive a turn: it names what a message can be addressed to, not what credential stands behind it.",
43
43
  })
44
+ .meta({ guest: true })
44
45
  .output(RunnableProvidersSchema),
45
46
  // Never empty: live discovery with a persisted/seed floor; order is the provider's own, not re-ranked.
46
- models: oc
47
+ models: procedure
47
48
  .route({
48
49
  method: "GET",
49
50
  path: "/providers/{provider}/models",
@@ -51,6 +52,7 @@ export const providersContract = {
51
52
  description:
52
53
  "Every model this provider serves and which one it defaults to. Never empty: it is discovered live with a stored list behind it. The order is the provider's own preference and is not rearranged here.",
53
54
  })
55
+ .meta({ guest: true })
54
56
  .input(NativeProviderParamSchema)
55
57
  .output(ModelsSchema),
56
58
  };
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { PublicListSchema, PublishResultSchema, PublishSchema, UnpublishSchema } from "../schemas/public.js";
3
3
  import { OkSchema } from "../schemas/shared.js";
4
4
 
@@ -9,7 +9,7 @@ import { OkSchema } from "../schemas/shared.js";
9
9
  // unauthenticated `public-<slot>` hostname, and a second, authenticated way in would just be the workspace file
10
10
  // API with extra steps.
11
11
  export const publicContract = {
12
- list: oc
12
+ list: procedure
13
13
  .route({
14
14
  method: "GET",
15
15
  path: "/public",
@@ -18,7 +18,7 @@ export const publicContract = {
18
18
  "Everything currently in the outbox and the address it answers on. There is no call to read a published file back: it is served openly to anyone with the link, which is the entire point of having put it there.",
19
19
  })
20
20
  .output(PublicListSchema),
21
- publish: oc
21
+ publish: procedure
22
22
  .route({
23
23
  method: "POST",
24
24
  path: "/public/publish",
@@ -28,7 +28,7 @@ export const publicContract = {
28
28
  })
29
29
  .input(PublishSchema)
30
30
  .output(PublishResultSchema),
31
- unpublish: oc
31
+ unpublish: procedure
32
32
  .route({
33
33
  method: "POST",
34
34
  path: "/public/unpublish",
@@ -1,7 +1,10 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { PushChannelIdSchema, PushChannelSchema, PushConfigQuerySchema, PushConfigSchema, PushTestSchema } from "../schemas/push.js";
3
3
  import { OkSchema } from "../schemas/shared.js";
4
4
 
5
+ // A member's own devices, which no control token reaches.
6
+ const pushRoute = procedure.meta({ control: "never" });
7
+
5
8
  // Push notifications for this sandbox. The daemon owns the VAPID keypair and the channel list (see
6
9
  // push/push-store.ts for why the key lives on the history volume), and sends on the three moments where the
7
10
  // operator's attention is genuinely wanted: a turn finished, the agent is blocked on an answer, and an
@@ -12,7 +15,7 @@ import { OkSchema } from "../schemas/shared.js";
12
15
  // (device permission, service-worker or shell registration, the daemon's key, the push service itself), a
13
16
  // button that proves the whole chain end-to-end is worth more than any amount of status rendering.
14
17
  export const pushContract = {
15
- config: oc
18
+ config: pushRoute
16
19
  .route({
17
20
  method: "GET",
18
21
  path: "/push/config",
@@ -21,7 +24,7 @@ export const pushContract = {
21
24
  })
22
25
  .input(PushConfigQuerySchema)
23
26
  .output(PushConfigSchema),
24
- subscribe: oc
27
+ subscribe: pushRoute
25
28
  .route({
26
29
  method: "POST",
27
30
  path: "/push/subscribe",
@@ -29,18 +32,21 @@ export const pushContract = {
29
32
  description:
30
33
  "Registers one device. The sandbox only interrupts you on the three moments where attention is genuinely wanted: a turn has finished, the agent is stuck on a question, and something is waiting for approval.",
31
34
  })
35
+ // A member's own device notifications.
36
+ .meta({ floor: "collaborator" })
32
37
  .input(PushChannelSchema)
33
38
  .output(OkSchema),
34
- unsubscribe: oc
39
+ unsubscribe: pushRoute
35
40
  .route({
36
41
  method: "POST",
37
42
  path: "/push/unsubscribe",
38
43
  summary: "Stop notifying a device",
39
44
  description: "Removes one registered device. Others keep receiving.",
40
45
  })
46
+ .meta({ floor: "collaborator" })
41
47
  .input(PushChannelIdSchema)
42
48
  .output(OkSchema),
43
- test: oc
49
+ test: pushRoute
44
50
  .route({
45
51
  method: "POST",
46
52
  path: "/push/test",
@@ -48,5 +54,6 @@ export const pushContract = {
48
54
  description:
49
55
  "Proves the whole chain end to end. Worth having, because there are four separate places a notification can be lost that nobody can inspect from the outside: the device's permission, its registration, the sandbox's key, and the delivery service.",
50
56
  })
57
+ .meta({ floor: "collaborator" })
51
58
  .output(PushTestSchema),
52
59
  };
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { SafetyLogEntrySchema, SafetyPolicySchema } from "../policy/safety-policy.js";
3
3
  import { OkSchema } from "../schemas/shared.js";
4
4
  import { z } from "zod";
@@ -7,7 +7,7 @@ import { z } from "zod";
7
7
  // the policy is a document edited at human speed, the log changes on its own mid-turn. The policy travels as text,
8
8
  // never parsed, since its reader is a model, not a parser.
9
9
  export const safetyContract = {
10
- policy: oc
10
+ policy: procedure
11
11
  .route({
12
12
  method: "GET",
13
13
  path: "/safety/policy",
@@ -16,7 +16,7 @@ export const safetyContract = {
16
16
  "The document that decides when an agent stops to ask you before running something. Prose, not settings: it is read by the model that judges each command. When nobody has written one, this is the text the product ships with, and it describes the behaviour a fresh sandbox already has.",
17
17
  })
18
18
  .output(SafetyPolicySchema),
19
- setPolicy: oc
19
+ setPolicy: procedure
20
20
  .route({
21
21
  method: "POST",
22
22
  path: "/safety/policy",
@@ -27,7 +27,7 @@ export const safetyContract = {
27
27
  .input(z.object({ text: z.string().describe("The policy, as you want it written.") }))
28
28
  .output(OkSchema),
29
29
  // Verdicts teach the owner which policy line to add next; answers why you weren't asked about something.
30
- log: oc
30
+ log: procedure
31
31
  .route({
32
32
  method: "GET",
33
33
  path: "/safety/log",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import {
3
3
  CredentialGateSchema,
4
4
  CredentialGuardSubjectParamSchema,
@@ -13,11 +13,14 @@ import {
13
13
  } from "../schemas/secrets.js";
14
14
  import { OkSchema } from "../schemas/shared.js";
15
15
 
16
+ // Credentials are the operating tier's, reads included: maintainer is the highest revokable grant, and no token's.
17
+ const secretRoute = procedure.meta({ floor: "maintainer", control: "never" });
18
+
16
19
  // User-supplied secrets, in the gitignored desired-state/.env; `apply` reloads them, no restart. `inventory` aggregates
17
20
  // every store (never values) and always answers; the rest refuse until desired-state is scaffolded. `reveal` alone
18
21
  // returns a value, owner-only, POST so the key avoids the URL.
19
22
  export const secretsContract = {
20
- set: oc
23
+ set: secretRoute
21
24
  .route({
22
25
  method: "POST",
23
26
  path: "/secrets",
@@ -27,7 +30,7 @@ export const secretsContract = {
27
30
  })
28
31
  .input(SecretSetSchema)
29
32
  .output(OkSchema),
30
- list: oc
33
+ list: secretRoute
31
34
  .route({
32
35
  method: "GET",
33
36
  path: "/secrets",
@@ -35,7 +38,7 @@ export const secretsContract = {
35
38
  description: "Which secrets exist here. Names only, never values.",
36
39
  })
37
40
  .output(SecretKeysSchema),
38
- remove: oc
41
+ remove: secretRoute
39
42
  .route({
40
43
  method: "DELETE",
41
44
  path: "/secrets/{key}",
@@ -44,7 +47,7 @@ export const secretsContract = {
44
47
  })
45
48
  .input(SecretKeyParamSchema)
46
49
  .output(OkSchema),
47
- inventory: oc
50
+ inventory: secretRoute
48
51
  .route({
49
52
  method: "GET",
50
53
  path: "/secrets/inventory",
@@ -53,7 +56,7 @@ export const secretsContract = {
53
56
  "One view across all the places secrets live here: what exists, where it came from and whether it is working. Never any values. This one always answers, even before there is a store to write to.",
54
57
  })
55
58
  .output(SecretInventorySchema),
56
- reveal: oc
59
+ reveal: secretRoute
57
60
  .route({
58
61
  method: "POST",
59
62
  path: "/secrets/reveal",
@@ -64,7 +67,7 @@ export const secretsContract = {
64
67
  .input(SecretKeyParamSchema)
65
68
  .output(SecretRevealSchema),
66
69
  // Gate policy lives off the workspace, not in agent-editable `.intentic/config/`, so agents can't hold the key.
67
- gates: oc
70
+ gates: secretRoute
68
71
  .route({
69
72
  method: "GET",
70
73
  path: "/secrets/gates",
@@ -72,8 +75,10 @@ export const secretsContract = {
72
75
  description:
73
76
  "What is gated and who may release it. Names and addresses only, never values, and the agent may read it too: knowing a credential needs Bob is what stops it concluding the account is simply not connected.",
74
77
  })
78
+ // The `secrets` CLI's names-only reads and its ask, on the agent token; never a value.
79
+ .meta({ agent: true })
75
80
  .output(CredentialGatesSchema),
76
- setGate: oc
81
+ setGate: secretRoute
77
82
  .route({
78
83
  method: "PUT",
79
84
  path: "/secrets/gates/{subject}",
@@ -83,7 +88,7 @@ export const secretsContract = {
83
88
  })
84
89
  .input(CredentialGateSchema)
85
90
  .output(OkSchema),
86
- removeGate: oc
91
+ removeGate: secretRoute
87
92
  .route({
88
93
  method: "DELETE",
89
94
  path: "/secrets/gates/{subject}",
@@ -92,7 +97,7 @@ export const secretsContract = {
92
97
  })
93
98
  .input(CredentialGuardSubjectParamSchema)
94
99
  .output(OkSchema),
95
- request: oc
100
+ request: secretRoute
96
101
  .route({
97
102
  method: "POST",
98
103
  path: "/secrets/request",
@@ -100,6 +105,7 @@ export const secretsContract = {
100
105
  description:
101
106
  "Raises the release card in the live conversation and waits for one of the people named on it. Refused, rather than held, when there is nobody to ask: an unattended turn, no live conversation, or a click with no verified identity behind it.",
102
107
  })
108
+ .meta({ agent: true })
103
109
  .input(CredentialRequestSchema)
104
110
  .output(CredentialGrantSchema),
105
111
  };
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { z } from "zod";
3
3
  import { SessionTranscriptSchema } from "../events/transcript.js";
4
4
  import { SessionIdParamSchema, SessionsListSchema } from "../schemas/sessions.js";
@@ -12,7 +12,7 @@ import { SessionIdParamSchema, SessionsListSchema } from "../schemas/sessions.js
12
12
  // not matter, and the two routes answer one query together (the board lists these rows under its own cards), so
13
13
  // a switch either of them ignored would show as one field returning two different match sets.
14
14
  export const sessionsContract = {
15
- list: oc
15
+ list: procedure
16
16
  .route({
17
17
  method: "GET",
18
18
  path: "/sessions",
@@ -20,15 +20,18 @@ export const sessionsContract = {
20
20
  description:
21
21
  "Summaries for a history menu, filtered when you pass a search. Covers conversations that worked in their own private copies too, so nothing is hidden just because it happened on a branch.",
22
22
  })
23
+ // The editor bridge's slice: the transcripts of the conversation it drives.
24
+ .meta({ control: "editor" })
23
25
  .input(z.object({ query: z.string().optional(), caseSensitive: z.stringbool().optional() }))
24
26
  .output(SessionsListSchema),
25
- get: oc
27
+ get: procedure
26
28
  .route({
27
29
  method: "GET",
28
30
  path: "/sessions/{id}",
29
31
  summary: "Read one past conversation",
30
32
  description: "The full record of a single conversation, restored for display.",
31
33
  })
34
+ .meta({ control: "editor" })
32
35
  .input(SessionIdParamSchema)
33
36
  .output(SessionTranscriptSchema),
34
37
  };
@@ -1,5 +1,5 @@
1
1
  import { FIELD_NOTES_FILE } from "@intentic/constants";
2
- import { oc } from "@orpc/contract";
2
+ import { procedure } from "../protocol/route-meta.js";
3
3
  import {
4
4
  BuiltinPromptSchema,
5
5
  BuiltinPromptTextSchema,
@@ -20,15 +20,16 @@ import { DayWindowQuerySchema } from "../schemas/providers/usage.js";
20
20
  // overwrites whole. `savings` measures each token-reduction mechanism's worth over the same UTC day window the spend
21
21
  // ledger takes. `builtinPrompt` returns a built-in prompt's actual text to show or fork.
22
22
  export const settingsContract = {
23
- get: oc
23
+ get: procedure
24
24
  .route({
25
25
  method: "GET",
26
26
  path: "/settings",
27
27
  summary: "How this sandbox is configured",
28
28
  description: "Every setting that governs how agents behave here, with the defaults filled in for anything nobody has chosen.",
29
29
  })
30
+ .meta({ guest: true })
30
31
  .output(SandboxSettingsSchema),
31
- set: oc
32
+ set: procedure
32
33
  .route({
33
34
  method: "POST",
34
35
  path: "/settings",
@@ -37,7 +38,7 @@ export const settingsContract = {
37
38
  })
38
39
  .input(SandboxSettingsSchema)
39
40
  .output(OkSchema),
40
- savings: oc
41
+ savings: procedure
41
42
  .route({
42
43
  method: "GET",
43
44
  path: "/settings/savings",
@@ -47,7 +48,7 @@ export const settingsContract = {
47
48
  })
48
49
  .input(DayWindowQuerySchema)
49
50
  .output(SavingsReportSchema),
50
- builtinPrompt: oc
51
+ builtinPrompt: procedure
51
52
  .route({
52
53
  method: "GET",
53
54
  path: "/settings/system-prompt/{base}",
@@ -58,7 +59,7 @@ export const settingsContract = {
58
59
  .input(BuiltinPromptSchema)
59
60
  .output(BuiltinPromptTextSchema),
60
61
  // Own route, not a settings field: a firing isn't an edit, so it shouldn't cost a settings write.
61
- firings: oc
62
+ firings: procedure
62
63
  .route({
63
64
  method: "GET",
64
65
  path: "/settings/rule-firings",
@@ -69,7 +70,7 @@ export const settingsContract = {
69
70
  .output(RuleFiringsSchema),
70
71
  // Read off the repositories themselves, not out of the settings file: the declaration is a tracked file in each
71
72
  // repository, and only the owner's answer to it lives here.
72
- repoChecks: oc
73
+ repoChecks: procedure
73
74
  .route({
74
75
  method: "GET",
75
76
  path: "/settings/repo-checks",
@@ -79,7 +80,7 @@ export const settingsContract = {
79
80
  .output(RepoChecksListSchema),
80
81
  // Read off the file and the automation store rather than the settings manifest: nothing here is a choice anyone
81
82
  // made, so storing it would only give it a second place to be wrong.
82
- fieldNotes: oc
83
+ fieldNotes: procedure
83
84
  .route({
84
85
  method: "GET",
85
86
  path: "/settings/field-notes",
@@ -91,7 +92,7 @@ export const settingsContract = {
91
92
  // browser offers the zone it is in; the daemon takes it only if nobody has chosen one. Folding it into the
92
93
  // whole-object `set` would mean the second machine to open the workspace silently moved every schedule to its own
93
94
  // clock, and an owner in Warsaw would find their chores on a colleague's Tokyo hours.
94
- adoptTimezone: oc
95
+ adoptTimezone: procedure
95
96
  .route({
96
97
  method: "POST",
97
98
  path: "/settings/timezone",
@@ -101,7 +102,7 @@ export const settingsContract = {
101
102
  })
102
103
  .input(TimezoneOfferSchema)
103
104
  .output(TimezoneStateSchema),
104
- adoptRepoChecks: oc
105
+ adoptRepoChecks: procedure
105
106
  .route({
106
107
  method: "POST",
107
108
  path: "/settings/repo-checks/adopt",
@@ -1,4 +1,4 @@
1
- import { oc } from "@orpc/contract";
1
+ import { procedure } from "../protocol/route-meta.js";
2
2
  import { ShareCreateSchema, SharedConversationSchema, ShareListSchema, ShareRemoveSchema, ShareUpdateSchema } from "../schemas/share.js";
3
3
  import { OkSchema } from "../schemas/shared.js";
4
4
 
@@ -6,7 +6,7 @@ import { OkSchema } from "../schemas/shared.js";
6
6
  // `public` copies bytes at a workspace path. No route reads a share back, the page itself is the read, on the
7
7
  // unauthenticated `public-<slot>` hostname.
8
8
  export const shareContract = {
9
- list: oc
9
+ list: procedure
10
10
  .route({
11
11
  method: "GET",
12
12
  path: "/share",
@@ -16,7 +16,7 @@ export const shareContract = {
16
16
  })
17
17
  .output(ShareListSchema),
18
18
  // Answers with the row it just wrote, link included, so the dialog can show the address without re-listing.
19
- create: oc
19
+ create: procedure
20
20
  .route({
21
21
  method: "POST",
22
22
  path: "/share",
@@ -27,7 +27,7 @@ export const shareContract = {
27
27
  .input(ShareCreateSchema)
28
28
  .output(SharedConversationSchema),
29
29
  // Re-render an existing share from the conversation as it stands now. Same id, same link, new snapshot.
30
- update: oc
30
+ update: procedure
31
31
  .route({
32
32
  method: "POST",
33
33
  path: "/share/update",
@@ -36,7 +36,7 @@ export const shareContract = {
36
36
  })
37
37
  .input(ShareUpdateSchema)
38
38
  .output(SharedConversationSchema),
39
- remove: oc
39
+ remove: procedure
40
40
  .route({
41
41
  method: "POST",
42
42
  path: "/share/remove",