@greatwait/contracts 0.1.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.
Files changed (241) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -0
  3. package/dist/authority.d.ts +217 -0
  4. package/dist/authority.js +261 -0
  5. package/dist/callback-ownership.d.ts +58 -0
  6. package/dist/callback-ownership.js +71 -0
  7. package/dist/callback-safety.d.ts +38 -0
  8. package/dist/callback-safety.js +403 -0
  9. package/dist/compatibility.d.ts +82 -0
  10. package/dist/compatibility.js +115 -0
  11. package/dist/delivery.d.ts +401 -0
  12. package/dist/delivery.js +311 -0
  13. package/dist/endpoints.d.ts +305 -0
  14. package/dist/endpoints.js +179 -0
  15. package/dist/events.d.ts +62 -0
  16. package/dist/events.js +38 -0
  17. package/dist/first-value-journey.d.ts +305 -0
  18. package/dist/first-value-journey.js +466 -0
  19. package/dist/forecast.d.ts +443 -0
  20. package/dist/forecast.js +729 -0
  21. package/dist/identifiers.d.ts +109 -0
  22. package/dist/identifiers.js +131 -0
  23. package/dist/identity.d.ts +196 -0
  24. package/dist/identity.js +182 -0
  25. package/dist/index.d.ts +27 -0
  26. package/dist/index.js +27 -0
  27. package/dist/mcp.d.ts +51 -0
  28. package/dist/mcp.js +56 -0
  29. package/dist/oauth.d.ts +796 -0
  30. package/dist/oauth.js +708 -0
  31. package/dist/operations.d.ts +3985 -0
  32. package/dist/operations.js +1837 -0
  33. package/dist/partition.d.ts +771 -0
  34. package/dist/partition.js +206 -0
  35. package/dist/policy.d.ts +93 -0
  36. package/dist/policy.js +180 -0
  37. package/dist/problems.d.ts +158 -0
  38. package/dist/problems.js +104 -0
  39. package/dist/protocol.d.ts +308 -0
  40. package/dist/protocol.js +515 -0
  41. package/dist/scheduling-records.d.ts +395 -0
  42. package/dist/scheduling-records.js +284 -0
  43. package/dist/scheduling.d.ts +1098 -0
  44. package/dist/scheduling.js +1116 -0
  45. package/dist/secrets.d.ts +383 -0
  46. package/dist/secrets.js +272 -0
  47. package/dist/signatures.d.ts +704 -0
  48. package/dist/signatures.js +867 -0
  49. package/dist/tenancy.d.ts +178 -0
  50. package/dist/tenancy.js +145 -0
  51. package/dist/test-sink.d.ts +986 -0
  52. package/dist/test-sink.js +755 -0
  53. package/dist/time.d.ts +45 -0
  54. package/dist/time.js +128 -0
  55. package/dist/usage.d.ts +121 -0
  56. package/dist/usage.js +200 -0
  57. package/dist/webhooks.d.ts +116 -0
  58. package/dist/webhooks.js +161 -0
  59. package/dist/workspace.d.ts +92 -0
  60. package/dist/workspace.js +59 -0
  61. package/generated/v1/callback-delivery-signature.json +467 -0
  62. package/generated/v1/callback-endpoint-verification.json +59 -0
  63. package/generated/v1/callback-receiver.json +241 -0
  64. package/generated/v1/examples/attempts.list.response.json +24 -0
  65. package/generated/v1/examples/attempts.read.response.json +20 -0
  66. package/generated/v1/examples/credentials.create.request.json +5 -0
  67. package/generated/v1/examples/credentials.create.response.json +10 -0
  68. package/generated/v1/examples/credentials.list.response.json +17 -0
  69. package/generated/v1/examples/credentials.revoke.response.json +11 -0
  70. package/generated/v1/examples/credentials.rotate.request.json +3 -0
  71. package/generated/v1/examples/credentials.rotate.response.json +22 -0
  72. package/generated/v1/examples/endpoints.create.request.json +3 -0
  73. package/generated/v1/examples/endpoints.create.response.json +16 -0
  74. package/generated/v1/examples/endpoints.disable.response.json +15 -0
  75. package/generated/v1/examples/endpoints.list.response.json +21 -0
  76. package/generated/v1/examples/endpoints.read.response.json +14 -0
  77. package/generated/v1/examples/endpoints.rotateSigningKey.request.json +3 -0
  78. package/generated/v1/examples/endpoints.rotateSigningKey.response.json +23 -0
  79. package/generated/v1/examples/endpoints.update.request.json +3 -0
  80. package/generated/v1/examples/endpoints.update.response.json +13 -0
  81. package/generated/v1/examples/endpoints.verify.response.json +15 -0
  82. package/generated/v1/examples/forecast.read.response.json +28 -0
  83. package/generated/v1/examples/forecast.windows.response.json +21 -0
  84. package/generated/v1/examples/grants.list.response.json +17 -0
  85. package/generated/v1/examples/grants.revoke.response.json +16 -0
  86. package/generated/v1/examples/meta.scaffold.response.json +5 -0
  87. package/generated/v1/examples/meta.version.response.json +5 -0
  88. package/generated/v1/examples/occurrences.list.response.json +17 -0
  89. package/generated/v1/examples/occurrences.read.response.json +15 -0
  90. package/generated/v1/examples/occurrences.redeliver.response.json +16 -0
  91. package/generated/v1/examples/projects.create.request.json +3 -0
  92. package/generated/v1/examples/projects.create.response.json +5 -0
  93. package/generated/v1/examples/projects.list.response.json +9 -0
  94. package/generated/v1/examples/schedules.archive.response.json +25 -0
  95. package/generated/v1/examples/schedules.cancel.response.json +24 -0
  96. package/generated/v1/examples/schedules.create.request.json +9 -0
  97. package/generated/v1/examples/schedules.create.response.json +25 -0
  98. package/generated/v1/examples/schedules.list.response.json +23 -0
  99. package/generated/v1/examples/schedules.pause.response.json +23 -0
  100. package/generated/v1/examples/schedules.read.response.json +25 -0
  101. package/generated/v1/examples/schedules.replace.request.json +8 -0
  102. package/generated/v1/examples/schedules.replace.response.json +25 -0
  103. package/generated/v1/examples/schedules.resume.response.json +23 -0
  104. package/generated/v1/examples/sinkdeliveries.list.response.json +19 -0
  105. package/generated/v1/examples/sinkdeliveries.read.response.json +16 -0
  106. package/generated/v1/examples/testsinks.configure.request.json +3 -0
  107. package/generated/v1/examples/testsinks.configure.response.json +13 -0
  108. package/generated/v1/examples/testsinks.create.request.json +8 -0
  109. package/generated/v1/examples/testsinks.create.response.json +13 -0
  110. package/generated/v1/examples/testsinks.delete.response.json +13 -0
  111. package/generated/v1/examples/testsinks.list.response.json +20 -0
  112. package/generated/v1/examples/testsinks.read.response.json +14 -0
  113. package/generated/v1/examples/usage.read.response.json +20 -0
  114. package/generated/v1/first-value-journey.json +436 -0
  115. package/generated/v1/manifest.json +1037 -0
  116. package/generated/v1/openapi.json +23665 -0
  117. package/generated/v1/policy-matrix.json +305 -0
  118. package/generated/v1/schemas/attempts.list.query.json +16 -0
  119. package/generated/v1/schemas/attempts.list.response.json +175 -0
  120. package/generated/v1/schemas/attempts.read.response.json +168 -0
  121. package/generated/v1/schemas/credentials.create.request.json +39 -0
  122. package/generated/v1/schemas/credentials.create.response.json +88 -0
  123. package/generated/v1/schemas/credentials.list.query.json +16 -0
  124. package/generated/v1/schemas/credentials.list.response.json +124 -0
  125. package/generated/v1/schemas/credentials.revoke.response.json +84 -0
  126. package/generated/v1/schemas/credentials.rotate.request.json +11 -0
  127. package/generated/v1/schemas/credentials.rotate.response.json +171 -0
  128. package/generated/v1/schemas/endpoints.create.request.json +12 -0
  129. package/generated/v1/schemas/endpoints.create.response.json +115 -0
  130. package/generated/v1/schemas/endpoints.disable.response-headers.json +11 -0
  131. package/generated/v1/schemas/endpoints.disable.response.json +100 -0
  132. package/generated/v1/schemas/endpoints.list.query.json +16 -0
  133. package/generated/v1/schemas/endpoints.list.response.json +146 -0
  134. package/generated/v1/schemas/endpoints.read.response-headers.json +11 -0
  135. package/generated/v1/schemas/endpoints.read.response.json +100 -0
  136. package/generated/v1/schemas/endpoints.rotateSigningKey.request-headers.json +10 -0
  137. package/generated/v1/schemas/endpoints.rotateSigningKey.request.json +11 -0
  138. package/generated/v1/schemas/endpoints.rotateSigningKey.response-headers.json +11 -0
  139. package/generated/v1/schemas/endpoints.rotateSigningKey.response.json +118 -0
  140. package/generated/v1/schemas/endpoints.update.request-headers.json +10 -0
  141. package/generated/v1/schemas/endpoints.update.request.json +12 -0
  142. package/generated/v1/schemas/endpoints.update.response-headers.json +11 -0
  143. package/generated/v1/schemas/endpoints.update.response.json +100 -0
  144. package/generated/v1/schemas/endpoints.verify.request-headers.json +10 -0
  145. package/generated/v1/schemas/endpoints.verify.response-headers.json +11 -0
  146. package/generated/v1/schemas/endpoints.verify.response.json +100 -0
  147. package/generated/v1/schemas/forecast.read.query.json +26 -0
  148. package/generated/v1/schemas/forecast.read.response.json +100 -0
  149. package/generated/v1/schemas/forecast.windows.query.json +26 -0
  150. package/generated/v1/schemas/forecast.windows.response.json +94 -0
  151. package/generated/v1/schemas/grants.list.response.json +98 -0
  152. package/generated/v1/schemas/grants.revoke.response.json +95 -0
  153. package/generated/v1/schemas/meta.scaffold.response.json +36 -0
  154. package/generated/v1/schemas/meta.version.response.json +19 -0
  155. package/generated/v1/schemas/occurrences.list.query.json +16 -0
  156. package/generated/v1/schemas/occurrences.list.response.json +83 -0
  157. package/generated/v1/schemas/occurrences.read.response.json +76 -0
  158. package/generated/v1/schemas/occurrences.redeliver.request-headers.json +13 -0
  159. package/generated/v1/schemas/occurrences.redeliver.response-headers.json +10 -0
  160. package/generated/v1/schemas/occurrences.redeliver.response.json +168 -0
  161. package/generated/v1/schemas/projects.create.request.json +12 -0
  162. package/generated/v1/schemas/projects.create.response.json +25 -0
  163. package/generated/v1/schemas/projects.list.response.json +35 -0
  164. package/generated/v1/schemas/schedules.archive.request-headers.json +10 -0
  165. package/generated/v1/schemas/schedules.archive.response-headers.json +11 -0
  166. package/generated/v1/schemas/schedules.archive.response.json +189 -0
  167. package/generated/v1/schemas/schedules.cancel.request-headers.json +10 -0
  168. package/generated/v1/schemas/schedules.cancel.response-headers.json +11 -0
  169. package/generated/v1/schemas/schedules.cancel.response.json +189 -0
  170. package/generated/v1/schemas/schedules.create.request-headers.json +12 -0
  171. package/generated/v1/schemas/schedules.create.request.json +99 -0
  172. package/generated/v1/schemas/schedules.create.response-headers.json +15 -0
  173. package/generated/v1/schemas/schedules.create.response.json +189 -0
  174. package/generated/v1/schemas/schedules.list.query.json +16 -0
  175. package/generated/v1/schemas/schedules.list.response.json +170 -0
  176. package/generated/v1/schemas/schedules.pause.request-headers.json +10 -0
  177. package/generated/v1/schemas/schedules.pause.response-headers.json +11 -0
  178. package/generated/v1/schemas/schedules.pause.response.json +189 -0
  179. package/generated/v1/schemas/schedules.read.response-headers.json +11 -0
  180. package/generated/v1/schemas/schedules.read.response.json +189 -0
  181. package/generated/v1/schemas/schedules.replace.request-headers.json +10 -0
  182. package/generated/v1/schemas/schedules.replace.request.json +99 -0
  183. package/generated/v1/schemas/schedules.replace.response-headers.json +11 -0
  184. package/generated/v1/schemas/schedules.replace.response.json +189 -0
  185. package/generated/v1/schemas/schedules.resume.request-headers.json +10 -0
  186. package/generated/v1/schemas/schedules.resume.response-headers.json +11 -0
  187. package/generated/v1/schemas/schedules.resume.response.json +189 -0
  188. package/generated/v1/schemas/sinkdeliveries.list.query.json +16 -0
  189. package/generated/v1/schemas/sinkdeliveries.list.response.json +126 -0
  190. package/generated/v1/schemas/sinkdeliveries.read.response.json +98 -0
  191. package/generated/v1/schemas/testsinks.configure.request.json +66 -0
  192. package/generated/v1/schemas/testsinks.configure.response.json +115 -0
  193. package/generated/v1/schemas/testsinks.create.request.json +76 -0
  194. package/generated/v1/schemas/testsinks.create.response.json +115 -0
  195. package/generated/v1/schemas/testsinks.delete.response.json +115 -0
  196. package/generated/v1/schemas/testsinks.list.query.json +16 -0
  197. package/generated/v1/schemas/testsinks.list.response.json +161 -0
  198. package/generated/v1/schemas/testsinks.read.response.json +115 -0
  199. package/generated/v1/schemas/usage.read.query.json +15 -0
  200. package/generated/v1/schemas/usage.read.response.json +71 -0
  201. package/generated/v1/snippets/attempts.list.json +5 -0
  202. package/generated/v1/snippets/attempts.read.json +5 -0
  203. package/generated/v1/snippets/credentials.create.json +5 -0
  204. package/generated/v1/snippets/credentials.list.json +5 -0
  205. package/generated/v1/snippets/credentials.revoke.json +5 -0
  206. package/generated/v1/snippets/credentials.rotate.json +5 -0
  207. package/generated/v1/snippets/endpoints.create.json +5 -0
  208. package/generated/v1/snippets/endpoints.disable.json +5 -0
  209. package/generated/v1/snippets/endpoints.list.json +5 -0
  210. package/generated/v1/snippets/endpoints.read.json +5 -0
  211. package/generated/v1/snippets/endpoints.rotateSigningKey.json +5 -0
  212. package/generated/v1/snippets/endpoints.update.json +5 -0
  213. package/generated/v1/snippets/endpoints.verify.json +5 -0
  214. package/generated/v1/snippets/forecast.read.json +5 -0
  215. package/generated/v1/snippets/forecast.windows.json +5 -0
  216. package/generated/v1/snippets/grants.list.json +5 -0
  217. package/generated/v1/snippets/grants.revoke.json +5 -0
  218. package/generated/v1/snippets/meta.scaffold.json +5 -0
  219. package/generated/v1/snippets/meta.version.json +5 -0
  220. package/generated/v1/snippets/occurrences.list.json +5 -0
  221. package/generated/v1/snippets/occurrences.read.json +5 -0
  222. package/generated/v1/snippets/occurrences.redeliver.json +5 -0
  223. package/generated/v1/snippets/projects.create.json +5 -0
  224. package/generated/v1/snippets/projects.list.json +5 -0
  225. package/generated/v1/snippets/schedules.archive.json +5 -0
  226. package/generated/v1/snippets/schedules.cancel.json +5 -0
  227. package/generated/v1/snippets/schedules.create.json +5 -0
  228. package/generated/v1/snippets/schedules.list.json +5 -0
  229. package/generated/v1/snippets/schedules.pause.json +5 -0
  230. package/generated/v1/snippets/schedules.read.json +5 -0
  231. package/generated/v1/snippets/schedules.replace.json +5 -0
  232. package/generated/v1/snippets/schedules.resume.json +5 -0
  233. package/generated/v1/snippets/sinkdeliveries.list.json +5 -0
  234. package/generated/v1/snippets/sinkdeliveries.read.json +5 -0
  235. package/generated/v1/snippets/testsinks.configure.json +5 -0
  236. package/generated/v1/snippets/testsinks.create.json +5 -0
  237. package/generated/v1/snippets/testsinks.delete.json +5 -0
  238. package/generated/v1/snippets/testsinks.list.json +5 -0
  239. package/generated/v1/snippets/testsinks.read.json +5 -0
  240. package/generated/v1/snippets/usage.read.json +5 -0
  241. package/package.json +153 -0
@@ -0,0 +1,178 @@
1
+ import { z } from "zod";
2
+ /**
3
+ * Organizations, projects, and environments.
4
+ *
5
+ * The tenancy spine. An organization owns projects; a project owns exactly two
6
+ * environments, `test` and `live`. Every scheduling resource belongs to one
7
+ * `(organization, project, environment)` tuple, and that tuple comes from a
8
+ * verified principal rather than from anything a client sends — see
9
+ * `authority.ts`.
10
+ *
11
+ * **Environments are not organizations.** The W1-02 guide forbids modelling them
12
+ * as duplicated organizations, and the reason is worth stating: a customer would
13
+ * then have two tenants to keep in step, membership would have to be granted
14
+ * twice, and "the same code serves test and live" — the property that makes a
15
+ * test environment worth having — would stop being true.
16
+ */
17
+ /**
18
+ * An organization, in Greatwait's own identifier space.
19
+ *
20
+ * `externalId` is the Clerk organization this projects from. The two are kept
21
+ * apart deliberately: a Greatwait `org_…` is what appears in public responses, so
22
+ * our surface never depends on the identity vendor and a caller never learns a
23
+ * second spelling of their own tenant. See `identity.ts`.
24
+ */
25
+ export declare const organizationSchema: z.ZodObject<{
26
+ externalId: z.ZodString;
27
+ id: z.ZodString;
28
+ version: z.ZodNumber;
29
+ }, z.core.$strip>;
30
+ export type Organization = z.infer<typeof organizationSchema>;
31
+ /**
32
+ * Whether a project accepts new work.
33
+ *
34
+ * `archived` is reversible and stops new schedules without destroying history;
35
+ * `deleted` is a tombstone. Deletion keeps the row rather than removing it,
36
+ * because a project identifier that vanishes makes every occurrence and audit
37
+ * entry that referenced it unexplainable — and because reusing a deleted
38
+ * project's identifier must be impossible.
39
+ */
40
+ export declare const PROJECT_STATUSES: readonly ["active", "archived", "deleted"];
41
+ export declare const projectStatusSchema: z.ZodEnum<{
42
+ active: "active";
43
+ archived: "archived";
44
+ deleted: "deleted";
45
+ }>;
46
+ export type ProjectStatus = z.infer<typeof projectStatusSchema>;
47
+ /**
48
+ * A human label for a project. Mutable, non-unique, and never an identifier.
49
+ *
50
+ * Deliberately not a slug. A name that doubles as an identifier invites callers
51
+ * to construct URLs from it, and then renaming a project becomes a breaking
52
+ * change for them. Identifiers are server-assigned and opaque; names are for
53
+ * people.
54
+ */
55
+ export declare const projectNameSchema: z.ZodString;
56
+ export declare const projectSchema: z.ZodObject<{
57
+ id: z.ZodString;
58
+ name: z.ZodString;
59
+ organization: z.ZodString;
60
+ status: z.ZodEnum<{
61
+ active: "active";
62
+ archived: "archived";
63
+ deleted: "deleted";
64
+ }>;
65
+ version: z.ZodNumber;
66
+ }, z.core.$strip>;
67
+ export type Project = z.infer<typeof projectSchema>;
68
+ /**
69
+ * One of a project's two environments.
70
+ *
71
+ * `kind` is immutable, and that is the whole point of the type. A mutable kind
72
+ * would mean a test environment could become live — silently promoting every
73
+ * schedule, endpoint and credential inside it, all of which were created under
74
+ * the assumption that nothing they did could reach a customer.
75
+ */
76
+ export declare const environmentSchema: z.ZodObject<{
77
+ id: z.ZodString;
78
+ kind: z.ZodEnum<{
79
+ test: "test";
80
+ live: "live";
81
+ }>;
82
+ project: z.ZodString;
83
+ }, z.core.$strip>;
84
+ export type Environment = z.infer<typeof environmentSchema>;
85
+ /**
86
+ * A project together with both of its environments.
87
+ *
88
+ * Returned as a unit because a project without both is not a valid state: they
89
+ * are provisioned in the same transaction, and any caller that has one has both.
90
+ */
91
+ export declare const provisionedProjectSchema: z.ZodObject<{
92
+ environments: z.ZodArray<z.ZodObject<{
93
+ id: z.ZodString;
94
+ kind: z.ZodEnum<{
95
+ test: "test";
96
+ live: "live";
97
+ }>;
98
+ project: z.ZodString;
99
+ }, z.core.$strip>>;
100
+ project: z.ZodObject<{
101
+ id: z.ZodString;
102
+ name: z.ZodString;
103
+ organization: z.ZodString;
104
+ status: z.ZodEnum<{
105
+ active: "active";
106
+ archived: "archived";
107
+ deleted: "deleted";
108
+ }>;
109
+ version: z.ZodNumber;
110
+ }, z.core.$strip>;
111
+ }, z.core.$strip>;
112
+ export type ProvisionedProject = z.infer<typeof provisionedProjectSchema>;
113
+ /**
114
+ * What a signed-in member is told about a project they may act in.
115
+ *
116
+ * **Not `provisionedProjectSchema`, deliberately.** That shape carries
117
+ * `organization`, `status`, `version` and both environment *identifiers*, and
118
+ * publishing environment ids would make them public names — while nothing on
119
+ * `/v1` takes one: every operation that names an environment names its
120
+ * `kind`. Publishing an identifier no operation accepts invites a client to
121
+ * build on it and then constrains us to keep it.
122
+ *
123
+ * `{id, name}` is exactly what the OAuth consent prompt already hands a browser,
124
+ * and the framing there applies here word for word: this is a display aid rather
125
+ * than an authorization control. Whatever the list shows, the authority for a
126
+ * request is re-resolved from the member's organization when the request
127
+ * arrives.
128
+ */
129
+ export declare const projectSummarySchema: z.ZodObject<{
130
+ environmentKinds: z.ZodArray<z.ZodEnum<{
131
+ test: "test";
132
+ live: "live";
133
+ }>>;
134
+ id: z.ZodString;
135
+ name: z.ZodString;
136
+ }, z.core.$strip>;
137
+ export type ProjectSummary = z.infer<typeof projectSummarySchema>;
138
+ /**
139
+ * Every project in the member's organization that they may act in.
140
+ *
141
+ * **Unpaged, with a stated ceiling, because the store beneath it is.**
142
+ * `listProjects` reads an organization's projects in one go; declaring a page
143
+ * request over it would publish a `limit` nothing honours, which is the drift
144
+ * the artifact pipeline exists to prevent. The cap is what makes the absence of
145
+ * paging a bounded promise rather than an unbounded one — an organization that
146
+ * reaches it is a signal to page this properly, not a customer who quietly gets
147
+ * a truncated answer.
148
+ */
149
+ export declare const PROJECT_LIST_LIMIT = 200;
150
+ export declare const projectListSchema: z.ZodObject<{
151
+ data: z.ZodArray<z.ZodObject<{
152
+ environmentKinds: z.ZodArray<z.ZodEnum<{
153
+ test: "test";
154
+ live: "live";
155
+ }>>;
156
+ id: z.ZodString;
157
+ name: z.ZodString;
158
+ }, z.core.$strip>>;
159
+ }, z.core.$strip>;
160
+ export type ProjectList = z.infer<typeof projectListSchema>;
161
+ /**
162
+ * What a member sends to create a project.
163
+ *
164
+ * **A name and nothing else.** The organization comes from the verified session
165
+ * and is never read from input — the rule `authority.ts` states for every
166
+ * request — and the two environments are provisioned with the project rather
167
+ * than asked for, because `provisionProject` mints both in one transaction and
168
+ * a project observable without one of them is a state this product does not
169
+ * have.
170
+ *
171
+ * There is no `status`: a project is created `active`, and a caller that could
172
+ * create an archived one would be creating something it must then unarchive
173
+ * through an operation that does not exist.
174
+ */
175
+ export declare const projectCreateRequestSchema: z.ZodObject<{
176
+ name: z.ZodString;
177
+ }, z.core.$strip>;
178
+ export type ProjectCreateRequest = z.infer<typeof projectCreateRequestSchema>;
@@ -0,0 +1,145 @@
1
+ import { z } from "zod";
2
+ import { environmentKindSchema } from "./authority.js";
3
+ import { environmentIdSchema, organizationIdSchema, projectIdSchema, } from "./identifiers.js";
4
+ import { versionSchema } from "./protocol.js";
5
+ /**
6
+ * Organizations, projects, and environments.
7
+ *
8
+ * The tenancy spine. An organization owns projects; a project owns exactly two
9
+ * environments, `test` and `live`. Every scheduling resource belongs to one
10
+ * `(organization, project, environment)` tuple, and that tuple comes from a
11
+ * verified principal rather than from anything a client sends — see
12
+ * `authority.ts`.
13
+ *
14
+ * **Environments are not organizations.** The W1-02 guide forbids modelling them
15
+ * as duplicated organizations, and the reason is worth stating: a customer would
16
+ * then have two tenants to keep in step, membership would have to be granted
17
+ * twice, and "the same code serves test and live" — the property that makes a
18
+ * test environment worth having — would stop being true.
19
+ */
20
+ /**
21
+ * An organization, in Greatwait's own identifier space.
22
+ *
23
+ * `externalId` is the Clerk organization this projects from. The two are kept
24
+ * apart deliberately: a Greatwait `org_…` is what appears in public responses, so
25
+ * our surface never depends on the identity vendor and a caller never learns a
26
+ * second spelling of their own tenant. See `identity.ts`.
27
+ */
28
+ export const organizationSchema = z.object({
29
+ externalId: z.string().min(1),
30
+ id: organizationIdSchema,
31
+ version: versionSchema,
32
+ });
33
+ /**
34
+ * Whether a project accepts new work.
35
+ *
36
+ * `archived` is reversible and stops new schedules without destroying history;
37
+ * `deleted` is a tombstone. Deletion keeps the row rather than removing it,
38
+ * because a project identifier that vanishes makes every occurrence and audit
39
+ * entry that referenced it unexplainable — and because reusing a deleted
40
+ * project's identifier must be impossible.
41
+ */
42
+ export const PROJECT_STATUSES = ["active", "archived", "deleted"];
43
+ export const projectStatusSchema = z.enum(PROJECT_STATUSES);
44
+ /**
45
+ * A human label for a project. Mutable, non-unique, and never an identifier.
46
+ *
47
+ * Deliberately not a slug. A name that doubles as an identifier invites callers
48
+ * to construct URLs from it, and then renaming a project becomes a breaking
49
+ * change for them. Identifiers are server-assigned and opaque; names are for
50
+ * people.
51
+ */
52
+ export const projectNameSchema = z
53
+ .string()
54
+ .trim()
55
+ .min(1, "must not be blank")
56
+ .max(120, "must be at most 120 characters");
57
+ export const projectSchema = z.object({
58
+ id: projectIdSchema,
59
+ name: projectNameSchema,
60
+ organization: organizationIdSchema,
61
+ status: projectStatusSchema,
62
+ version: versionSchema,
63
+ });
64
+ /**
65
+ * One of a project's two environments.
66
+ *
67
+ * `kind` is immutable, and that is the whole point of the type. A mutable kind
68
+ * would mean a test environment could become live — silently promoting every
69
+ * schedule, endpoint and credential inside it, all of which were created under
70
+ * the assumption that nothing they did could reach a customer.
71
+ */
72
+ export const environmentSchema = z.object({
73
+ id: environmentIdSchema,
74
+ kind: environmentKindSchema,
75
+ project: projectIdSchema,
76
+ });
77
+ /**
78
+ * A project together with both of its environments.
79
+ *
80
+ * Returned as a unit because a project without both is not a valid state: they
81
+ * are provisioned in the same transaction, and any caller that has one has both.
82
+ */
83
+ export const provisionedProjectSchema = z.object({
84
+ environments: z
85
+ .array(environmentSchema)
86
+ .length(2, "a project has exactly two environments"),
87
+ project: projectSchema,
88
+ });
89
+ /**
90
+ * What a signed-in member is told about a project they may act in.
91
+ *
92
+ * **Not `provisionedProjectSchema`, deliberately.** That shape carries
93
+ * `organization`, `status`, `version` and both environment *identifiers*, and
94
+ * publishing environment ids would make them public names — while nothing on
95
+ * `/v1` takes one: every operation that names an environment names its
96
+ * `kind`. Publishing an identifier no operation accepts invites a client to
97
+ * build on it and then constrains us to keep it.
98
+ *
99
+ * `{id, name}` is exactly what the OAuth consent prompt already hands a browser,
100
+ * and the framing there applies here word for word: this is a display aid rather
101
+ * than an authorization control. Whatever the list shows, the authority for a
102
+ * request is re-resolved from the member's organization when the request
103
+ * arrives.
104
+ */
105
+ export const projectSummarySchema = z.object({
106
+ environmentKinds: z
107
+ .array(environmentKindSchema)
108
+ .length(2, "a project has exactly two environments"),
109
+ id: projectIdSchema,
110
+ name: projectNameSchema,
111
+ });
112
+ /**
113
+ * Every project in the member's organization that they may act in.
114
+ *
115
+ * **Unpaged, with a stated ceiling, because the store beneath it is.**
116
+ * `listProjects` reads an organization's projects in one go; declaring a page
117
+ * request over it would publish a `limit` nothing honours, which is the drift
118
+ * the artifact pipeline exists to prevent. The cap is what makes the absence of
119
+ * paging a bounded promise rather than an unbounded one — an organization that
120
+ * reaches it is a signal to page this properly, not a customer who quietly gets
121
+ * a truncated answer.
122
+ */
123
+ export const PROJECT_LIST_LIMIT = 200;
124
+ export const projectListSchema = z.object({
125
+ data: z
126
+ .array(projectSummarySchema)
127
+ .max(PROJECT_LIST_LIMIT, "more projects than this response can carry; paging is required"),
128
+ });
129
+ /**
130
+ * What a member sends to create a project.
131
+ *
132
+ * **A name and nothing else.** The organization comes from the verified session
133
+ * and is never read from input — the rule `authority.ts` states for every
134
+ * request — and the two environments are provisioned with the project rather
135
+ * than asked for, because `provisionProject` mints both in one transaction and
136
+ * a project observable without one of them is a state this product does not
137
+ * have.
138
+ *
139
+ * There is no `status`: a project is created `active`, and a caller that could
140
+ * create an archived one would be creating something it must then unarchive
141
+ * through an operation that does not exist.
142
+ */
143
+ export const projectCreateRequestSchema = z.object({
144
+ name: projectNameSchema,
145
+ });