@pithy-sh/core 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/capability/bindings.d.ts +5 -0
  2. package/dist/capability/bindings.d.ts.map +1 -1
  3. package/dist/capability/bindings.js +44 -3
  4. package/dist/capability/capability.d.ts +33 -0
  5. package/dist/capability/capability.d.ts.map +1 -1
  6. package/dist/capability/manifest.d.ts +5 -0
  7. package/dist/capability/manifest.d.ts.map +1 -1
  8. package/dist/capability/manifest.js +1 -1
  9. package/dist/capability/validateBindings.js +1 -1
  10. package/dist/controlPlane/http/cors.js +1 -1
  11. package/dist/createBackend.d.ts +2 -1
  12. package/dist/createBackend.d.ts.map +1 -1
  13. package/dist/createBackend.js +5 -4
  14. package/dist/error/http.d.ts +27 -5
  15. package/dist/error/http.d.ts.map +1 -1
  16. package/dist/error/http.js +33 -9
  17. package/dist/error/messageParams.d.ts +28 -0
  18. package/dist/error/messageParams.d.ts.map +1 -0
  19. package/dist/error/messageParams.js +31 -0
  20. package/dist/error/terminal.d.ts +16 -5
  21. package/dist/error/terminal.d.ts.map +1 -1
  22. package/dist/error/terminal.js +16 -5
  23. package/dist/http/oidcWebhook.d.ts +283 -0
  24. package/dist/http/oidcWebhook.d.ts.map +1 -0
  25. package/dist/http/oidcWebhook.js +414 -0
  26. package/dist/http/signedWebhook.d.ts +9 -65
  27. package/dist/http/signedWebhook.d.ts.map +1 -1
  28. package/dist/http/signedWebhook.js +19 -9
  29. package/dist/http/webhookWindow.d.ts +33 -0
  30. package/dist/http/webhookWindow.d.ts.map +1 -0
  31. package/dist/http/webhookWindow.js +35 -0
  32. package/dist/logger/errorHandler.d.ts +11 -0
  33. package/dist/logger/errorHandler.d.ts.map +1 -0
  34. package/dist/logger/errorHandler.js +87 -0
  35. package/dist/naming/environment.js +1 -1
  36. package/dist/naming/provisionScope.d.ts +108 -3
  37. package/dist/naming/provisionScope.d.ts.map +1 -1
  38. package/dist/naming/provisionScope.js +27 -2
  39. package/dist/naming/resource.js +1 -1
  40. package/dist/naming/resourceNames.js +1 -1
  41. package/dist/schema/describedness.d.ts +30 -1
  42. package/dist/schema/describedness.d.ts.map +1 -1
  43. package/dist/schema/describedness.js +42 -6
  44. package/dist/test-utils/oidcFixtures.d.ts +93 -0
  45. package/dist/test-utils/oidcFixtures.d.ts.map +1 -0
  46. package/dist/test-utils/oidcFixtures.js +111 -0
  47. package/dist/version.generated.d.ts +1 -1
  48. package/dist/version.generated.js +1 -1
  49. package/dist/workflow/naming.js +1 -1
  50. package/dist/workflow/stepMessage.d.ts +28 -3
  51. package/dist/workflow/stepMessage.d.ts.map +1 -1
  52. package/dist/workflow/stepMessage.js +48 -6
  53. package/package.json +1 -1
  54. package/src/capability/bindings.ts +49 -0
  55. package/src/capability/capability.ts +34 -0
  56. package/src/createBackend.ts +7 -3
  57. package/src/error/http.ts +34 -10
  58. package/src/error/messageParams.ts +38 -0
  59. package/src/error/terminal.ts +16 -5
  60. package/src/http/oidcWebhook.ts +672 -0
  61. package/src/http/signedWebhook.ts +44 -16
  62. package/src/http/webhookWindow.ts +35 -0
  63. package/src/logger/errorHandler.ts +94 -0
  64. package/src/naming/provisionScope.ts +150 -4
  65. package/src/schema/describedness.ts +51 -6
  66. package/src/test-utils/oidcFixtures.ts +138 -0
  67. package/src/version.generated.ts +1 -1
  68. package/src/workflow/stepMessage.ts +52 -6
@@ -0,0 +1,283 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import type { MiddlewareHandler } from "hono";
4
+ import { z } from "zod";
5
+ import type { PithyHonoEnv } from "../capability/capability";
6
+ /**
7
+ * The `signed-webhook` strategy for a sender that proves itself with an **OIDC token** rather than an HMAC.
8
+ * Issuers, key endpoint, audience and a claims predicate in; the verified claims, or a `PithyError`, out.
9
+ *
10
+ * Two mechanisms, one declared strategy. {@link ./verification.VerificationStrategy} already says as much —
11
+ * *"an HMAC, a signed JWS chain, an OIDC token… a rail whose sender proves it differently implements its
12
+ * own"* — so this sits beside {@link ./signedWebhook.requireSignedWebhook} and wears its seams, rather than
13
+ * adding a word to that union. What changes is where the proof comes from: with an HMAC both ends hold a
14
+ * secret, and with OIDC neither end holds anything. The sender asks its identity provider for a token that
15
+ * expires in minutes; the receiver asks the same provider for the public keys that check it.
16
+ *
17
+ * ## The claims check is the boundary, not the signature
18
+ *
19
+ * An identity provider signs tokens for **everybody** with the same handful of keys. GitHub signs one for
20
+ * every repository on the planet; Google signs one for every Pub/Sub push subscription. So a valid signature
21
+ * proves only *that provider minted this*, which any of their users can arrange in under a minute. What makes
22
+ * a token **ours** is what it claims: `aud`, which the sender names when it mints the token and which is the
23
+ * endpoint it was minted for, and whatever the {@link OidcWebhookScheme.claims} predicate asserts on top —
24
+ * `sub === "repo:pithy-sh/pithy:environment:npm-publish"` for a release job, an issuer's service account for
25
+ * a push subscription. Verify the signature, skip those, and the result is an endpoint every user of that
26
+ * provider can post to.
27
+ *
28
+ * That is why `claims` is a **predicate the route holds** rather than a value in configuration. It is the
29
+ * same constraint as a `ValueRotator`: the declaration is the `signed-webhook` tag on the route, and the code
30
+ * that decides who is allowed lives with the route, where it can be read beside the handler it protects.
31
+ *
32
+ * ## Four steps, in this order, and the order is the security property
33
+ *
34
+ * 1. **Pin the algorithm before touching a key.** `alg` arrives in a header nobody has verified yet, so it is
35
+ * parsed against a literal `RS256` rather than looked up. That is what makes the two published confusions
36
+ * unreachable — `none`, which asks for the signature to be skipped, and `HS256`, which asks the verifier to
37
+ * HMAC with the *public* key as if it were a shared secret. Neither survives a literal.
38
+ * 2. **Resolve the key by `kid` from the issuer's published set.** Never from the token, which is why there is
39
+ * no `jwk`/`x5u` handling here: a token that carries its own key is a token that verifies itself.
40
+ * 3. **Verify the signature over the exact received segments** — `header.claims` as encoded, never a
41
+ * re-serialization. Key order and whitespace belong to the sender, not to us.
42
+ * 4. **Then read the claims,** and only then. A claim from an unverified token is a claim an attacker wrote,
43
+ * so a verifier that reads `iss` or `sub` to decide *which key to fetch* has already trusted the forgery it
44
+ * is about to check. Issuer, audience, expiry, and the caller's predicate are all after the signature.
45
+ *
46
+ * ## What a refusal says
47
+ *
48
+ * `core/webhook_unverified`, 401, one code for every step a sender can fail — unreadable token, unknown key,
49
+ * bad signature, wrong audience, expired, predicate false. The step goes in `detail`, which the HTTP codec
50
+ * strips, so an operator reading a log learns which check refused it and the sender learns only that
51
+ * something did. Values that decide something are named there (`kid`, `iss`, `aud`) because a misconfigured
52
+ * audience is the realistic failure and an operator cannot fix what the log will not name — truncated by
53
+ * {@link snippet}, and never the signature and never the whole token.
54
+ *
55
+ * Two failures are deliberately **not** the sender's. An endpoint with no issuers, no audience, no key
56
+ * endpoint, or a clock that is not a clock is a configuration fault and takes `core/internal` — reporting it
57
+ * as an unverified webhook sends an operator hunting a forger who is not there. And a key endpoint that
58
+ * cannot be reached or answers nonsense is `core/upstream_failed` (502), because a 500 tells an operator to
59
+ * read *our* logs and the thing that broke is the issuer's. Both still refuse the delivery: fail closed is
60
+ * about what happens to the request, not about whose code goes on it.
61
+ *
62
+ * ## What this proves, and what it does not
63
+ *
64
+ * The same caveat as the HMAC scheme, for the same reason: this proves a delivery is authentic and fresh,
65
+ * never that it is *new*. A captured token replays until it expires. A handler that grants, charges, or
66
+ * deletes needs its own uniqueness key.
67
+ */
68
+ /** How long a fetched key set is reused. Issuers rotate slowly, and an unknown `kid` forces a refresh anyway. */
69
+ export declare const OIDC_JWKS_TTL_SECONDS = 3600;
70
+ /** Tolerance on `exp`, `nbf` and `iat`. A minute covers clock drift; an hour would cover a replay. */
71
+ export declare const OIDC_CLOCK_SKEW_SECONDS = 60;
72
+ /**
73
+ * The most tolerance this verifier accepts, and it refuses above rather than clamping.
74
+ *
75
+ * A skew is a replay window in the plainest possible units: every second of it is a second longer a captured
76
+ * token keeps working. Five minutes is the far end of real drift between two machines that both run NTP; past
77
+ * that a number has stopped covering drift and started covering a capture, which is what the sentence above
78
+ * says about an hour. Refused rather than clamped because a `604800` is a typo or a misunderstanding either
79
+ * way — clamped, it boots and nobody reads the line again; refused, it is a red boot and a two-character fix.
80
+ */
81
+ export declare const OIDC_MAX_CLOCK_SKEW_SECONDS = 300;
82
+ /**
83
+ * One published RSA verification key, in the shape a JWKS endpoint returns. `.loose()` because providers add
84
+ * fields, and a key set must not be rejected for carrying something this build does not read.
85
+ */
86
+ export declare const OidcJwk: z.ZodObject<{
87
+ kid: z.ZodString;
88
+ kty: z.ZodString;
89
+ n: z.ZodString;
90
+ e: z.ZodString;
91
+ alg: z.ZodOptional<z.ZodString>;
92
+ use: z.ZodOptional<z.ZodString>;
93
+ }, z.core.$loose>;
94
+ export type OidcJwk = z.infer<typeof OidcJwk>;
95
+ /** A published key set. At least one key: an empty set is an endpoint that is not answering properly. */
96
+ export declare const OidcJwks: z.ZodObject<{
97
+ keys: z.ZodArray<z.ZodObject<{
98
+ kid: z.ZodString;
99
+ kty: z.ZodString;
100
+ n: z.ZodString;
101
+ e: z.ZodString;
102
+ alg: z.ZodOptional<z.ZodString>;
103
+ use: z.ZodOptional<z.ZodString>;
104
+ }, z.core.$loose>>;
105
+ }, z.core.$loose>;
106
+ export type OidcJwks = z.infer<typeof OidcJwks>;
107
+ /**
108
+ * The claims an OIDC token carries, narrowed to the ones that decide anything. `.loose()` keeps the rest —
109
+ * the predicate reads them, and a claim set must not be refused for being richer than expected.
110
+ *
111
+ * `aud` is a **string and only a string**, though RFC 7519 permits an array. The audience check is the
112
+ * boundary, and an array turns an equality into a set membership — one more shape for a verifier to be wrong
113
+ * about, on the check the whole scheme rests on. No sender the kit talks to mints one.
114
+ */
115
+ export declare const OidcClaims: z.ZodObject<{
116
+ iss: z.ZodString;
117
+ aud: z.ZodString;
118
+ sub: z.ZodOptional<z.ZodString>;
119
+ exp: z.ZodNumber;
120
+ nbf: z.ZodOptional<z.ZodNumber>;
121
+ iat: z.ZodOptional<z.ZodNumber>;
122
+ }, z.core.$loose>;
123
+ export type OidcClaims = z.infer<typeof OidcClaims>;
124
+ /** The response shape this module reads. Structural, so a test's transport need not be a whole `Response`. */
125
+ export interface OidcJwksResponse {
126
+ /** Whether the status is 2xx. */
127
+ ok: boolean;
128
+ /** The status code, which is what decides the mapping. */
129
+ status: number;
130
+ /** The body as text. Read as text rather than JSON so a non-JSON answer is a diagnosis, not a throw. */
131
+ text(): Promise<string>;
132
+ }
133
+ /**
134
+ * The HTTP seam the key endpoint is reached through.
135
+ *
136
+ * Injectable for exactly one reason: **no test may reach a live identity provider**, and a verifier whose
137
+ * network call could not be substituted would have to be tested through a stub of itself, which proves
138
+ * nothing. One explicit parameter rather than a reassigned global — a global stub leaks between suites and
139
+ * hides which module was actually exercised.
140
+ */
141
+ export type OidcJwksFetch = (url: string) => Promise<OidcJwksResponse>;
142
+ /** The default transport: the runtime's own `fetch`. */
143
+ export declare const oidcJwksFetch: OidcJwksFetch;
144
+ /**
145
+ * Where a fetched key set is held between requests.
146
+ *
147
+ * **Injected, never a module global.** A cache in a module variable is one cache for the whole isolate that
148
+ * no caller owns, which is how `resetGoogleJwksCache` came to exist: once the state is unreachable, a test
149
+ * suite needs an exported function whose only purpose is to undo the previous suite. Passing the store in
150
+ * deletes that function and the class of bug it papers over — a test seeds its own, and a Worker gives one
151
+ * over KV or the Cache API and shares it across isolates.
152
+ *
153
+ * **Owning the store is not the same as having none.** {@link requireOidcWebhook} builds one per guard when a
154
+ * route gives none, because the guard is the surface anonymous traffic arrives on: with no cache, a 49-byte
155
+ * forged token naming a published `kid` buys a round trip to the issuer, 1:1, until the issuer rate-limits us
156
+ * and the real deliveries 502 alongside the forgeries. {@link verifyOidcToken} called directly is the other
157
+ * case and does fetch per call — its caller holds one token it has already decided to check, so there is no
158
+ * flood to absorb and no cache to acquire by surprise.
159
+ *
160
+ * Public keys, so nothing here is what CLAUDE.md's secrets rule governs: the whole point of a JWKS endpoint
161
+ * is that anyone may read it. What the cache buys is one round trip per TTL instead of one per delivery.
162
+ */
163
+ export interface JwksCache {
164
+ /** The key set held for `url`, or `undefined` when nothing usable is held. */
165
+ get(url: string): Promise<readonly OidcJwk[] | undefined>;
166
+ /** Hold a freshly fetched key set for `url` for `ttlSeconds`. */
167
+ set(url: string, keys: readonly OidcJwk[], ttlSeconds: number): Promise<void>;
168
+ }
169
+ /**
170
+ * A key cache in memory, expiring on a clock the caller owns.
171
+ *
172
+ * One object per call, so two callers never share one by accident and a test's cache dies with its test. The
173
+ * clock is injected for the same reason it is everywhere else here: an expiry that depends on wall time is an
174
+ * assertion nobody can write.
175
+ */
176
+ export declare function memoryJwksCache(options?: {
177
+ now?: () => Date;
178
+ }): JwksCache;
179
+ /** What the two ends of the scheme must agree on, and what the receiver decides for itself. */
180
+ export interface OidcWebhookScheme {
181
+ /**
182
+ * The `iss` values this endpoint accepts. More than one only where a provider publishes more than one
183
+ * spelling of itself — Google issues under both `accounts.google.com` and `https://accounts.google.com`;
184
+ * GitHub uses one. Empty is a configuration fault, never "accept anything".
185
+ */
186
+ issuers: readonly string[];
187
+ /** Where the issuer publishes the keys that sign its tokens. Public, so it is configuration and not a secret. */
188
+ jwksUrl: string;
189
+ /** The `aud` the token must claim — the value the sender named when it minted one. The real boundary. */
190
+ audience: string;
191
+ /**
192
+ * Whatever else makes a token *this endpoint's*: `(claims) => claims.sub === "repo:owner/name:environment:x"`.
193
+ *
194
+ * A predicate rather than configuration, because it cannot cross into `pithy.manifest.json` and should not
195
+ * try: the manifest declares the strategy, the route holds the rule. Run **last**, after the signature and
196
+ * every standard claim, so it is only ever handed claims that are already proven to be the issuer's.
197
+ */
198
+ claims: (claims: OidcClaims) => boolean | Promise<boolean>;
199
+ /**
200
+ * Tolerance on `exp`, `nbf` and `iat`, in seconds. Defaults to {@link OIDC_CLOCK_SKEW_SECONDS} and must be
201
+ * a finite number from 0 to {@link OIDC_MAX_CLOCK_SKEW_SECONDS}; anything else is `core/internal`, because
202
+ * this is the second operand of all three freshness comparisons and one `NaN` disables them together.
203
+ */
204
+ skewSeconds?: number;
205
+ /**
206
+ * How long a fetched key set is held. Defaults to {@link OIDC_JWKS_TTL_SECONDS} and must be a finite number
207
+ * of seconds — a `NaN` is an entry that never expires, which pins a key the issuer has rotated out.
208
+ */
209
+ jwksTtlSeconds?: number;
210
+ /**
211
+ * Where fetched keys are held between deliveries. Never a module global: {@link requireOidcWebhook} builds
212
+ * one per guard when a route gives none, and {@link verifyOidcToken} called directly fetches per call.
213
+ */
214
+ jwksCache?: JwksCache;
215
+ /** The HTTP seam the key endpoint is reached through. Defaults to the runtime's `fetch`. */
216
+ transport?: OidcJwksFetch;
217
+ }
218
+ /** Everything {@link verifyOidcToken} needs beyond the token itself. */
219
+ export interface VerifyOidcTokenOptions extends OidcWebhookScheme {
220
+ /** The clock. Injectable so an expiry refusal is deterministic rather than wall-clock dependent. */
221
+ now?: Date;
222
+ }
223
+ /** Everything {@link requireOidcWebhook} needs, as a route wears it. */
224
+ export interface OidcWebhookGuardOptions extends OidcWebhookScheme {
225
+ /** The header the token arrives in, lower case. Defaults to `authorization`, carrying `Bearer <token>`. */
226
+ header?: string;
227
+ /** The clock, for the freshness checks. A function because a guard is built once and used per request. */
228
+ now?: () => Date;
229
+ }
230
+ /**
231
+ * Verify one OIDC token and return its claims. Throws, never reports.
232
+ *
233
+ * The steps run in the order the module doc gives, and that order **is** the security property: algorithm
234
+ * pinned, key resolved by `kid` from the published set, signature checked over the received bytes, and only
235
+ * then a single claim read. A verifier that reads a claim to decide which key to fetch has trusted the thing
236
+ * it has not checked yet.
237
+ *
238
+ * @throws {@link WebhookUnverifiedError} (401) when the sender did not prove itself — unreadable token,
239
+ * unknown key, bad signature, wrong issuer or audience, expired, not yet valid, predicate false.
240
+ * @throws {@link InternalError} (500) when this endpoint is not configured to verify anything.
241
+ * @throws {@link UpstreamError} (502) when the issuer's key endpoint could not be read.
242
+ */
243
+ export declare function verifyOidcToken(token: string, options: VerifyOidcTokenOptions): Promise<OidcClaims>;
244
+ /**
245
+ * The OIDC gate, as a route wears it: `app.post(path, requireOidcWebhook({…}), zValidator("json", Body,
246
+ * validationHook), handler)`.
247
+ *
248
+ * ## Why the header is read before anything else
249
+ *
250
+ * The bearer header is the cheapest thing to check and the commonest thing to be missing, so it goes first. A
251
+ * delivery carrying no token is refused whatever the body holds, and fetching a key set before looking would
252
+ * be unauthenticated work an anonymous POST could buy on the one route whose purpose is to refuse anonymous
253
+ * callers.
254
+ *
255
+ * ## Why a cache is not optional here
256
+ *
257
+ * A caller that presents *something* is past that first check, and the next thing the verifier needs is the
258
+ * issuer's key set. So the guard builds a {@link memoryJwksCache} when the route gives none — once, when the
259
+ * middleware is constructed, never per request, which is a cache that has never held anything. A `kid` is
260
+ * published by definition, which makes a 49-byte token naming one the cheapest thing on the internet to send,
261
+ * and with no cache each one is a round trip to the issuer, 1:1. That is a bandwidth multiplier aimed at
262
+ * somebody else's endpoint, and once the issuer rate-limits us {@link fetchJwks} maps it to
263
+ * `core/upstream_failed` for the genuine deliveries too — an anonymous caller taking the boundary down by
264
+ * asking it politely. A route wanting a harder bound (shared across isolates, or rate-limiting) passes its
265
+ * own {@link OidcWebhookScheme.jwksCache}, and this one is never built.
266
+ *
267
+ * A `kid` **nobody** publishes still costs one fetch per delivery, cache or no cache, because an unknown key
268
+ * id is how rotation announces itself and declining to look is an outage. That bound is per delivery and
269
+ * lives in {@link resolveKey}; the cache is what collapses the other flood, the one naming a key that exists.
270
+ *
271
+ * ## Why nothing is published to the request
272
+ *
273
+ * The gate proves the caller and returns; it sets no request variable. The claims a route cares about are the
274
+ * ones its own {@link OidcWebhookScheme.claims} predicate already asserted, and a handler that needs the
275
+ * whole claim set calls {@link verifyOidcToken} directly rather than reading a variable it must remember to
276
+ * null-check.
277
+ *
278
+ * The body is never read here — unlike the HMAC gate, whose proof covers the bytes. An OIDC token proves who
279
+ * sent the request and says nothing about what they sent, so the route's `zValidator` is the only thing that
280
+ * touches the body, and it sees an untouched stream.
281
+ */
282
+ export declare function requireOidcWebhook(options: OidcWebhookGuardOptions): MiddlewareHandler<PithyHonoEnv>;
283
+ //# sourceMappingURL=oidcWebhook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidcWebhook.d.ts","sourceRoot":"","sources":["../../src/http/oidcWebhook.ts"],"names":[],"mappings":"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"}