@pithy-sh/core 0.9.0 → 0.11.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.
- package/dist/access/access.d.ts +172 -0
- package/dist/access/access.d.ts.map +1 -0
- package/dist/access/access.js +147 -0
- package/dist/access/acting.d.ts +49 -0
- package/dist/access/acting.d.ts.map +1 -0
- package/dist/access/acting.js +21 -0
- package/dist/access/policyCheck.d.ts +33 -0
- package/dist/access/policyCheck.d.ts.map +1 -0
- package/dist/access/policyCheck.js +48 -0
- package/dist/access/usage.d.ts +83 -0
- package/dist/access/usage.d.ts.map +1 -0
- package/dist/access/usage.js +104 -0
- package/dist/access/visibility.d.ts +66 -0
- package/dist/access/visibility.d.ts.map +1 -0
- package/dist/access/visibility.js +86 -0
- package/dist/asyncapi/document.d.ts +46 -0
- package/dist/asyncapi/document.d.ts.map +1 -0
- package/dist/asyncapi/document.js +115 -0
- package/dist/audit/auditEvent.d.ts +5 -0
- package/dist/audit/auditEvent.d.ts.map +1 -1
- package/dist/audit/auditEvent.js +2 -0
- package/dist/capability/bindings.d.ts +47 -2
- package/dist/capability/bindings.d.ts.map +1 -1
- package/dist/capability/bindings.js +117 -7
- package/dist/capability/capability.d.ts +105 -28
- package/dist/capability/capability.d.ts.map +1 -1
- package/dist/capability/composition.d.ts.map +1 -1
- package/dist/capability/composition.js +5 -1
- package/dist/capability/manifest.d.ts +2 -1
- package/dist/capability/manifest.d.ts.map +1 -1
- package/dist/capability/manifest.js +1 -1
- package/dist/capability/settings.d.ts +96 -4
- package/dist/capability/settings.d.ts.map +1 -1
- package/dist/capability/settings.js +85 -4
- package/dist/cli/command.d.ts +364 -0
- package/dist/cli/command.d.ts.map +1 -0
- package/dist/cli/command.js +418 -0
- package/dist/cli/commandCatalog.generated.d.ts +2437 -0
- package/dist/cli/commandCatalog.generated.d.ts.map +1 -0
- package/dist/cli/commandCatalog.generated.js +2564 -0
- package/dist/cli/commandFacts.d.ts +164 -0
- package/dist/cli/commandFacts.d.ts.map +1 -0
- package/dist/cli/commandFacts.js +216 -0
- package/dist/controlPlane/capability.d.ts.map +1 -1
- package/dist/controlPlane/capability.js +12 -2
- package/dist/controlPlane/context.d.ts +5 -0
- package/dist/controlPlane/context.d.ts.map +1 -1
- package/dist/controlPlane/context.js +3 -1
- package/dist/controlPlane/data/connection.d.ts +47 -0
- package/dist/controlPlane/data/connection.d.ts.map +1 -1
- package/dist/controlPlane/data/connection.js +55 -1
- package/dist/controlPlane/error/errors.d.ts.map +1 -1
- package/dist/controlPlane/error/errors.js +4 -3
- package/dist/controlPlane/http/cors.d.ts +4 -4
- package/dist/controlPlane/http/cors.js +4 -4
- package/dist/controlPlane/http/guard.d.ts +11 -0
- package/dist/controlPlane/http/guard.d.ts.map +1 -1
- package/dist/controlPlane/http/guard.js +28 -2
- package/dist/controlPlane/http/handlers.d.ts +60 -0
- package/dist/controlPlane/http/handlers.d.ts.map +1 -1
- package/dist/controlPlane/http/handlers.js +31 -2
- package/dist/controlPlane/http/readiness.d.ts +33 -0
- package/dist/controlPlane/http/readiness.d.ts.map +1 -0
- package/dist/controlPlane/http/readiness.js +39 -0
- package/dist/controlPlane/http/responses.d.ts +147 -0
- package/dist/controlPlane/http/responses.d.ts.map +1 -1
- package/dist/controlPlane/http/responses.js +61 -4
- package/dist/controlPlane/http/routes.d.ts +2 -1
- package/dist/controlPlane/http/routes.d.ts.map +1 -1
- package/dist/controlPlane/http/routes.js +50 -9
- package/dist/controlPlane/http/verify.d.ts.map +1 -1
- package/dist/controlPlane/http/verify.js +2 -1
- package/dist/controlPlane/migrationState/migrationState.d.ts +102 -0
- package/dist/controlPlane/migrationState/migrationState.d.ts.map +1 -0
- package/dist/controlPlane/migrationState/migrationState.js +142 -0
- package/dist/controlPlane/migrations/0003_connection_principal.d.ts +21 -0
- package/dist/controlPlane/migrations/0003_connection_principal.d.ts.map +1 -0
- package/dist/controlPlane/migrations/0003_connection_principal.js +33 -0
- package/dist/controlPlane/scope/scope.d.ts +13 -2
- package/dist/controlPlane/scope/scope.d.ts.map +1 -1
- package/dist/controlPlane/scope/scope.js +14 -3
- package/dist/createBackend.d.ts +7 -0
- package/dist/createBackend.d.ts.map +1 -1
- package/dist/createBackend.js +41 -6
- package/dist/createEntrypoint.d.ts.map +1 -1
- package/dist/createEntrypoint.js +5 -3
- package/dist/entitlement/allowance.d.ts +25 -0
- package/dist/entitlement/allowance.d.ts.map +1 -0
- package/dist/entitlement/allowance.js +80 -0
- package/dist/entitlement/entitlement.d.ts +41 -0
- package/dist/entitlement/entitlement.d.ts.map +1 -1
- package/dist/entitlement/meter.d.ts +57 -0
- package/dist/entitlement/meter.d.ts.map +1 -0
- package/dist/entitlement/meter.js +13 -0
- package/dist/entitlement/require.js +1 -1
- package/dist/error/cause.d.ts +16 -116
- package/dist/error/cause.d.ts.map +1 -1
- package/dist/error/cause.js +19 -153
- package/dist/error/http.d.ts +184 -0
- package/dist/error/http.d.ts.map +1 -1
- package/dist/error/payload.d.ts +368 -0
- package/dist/error/payload.d.ts.map +1 -1
- package/dist/error/payload.js +126 -4
- package/dist/error/pithyError.d.ts +44 -0
- package/dist/error/pithyError.d.ts.map +1 -1
- package/dist/error/pithyError.js +56 -1
- package/dist/error/unresolved.d.ts +265 -0
- package/dist/error/unresolved.d.ts.map +1 -0
- package/dist/error/unresolved.js +599 -0
- package/dist/error/wire.d.ts +20 -0
- package/dist/error/wire.d.ts.map +1 -0
- package/dist/error/wire.js +19 -0
- package/dist/http/authContext.d.ts +7 -0
- package/dist/http/authContext.d.ts.map +1 -1
- package/dist/http/authContext.js +8 -1
- package/dist/http/oidcWebhook.d.ts +3 -3
- package/dist/http/oidcWebhook.js +3 -3
- package/dist/http/routeContract.js +1 -1
- package/dist/http/routeSpec.d.ts +66 -0
- package/dist/http/routeSpec.d.ts.map +1 -0
- package/dist/http/routeSpec.js +40 -0
- package/dist/http/sameOrigin.d.ts +1 -1
- package/dist/http/sameOrigin.js +1 -1
- package/dist/http/scopeGates.d.ts +20 -0
- package/dist/http/scopeGates.d.ts.map +1 -0
- package/dist/http/scopeGates.js +36 -0
- package/dist/http/signedWebhook.d.ts +3 -3
- package/dist/http/signedWebhook.js +3 -3
- package/dist/http/socket.d.ts +52 -0
- package/dist/http/socket.d.ts.map +1 -0
- package/dist/http/socket.js +2 -0
- package/dist/http/subprotocol.d.ts +29 -0
- package/dist/http/subprotocol.d.ts.map +1 -0
- package/dist/http/subprotocol.js +37 -0
- package/dist/http/validation.d.ts +40 -8
- package/dist/http/validation.d.ts.map +1 -1
- package/dist/http/validation.js +25 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/logger/record.d.ts +107 -0
- package/dist/logger/record.d.ts.map +1 -1
- package/dist/migrations/bookkeeping.d.ts +21 -0
- package/dist/migrations/bookkeeping.d.ts.map +1 -1
- package/dist/migrations/bookkeeping.js +32 -3
- package/dist/migrations/capabilitySets.d.ts +23 -0
- package/dist/migrations/capabilitySets.d.ts.map +1 -0
- package/dist/migrations/capabilitySets.js +74 -0
- package/dist/migrations/groups.d.ts +140 -0
- package/dist/migrations/groups.d.ts.map +1 -0
- package/dist/migrations/groups.js +191 -0
- package/dist/migrations/migrateStep.d.ts +13 -0
- package/dist/migrations/migrateStep.d.ts.map +1 -0
- package/dist/migrations/migrateStep.js +20 -0
- package/dist/migrations/owner.d.ts +7 -0
- package/dist/migrations/owner.d.ts.map +1 -1
- package/dist/migrations/owner.js +11 -7
- package/dist/migrations/registry.d.ts +26 -0
- package/dist/migrations/registry.d.ts.map +1 -1
- package/dist/migrations/registry.js +38 -7
- package/dist/migrations/retained.js +2 -2
- package/dist/migrations/runner.d.ts +76 -5
- package/dist/migrations/runner.d.ts.map +1 -1
- package/dist/migrations/runner.js +130 -19
- package/dist/migrations/state.d.ts +60 -0
- package/dist/migrations/state.d.ts.map +1 -0
- package/dist/migrations/state.js +46 -0
- package/dist/naming/domains.d.ts +17 -0
- package/dist/naming/domains.d.ts.map +1 -1
- package/dist/naming/domains.js +62 -4
- package/dist/naming/environment.d.ts.map +1 -1
- package/dist/naming/environment.js +2 -1
- package/dist/naming/feature.d.ts +27 -5
- package/dist/naming/feature.d.ts.map +1 -1
- package/dist/naming/feature.js +36 -6
- package/dist/naming/limits.d.ts +47 -3
- package/dist/naming/limits.d.ts.map +1 -1
- package/dist/naming/limits.js +47 -3
- package/dist/naming/packageName.d.ts +17 -0
- package/dist/naming/packageName.d.ts.map +1 -0
- package/dist/naming/packageName.js +22 -0
- package/dist/naming/provisionScope.d.ts +6 -0
- package/dist/naming/provisionScope.d.ts.map +1 -1
- package/dist/naming/provisionScope.js +10 -4
- package/dist/naming/resourceNames.d.ts +21 -2
- package/dist/naming/resourceNames.d.ts.map +1 -1
- package/dist/naming/resourceNames.js +21 -3
- package/dist/openapi/document.d.ts +106 -0
- package/dist/openapi/document.d.ts.map +1 -0
- package/dist/openapi/document.js +314 -0
- package/dist/openapi/routeGroups.d.ts +8 -0
- package/dist/openapi/routeGroups.d.ts.map +1 -0
- package/dist/openapi/routeGroups.js +23 -0
- package/dist/seed/writeD1.d.ts +7 -1
- package/dist/seed/writeD1.d.ts.map +1 -1
- package/dist/seed/writeD1.js +9 -3
- package/dist/seed/writeKv.d.ts +2 -0
- package/dist/seed/writeKv.d.ts.map +1 -1
- package/dist/seed/writeKv.js +6 -2
- package/dist/text/comments.js +66 -4
- package/dist/text/literals.d.ts +43 -0
- package/dist/text/literals.d.ts.map +1 -0
- package/dist/text/literals.js +293 -0
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.d.ts.map +1 -1
- package/dist/version.generated.js +1 -1
- package/dist/worker/serviceLoopback.d.ts +36 -0
- package/dist/worker/serviceLoopback.d.ts.map +1 -0
- package/dist/worker/serviceLoopback.js +74 -0
- package/dist/workflow/dispatchRoute.d.ts.map +1 -1
- package/dist/workflow/dispatchRoute.js +12 -6
- package/dist/workflow/faults.d.ts +12 -1
- package/dist/workflow/faults.d.ts.map +1 -1
- package/dist/workflow/faults.js +24 -18
- package/dist/workflow/hostEnv.d.ts +1 -0
- package/dist/workflow/hostEnv.d.ts.map +1 -1
- package/dist/workflow/hostEnv.js +4 -2
- package/dist/workflow/loopback.d.ts.map +1 -1
- package/dist/workflow/loopback.js +2 -1
- package/package.json +4 -4
- package/src/access/access.ts +298 -0
- package/src/access/acting.ts +59 -0
- package/src/access/policyCheck.ts +77 -0
- package/src/access/usage.ts +141 -0
- package/src/access/visibility.ts +109 -0
- package/src/asyncapi/document.ts +164 -0
- package/src/audit/auditEvent.ts +4 -0
- package/src/capability/bindings.ts +159 -13
- package/src/capability/capability.ts +106 -29
- package/src/capability/composition.ts +2 -1
- package/src/capability/settings.ts +165 -4
- package/src/cli/command.ts +865 -0
- package/src/cli/commandCatalog.generated.ts +2723 -0
- package/src/cli/commandFacts.ts +220 -0
- package/src/controlPlane/capability.ts +25 -1
- package/src/controlPlane/context.ts +4 -0
- package/src/controlPlane/data/connection.ts +90 -0
- package/src/controlPlane/error/errors.ts +10 -3
- package/src/controlPlane/http/cors.ts +4 -4
- package/src/controlPlane/http/guard.ts +35 -2
- package/src/controlPlane/http/handlers.ts +41 -0
- package/src/controlPlane/http/readiness.ts +50 -0
- package/src/controlPlane/http/responses.ts +140 -2
- package/src/controlPlane/http/routes.ts +82 -10
- package/src/controlPlane/http/verify.ts +2 -0
- package/src/controlPlane/migrationState/migrationState.ts +200 -0
- package/src/controlPlane/migrations/0003_connection_principal.ts +37 -0
- package/src/controlPlane/scope/scope.ts +14 -2
- package/src/createBackend.ts +59 -8
- package/src/createEntrypoint.ts +9 -3
- package/src/entitlement/allowance.ts +85 -0
- package/src/entitlement/entitlement.ts +38 -0
- package/src/entitlement/meter.ts +69 -0
- package/src/entitlement/require.ts +1 -1
- package/src/error/cause.ts +18 -181
- package/src/error/payload.ts +270 -4
- package/src/error/pithyError.ts +76 -0
- package/src/error/unresolved.ts +853 -0
- package/src/error/wire.ts +40 -0
- package/src/http/authContext.ts +13 -1
- package/src/http/oidcWebhook.ts +3 -3
- package/src/http/routeContract.ts +1 -1
- package/src/http/routeSpec.ts +81 -0
- package/src/http/sameOrigin.ts +1 -1
- package/src/http/scopeGates.ts +34 -0
- package/src/http/signedWebhook.ts +3 -3
- package/src/http/socket.ts +55 -0
- package/src/http/subprotocol.ts +47 -0
- package/src/http/validation.ts +50 -8
- package/src/index.ts +1 -0
- package/src/migrations/bookkeeping.ts +39 -2
- package/src/migrations/capabilitySets.ts +87 -0
- package/src/migrations/groups.ts +295 -0
- package/src/migrations/migrateStep.ts +19 -0
- package/src/migrations/owner.ts +10 -6
- package/src/migrations/registry.ts +46 -2
- package/src/migrations/retained.ts +2 -2
- package/src/migrations/runner.ts +214 -22
- package/src/migrations/state.ts +94 -0
- package/src/naming/domains.ts +75 -16
- package/src/naming/environment.ts +2 -1
- package/src/naming/feature.ts +46 -7
- package/src/naming/limits.ts +35 -3
- package/src/naming/packageName.ts +20 -0
- package/src/naming/provisionScope.ts +21 -2
- package/src/naming/resourceNames.ts +52 -5
- package/src/openapi/document.ts +412 -0
- package/src/openapi/routeGroups.ts +25 -0
- package/src/seed/writeD1.ts +13 -4
- package/src/seed/writeKv.ts +6 -2
- package/src/text/comments.ts +56 -4
- package/src/text/literals.ts +294 -0
- package/src/version.generated.ts +1 -1
- package/src/worker/serviceLoopback.ts +105 -0
- package/src/workflow/dispatchRoute.ts +13 -6
- package/src/workflow/faults.ts +56 -27
- package/src/workflow/hostEnv.ts +9 -1
- package/src/workflow/loopback.ts +2 -1
|
@@ -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 ??
|
|
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 ??
|
|
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 ??
|
|
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);
|
|
@@ -93,10 +93,10 @@ export declare function corsMiddleware(entry: CorsSurfaceEntry, origins: Readonl
|
|
|
93
93
|
/**
|
|
94
94
|
* Mount one `app.use(path, …)` per entry.
|
|
95
95
|
*
|
|
96
|
-
* **Called from
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
96
|
+
* **Called from `createBackend` ahead of every capability's `middleware`, never from a `routes` hook,
|
|
97
|
+
* and that is load-bearing.** Registered there, it is independent of the order an adopter happens to
|
|
98
|
+
* list their capabilities in, and it can put a header on whatever a capability's middleware or a
|
|
99
|
+
* readiness guard short-circuits.
|
|
100
100
|
*
|
|
101
101
|
* From `routes` it looks like it works and does not. The preflight still answers — an `OPTIONS` has no
|
|
102
102
|
* route handler to lose to, so this `use` is the only thing that matches it — but a capability composed
|
|
@@ -170,10 +170,10 @@ function corsMiddleware(entry, origins, maxAgeSeconds) {
|
|
|
170
170
|
/**
|
|
171
171
|
* Mount one `app.use(path, …)` per entry.
|
|
172
172
|
*
|
|
173
|
-
* **Called from
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
173
|
+
* **Called from `createBackend` ahead of every capability's `middleware`, never from a `routes` hook,
|
|
174
|
+
* and that is load-bearing.** Registered there, it is independent of the order an adopter happens to
|
|
175
|
+
* list their capabilities in, and it can put a header on whatever a capability's middleware or a
|
|
176
|
+
* readiness guard short-circuits.
|
|
177
177
|
*
|
|
178
178
|
* From `routes` it looks like it works and does not. The preflight still answers — an `OPTIONS` has no
|
|
179
179
|
* route handler to lose to, so this `use` is the only thing that matches it — but a capability composed
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
import type { MiddlewareHandler } from "hono";
|
|
4
|
+
import type { AuditEmit } from "../../audit/recorder";
|
|
4
5
|
import type { PithyHonoEnv } from "../../capability/capability";
|
|
5
6
|
import type { ControlPlaneContext } from "../context";
|
|
7
|
+
import type { ControlPlaneActorKind } from "../data/connection";
|
|
6
8
|
import type { ControlPlaneRequirement } from "../scope/scope";
|
|
7
9
|
import { type ControlPlaneVerifyDeps } from "./verify";
|
|
8
10
|
/**
|
|
@@ -76,4 +78,13 @@ export declare const CONTROL_PLANE_GUARD: unique symbol;
|
|
|
76
78
|
/** Whether a mounted handler is a control-plane gate. */
|
|
77
79
|
export declare function isControlPlaneGuard(handler: unknown): boolean;
|
|
78
80
|
export declare function requireControlPlane(requirement: ControlPlaneRequirement): MiddlewareHandler<PithyHonoEnv>;
|
|
81
|
+
/**
|
|
82
|
+
* The recorder a verified call's handlers write through: the request's own, with the connection's actor
|
|
83
|
+
* kind added to every `control-plane` event that does not already carry one.
|
|
84
|
+
*
|
|
85
|
+
* Only `control-plane` events, because the kind describes a management client and nothing else — a
|
|
86
|
+
* handler recording what happened to a user is recording a user. An event that states a kind keeps it.
|
|
87
|
+
* A connection with no recorded kind adds nothing, so its rows read exactly as they did before.
|
|
88
|
+
*/
|
|
89
|
+
export declare function stampActorKind(emit: AuditEmit, actorKind: ControlPlaneActorKind | null): AuditEmit;
|
|
79
90
|
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -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;
|
|
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,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAMhE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,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,CAuEzG;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,qBAAqB,GAAG,IAAI,GAAG,SAAS,CAIlG"}
|
|
@@ -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:
|
|
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);
|
|
@@ -83,6 +85,7 @@ function requireControlPlane(requirement) {
|
|
|
83
85
|
throw cause;
|
|
84
86
|
}
|
|
85
87
|
c.set("controlPlane", context);
|
|
88
|
+
c.set("emit", stampActorKind(c.var.emit, context.actorKind));
|
|
86
89
|
await safeEmit(c.var.emit, {
|
|
87
90
|
action: ControlPlaneAuditActions.callAllowed,
|
|
88
91
|
outcome: "success",
|
|
@@ -108,6 +111,21 @@ function requireControlPlane(requirement) {
|
|
|
108
111
|
return guard;
|
|
109
112
|
}
|
|
110
113
|
/**
|
|
114
|
+
* The recorder a verified call's handlers write through: the request's own, with the connection's actor
|
|
115
|
+
* kind added to every `control-plane` event that does not already carry one.
|
|
116
|
+
*
|
|
117
|
+
* Only `control-plane` events, because the kind describes a management client and nothing else — a
|
|
118
|
+
* handler recording what happened to a user is recording a user. An event that states a kind keeps it.
|
|
119
|
+
* A connection with no recorded kind adds nothing, so its rows read exactly as they did before.
|
|
120
|
+
*/
|
|
121
|
+
function stampActorKind(emit, actorKind) {
|
|
122
|
+
if (actorKind === null) return emit;
|
|
123
|
+
return (event) => emit(event.actorType === "control-plane" && event.actorKind == null ? {
|
|
124
|
+
...event,
|
|
125
|
+
actorKind
|
|
126
|
+
} : event);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
111
129
|
* Record a refused call.
|
|
112
130
|
*
|
|
113
131
|
* **Denials are audited, not only successes.** `denied` is a first-class outcome precisely for this, and
|
|
@@ -140,5 +158,13 @@ async function auditDenial(c, requirement, cause) {
|
|
|
140
158
|
}
|
|
141
159
|
}, c.var.log);
|
|
142
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* The step that connects a management client, as this deployed Worker can name it: with its own environment when
|
|
163
|
+
* it knows it, and never with a Worker — it cannot know the `apps/` directory that provisioned it (#711).
|
|
164
|
+
*/
|
|
165
|
+
function connectStep(env) {
|
|
166
|
+
if (env === void 0) return `connect one with ${commandName("dashboard connect")}, naming this environment with --env`;
|
|
167
|
+
return remedy("dashboard connect", { flags: { "--env": env } }, { runtime: true }).say((command) => `run ${command}`);
|
|
168
|
+
}
|
|
143
169
|
//#endregion
|
|
144
|
-
export { CONTROL_PLANE_GUARD, createControlPlaneVerifier, isControlPlaneGuard, requireControlPlane, workerVersionHeaders };
|
|
170
|
+
export { CONTROL_PLANE_GUARD, createControlPlaneVerifier, isControlPlaneGuard, requireControlPlane, stampActorKind, workerVersionHeaders };
|
|
@@ -6,6 +6,7 @@ import type { ControlPlaneConfig } from "../config/config";
|
|
|
6
6
|
import { type ControlPlaneDatabase } from "../data/tables";
|
|
7
7
|
import type { CapabilityDeclaration } from "../discovery/adminRoute";
|
|
8
8
|
import { type CapabilityHealthSource } from "../discovery/health";
|
|
9
|
+
import { type ComposedMigrationDatabase } from "../migrationState/migrationState";
|
|
9
10
|
import type { ExpireKeyParams, ExpireKeyRequest, RegisterKeyRequest } from "./schemas";
|
|
10
11
|
/** The pieces of the composed capability a handler needs. Passed in, so nothing reaches for a global. */
|
|
11
12
|
export interface ControlPlaneHandlerDeps {
|
|
@@ -31,6 +32,11 @@ export interface ControlPlaneHandlerDeps {
|
|
|
31
32
|
* value is not: the numbers are resolved per request, behind the scope each one is declared under.
|
|
32
33
|
*/
|
|
33
34
|
composedHealth: () => ReadonlyMap<string, CapabilityHealthSource>;
|
|
35
|
+
/**
|
|
36
|
+
* Every database this Worker binds, with the provider this build composes for it — captured by the same
|
|
37
|
+
* `compose` hook through `collectMigrationSets`, the function `pithy migrate` composes with (#729).
|
|
38
|
+
*/
|
|
39
|
+
composedMigrations: () => readonly ComposedMigrationDatabase[];
|
|
34
40
|
/** The clock, injected so a test can stand at any instant. */
|
|
35
41
|
now: () => Date;
|
|
36
42
|
}
|
|
@@ -108,6 +114,57 @@ export declare function manifestHandler(deps: ControlPlaneHandlerDeps): (c: Cont
|
|
|
108
114
|
}[];
|
|
109
115
|
grantedScopes: string[];
|
|
110
116
|
}, import("hono/utils/http-status").ContentfulStatusCode, "json">>;
|
|
117
|
+
/**
|
|
118
|
+
* `GET /control-plane/migrations` — where each database this Worker binds stands (#729).
|
|
119
|
+
*
|
|
120
|
+
* Read-only: it reports, and nothing over the seam runs, reverses or resets a migration.
|
|
121
|
+
*
|
|
122
|
+
* **One unreadable ledger costs one database its answer.** Each read catches its own failure and lands on
|
|
123
|
+
* `unreadable`, so `Promise.all` still resolves and the route answers 200 with what it has. The cause is
|
|
124
|
+
* logged here, for the operator, and never projected: a D1 error can name a table or a query.
|
|
125
|
+
*/
|
|
126
|
+
export declare function migrationsHandler(deps: ControlPlaneHandlerDeps): (c: Context<PithyHonoEnv>) => Promise<Response & import("hono").TypedResponse<{
|
|
127
|
+
environment: string;
|
|
128
|
+
databases: ({
|
|
129
|
+
state: "readable";
|
|
130
|
+
database: string;
|
|
131
|
+
binding: string;
|
|
132
|
+
applied: {
|
|
133
|
+
name: string;
|
|
134
|
+
namespace: string | null;
|
|
135
|
+
}[];
|
|
136
|
+
pending: {
|
|
137
|
+
name: string;
|
|
138
|
+
namespace: string | null;
|
|
139
|
+
}[];
|
|
140
|
+
undeclared: {
|
|
141
|
+
name: string;
|
|
142
|
+
namespace: string | null;
|
|
143
|
+
}[];
|
|
144
|
+
lastGroup: {
|
|
145
|
+
group: string;
|
|
146
|
+
appliedAt: string;
|
|
147
|
+
migrations: {
|
|
148
|
+
name: string;
|
|
149
|
+
namespace: string | null;
|
|
150
|
+
}[];
|
|
151
|
+
position: {
|
|
152
|
+
state: "top";
|
|
153
|
+
} | {
|
|
154
|
+
state: "buried";
|
|
155
|
+
above: string[];
|
|
156
|
+
ungrouped: {
|
|
157
|
+
name: string;
|
|
158
|
+
namespace: string | null;
|
|
159
|
+
}[];
|
|
160
|
+
};
|
|
161
|
+
} | null;
|
|
162
|
+
} | {
|
|
163
|
+
state: "unreadable";
|
|
164
|
+
database: string;
|
|
165
|
+
binding: string;
|
|
166
|
+
})[];
|
|
167
|
+
}, import("hono/utils/http-status").ContentfulStatusCode, "json">>;
|
|
111
168
|
/** `GET /control-plane/keys` — the registration state, so a client can surface a stale key. */
|
|
112
169
|
export declare function listKeysHandler(deps: ControlPlaneHandlerDeps): (c: Context<PithyHonoEnv>) => Promise<Response & import("hono").TypedResponse<{
|
|
113
170
|
connectionId: string;
|
|
@@ -123,6 +180,9 @@ export declare function listKeysHandler(deps: ControlPlaneHandlerDeps): (c: Cont
|
|
|
123
180
|
validUntil: string | null;
|
|
124
181
|
revokedAt: string | null;
|
|
125
182
|
}[];
|
|
183
|
+
authorizedBy: string | null;
|
|
184
|
+
actorKind: "agent" | "dashboard" | "script" | null;
|
|
185
|
+
purpose: string | null;
|
|
126
186
|
}, import("hono/utils/http-status").ContentfulStatusCode, "json">>;
|
|
127
187
|
/**
|
|
128
188
|
* `POST /control-plane/keys` — register a new public key, authenticated by the key it succeeds.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/http/handlers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/http/handlers.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAIhE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAI3D,OAAO,EAAmC,KAAK,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC5F,OAAO,KAAK,EAAE,qBAAqB,EAA4B,MAAM,yBAAyB,CAAC;AAC/F,OAAO,EAAE,KAAK,sBAAsB,EAAwB,MAAM,qBAAqB,CAAC;AAGxF,OAAO,EAAE,KAAK,yBAAyB,EAA0B,MAAM,kCAAkC,CAAC;AAS1G,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAuBvF,yGAAyG;AACzG,MAAM,WAAW,uBAAuB;IACtC,yDAAyD;IACzD,MAAM,EAAE,kBAAkB,CAAC;IAC3B,oEAAoE;IACpE,QAAQ,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,oBAAoB,CAAC;IAC7D;;;;;;;;OAQG;IACH,oBAAoB,EAAE,MAAM,SAAS,qBAAqB,EAAE,CAAC;IAC7D;;;;;;OAMG;IACH,cAAc,EAAE,MAAM,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IAClE;;;OAGG;IACH,kBAAkB,EAAE,MAAM,SAAS,yBAAyB,EAAE,CAAC;IAC/D,8DAA8D;IAC9D,GAAG,EAAE,MAAM,IAAI,CAAC;CACjB;AAgED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,uBAAuB,OAC5C,OAAO,CAAC,YAAY,CAAC;;;;;;kEAUjC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,uBAAuB,OAC1C,OAAO,CAAC,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mEAyBvC;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,uBAAuB,OAC5C,OAAO,CAAC,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mEAgBvC;AAED,+FAA+F;AAC/F,wBAAgB,eAAe,CAAC,IAAI,EAAE,uBAAuB,OAC1C,OAAO,CAAC,YAAY,CAAC;;;;;;;;;;;;;;;;;mEAcvC;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,uBAAuB,OAC7C,OAAO,CAAC,YAAY,CAAC,QAAQ,kBAAkB;;;;;;;;;;;;;;iBAoDjE;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,uBAAuB,OAC3C,OAAO,CAAC,YAAY,CAAC,UAAU,eAAe,QAAQ,gBAAgB;;;;;;;;;;;;;;mEA8CxF"}
|
|
@@ -8,6 +8,8 @@ import { readCapabilityHealth } from "../discovery/health.js";
|
|
|
8
8
|
import { ControlPlaneAuditActions, safeEmit } from "../audit/actions.js";
|
|
9
9
|
import { ControlPlaneInvalidCredentialError, ControlPlaneKeyConflictError } from "../error/errors.js";
|
|
10
10
|
import { appendKey, expireKey, pruneKeys } from "../data/keyLifecycle.js";
|
|
11
|
+
import { causeMessage } from "../../error/cause.js";
|
|
12
|
+
import { readDatabaseMigrations } from "../migrationState/migrationState.js";
|
|
11
13
|
//#region src/controlPlane/http/handlers.ts
|
|
12
14
|
/**
|
|
13
15
|
* The seam's own route handlers.
|
|
@@ -121,6 +123,30 @@ function manifestHandler(deps) {
|
|
|
121
123
|
});
|
|
122
124
|
};
|
|
123
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* `GET /control-plane/migrations` — where each database this Worker binds stands (#729).
|
|
128
|
+
*
|
|
129
|
+
* Read-only: it reports, and nothing over the seam runs, reverses or resets a migration.
|
|
130
|
+
*
|
|
131
|
+
* **One unreadable ledger costs one database its answer.** Each read catches its own failure and lands on
|
|
132
|
+
* `unreadable`, so `Promise.all` still resolves and the route answers 200 with what it has. The cause is
|
|
133
|
+
* logged here, for the operator, and never projected: a D1 error can name a table or a query.
|
|
134
|
+
*/
|
|
135
|
+
function migrationsHandler(deps) {
|
|
136
|
+
return async (c) => {
|
|
137
|
+
const context = caller(c);
|
|
138
|
+
const env = c.env;
|
|
139
|
+
const databases = await Promise.all(deps.composedMigrations().map((entry) => readDatabaseMigrations(env, entry, (failed, cause) => c.var.log.warn("migration ledger unreadable", {
|
|
140
|
+
database: failed.database,
|
|
141
|
+
binding: failed.binding,
|
|
142
|
+
reason: causeMessage(cause) ?? String(cause)
|
|
143
|
+
}))));
|
|
144
|
+
return c.json({
|
|
145
|
+
environment: context.environment,
|
|
146
|
+
databases
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
}
|
|
124
150
|
/** `GET /control-plane/keys` — the registration state, so a client can surface a stale key. */
|
|
125
151
|
function listKeysHandler(deps) {
|
|
126
152
|
return async (c) => {
|
|
@@ -129,7 +155,10 @@ function listKeysHandler(deps) {
|
|
|
129
155
|
return c.json({
|
|
130
156
|
connectionId: connection.id,
|
|
131
157
|
environment: connection.environment,
|
|
132
|
-
keys: connection.keys.map(publicKeyView)
|
|
158
|
+
keys: connection.keys.map(publicKeyView),
|
|
159
|
+
authorizedBy: connection.authorizedBy,
|
|
160
|
+
actorKind: connection.actorKind,
|
|
161
|
+
purpose: connection.purpose
|
|
133
162
|
});
|
|
134
163
|
};
|
|
135
164
|
}
|
|
@@ -244,4 +273,4 @@ function expireKeyHandler(deps) {
|
|
|
244
273
|
};
|
|
245
274
|
}
|
|
246
275
|
//#endregion
|
|
247
|
-
export { expireKeyHandler, listKeysHandler, manifestHandler, pingHandler, registerKeyHandler };
|
|
276
|
+
export { expireKeyHandler, listKeysHandler, manifestHandler, migrationsHandler, pingHandler, registerKeyHandler };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
import type { Hono } from "hono";
|
|
4
|
+
import type { PithyHonoEnv, PithyReadinessGuard } from "../../capability/capability";
|
|
5
|
+
/**
|
|
6
|
+
* Mount every capability's readiness guard, exempting the admin surface.
|
|
7
|
+
*
|
|
8
|
+
* **The control plane answers whatever else is wrong with the Worker.** It is the diagnostic surface: a
|
|
9
|
+
* management client reads the manifest, migration state and drift through it. A guard that refuses every
|
|
10
|
+
* request because an index drifted would take that surface down on exactly the fault it exists to report,
|
|
11
|
+
* and the client could not tell drift from a Worker that is simply down.
|
|
12
|
+
*
|
|
13
|
+
* **The exemption is the guard, not the middleware.** The seam itself runs on capability middleware —
|
|
14
|
+
* `controlplane()` publishes the verifier and `audit()` publishes `emit` — so skipping middleware on a
|
|
15
|
+
* seam request would trade a 500 for a seam that denies everything, or one that stops auditing without a
|
|
16
|
+
* word. Readiness guards are the only middleware that refuses because the Worker is broken, so they are
|
|
17
|
+
* the only thing skipped.
|
|
18
|
+
*
|
|
19
|
+
* **Hono decides what is on the surface, not a matcher written here.** One `app.use` per admin path marks
|
|
20
|
+
* the request, so a `:segment` matches exactly as it does for the route and the CORS layer, and a literal
|
|
21
|
+
* path never matches what is beneath it. The surface is the one `corsSurface(all)` computes, which
|
|
22
|
+
* `routeContract.test.ts` already holds to the registered routes, so there is no second list to drift.
|
|
23
|
+
*
|
|
24
|
+
* The mark is a `WeakSet` over the raw `Request`, closed over here. A context variable would put an
|
|
25
|
+
* internal flag on `PithyVars`, where every capability could read it and one could set it.
|
|
26
|
+
*
|
|
27
|
+
* Call after every capability's `middleware` and before any capability's `routes`. Before the routes,
|
|
28
|
+
* because a terminal handler never calls `next()` and a guard mounted after it never runs.
|
|
29
|
+
*/
|
|
30
|
+
export declare function registerReadinessGuards(app: Hono<PithyHonoEnv>, surface: readonly {
|
|
31
|
+
path: string;
|
|
32
|
+
}[], guards: readonly PithyReadinessGuard[]): void;
|
|
33
|
+
//# sourceMappingURL=readiness.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readiness.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/http/readiness.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAErF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,IAAI,CAAC,YAAY,CAAC,EACvB,OAAO,EAAE,SAAS;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,EACpC,MAAM,EAAE,SAAS,mBAAmB,EAAE,GACrC,IAAI,CAcN"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2026 Pithy
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
//#region src/controlPlane/http/readiness.ts
|
|
4
|
+
/**
|
|
5
|
+
* Mount every capability's readiness guard, exempting the admin surface.
|
|
6
|
+
*
|
|
7
|
+
* **The control plane answers whatever else is wrong with the Worker.** It is the diagnostic surface: a
|
|
8
|
+
* management client reads the manifest, migration state and drift through it. A guard that refuses every
|
|
9
|
+
* request because an index drifted would take that surface down on exactly the fault it exists to report,
|
|
10
|
+
* and the client could not tell drift from a Worker that is simply down.
|
|
11
|
+
*
|
|
12
|
+
* **The exemption is the guard, not the middleware.** The seam itself runs on capability middleware —
|
|
13
|
+
* `controlplane()` publishes the verifier and `audit()` publishes `emit` — so skipping middleware on a
|
|
14
|
+
* seam request would trade a 500 for a seam that denies everything, or one that stops auditing without a
|
|
15
|
+
* word. Readiness guards are the only middleware that refuses because the Worker is broken, so they are
|
|
16
|
+
* the only thing skipped.
|
|
17
|
+
*
|
|
18
|
+
* **Hono decides what is on the surface, not a matcher written here.** One `app.use` per admin path marks
|
|
19
|
+
* the request, so a `:segment` matches exactly as it does for the route and the CORS layer, and a literal
|
|
20
|
+
* path never matches what is beneath it. The surface is the one `corsSurface(all)` computes, which
|
|
21
|
+
* `routeContract.test.ts` already holds to the registered routes, so there is no second list to drift.
|
|
22
|
+
*
|
|
23
|
+
* The mark is a `WeakSet` over the raw `Request`, closed over here. A context variable would put an
|
|
24
|
+
* internal flag on `PithyVars`, where every capability could read it and one could set it.
|
|
25
|
+
*
|
|
26
|
+
* Call after every capability's `middleware` and before any capability's `routes`. Before the routes,
|
|
27
|
+
* because a terminal handler never calls `next()` and a guard mounted after it never runs.
|
|
28
|
+
*/
|
|
29
|
+
function registerReadinessGuards(app, surface, guards) {
|
|
30
|
+
if (guards.length === 0) return;
|
|
31
|
+
const onSurface = /* @__PURE__ */ new WeakSet();
|
|
32
|
+
for (const path of new Set(surface.map((entry) => entry.path))) app.use(path, async (c, next) => {
|
|
33
|
+
onSurface.add(c.req.raw);
|
|
34
|
+
await next();
|
|
35
|
+
});
|
|
36
|
+
for (const guard of guards) app.use("*", (c, next) => onSurface.has(c.req.raw) ? next() : guard(c, next));
|
|
37
|
+
}
|
|
38
|
+
//#endregion
|
|
39
|
+
export { registerReadinessGuards };
|
|
@@ -62,6 +62,13 @@ export declare const ControlPlaneKeysResponse: z.ZodObject<{
|
|
|
62
62
|
validUntil: z.ZodNullable<z.ZodISODateTime>;
|
|
63
63
|
revokedAt: z.ZodNullable<z.ZodISODateTime>;
|
|
64
64
|
}, z.core.$strip>>;
|
|
65
|
+
authorizedBy: z.ZodOptional<z.ZodNullable<z.ZodEmail>>;
|
|
66
|
+
actorKind: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
67
|
+
agent: "agent";
|
|
68
|
+
dashboard: "dashboard";
|
|
69
|
+
script: "script";
|
|
70
|
+
}>>>;
|
|
71
|
+
purpose: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
65
72
|
}, z.core.$strip>;
|
|
66
73
|
export type ControlPlaneKeysResponse = z.output<typeof ControlPlaneKeysResponse>;
|
|
67
74
|
/** `POST /control-plane/keys` — the appended key, and the set as it now stands. */
|
|
@@ -98,4 +105,144 @@ export declare const ExpireKeyResponse: z.ZodObject<{
|
|
|
98
105
|
}, z.core.$strip>>;
|
|
99
106
|
}, z.core.$strip>;
|
|
100
107
|
export type ExpireKeyResponse = z.output<typeof ExpireKeyResponse>;
|
|
108
|
+
/**
|
|
109
|
+
* One migration as `GET {basePath}/migrations` reports it: its composed name, and whose it is.
|
|
110
|
+
*
|
|
111
|
+
* The namespace is a capability's name, which the manifest already reports in `capabilities[]`. So a
|
|
112
|
+
* client tells an adopter's own migrations from a composed capability's by comparing the two — no
|
|
113
|
+
* convention, and no list kept anywhere.
|
|
114
|
+
*/
|
|
115
|
+
export declare const MigrationView: z.ZodObject<{
|
|
116
|
+
name: z.ZodString;
|
|
117
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
118
|
+
}, z.core.$strip>;
|
|
119
|
+
export type MigrationView = z.output<typeof MigrationView>;
|
|
120
|
+
/** Whether the last group is still reversible by name, or what is in its way. */
|
|
121
|
+
export declare const MigrationGroupPositionView: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
122
|
+
state: z.ZodLiteral<"top">;
|
|
123
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
124
|
+
state: z.ZodLiteral<"buried">;
|
|
125
|
+
above: z.ZodArray<z.ZodString>;
|
|
126
|
+
ungrouped: z.ZodArray<z.ZodObject<{
|
|
127
|
+
name: z.ZodString;
|
|
128
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
129
|
+
}, z.core.$strip>>;
|
|
130
|
+
}, z.core.$strip>], "state">;
|
|
131
|
+
export type MigrationGroupPositionView = z.output<typeof MigrationGroupPositionView>;
|
|
132
|
+
/** The run that last moved a database, and whether it can still be taken back. */
|
|
133
|
+
export declare const MigrationGroupView: z.ZodObject<{
|
|
134
|
+
group: z.ZodString;
|
|
135
|
+
appliedAt: z.ZodISODateTime;
|
|
136
|
+
migrations: z.ZodArray<z.ZodObject<{
|
|
137
|
+
name: z.ZodString;
|
|
138
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
139
|
+
}, z.core.$strip>>;
|
|
140
|
+
position: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
141
|
+
state: z.ZodLiteral<"top">;
|
|
142
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
143
|
+
state: z.ZodLiteral<"buried">;
|
|
144
|
+
above: z.ZodArray<z.ZodString>;
|
|
145
|
+
ungrouped: z.ZodArray<z.ZodObject<{
|
|
146
|
+
name: z.ZodString;
|
|
147
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
148
|
+
}, z.core.$strip>>;
|
|
149
|
+
}, z.core.$strip>], "state">;
|
|
150
|
+
}, z.core.$strip>;
|
|
151
|
+
export type MigrationGroupView = z.output<typeof MigrationGroupView>;
|
|
152
|
+
/**
|
|
153
|
+
* One database this Worker binds, read or not.
|
|
154
|
+
*
|
|
155
|
+
* **An unreadable database carries no list at all**, never empty ones. `pending: []` reads as up to date,
|
|
156
|
+
* and a database nobody read is not that. The state is on the value, so a client reaches a list only by
|
|
157
|
+
* narrowing.
|
|
158
|
+
*/
|
|
159
|
+
export declare const MigrationDatabaseView: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
160
|
+
state: z.ZodLiteral<"readable">;
|
|
161
|
+
database: z.ZodString;
|
|
162
|
+
binding: z.ZodString;
|
|
163
|
+
applied: z.ZodArray<z.ZodObject<{
|
|
164
|
+
name: z.ZodString;
|
|
165
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
166
|
+
}, z.core.$strip>>;
|
|
167
|
+
pending: z.ZodArray<z.ZodObject<{
|
|
168
|
+
name: z.ZodString;
|
|
169
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
170
|
+
}, z.core.$strip>>;
|
|
171
|
+
undeclared: z.ZodArray<z.ZodObject<{
|
|
172
|
+
name: z.ZodString;
|
|
173
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
174
|
+
}, z.core.$strip>>;
|
|
175
|
+
lastGroup: z.ZodNullable<z.ZodObject<{
|
|
176
|
+
group: z.ZodString;
|
|
177
|
+
appliedAt: z.ZodISODateTime;
|
|
178
|
+
migrations: z.ZodArray<z.ZodObject<{
|
|
179
|
+
name: z.ZodString;
|
|
180
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
181
|
+
}, z.core.$strip>>;
|
|
182
|
+
position: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
183
|
+
state: z.ZodLiteral<"top">;
|
|
184
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
185
|
+
state: z.ZodLiteral<"buried">;
|
|
186
|
+
above: z.ZodArray<z.ZodString>;
|
|
187
|
+
ungrouped: z.ZodArray<z.ZodObject<{
|
|
188
|
+
name: z.ZodString;
|
|
189
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
190
|
+
}, z.core.$strip>>;
|
|
191
|
+
}, z.core.$strip>], "state">;
|
|
192
|
+
}, z.core.$strip>>;
|
|
193
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
194
|
+
state: z.ZodLiteral<"unreadable">;
|
|
195
|
+
database: z.ZodString;
|
|
196
|
+
binding: z.ZodString;
|
|
197
|
+
}, z.core.$strip>], "state">;
|
|
198
|
+
export type MigrationDatabaseView = z.output<typeof MigrationDatabaseView>;
|
|
199
|
+
/**
|
|
200
|
+
* `GET /control-plane/migrations` — where every database this Worker binds stands.
|
|
201
|
+
*
|
|
202
|
+
* Asked of the Worker because the Worker *is* the deployed build. `pithy doctor` reads the project on disk,
|
|
203
|
+
* which is what the operator has and not necessarily what is deployed.
|
|
204
|
+
*/
|
|
205
|
+
export declare const ControlPlaneMigrationsResponse: z.ZodObject<{
|
|
206
|
+
environment: z.ZodString;
|
|
207
|
+
databases: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
208
|
+
state: z.ZodLiteral<"readable">;
|
|
209
|
+
database: z.ZodString;
|
|
210
|
+
binding: z.ZodString;
|
|
211
|
+
applied: z.ZodArray<z.ZodObject<{
|
|
212
|
+
name: z.ZodString;
|
|
213
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
214
|
+
}, z.core.$strip>>;
|
|
215
|
+
pending: z.ZodArray<z.ZodObject<{
|
|
216
|
+
name: z.ZodString;
|
|
217
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
218
|
+
}, z.core.$strip>>;
|
|
219
|
+
undeclared: z.ZodArray<z.ZodObject<{
|
|
220
|
+
name: z.ZodString;
|
|
221
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
222
|
+
}, z.core.$strip>>;
|
|
223
|
+
lastGroup: z.ZodNullable<z.ZodObject<{
|
|
224
|
+
group: z.ZodString;
|
|
225
|
+
appliedAt: z.ZodISODateTime;
|
|
226
|
+
migrations: z.ZodArray<z.ZodObject<{
|
|
227
|
+
name: z.ZodString;
|
|
228
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
229
|
+
}, z.core.$strip>>;
|
|
230
|
+
position: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
231
|
+
state: z.ZodLiteral<"top">;
|
|
232
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
233
|
+
state: z.ZodLiteral<"buried">;
|
|
234
|
+
above: z.ZodArray<z.ZodString>;
|
|
235
|
+
ungrouped: z.ZodArray<z.ZodObject<{
|
|
236
|
+
name: z.ZodString;
|
|
237
|
+
namespace: z.ZodNullable<z.ZodString>;
|
|
238
|
+
}, z.core.$strip>>;
|
|
239
|
+
}, z.core.$strip>], "state">;
|
|
240
|
+
}, z.core.$strip>>;
|
|
241
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
242
|
+
state: z.ZodLiteral<"unreadable">;
|
|
243
|
+
database: z.ZodString;
|
|
244
|
+
binding: z.ZodString;
|
|
245
|
+
}, z.core.$strip>], "state">>;
|
|
246
|
+
}, z.core.$strip>;
|
|
247
|
+
export type ControlPlaneMigrationsResponse = z.output<typeof ControlPlaneMigrationsResponse>;
|
|
101
248
|
//# sourceMappingURL=responses.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"responses.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/http/responses.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;GAkBG;AAEH,8EAA8E;AAC9E,eAAO,MAAM,aAAa;;;;;;;;;;iBAcmF,CAAC;AAC9G,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAE3D;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;;;;iBAQwB,CAAC;AAC9D,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEjF,+FAA+F;AAC/F,eAAO,MAAM,wBAAwB
|
|
1
|
+
{"version":3,"file":"responses.d.ts","sourceRoot":"","sources":["../../../src/controlPlane/http/responses.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;GAkBG;AAEH,8EAA8E;AAC9E,eAAO,MAAM,aAAa;;;;;;;;;;iBAcmF,CAAC;AAC9G,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAE3D;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;;;;iBAQwB,CAAC;AAC9D,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEjF,+FAA+F;AAC/F,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;iBAuBwE,CAAC;AAC9G,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAEjF,mFAAmF;AACnF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;iBAQyB,CAAC;AAC1D,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEvE,gGAAgG;AAChG,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;iBAM6B,CAAC;AAC5D,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEnE;;;;;;GAMG;AACH,eAAO,MAAM,aAAa;;;iBAU+C,CAAC;AAC1E,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,aAAa,CAAC,CAAC;AAE3D,iFAAiF;AACjF,eAAO,MAAM,0BAA0B;;;;;;;;;4BAyBkE,CAAC;AAC1G,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAErF,kFAAkF;AAClF,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;iBAW8C,CAAC;AAC9E,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAErE;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BA+BwE,CAAC;AAC3G,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE3E;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAO+D,CAAC;AAC3G,MAAM,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
|