@pithy-sh/core 0.9.0 → 0.10.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 (162) hide show
  1. package/dist/asyncapi/document.d.ts +46 -0
  2. package/dist/asyncapi/document.d.ts.map +1 -0
  3. package/dist/asyncapi/document.js +115 -0
  4. package/dist/capability/capability.d.ts +7 -0
  5. package/dist/capability/capability.d.ts.map +1 -1
  6. package/dist/capability/composition.d.ts.map +1 -1
  7. package/dist/capability/composition.js +5 -1
  8. package/dist/capability/settings.d.ts +10 -2
  9. package/dist/capability/settings.d.ts.map +1 -1
  10. package/dist/capability/settings.js +5 -3
  11. package/dist/cli/command.d.ts +364 -0
  12. package/dist/cli/command.d.ts.map +1 -0
  13. package/dist/cli/command.js +418 -0
  14. package/dist/cli/commandCatalog.generated.d.ts +2275 -0
  15. package/dist/cli/commandCatalog.generated.d.ts.map +1 -0
  16. package/dist/cli/commandCatalog.generated.js +2390 -0
  17. package/dist/cli/commandFacts.d.ts +164 -0
  18. package/dist/cli/commandFacts.d.ts.map +1 -0
  19. package/dist/cli/commandFacts.js +215 -0
  20. package/dist/controlPlane/error/errors.d.ts.map +1 -1
  21. package/dist/controlPlane/error/errors.js +4 -3
  22. package/dist/controlPlane/http/guard.d.ts.map +1 -1
  23. package/dist/controlPlane/http/guard.js +11 -1
  24. package/dist/controlPlane/http/routes.d.ts +1 -1
  25. package/dist/controlPlane/http/routes.d.ts.map +1 -1
  26. package/dist/controlPlane/http/routes.js +34 -7
  27. package/dist/createBackend.d.ts +7 -0
  28. package/dist/createBackend.d.ts.map +1 -1
  29. package/dist/createBackend.js +34 -4
  30. package/dist/entitlement/require.js +1 -1
  31. package/dist/error/cause.d.ts +16 -116
  32. package/dist/error/cause.d.ts.map +1 -1
  33. package/dist/error/cause.js +19 -153
  34. package/dist/error/http.d.ts +40 -0
  35. package/dist/error/http.d.ts.map +1 -1
  36. package/dist/error/payload.d.ts +80 -0
  37. package/dist/error/payload.d.ts.map +1 -1
  38. package/dist/error/payload.js +26 -0
  39. package/dist/error/pithyError.d.ts +44 -0
  40. package/dist/error/pithyError.d.ts.map +1 -1
  41. package/dist/error/pithyError.js +56 -1
  42. package/dist/error/unresolved.d.ts +265 -0
  43. package/dist/error/unresolved.d.ts.map +1 -0
  44. package/dist/error/unresolved.js +599 -0
  45. package/dist/error/wire.d.ts +20 -0
  46. package/dist/error/wire.d.ts.map +1 -0
  47. package/dist/error/wire.js +19 -0
  48. package/dist/http/oidcWebhook.d.ts +3 -3
  49. package/dist/http/oidcWebhook.js +3 -3
  50. package/dist/http/routeContract.js +1 -1
  51. package/dist/http/routeSpec.d.ts +66 -0
  52. package/dist/http/routeSpec.d.ts.map +1 -0
  53. package/dist/http/routeSpec.js +40 -0
  54. package/dist/http/sameOrigin.d.ts +1 -1
  55. package/dist/http/sameOrigin.js +1 -1
  56. package/dist/http/signedWebhook.d.ts +3 -3
  57. package/dist/http/signedWebhook.js +3 -3
  58. package/dist/http/socket.d.ts +52 -0
  59. package/dist/http/socket.d.ts.map +1 -0
  60. package/dist/http/socket.js +2 -0
  61. package/dist/http/subprotocol.d.ts +29 -0
  62. package/dist/http/subprotocol.d.ts.map +1 -0
  63. package/dist/http/subprotocol.js +37 -0
  64. package/dist/http/validation.d.ts +40 -8
  65. package/dist/http/validation.d.ts.map +1 -1
  66. package/dist/http/validation.js +25 -1
  67. package/dist/index.js +2 -2
  68. package/dist/logger/record.d.ts +23 -0
  69. package/dist/logger/record.d.ts.map +1 -1
  70. package/dist/migrations/bookkeeping.d.ts +21 -0
  71. package/dist/migrations/bookkeeping.d.ts.map +1 -1
  72. package/dist/migrations/bookkeeping.js +32 -3
  73. package/dist/migrations/groups.d.ts +140 -0
  74. package/dist/migrations/groups.d.ts.map +1 -0
  75. package/dist/migrations/groups.js +191 -0
  76. package/dist/migrations/migrateStep.d.ts +13 -0
  77. package/dist/migrations/migrateStep.d.ts.map +1 -0
  78. package/dist/migrations/migrateStep.js +20 -0
  79. package/dist/migrations/owner.d.ts +7 -0
  80. package/dist/migrations/owner.d.ts.map +1 -1
  81. package/dist/migrations/owner.js +11 -7
  82. package/dist/migrations/retained.js +2 -2
  83. package/dist/migrations/runner.d.ts +76 -5
  84. package/dist/migrations/runner.d.ts.map +1 -1
  85. package/dist/migrations/runner.js +130 -19
  86. package/dist/naming/domains.d.ts +17 -0
  87. package/dist/naming/domains.d.ts.map +1 -1
  88. package/dist/naming/domains.js +62 -4
  89. package/dist/naming/environment.d.ts.map +1 -1
  90. package/dist/naming/environment.js +2 -1
  91. package/dist/naming/packageName.d.ts +17 -0
  92. package/dist/naming/packageName.d.ts.map +1 -0
  93. package/dist/naming/packageName.js +22 -0
  94. package/dist/naming/provisionScope.d.ts.map +1 -1
  95. package/dist/naming/provisionScope.js +2 -1
  96. package/dist/openapi/document.d.ts +106 -0
  97. package/dist/openapi/document.d.ts.map +1 -0
  98. package/dist/openapi/document.js +314 -0
  99. package/dist/openapi/routeGroups.d.ts +8 -0
  100. package/dist/openapi/routeGroups.d.ts.map +1 -0
  101. package/dist/openapi/routeGroups.js +23 -0
  102. package/dist/text/comments.js +66 -4
  103. package/dist/text/literals.d.ts +43 -0
  104. package/dist/text/literals.d.ts.map +1 -0
  105. package/dist/text/literals.js +293 -0
  106. package/dist/version.generated.d.ts +1 -1
  107. package/dist/version.generated.d.ts.map +1 -1
  108. package/dist/version.generated.js +1 -1
  109. package/dist/workflow/dispatchRoute.d.ts.map +1 -1
  110. package/dist/workflow/dispatchRoute.js +12 -6
  111. package/dist/workflow/faults.d.ts.map +1 -1
  112. package/dist/workflow/faults.js +2 -3
  113. package/dist/workflow/hostEnv.d.ts +1 -0
  114. package/dist/workflow/hostEnv.d.ts.map +1 -1
  115. package/dist/workflow/hostEnv.js +4 -2
  116. package/dist/workflow/loopback.d.ts.map +1 -1
  117. package/dist/workflow/loopback.js +2 -1
  118. package/package.json +3 -3
  119. package/src/asyncapi/document.ts +164 -0
  120. package/src/capability/capability.ts +7 -0
  121. package/src/capability/composition.ts +2 -1
  122. package/src/capability/settings.ts +19 -2
  123. package/src/cli/command.ts +865 -0
  124. package/src/cli/commandCatalog.generated.ts +2533 -0
  125. package/src/cli/commandFacts.ts +219 -0
  126. package/src/controlPlane/error/errors.ts +10 -3
  127. package/src/controlPlane/http/guard.ts +14 -2
  128. package/src/controlPlane/http/routes.ts +57 -9
  129. package/src/createBackend.ts +35 -2
  130. package/src/entitlement/require.ts +1 -1
  131. package/src/error/cause.ts +18 -181
  132. package/src/error/payload.ts +59 -0
  133. package/src/error/pithyError.ts +76 -0
  134. package/src/error/unresolved.ts +853 -0
  135. package/src/error/wire.ts +40 -0
  136. package/src/http/oidcWebhook.ts +3 -3
  137. package/src/http/routeContract.ts +1 -1
  138. package/src/http/routeSpec.ts +81 -0
  139. package/src/http/sameOrigin.ts +1 -1
  140. package/src/http/signedWebhook.ts +3 -3
  141. package/src/http/socket.ts +55 -0
  142. package/src/http/subprotocol.ts +47 -0
  143. package/src/http/validation.ts +50 -8
  144. package/src/migrations/bookkeeping.ts +39 -2
  145. package/src/migrations/groups.ts +295 -0
  146. package/src/migrations/migrateStep.ts +19 -0
  147. package/src/migrations/owner.ts +10 -6
  148. package/src/migrations/retained.ts +2 -2
  149. package/src/migrations/runner.ts +214 -22
  150. package/src/naming/domains.ts +75 -16
  151. package/src/naming/environment.ts +2 -1
  152. package/src/naming/packageName.ts +20 -0
  153. package/src/naming/provisionScope.ts +2 -1
  154. package/src/openapi/document.ts +412 -0
  155. package/src/openapi/routeGroups.ts +25 -0
  156. package/src/text/comments.ts +56 -4
  157. package/src/text/literals.ts +294 -0
  158. package/src/version.generated.ts +1 -1
  159. package/src/workflow/dispatchRoute.ts +13 -6
  160. package/src/workflow/faults.ts +5 -3
  161. package/src/workflow/hostEnv.ts +9 -1
  162. package/src/workflow/loopback.ts +2 -1
@@ -0,0 +1,164 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ /**
4
+ * **What the catalog cannot say about a `pithy` command, written down once (#711).**
5
+ *
6
+ * `commandCatalog.generated.ts` is the parser's own account of every command: its arguments, its flags, which
7
+ * are required, which have defaults, which go together. Four facts are not in any parser, and each was the
8
+ * fault behind a line that did not run as written:
9
+ *
10
+ * - **Which commands act on one Worker**, and are refused `input/required` without `--worker` where a project
11
+ * has several. `packages/cli/src/ci/runnableCommands.test.ts` proves every entry by running it in a
12
+ * two-Worker project, and fails on a command that takes `--worker` and is not classified here.
13
+ * - **Which flag's default changes what the command acts on.** `pithy vector provision` with no `--env`
14
+ * provisions `dev`, so a line about staging that leaves it off sends the reader to the wrong environment.
15
+ * - **Which commands destroy something**, and are never a remedy for a smaller fault. `pithy feature destroy`
16
+ * was offered as the fix for one mis-shaped vector index.
17
+ * - **Which flag needs another beside it** that the parser does not enforce: `pithy provision --env` is refused
18
+ * without `--yes`, at run time.
19
+ *
20
+ * `command.ts` builds every command a line names from these and the catalog, and refuses one that breaks them.
21
+ * Nothing here imports anything, so a Worker that names a command pays for two tables and nothing more.
22
+ */
23
+ /**
24
+ * The commands that act on exactly one Worker, and refuse `input/required` without `--worker` when a project
25
+ * has several and the run cannot ask. Every line that names one names the Worker, by its `apps/` directory.
26
+ */
27
+ export declare const WORKER_SCOPED: readonly ["add", "dashboard connect", "email provision", "media provision", "payments provision", "storage provision", "support provision", "testers provision", "turnstile deprovision", "turnstile provision", "ui add", "ui sync", "vector provision", "vector reprocess", "vector reset", "worker sync"];
28
+ /** A command that acts on one Worker. */
29
+ export type WorkerScopedPath = (typeof WORKER_SCOPED)[number];
30
+ /**
31
+ * The commands that take `--worker` and do not need it: each fans out over every Worker, or falls back to the
32
+ * first that answers, and the flag narrows.
33
+ */
34
+ export declare const WORKER_NARROWS: readonly ["contract", "dashboard disconnect", "dashboard revoke-key", "dashboard rotate", "dashboard status", "doctor", "env", "init", "migrate", "seed", "support deprovision", "upgrade"];
35
+ /**
36
+ * A command only a person runs, at a terminal, where the Worker is asked for. `pithy remove` refuses every run
37
+ * that cannot ask (`core/person_required`).
38
+ */
39
+ export declare const PERSON_ONLY: readonly ["remove"];
40
+ /** A flag that turns a Worker-scoped command into one that acts on no Worker: `pithy add --list` reads the catalog. */
41
+ export declare const NO_WORKER_MODES: Readonly<Record<string, readonly string[]>>;
42
+ /**
43
+ * **A flag whose default decides what the command acts on.** Left off a line, the command still runs — on the
44
+ * default, which is rarely the environment the line was about. Every `--env` with a default is one: `dev` for
45
+ * `vector provision`, `migrate` and `testers list`, `staging` for `payments reconcile`. A line names it, always.
46
+ */
47
+ export declare const MEANING_FLAGS: readonly ["--env"];
48
+ /**
49
+ * The commands whose `--env` decides nothing until another flag asks it to: `pithy remove` touches no database
50
+ * without `--drop`, and `pithy upgrade` migrates none without `--migrate`. Without that flag a line need not
51
+ * name the environment; with it, it must.
52
+ */
53
+ export declare const MEANING_ONLY_WITH: {
54
+ readonly remove: "--drop";
55
+ readonly upgrade: "--migrate";
56
+ };
57
+ /**
58
+ * **The commands that destroy something, by what they destroy.** None is ever built as a remedy: a line that
59
+ * names one says it is a person's decision and what it deletes (`command.ts`'s `personDecision`), and carries
60
+ * no `fix`. `packages/core/src/cli/command.test.ts` holds every command the catalog has to this list or to
61
+ * {@link NOT_DESTRUCTIVE}, so a new one cannot arrive unexamined.
62
+ */
63
+ export declare const DESTRUCTIVE_COMMANDS: {
64
+ readonly "dashboard disconnect": "the environment's dashboard connection and the key it signs with";
65
+ readonly "dashboard revoke-key": "a signing key the dashboard holds";
66
+ readonly "email deprovision": "the email Workers, and with --suppression the suppression database";
67
+ readonly "feature destroy": "the feature's worktree, its branch and every resource it provisioned";
68
+ readonly "media deprovision": "the media Worker, and with --storage its bucket";
69
+ readonly remove: "a capability's wiring";
70
+ readonly "secrets deprovision": "the secrets manager, and with --keys the store's keys";
71
+ readonly "secrets rm": "a stored secret";
72
+ readonly "storage deprovision": "the storage Worker, and with --storage its bucket";
73
+ readonly "support deprovision": "the support Workers, and with --storage its attachments";
74
+ readonly "testers deprovision": "the testers Worker";
75
+ readonly "token revoke": "an API token";
76
+ readonly "turnstile deprovision": "the Turnstile widget, whose sitekey every client embeds";
77
+ readonly "vector reset": "every vector in the index";
78
+ readonly "worker remove": "a Worker's directory";
79
+ };
80
+ /** A command that destroys something. */
81
+ export type DestructivePath = keyof typeof DESTRUCTIVE_COMMANDS;
82
+ /**
83
+ * **The flags that make a command destroy something**, on any command that declares them. Each is refused by
84
+ * the builder; a line that needs one is a person's decision.
85
+ */
86
+ export declare const DESTRUCTIVE_FLAGS: {
87
+ readonly "--destroy-retained": "a resource kept for recovery";
88
+ readonly "--drop": "a capability's tables";
89
+ readonly "--redo": "the data a seed wrote";
90
+ readonly "--rollback": "the schema a migration group applied";
91
+ };
92
+ /** A flag that makes a command destroy something. */
93
+ export type DestructiveFlag = keyof typeof DESTRUCTIVE_FLAGS;
94
+ /**
95
+ * The commands whose name reads as destructive and which are not, and why. A command named here is built like
96
+ * any other.
97
+ */
98
+ export declare const NOT_DESTRUCTIVE: Readonly<Record<string, string>>;
99
+ /**
100
+ * **A flag whose value is a person's confirmation**, never written into a line an agent reads: a phrase spelled
101
+ * in a remedy is a confirmation nobody gave. A person's decision names the flag and leaves the phrase to them.
102
+ */
103
+ export declare const CONFIRM_FLAGS: readonly ["--confirm", "--confirm-production", "--confirm-reset", "--confirm-rollback"];
104
+ /**
105
+ * When a command asks for a confirmation: always, when a flag is passed (`when`), or in every environment but the
106
+ * ones it trusts (`unlessEnv`) — `vector reset` asks nothing of `dev`, whose index is a laptop's.
107
+ */
108
+ export declare const CONFIRMATIONS: readonly {
109
+ path: string;
110
+ when?: string;
111
+ unlessEnv?: readonly string[];
112
+ flag: string;
113
+ }[];
114
+ /**
115
+ * **A flag whose value is a credential**, never written into a line: an error's action reaches logs, a terminal
116
+ * scrollback and a `--json` consumer, none of which should hold a key. A run named again carries the flag's name
117
+ * and leaves its value to whoever passed it.
118
+ */
119
+ export declare const CREDENTIAL_FLAGS: readonly ["--api-token", "--r2-access-key-id", "--r2-api-token", "--r2-secret-access-key"];
120
+ /**
121
+ * The environments every project treats as production. A project can name more in `seed.productionEnvironments`;
122
+ * a builder that has them passes them.
123
+ */
124
+ export declare const PRODUCTION_ENVIRONMENTS: readonly ["prod", "production"];
125
+ /**
126
+ * **What a production run of a command needs from a person**, by command: the confirmation it asks for, or `null`
127
+ * for one that asks none. A production provision or seed is never a remedy — a line names it as a person's
128
+ * decision either way, and names a confirmation only when the command declares it: `testers provision` and
129
+ * `vector provision` take no `--confirm`, and a line that told a person to pass one would be refused.
130
+ */
131
+ export declare const PRODUCTION_CONFIRMS: {
132
+ readonly provision: "--confirm";
133
+ readonly seed: "--confirm-production";
134
+ readonly "secrets provision": null;
135
+ readonly "testers provision": null;
136
+ readonly "vector provision": null;
137
+ };
138
+ /** A command whose production run is a person's decision. */
139
+ export type ProductionPath = keyof typeof PRODUCTION_CONFIRMS;
140
+ /**
141
+ * **A command that acts on every environment when its `--env` is left off (#711)**, production among them. `pithy
142
+ * testers provision` with no `--env` provisions every declared environment, so the bare line touches production as
143
+ * surely as `--env prod` does, and is a person's decision for the same reason. Each declares `--env` with no
144
+ * default; `command.test.ts` holds that against the catalog.
145
+ */
146
+ export declare const EVERY_ENVIRONMENT_WITHOUT_ENV: readonly ["testers provision"];
147
+ /**
148
+ * **A command that acts on every environment on every run (#711)**, production among them, with no `--env` to narrow
149
+ * it. `pithy secrets provision` deploys each declared environment's manager and mints its store entries, so every line
150
+ * naming it touches production and is a person's decision — never the fix for one binding, one database or one
151
+ * setting. None declares `--env`; `command.test.ts` holds that against the catalog.
152
+ */
153
+ export declare const EVERY_ENVIRONMENT_ALWAYS: readonly ["secrets provision"];
154
+ /**
155
+ * A flag a command refuses to run without, beside another, that the parser does not enforce. `pithy provision
156
+ * --env <env>` with no `--yes` is refused before it does anything; a dry run needs neither.
157
+ */
158
+ export declare const REQUIRED_BESIDE: readonly {
159
+ path: string;
160
+ with: string;
161
+ needs: string;
162
+ unless: string;
163
+ }[];
164
+ //# sourceMappingURL=commandFacts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandFacts.d.ts","sourceRoot":"","sources":["../../src/cli/commandFacts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,215 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ //#region src/cli/commandFacts.ts
4
+ /**
5
+ * **What the catalog cannot say about a `pithy` command, written down once (#711).**
6
+ *
7
+ * `commandCatalog.generated.ts` is the parser's own account of every command: its arguments, its flags, which
8
+ * are required, which have defaults, which go together. Four facts are not in any parser, and each was the
9
+ * fault behind a line that did not run as written:
10
+ *
11
+ * - **Which commands act on one Worker**, and are refused `input/required` without `--worker` where a project
12
+ * has several. `packages/cli/src/ci/runnableCommands.test.ts` proves every entry by running it in a
13
+ * two-Worker project, and fails on a command that takes `--worker` and is not classified here.
14
+ * - **Which flag's default changes what the command acts on.** `pithy vector provision` with no `--env`
15
+ * provisions `dev`, so a line about staging that leaves it off sends the reader to the wrong environment.
16
+ * - **Which commands destroy something**, and are never a remedy for a smaller fault. `pithy feature destroy`
17
+ * was offered as the fix for one mis-shaped vector index.
18
+ * - **Which flag needs another beside it** that the parser does not enforce: `pithy provision --env` is refused
19
+ * without `--yes`, at run time.
20
+ *
21
+ * `command.ts` builds every command a line names from these and the catalog, and refuses one that breaks them.
22
+ * Nothing here imports anything, so a Worker that names a command pays for two tables and nothing more.
23
+ */
24
+ /**
25
+ * The commands that act on exactly one Worker, and refuse `input/required` without `--worker` when a project
26
+ * has several and the run cannot ask. Every line that names one names the Worker, by its `apps/` directory.
27
+ */
28
+ const WORKER_SCOPED = [
29
+ "add",
30
+ "dashboard connect",
31
+ "email provision",
32
+ "media provision",
33
+ "payments provision",
34
+ "storage provision",
35
+ "support provision",
36
+ "testers provision",
37
+ "turnstile deprovision",
38
+ "turnstile provision",
39
+ "ui add",
40
+ "ui sync",
41
+ "vector provision",
42
+ "vector reprocess",
43
+ "vector reset",
44
+ "worker sync"
45
+ ];
46
+ /**
47
+ * The commands that take `--worker` and do not need it: each fans out over every Worker, or falls back to the
48
+ * first that answers, and the flag narrows.
49
+ */
50
+ const WORKER_NARROWS = [
51
+ "contract",
52
+ "dashboard disconnect",
53
+ "dashboard revoke-key",
54
+ "dashboard rotate",
55
+ "dashboard status",
56
+ "doctor",
57
+ "env",
58
+ "init",
59
+ "migrate",
60
+ "seed",
61
+ "support deprovision",
62
+ "upgrade"
63
+ ];
64
+ /**
65
+ * A command only a person runs, at a terminal, where the Worker is asked for. `pithy remove` refuses every run
66
+ * that cannot ask (`core/person_required`).
67
+ */
68
+ const PERSON_ONLY = ["remove"];
69
+ /** A flag that turns a Worker-scoped command into one that acts on no Worker: `pithy add --list` reads the catalog. */
70
+ const NO_WORKER_MODES = { add: ["--list"] };
71
+ /**
72
+ * **A flag whose default decides what the command acts on.** Left off a line, the command still runs — on the
73
+ * default, which is rarely the environment the line was about. Every `--env` with a default is one: `dev` for
74
+ * `vector provision`, `migrate` and `testers list`, `staging` for `payments reconcile`. A line names it, always.
75
+ */
76
+ const MEANING_FLAGS = ["--env"];
77
+ /**
78
+ * The commands whose `--env` decides nothing until another flag asks it to: `pithy remove` touches no database
79
+ * without `--drop`, and `pithy upgrade` migrates none without `--migrate`. Without that flag a line need not
80
+ * name the environment; with it, it must.
81
+ */
82
+ const MEANING_ONLY_WITH = {
83
+ remove: "--drop",
84
+ upgrade: "--migrate"
85
+ };
86
+ /**
87
+ * **The commands that destroy something, by what they destroy.** None is ever built as a remedy: a line that
88
+ * names one says it is a person's decision and what it deletes (`command.ts`'s `personDecision`), and carries
89
+ * no `fix`. `packages/core/src/cli/command.test.ts` holds every command the catalog has to this list or to
90
+ * {@link NOT_DESTRUCTIVE}, so a new one cannot arrive unexamined.
91
+ */
92
+ const DESTRUCTIVE_COMMANDS = {
93
+ "dashboard disconnect": "the environment's dashboard connection and the key it signs with",
94
+ "dashboard revoke-key": "a signing key the dashboard holds",
95
+ "email deprovision": "the email Workers, and with --suppression the suppression database",
96
+ "feature destroy": "the feature's worktree, its branch and every resource it provisioned",
97
+ "media deprovision": "the media Worker, and with --storage its bucket",
98
+ remove: "a capability's wiring",
99
+ "secrets deprovision": "the secrets manager, and with --keys the store's keys",
100
+ "secrets rm": "a stored secret",
101
+ "storage deprovision": "the storage Worker, and with --storage its bucket",
102
+ "support deprovision": "the support Workers, and with --storage its attachments",
103
+ "testers deprovision": "the testers Worker",
104
+ "token revoke": "an API token",
105
+ "turnstile deprovision": "the Turnstile widget, whose sitekey every client embeds",
106
+ "vector reset": "every vector in the index",
107
+ "worker remove": "a Worker's directory"
108
+ };
109
+ /**
110
+ * **The flags that make a command destroy something**, on any command that declares them. Each is refused by
111
+ * the builder; a line that needs one is a person's decision.
112
+ */
113
+ const DESTRUCTIVE_FLAGS = {
114
+ "--destroy-retained": "a resource kept for recovery",
115
+ "--drop": "a capability's tables",
116
+ "--redo": "the data a seed wrote",
117
+ "--rollback": "the schema a migration group applied"
118
+ };
119
+ /**
120
+ * The commands whose name reads as destructive and which are not, and why. A command named here is built like
121
+ * any other.
122
+ */
123
+ const NOT_DESTRUCTIVE = {
124
+ "cloudflare disconnect": "revokes a sign-in and deletes no data, which `cloudflare connect` gives back",
125
+ "docs disconnect": "removes the docs server from an editor's config, which `docs connect` restores",
126
+ "feature prune": "forgets worktrees that are already gone",
127
+ "testers close": "stops a cohort accruing, and keeps its history",
128
+ "testers remove": "takes one tester off a roster, which `testers invite` reverses"
129
+ };
130
+ /**
131
+ * **A flag whose value is a person's confirmation**, never written into a line an agent reads: a phrase spelled
132
+ * in a remedy is a confirmation nobody gave. A person's decision names the flag and leaves the phrase to them.
133
+ */
134
+ const CONFIRM_FLAGS = [
135
+ "--confirm",
136
+ "--confirm-production",
137
+ "--confirm-reset",
138
+ "--confirm-rollback"
139
+ ];
140
+ /**
141
+ * When a command asks for a confirmation: always, when a flag is passed (`when`), or in every environment but the
142
+ * ones it trusts (`unlessEnv`) — `vector reset` asks nothing of `dev`, whose index is a laptop's.
143
+ */
144
+ const CONFIRMATIONS = [
145
+ {
146
+ path: "vector reset",
147
+ unlessEnv: ["dev"],
148
+ flag: "--confirm-reset"
149
+ },
150
+ {
151
+ path: "migrate",
152
+ when: "--rollback",
153
+ flag: "--confirm-rollback"
154
+ },
155
+ {
156
+ path: "seed",
157
+ when: "--redo",
158
+ flag: "--confirm-reset"
159
+ }
160
+ ];
161
+ /**
162
+ * **A flag whose value is a credential**, never written into a line: an error's action reaches logs, a terminal
163
+ * scrollback and a `--json` consumer, none of which should hold a key. A run named again carries the flag's name
164
+ * and leaves its value to whoever passed it.
165
+ */
166
+ const CREDENTIAL_FLAGS = [
167
+ "--api-token",
168
+ "--r2-access-key-id",
169
+ "--r2-api-token",
170
+ "--r2-secret-access-key"
171
+ ];
172
+ /**
173
+ * The environments every project treats as production. A project can name more in `seed.productionEnvironments`;
174
+ * a builder that has them passes them.
175
+ */
176
+ const PRODUCTION_ENVIRONMENTS = ["prod", "production"];
177
+ /**
178
+ * **What a production run of a command needs from a person**, by command: the confirmation it asks for, or `null`
179
+ * for one that asks none. A production provision or seed is never a remedy — a line names it as a person's
180
+ * decision either way, and names a confirmation only when the command declares it: `testers provision` and
181
+ * `vector provision` take no `--confirm`, and a line that told a person to pass one would be refused.
182
+ */
183
+ const PRODUCTION_CONFIRMS = {
184
+ provision: "--confirm",
185
+ seed: "--confirm-production",
186
+ "secrets provision": null,
187
+ "testers provision": null,
188
+ "vector provision": null
189
+ };
190
+ /**
191
+ * **A command that acts on every environment when its `--env` is left off (#711)**, production among them. `pithy
192
+ * testers provision` with no `--env` provisions every declared environment, so the bare line touches production as
193
+ * surely as `--env prod` does, and is a person's decision for the same reason. Each declares `--env` with no
194
+ * default; `command.test.ts` holds that against the catalog.
195
+ */
196
+ const EVERY_ENVIRONMENT_WITHOUT_ENV = ["testers provision"];
197
+ /**
198
+ * **A command that acts on every environment on every run (#711)**, production among them, with no `--env` to narrow
199
+ * it. `pithy secrets provision` deploys each declared environment's manager and mints its store entries, so every line
200
+ * naming it touches production and is a person's decision — never the fix for one binding, one database or one
201
+ * setting. None declares `--env`; `command.test.ts` holds that against the catalog.
202
+ */
203
+ const EVERY_ENVIRONMENT_ALWAYS = ["secrets provision"];
204
+ /**
205
+ * A flag a command refuses to run without, beside another, that the parser does not enforce. `pithy provision
206
+ * --env <env>` with no `--yes` is refused before it does anything; a dry run needs neither.
207
+ */
208
+ const REQUIRED_BESIDE = [{
209
+ path: "provision",
210
+ with: "--env",
211
+ needs: "--yes",
212
+ unless: "--dry-run"
213
+ }];
214
+ //#endregion
215
+ export { CONFIRMATIONS, CONFIRM_FLAGS, CREDENTIAL_FLAGS, DESTRUCTIVE_COMMANDS, DESTRUCTIVE_FLAGS, EVERY_ENVIRONMENT_ALWAYS, EVERY_ENVIRONMENT_WITHOUT_ENV, MEANING_FLAGS, MEANING_ONLY_WITH, NOT_DESTRUCTIVE, NO_WORKER_MODES, PERSON_ONLY, PRODUCTION_CONFIRMS, PRODUCTION_ENVIRONMENTS, REQUIRED_BESIDE, WORKER_NARROWS, WORKER_SCOPED };
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/error/errors.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;;;;;;;;;;GAYG;AAEH,UAAU,qBAAqB;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,UAAU;IAC3D,YAAY,IAAI,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY1E;CACF;AAED;;;GAGG;AACH,qBAAa,kCAAmC,SAAQ,UAAU;IAChE,YAAY,IAAI,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY1E;CACF;AAED,sEAAsE;AACtE,qBAAa,kCAAmC,SAAQ,UAAU;IAChE,YAAY,IAAI,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY1E;CACF;AAED,0DAA0D;AAC1D,qBAAa,4BAA6B,SAAQ,UAAU;IAC1D,YAAY,IAAI,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY1E;CACF;AAED;;;;GAIG;AACH,qBAAa,4BAA6B,SAAQ,UAAU;IAC1D,YAAY,IAAI,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY1E;CACF"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/error/errors.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;;;;;;;;;;GAYG;AAEH,UAAU,qBAAqB;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED;;;GAGG;AACH,qBAAa,6BAA8B,SAAQ,UAAU;IAC3D,YAAY,IAAI,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAc1E;CACF;AAED;;;GAGG;AACH,qBAAa,kCAAmC,SAAQ,UAAU;IAChE,YAAY,IAAI,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAc1E;CACF;AAED,sEAAsE;AACtE,qBAAa,kCAAmC,SAAQ,UAAU;IAChE,YAAY,IAAI,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAc1E;CACF;AAED,0DAA0D;AAC1D,qBAAa,4BAA6B,SAAQ,UAAU;IAC1D,YAAY,IAAI,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY1E;CACF;AAED;;;;GAIG;AACH,qBAAa,4BAA6B,SAAQ,UAAU;IAC1D,YAAY,IAAI,GAAE,qBAA0B,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY1E;CACF"}
@@ -1,6 +1,7 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
3
  import { PithyError } from "../../error/pithyError.js";
4
+ import { commandName } from "../../cli/command.js";
4
5
  //#region src/controlPlane/error/errors.ts
5
6
  /**
6
7
  * No connection is registered for this environment. The shipped default of a Worker that composes the
@@ -12,7 +13,7 @@ var ControlPlaneNotConnectedError = class extends PithyError {
12
13
  code: "controlplane/not_connected",
13
14
  status: 403,
14
15
  message: args.message ?? "No management client is connected to this environment.",
15
- action: args.action ?? "Run pithy dashboard connect --env <environment> to register one.",
16
+ action: args.action ?? `Register one for this environment with ${commandName("dashboard connect")}, naming it with --env.`,
16
17
  detail: args.detail,
17
18
  params: args.params
18
19
  }, options);
@@ -28,7 +29,7 @@ var ControlPlaneInvalidCredentialError = class extends PithyError {
28
29
  code: "controlplane/invalid_credential",
29
30
  status: 401,
30
31
  message: args.message ?? "That credential is not valid here.",
31
- action: args.action ?? "Rotate the connection's key, or re-run pithy dashboard connect --update.",
32
+ action: args.action ?? `Rotate the connection's key, or update this environment's connection with ${commandName("dashboard connect")} and its --update flag.`,
32
33
  detail: args.detail,
33
34
  params: args.params
34
35
  }, options);
@@ -41,7 +42,7 @@ var ControlPlaneInsufficientScopeError = class extends PithyError {
41
42
  code: "controlplane/insufficient_scope",
42
43
  status: 403,
43
44
  message: args.message ?? "This connection is not scoped for that operation.",
44
- action: args.action ?? "Re-run pithy dashboard connect --update and grant the scope this call needs.",
45
+ action: args.action ?? `Update this environment's connection with ${commandName("dashboard connect")} and its --update flag, granting the scope this call needs.`,
45
46
  detail: args.detail,
46
47
  params: args.params
47
48
  }, options);
@@ -1 +1 @@
1
- {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/http/guard.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAIhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EAAE,KAAK,sBAAsB,EAA0B,MAAM,UAAU,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,uBAAuB,KACjC,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAElC;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,sBAAsB,GAAG,oBAAoB,CAgB7F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMzE;AAED;;;;;;GAMG;AACH;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,eAAwC,CAAC;AAEzE,yDAAyD;AACzD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAE7D;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,uBAAuB,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAkEzG"}
1
+ {"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/http/guard.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAMhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAE9D,OAAO,EAAE,KAAK,sBAAsB,EAA0B,MAAM,UAAU,CAAC;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,CACjC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,uBAAuB,KACjC,OAAO,CAAC,mBAAmB,CAAC,CAAC;AAElC;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,sBAAsB,GAAG,oBAAoB,CAgB7F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMzE;AAED;;;;;;GAMG;AACH;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,eAAwC,CAAC;AAEzE,yDAAyD;AACzD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAE7D;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,uBAAuB,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAkEzG"}
@@ -1,7 +1,9 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
3
  import { PithyError } from "../../error/pithyError.js";
4
+ import { commandName, remedy } from "../../cli/command.js";
4
5
  import { workerVersionMetadata } from "../../worker/identity.js";
6
+ import { compositionEnvironment } from "../../env/ambient.js";
5
7
  import { ControlPlaneAuditActions, safeEmit } from "../audit/actions.js";
6
8
  import { ControlPlaneNotConnectedError } from "../error/errors.js";
7
9
  import { CONTROL_PLANE_VERSION_CREATED_HEADER, CONTROL_PLANE_VERSION_HEADER } from "../wire.js";
@@ -69,7 +71,7 @@ function requireControlPlane(requirement) {
69
71
  if (!verify) {
70
72
  const denial = new ControlPlaneNotConnectedError({
71
73
  message: "This deployment does not accept management-client calls.",
72
- action: "Add `controlplane()` to this Worker's pithy.config.ts, then run pithy dashboard connect.",
74
+ action: `Add \`controlplane()\` to this Worker's pithy.config.ts, then ${connectStep(compositionEnvironment(c.env))}.`,
73
75
  detail: "no control-plane verifier on the request — the controlplane capability is not composed"
74
76
  });
75
77
  await auditDenial(c, requirement, denial);
@@ -140,5 +142,13 @@ async function auditDenial(c, requirement, cause) {
140
142
  }
141
143
  }, c.var.log);
142
144
  }
145
+ /**
146
+ * The step that connects a management client, as this deployed Worker can name it: with its own environment when
147
+ * it knows it, and never with a Worker — it cannot know the `apps/` directory that provisioned it (#711).
148
+ */
149
+ function connectStep(env) {
150
+ if (env === void 0) return `connect one with ${commandName("dashboard connect")}, naming this environment with --env`;
151
+ return remedy("dashboard connect", { flags: { "--env": env } }, { runtime: true }).say((command) => `run ${command}`);
152
+ }
143
153
  //#endregion
144
154
  export { CONTROL_PLANE_GUARD, createControlPlaneVerifier, isControlPlaneGuard, requireControlPlane, workerVersionHeaders };
@@ -2,7 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  import type { Hono } from "hono";
4
4
  import type { PithyHonoEnv } from "../../capability/capability";
5
- import type { AdminRoute } from "../discovery/adminRoute";
5
+ import { type AdminRoute } from "../discovery/adminRoute";
6
6
  import { type ControlPlaneHandlerDeps } from "./handlers";
7
7
  /**
8
8
  * The seam's own routes, distinct from the admin routes capabilities contribute.
@@ -1 +1 @@
1
- {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/http/routes.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAG1D,OAAO,EACL,KAAK,uBAAuB,EAM7B,MAAM,YAAY,CAAC;AAGpB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CAiC3E;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,IAAI,CAAC,YAAY,CAAC,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,uBAAuB,GAC5B,IAAI,CAqBN"}
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/http/routes.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAGhE,OAAO,EAAE,KAAK,UAAU,EAAwB,MAAM,yBAAyB,CAAC;AAGhF,OAAO,EACL,KAAK,uBAAuB,EAM7B,MAAM,YAAY,CAAC;AASpB;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CAiC3E;AAED,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,IAAI,CAAC,YAAY,CAAC,EACvB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,uBAAuB,GAC5B,IAAI,CA+DN"}
@@ -2,10 +2,12 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  import { ANY_VERIFIED_CALLER, KEYS_ROTATE_SCOPE, MANIFEST_READ_SCOPE } from "../scope/scope.js";
4
4
  import { requireControlPlane } from "./guard.js";
5
- import { validationHook } from "../../http/validation.js";
5
+ import { describeRoute } from "../../http/routeSpec.js";
6
+ import { validate } from "../../http/validation.js";
7
+ import { ControlPlaneManifest } from "../discovery/adminRoute.js";
6
8
  import { expireKeyHandler, listKeysHandler, manifestHandler, pingHandler, registerKeyHandler } from "./handlers.js";
9
+ import { ControlPlaneKeysResponse, ControlPlanePingResponse, ExpireKeyResponse, RegisterKeyResponse } from "./responses.js";
7
10
  import { ExpireKeyParams, ExpireKeyRequest, RegisterKeyRequest } from "./schemas.js";
8
- import { zValidator } from "@hono/zod-validator";
9
11
  //#region src/controlPlane/http/routes.ts
10
12
  /**
11
13
  * The seam's own routes, distinct from the admin routes capabilities contribute.
@@ -75,11 +77,36 @@ function controlPlaneRouteDescriptors(basePath) {
75
77
  ];
76
78
  }
77
79
  function registerControlPlaneRoutes(app, basePath, deps) {
78
- app.get(`${basePath}/ping`, requireControlPlane(ANY_VERIFIED_CALLER), pingHandler(deps));
79
- app.get(`${basePath}/manifest`, requireControlPlane(MANIFEST_READ_SCOPE), manifestHandler(deps));
80
- app.get(`${basePath}/keys`, requireControlPlane(KEYS_ROTATE_SCOPE), listKeysHandler(deps));
81
- app.post(`${basePath}/keys`, requireControlPlane(KEYS_ROTATE_SCOPE), zValidator("json", RegisterKeyRequest, validationHook), (c) => registerKeyHandler(deps)(c, c.req.valid("json")));
82
- app.post(`${basePath}/keys/:keyId/expire`, requireControlPlane(KEYS_ROTATE_SCOPE), zValidator("param", ExpireKeyParams, validationHook), zValidator("json", ExpireKeyRequest, validationHook), (c) => expireKeyHandler(deps)(c, c.req.valid("param"), c.req.valid("json")));
80
+ app.get(`${basePath}/ping`, describeRoute({
81
+ summary: "Prove the connection and the key it signs with.",
82
+ verification: "control-plane",
83
+ responses: { 200: ControlPlanePingResponse }
84
+ }), requireControlPlane(ANY_VERIFIED_CALLER), pingHandler(deps));
85
+ app.get(`${basePath}/manifest`, describeRoute({
86
+ summary: "Describe what this Worker composes and how to call its admin surface.",
87
+ verification: "control-plane",
88
+ scopes: [MANIFEST_READ_SCOPE],
89
+ responses: { 200: ControlPlaneManifest }
90
+ }), requireControlPlane(MANIFEST_READ_SCOPE), manifestHandler(deps));
91
+ app.get(`${basePath}/keys`, describeRoute({
92
+ summary: "Read the connection's key registration state.",
93
+ verification: "control-plane",
94
+ scopes: [KEYS_ROTATE_SCOPE],
95
+ responses: { 200: ControlPlaneKeysResponse }
96
+ }), requireControlPlane(KEYS_ROTATE_SCOPE), listKeysHandler(deps));
97
+ app.post(`${basePath}/keys`, describeRoute({
98
+ summary: "Register a key for the connection.",
99
+ verification: "control-plane",
100
+ scopes: [KEYS_ROTATE_SCOPE],
101
+ responses: { 201: RegisterKeyResponse }
102
+ }), requireControlPlane(KEYS_ROTATE_SCOPE), validate("json", RegisterKeyRequest), (c) => registerKeyHandler(deps)(c, c.req.valid("json")));
103
+ app.post(`${basePath}/keys/:keyId/expire`, describeRoute({
104
+ summary: "Retire a superseded key.",
105
+ description: "Must be signed with the successor it names as proven.",
106
+ verification: "control-plane",
107
+ scopes: [KEYS_ROTATE_SCOPE],
108
+ responses: { 200: ExpireKeyResponse }
109
+ }), requireControlPlane(KEYS_ROTATE_SCOPE), validate("param", ExpireKeyParams), validate("json", ExpireKeyRequest), (c) => expireKeyHandler(deps)(c, c.req.valid("param"), c.req.valid("json")));
83
110
  }
84
111
  //#endregion
85
112
  export { controlPlaneRouteDescriptors, registerControlPlaneRoutes };
@@ -1,6 +1,7 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
3
  import { Hono } from "hono";
4
+ import { z } from "zod";
4
5
  import type { Capability, MergedDatabases, MergedKvNamespaces, MergedWorkflowParams, PithyVars } from "./capability/capability";
5
6
  import { type DbRegistry } from "./data/databases";
6
7
  import { type KvRegistry } from "./kv/namespaces";
@@ -39,6 +40,12 @@ type BackendEnv<Caps extends readonly Capability[]> = {
39
40
  workflows: WorkflowDispatcher<MergedWorkflowParams<Caps>>;
40
41
  };
41
42
  };
43
+ /** What `GET /health` answers. */
44
+ export declare const HealthBody: z.ZodObject<{
45
+ status: z.ZodLiteral<"ok">;
46
+ version: z.ZodNullable<z.ZodString>;
47
+ }, z.core.$strip>;
48
+ export type HealthBody = z.infer<typeof HealthBody>;
42
49
  /**
43
50
  * Assemble capabilities into a deployable Hono app — a valid Worker `fetch` handler.
44
51
  *
@@ -1 +1 @@
1
- {"version":3,"file":"createBackend.d.ts","sourceRoot":"","sources":["../src/createBackend.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAG5B,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EAEpB,SAAS,EACV,MAAM,yBAAyB,CAAC;AAKjC,OAAO,EAAqC,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAKtF,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE9E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAK9C,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGvF,oGAAoG;AACpG,MAAM,WAAW,oBAAoB,CAAC,IAAI,SAAS,SAAS,UAAU,EAAE,EAAE,GAAG,SAAS,UAAU;IAC9F,2EAA2E;IAC3E,YAAY,EAAE,IAAI,CAAC;IACnB;;;OAGG;IACH,GAAG,CAAC,EAAE,GAAG,CAAC;IACV;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,iHAAiH;AACjH,KAAK,UAAU,CAAC,IAAI,SAAS,SAAS,UAAU,EAAE,IAAI;IACpD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,GAAG,IAAI,GAAG,WAAW,CAAC,GAAG;QACtD,EAAE,EAAE,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,EAAE,EAAE,UAAU,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;QACzC,SAAS,EAAE,kBAAkB,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;KAC3D,CAAC;CACH,CAAC;AAuCF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAC3B,KAAK,CAAC,IAAI,SAAS,SAAS,UAAU,EAAE,EACxC,KAAK,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EACrF,OAAO,EAAE,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CA0KrF"}
1
+ {"version":3,"file":"createBackend.d.ts","sourceRoot":"","sources":["../src/createBackend.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,oBAAoB,EAEpB,SAAS,EACV,MAAM,yBAAyB,CAAC;AAMjC,OAAO,EAAqC,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAMtF,OAAO,EAA8B,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE9E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAO9C,OAAO,EAA2B,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAGvF,oGAAoG;AACpG,MAAM,WAAW,oBAAoB,CAAC,IAAI,SAAS,SAAS,UAAU,EAAE,EAAE,GAAG,SAAS,UAAU;IAC9F,2EAA2E;IAC3E,YAAY,EAAE,IAAI,CAAC;IACnB;;;OAGG;IACH,GAAG,CAAC,EAAE,GAAG,CAAC;IACV;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,iHAAiH;AACjH,KAAK,UAAU,CAAC,IAAI,SAAS,SAAS,UAAU,EAAE,IAAI;IACpD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,GAAG,IAAI,GAAG,WAAW,CAAC,GAAG;QACtD,EAAE,EAAE,UAAU,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;QACtC,EAAE,EAAE,UAAU,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;QACzC,SAAS,EAAE,kBAAkB,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC;KAC3D,CAAC;CACH,CAAC;AAuCF,kCAAkC;AAClC,eAAO,MAAM,UAAU;;;iBAQ+B,CAAC;AACvD,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAC3B,KAAK,CAAC,IAAI,SAAS,SAAS,UAAU,EAAE,EACxC,KAAK,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EACrF,OAAO,EAAE,oBAAoB,CAAC,IAAI,EAAE,GAAG,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,CA0LrF"}