@pithy-sh/core 0.12.0 → 0.14.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/README.md +54 -0
- package/dist/audit/auditEvent.js +1 -1
- package/dist/audit/chain.d.ts +289 -0
- package/dist/audit/chain.d.ts.map +1 -0
- package/dist/audit/chain.js +400 -0
- package/dist/audit/citations.d.ts +52 -0
- package/dist/audit/citations.d.ts.map +1 -0
- package/dist/audit/citations.js +13 -0
- package/dist/audit/composed.d.ts +18 -0
- package/dist/audit/composed.d.ts.map +1 -0
- package/dist/audit/composed.js +28 -0
- package/dist/capability/bindings.d.ts +22 -0
- package/dist/capability/bindings.d.ts.map +1 -1
- package/dist/capability/bindings.js +32 -2
- package/dist/capability/capability.d.ts +133 -15
- package/dist/capability/capability.d.ts.map +1 -1
- package/dist/capability/capability.js +17 -2
- package/dist/capability/erasure.d.ts +75 -0
- package/dist/capability/erasure.d.ts.map +1 -0
- package/dist/capability/erasure.js +2 -0
- package/dist/capability/manifest.d.ts +5 -0
- package/dist/capability/manifest.d.ts.map +1 -1
- package/dist/capability/personColumns.d.ts +28 -0
- package/dist/capability/personColumns.d.ts.map +1 -0
- package/dist/capability/personColumns.js +66 -0
- package/dist/capability/personRows.d.ts +62 -0
- package/dist/capability/personRows.d.ts.map +1 -0
- package/dist/capability/personRows.js +59 -0
- package/dist/capability/purge.d.ts +113 -4
- package/dist/capability/purge.d.ts.map +1 -1
- package/dist/capability/purge.js +138 -5
- package/dist/capability/settings.d.ts +10 -0
- package/dist/capability/settings.d.ts.map +1 -1
- package/dist/capability/vectorIndex.d.ts +36 -0
- package/dist/capability/vectorIndex.d.ts.map +1 -0
- package/dist/capability/vectorIndex.js +25 -0
- package/dist/cli/commandCatalog.generated.d.ts +434 -4
- package/dist/cli/commandCatalog.generated.d.ts.map +1 -1
- package/dist/cli/commandCatalog.generated.js +455 -2
- package/dist/cli/commandFacts.d.ts +8 -5
- package/dist/cli/commandFacts.d.ts.map +1 -1
- package/dist/cli/commandFacts.js +12 -3
- package/dist/consent/purpose.d.ts +70 -0
- package/dist/consent/purpose.d.ts.map +1 -0
- package/dist/consent/purpose.js +97 -0
- package/dist/consent/reader.d.ts +99 -0
- package/dist/consent/reader.d.ts.map +1 -0
- package/dist/consent/reader.js +33 -0
- package/dist/controlPlane/audit/actions.d.ts +15 -4
- package/dist/controlPlane/audit/actions.d.ts.map +1 -1
- package/dist/controlPlane/audit/actions.js +16 -5
- package/dist/controlPlane/capability.d.ts +10 -0
- package/dist/controlPlane/capability.d.ts.map +1 -1
- package/dist/controlPlane/capability.js +56 -8
- package/dist/controlPlane/context.d.ts +4 -0
- package/dist/controlPlane/context.d.ts.map +1 -1
- package/dist/controlPlane/context.js +3 -2
- package/dist/controlPlane/data/connection.d.ts +21 -2
- package/dist/controlPlane/data/connection.d.ts.map +1 -1
- package/dist/controlPlane/data/connection.js +13 -4
- package/dist/controlPlane/data/connections.d.ts +94 -0
- package/dist/controlPlane/data/connections.d.ts.map +1 -0
- package/dist/controlPlane/data/connections.js +151 -0
- package/dist/controlPlane/data/hold.d.ts +46 -0
- package/dist/controlPlane/data/hold.d.ts.map +1 -0
- package/dist/controlPlane/data/hold.js +36 -0
- package/dist/controlPlane/data/oidcTrust.d.ts +122 -0
- package/dist/controlPlane/data/oidcTrust.d.ts.map +1 -0
- package/dist/controlPlane/data/oidcTrust.js +173 -0
- package/dist/controlPlane/data/tables.d.ts +4 -0
- package/dist/controlPlane/data/tables.d.ts.map +1 -1
- package/dist/controlPlane/data/tables.js +9 -4
- package/dist/controlPlane/data/trustFirstCall.d.ts +16 -0
- package/dist/controlPlane/data/trustFirstCall.d.ts.map +1 -0
- package/dist/controlPlane/data/trustFirstCall.js +25 -0
- package/dist/controlPlane/discovery/adminRoute.d.ts +165 -2
- package/dist/controlPlane/discovery/adminRoute.d.ts.map +1 -1
- package/dist/controlPlane/discovery/adminRoute.js +32 -8
- package/dist/controlPlane/discovery/routeInput.d.ts +23 -0
- package/dist/controlPlane/discovery/routeInput.d.ts.map +1 -0
- package/dist/controlPlane/discovery/routeInput.js +80 -0
- package/dist/controlPlane/discovery/toolName.d.ts +21 -0
- package/dist/controlPlane/discovery/toolName.d.ts.map +1 -0
- package/dist/controlPlane/discovery/toolName.js +25 -0
- package/dist/controlPlane/erasure/attest.d.ts +78 -0
- package/dist/controlPlane/erasure/attest.d.ts.map +1 -0
- package/dist/controlPlane/erasure/attest.js +164 -0
- package/dist/controlPlane/erasure/read.d.ts +39 -0
- package/dist/controlPlane/erasure/read.d.ts.map +1 -0
- package/dist/controlPlane/erasure/read.js +140 -0
- package/dist/controlPlane/error/errors.d.ts +61 -2
- package/dist/controlPlane/error/errors.d.ts.map +1 -1
- package/dist/controlPlane/error/errors.js +13 -0
- package/dist/controlPlane/evidence/derive.d.ts +124 -0
- package/dist/controlPlane/evidence/derive.d.ts.map +1 -0
- package/dist/controlPlane/evidence/derive.js +343 -0
- package/dist/controlPlane/evidence/mapping.d.ts +85 -0
- package/dist/controlPlane/evidence/mapping.d.ts.map +1 -0
- package/dist/controlPlane/evidence/mapping.js +114 -0
- package/dist/controlPlane/evidence/pack.d.ts +46 -0
- package/dist/controlPlane/evidence/pack.d.ts.map +1 -0
- package/dist/controlPlane/evidence/pack.js +124 -0
- package/dist/controlPlane/http/connections.d.ts +96 -0
- package/dist/controlPlane/http/connections.d.ts.map +1 -0
- package/dist/controlPlane/http/connections.js +109 -0
- package/dist/controlPlane/http/guard.d.ts +23 -2
- package/dist/controlPlane/http/guard.d.ts.map +1 -1
- package/dist/controlPlane/http/guard.js +103 -7
- package/dist/controlPlane/http/handlers.d.ts +212 -10
- package/dist/controlPlane/http/handlers.d.ts.map +1 -1
- package/dist/controlPlane/http/handlers.js +117 -26
- package/dist/controlPlane/http/holds.d.ts +57 -0
- package/dist/controlPlane/http/holds.d.ts.map +1 -0
- package/dist/controlPlane/http/holds.js +98 -0
- package/dist/controlPlane/http/presence.d.ts +27 -0
- package/dist/controlPlane/http/presence.d.ts.map +1 -0
- package/dist/controlPlane/http/presence.js +67 -0
- package/dist/controlPlane/http/processing.d.ts +73 -0
- package/dist/controlPlane/http/processing.d.ts.map +1 -0
- package/dist/controlPlane/http/processing.js +17 -0
- package/dist/controlPlane/http/responses.d.ts +927 -3
- package/dist/controlPlane/http/responses.d.ts.map +1 -1
- package/dist/controlPlane/http/responses.js +283 -7
- package/dist/controlPlane/http/routes.d.ts +12 -2
- package/dist/controlPlane/http/routes.d.ts.map +1 -1
- package/dist/controlPlane/http/routes.js +182 -5
- package/dist/controlPlane/http/schemas.d.ts +63 -0
- package/dist/controlPlane/http/schemas.d.ts.map +1 -1
- package/dist/controlPlane/http/schemas.js +39 -1
- package/dist/controlPlane/http/verify.d.ts.map +1 -1
- package/dist/controlPlane/http/verify.js +13 -1
- package/dist/controlPlane/http/verifyTrust.d.ts +76 -0
- package/dist/controlPlane/http/verifyTrust.d.ts.map +1 -0
- package/dist/controlPlane/http/verifyTrust.js +75 -0
- package/dist/controlPlane/migrations/0004_connection_trusts.d.ts +15 -0
- package/dist/controlPlane/migrations/0004_connection_trusts.d.ts.map +1 -0
- package/dist/controlPlane/migrations/0004_connection_trusts.js +23 -0
- package/dist/controlPlane/migrations/0005_holds.d.ts +12 -0
- package/dist/controlPlane/migrations/0005_holds.d.ts.map +1 -0
- package/dist/controlPlane/migrations/0005_holds.js +26 -0
- package/dist/controlPlane/processing/derive.d.ts +77 -0
- package/dist/controlPlane/processing/derive.d.ts.map +1 -0
- package/dist/controlPlane/processing/derive.js +206 -0
- package/dist/controlPlane/processing/read.d.ts +10 -0
- package/dist/controlPlane/processing/read.d.ts.map +1 -0
- package/dist/controlPlane/processing/read.js +89 -0
- package/dist/controlPlane/scope/kind.d.ts +46 -0
- package/dist/controlPlane/scope/kind.d.ts.map +1 -0
- package/dist/controlPlane/scope/kind.js +52 -0
- package/dist/controlPlane/scope/scope.d.ts +58 -3
- package/dist/controlPlane/scope/scope.d.ts.map +1 -1
- package/dist/controlPlane/scope/scope.js +59 -4
- package/dist/controlPlane/token/jws.js +1 -1
- package/dist/controlPlane/token/mint.js +1 -1
- package/dist/controlPlane/wire.d.ts +23 -0
- package/dist/controlPlane/wire.d.ts.map +1 -1
- package/dist/controlPlane/wire.js +24 -1
- package/dist/createBackend.d.ts +13 -0
- package/dist/createBackend.d.ts.map +1 -1
- package/dist/createBackend.js +11 -3
- package/dist/createEntrypoint.d.ts +14 -1
- package/dist/createEntrypoint.d.ts.map +1 -1
- package/dist/createEntrypoint.js +19 -5
- package/dist/error/http.d.ts +216 -0
- package/dist/error/http.d.ts.map +1 -1
- package/dist/error/payload.d.ts +432 -0
- package/dist/error/payload.d.ts.map +1 -1
- package/dist/error/payload.js +144 -0
- package/dist/error/pithyError.d.ts +22 -0
- package/dist/error/pithyError.d.ts.map +1 -1
- package/dist/error/pithyError.js +31 -1
- package/dist/http/routeSpec.d.ts +46 -1
- package/dist/http/routeSpec.d.ts.map +1 -1
- package/dist/http/routeSpec.js +39 -5
- package/dist/http/validation.d.ts +11 -2
- package/dist/http/validation.d.ts.map +1 -1
- package/dist/http/validation.js +20 -3
- package/dist/http/verification.d.ts.map +1 -1
- package/dist/http/verification.js +1 -1
- package/dist/i18n/translator.d.ts +2 -1
- package/dist/i18n/translator.d.ts.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/logger/record.d.ts +126 -0
- package/dist/logger/record.d.ts.map +1 -1
- package/dist/mcp/annotations.d.ts +20 -0
- package/dist/mcp/annotations.d.ts.map +1 -0
- package/dist/mcp/annotations.js +23 -0
- package/dist/mcp/tools.d.ts +75 -0
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +118 -0
- package/dist/openapi/document.d.ts.map +1 -1
- package/dist/openapi/document.js +8 -26
- package/dist/openapi/operations.d.ts +35 -0
- package/dist/openapi/operations.d.ts.map +1 -0
- package/dist/openapi/operations.js +37 -0
- package/dist/presence/channel.d.ts +11 -0
- package/dist/presence/channel.d.ts.map +1 -0
- package/dist/presence/channel.js +65 -0
- package/dist/presence/declaration.d.ts +154 -0
- package/dist/presence/declaration.d.ts.map +1 -0
- package/dist/presence/declaration.js +164 -0
- package/dist/presence/durableObject.d.ts +61 -0
- package/dist/presence/durableObject.d.ts.map +1 -0
- package/dist/presence/durableObject.js +257 -0
- package/dist/presence/frames.d.ts +166 -0
- package/dist/presence/frames.d.ts.map +1 -0
- package/dist/presence/frames.js +90 -0
- package/dist/presence/http/guard.d.ts +11 -0
- package/dist/presence/http/guard.d.ts.map +1 -0
- package/dist/presence/http/guard.js +20 -0
- package/dist/presence/http/responses.d.ts +31 -0
- package/dist/presence/http/responses.d.ts.map +1 -0
- package/dist/presence/http/responses.js +34 -0
- package/dist/presence/http/routes.d.ts +24 -0
- package/dist/presence/http/routes.d.ts.map +1 -0
- package/dist/presence/http/routes.js +127 -0
- package/dist/presence/http/schemas.d.ts +29 -0
- package/dist/presence/http/schemas.d.ts.map +1 -0
- package/dist/presence/http/schemas.js +28 -0
- package/dist/presence/names.d.ts +23 -0
- package/dist/presence/names.d.ts.map +1 -0
- package/dist/presence/names.js +22 -0
- package/dist/presence/room.d.ts +95 -0
- package/dist/presence/room.d.ts.map +1 -0
- package/dist/presence/room.js +105 -0
- package/dist/presence/ticket.d.ts +55 -0
- package/dist/presence/ticket.d.ts.map +1 -0
- package/dist/presence/ticket.js +109 -0
- package/dist/privacy/classify.js +1 -1
- package/dist/privacy/encrypted.js +1 -1
- package/dist/processing/activity.d.ts +134 -0
- package/dist/processing/activity.d.ts.map +1 -0
- package/dist/processing/activity.js +161 -0
- package/dist/processing/composed.d.ts +18 -0
- package/dist/processing/composed.d.ts.map +1 -0
- package/dist/processing/composed.js +28 -0
- package/dist/processing/vocabulary.d.ts +26 -0
- package/dist/processing/vocabulary.d.ts.map +1 -0
- package/dist/processing/vocabulary.js +35 -0
- package/dist/queue/consumer.d.ts +59 -0
- package/dist/queue/consumer.d.ts.map +1 -0
- package/dist/queue/consumer.js +46 -0
- package/dist/retention/composed.d.ts +37 -0
- package/dist/retention/composed.d.ts.map +1 -0
- package/dist/retention/composed.js +66 -0
- package/dist/retention/holds.d.ts +61 -0
- package/dist/retention/holds.d.ts.map +1 -0
- package/dist/retention/holds.js +107 -0
- package/dist/retention/holdsPurge.d.ts +22 -0
- package/dist/retention/holdsPurge.d.ts.map +1 -0
- package/dist/retention/holdsPurge.js +50 -0
- package/dist/retention/policy.d.ts +132 -0
- package/dist/retention/policy.d.ts.map +1 -0
- package/dist/retention/policy.js +197 -0
- package/dist/session/rotated.d.ts +34 -0
- package/dist/session/rotated.d.ts.map +1 -0
- package/dist/session/rotated.js +25 -0
- package/dist/test-utils/connectionFixtures.d.ts +13 -0
- package/dist/test-utils/connectionFixtures.d.ts.map +1 -0
- package/dist/test-utils/connectionFixtures.js +58 -0
- package/dist/test-utils/interleave.d.ts +12 -0
- package/dist/test-utils/interleave.d.ts.map +1 -0
- package/dist/test-utils/interleave.js +26 -0
- package/dist/testWorker.d.ts +8 -0
- package/dist/testWorker.d.ts.map +1 -0
- package/dist/testWorker.js +9 -0
- package/dist/version.generated.d.ts +1 -1
- package/dist/version.generated.js +1 -1
- package/dist/workflow/dispatchRoute.js +1 -1
- package/package.json +1 -1
- package/src/audit/auditEvent.ts +1 -1
- package/src/audit/chain.ts +551 -0
- package/src/audit/citations.ts +63 -0
- package/src/audit/composed.ts +30 -0
- package/src/capability/bindings.ts +61 -0
- package/src/capability/capability.ts +166 -18
- package/src/capability/erasure.ts +82 -0
- package/src/capability/personColumns.ts +83 -0
- package/src/capability/personRows.ts +125 -0
- package/src/capability/purge.ts +208 -8
- package/src/capability/settings.ts +7 -0
- package/src/capability/vectorIndex.ts +60 -0
- package/src/cli/commandCatalog.generated.ts +488 -2
- package/src/cli/commandFacts.ts +12 -3
- package/src/cloudflare-test.d.ts +3 -1
- package/src/consent/purpose.ts +160 -0
- package/src/consent/reader.ts +134 -0
- package/src/controlPlane/audit/actions.ts +15 -4
- package/src/controlPlane/capability.ts +99 -20
- package/src/controlPlane/context.ts +10 -2
- package/src/controlPlane/data/connection.ts +16 -2
- package/src/controlPlane/data/connections.ts +231 -0
- package/src/controlPlane/data/hold.ts +52 -0
- package/src/controlPlane/data/oidcTrust.ts +249 -0
- package/src/controlPlane/data/tables.ts +7 -0
- package/src/controlPlane/data/trustFirstCall.ts +37 -0
- package/src/controlPlane/discovery/adminRoute.ts +71 -9
- package/src/controlPlane/discovery/routeInput.ts +86 -0
- package/src/controlPlane/discovery/toolName.ts +23 -0
- package/src/controlPlane/erasure/attest.ts +205 -0
- package/src/controlPlane/erasure/read.ts +169 -0
- package/src/controlPlane/error/errors.ts +69 -2
- package/src/controlPlane/evidence/derive.ts +426 -0
- package/src/controlPlane/evidence/mapping.ts +118 -0
- package/src/controlPlane/evidence/pack.ts +190 -0
- package/src/controlPlane/http/connections.ts +129 -0
- package/src/controlPlane/http/guard.ts +178 -10
- package/src/controlPlane/http/handlers.ts +172 -40
- package/src/controlPlane/http/holds.ts +108 -0
- package/src/controlPlane/http/presence.ts +71 -0
- package/src/controlPlane/http/processing.ts +19 -0
- package/src/controlPlane/http/responses.ts +590 -7
- package/src/controlPlane/http/routes.ts +302 -3
- package/src/controlPlane/http/schemas.ts +126 -0
- package/src/controlPlane/http/verify.ts +19 -2
- package/src/controlPlane/http/verifyTrust.ts +176 -0
- package/src/controlPlane/migrations/0004_connection_trusts.ts +30 -0
- package/src/controlPlane/migrations/0005_holds.ts +40 -0
- package/src/controlPlane/processing/derive.ts +359 -0
- package/src/controlPlane/processing/read.ts +102 -0
- package/src/controlPlane/scope/kind.ts +63 -0
- package/src/controlPlane/scope/scope.ts +65 -3
- package/src/controlPlane/wire.ts +26 -0
- package/src/createBackend.ts +31 -6
- package/src/createEntrypoint.ts +34 -2
- package/src/error/payload.ts +302 -0
- package/src/error/pithyError.ts +42 -0
- package/src/http/routeSpec.ts +75 -5
- package/src/http/validation.ts +35 -3
- package/src/http/verification.ts +3 -1
- package/src/i18n/translator.ts +2 -1
- package/src/index.ts +2 -0
- package/src/mcp/annotations.ts +38 -0
- package/src/mcp/tools.ts +220 -0
- package/src/openapi/document.ts +8 -28
- package/src/openapi/operations.ts +62 -0
- package/src/presence/channel.ts +46 -0
- package/src/presence/declaration.ts +283 -0
- package/src/presence/durableObject.ts +287 -0
- package/src/presence/frames.ts +153 -0
- package/src/presence/http/guard.ts +23 -0
- package/src/presence/http/responses.ts +63 -0
- package/src/presence/http/routes.ts +165 -0
- package/src/presence/http/schemas.ts +39 -0
- package/src/presence/names.ts +45 -0
- package/src/presence/room.ts +145 -0
- package/src/presence/ticket.ts +145 -0
- package/src/processing/activity.ts +289 -0
- package/src/processing/composed.ts +33 -0
- package/src/processing/vocabulary.ts +43 -0
- package/src/queue/consumer.ts +104 -0
- package/src/retention/composed.ts +75 -0
- package/src/retention/holds.ts +175 -0
- package/src/retention/holdsPurge.ts +50 -0
- package/src/retention/policy.ts +305 -0
- package/src/session/rotated.ts +53 -0
- package/src/test-utils/connectionFixtures.ts +58 -0
- package/src/test-utils/interleave.ts +31 -0
- package/src/testWorker.ts +13 -0
- package/src/version.generated.ts +1 -1
package/src/error/payload.ts
CHANGED
|
@@ -213,6 +213,20 @@ const AuthAccountDeletedPublic = z
|
|
|
213
213
|
})
|
|
214
214
|
.describe("The account is deleted and awaiting its purge (403).");
|
|
215
215
|
|
|
216
|
+
const AuthHandoffInvalidPublic = z
|
|
217
|
+
.object({
|
|
218
|
+
code: z
|
|
219
|
+
.literal("auth/handoff_invalid")
|
|
220
|
+
.describe(
|
|
221
|
+
"The one-time code a native app trades for its session after a redirect sign-in is spent, expired, was never issued, or came with the wrong verifier. One code for all four, so the answer says nothing about which codes exist or why a trade failed. The remedy is the same for each: sign in again.",
|
|
222
|
+
),
|
|
223
|
+
status: z
|
|
224
|
+
.literal(400)
|
|
225
|
+
.describe("Bad Request — the code presented cannot be traded. Not 401: no credential was presented to refuse."),
|
|
226
|
+
...publicFields,
|
|
227
|
+
})
|
|
228
|
+
.describe("A sign-in handoff code that is spent, expired, unknown or presented with the wrong verifier (400).");
|
|
229
|
+
|
|
216
230
|
const NotFoundPublic = z
|
|
217
231
|
.object({
|
|
218
232
|
code: z.literal("core/not_found").describe("The requested resource does not exist."),
|
|
@@ -339,6 +353,30 @@ const WebhookUnverifiedPublic = z
|
|
|
339
353
|
})
|
|
340
354
|
.describe("An inbound webhook failed its signature check (401).");
|
|
341
355
|
|
|
356
|
+
// --- @pithy-sh/core: presence rooms ---
|
|
357
|
+
|
|
358
|
+
const PresenceTicketInvalidPublic = z
|
|
359
|
+
.object({
|
|
360
|
+
code: z
|
|
361
|
+
.literal("core/presence_ticket_invalid")
|
|
362
|
+
.describe(
|
|
363
|
+
"A presence socket was opened without a ticket this Worker accepts. Deliberately one code for every failing step — no ticket, a bad signature, an expired one, one already spent, or one minted for another room — so a caller holding a stolen ticket learns nothing about which check it tripped. `detail` names the step for the log, and the codec strips it.",
|
|
364
|
+
),
|
|
365
|
+
status: z.literal(401).describe("Unauthorized — mint a fresh ticket and open the socket with it."),
|
|
366
|
+
...publicFields,
|
|
367
|
+
})
|
|
368
|
+
.describe("A presence socket upgrade carried no valid ticket (401).");
|
|
369
|
+
|
|
370
|
+
const PresenceRoomFullPublic = z
|
|
371
|
+
.object({
|
|
372
|
+
code: z
|
|
373
|
+
.literal("core/presence_room_full")
|
|
374
|
+
.describe("A presence room already holds as many participants as its room kind allows."),
|
|
375
|
+
status: z.literal(409).describe("Conflict — the room is at its participant cap. Try again when someone leaves."),
|
|
376
|
+
...publicFields,
|
|
377
|
+
})
|
|
378
|
+
.describe("A presence room is at its participant cap (409).");
|
|
379
|
+
|
|
342
380
|
// --- @pithy-sh/cloudflare: out-of-Worker CF REST client codes ---
|
|
343
381
|
|
|
344
382
|
const CloudflareNotConfiguredPublic = z
|
|
@@ -855,6 +893,42 @@ const LedgerInvalidAmountPublic = z
|
|
|
855
893
|
})
|
|
856
894
|
.describe("An amount is not a positive integer (400).");
|
|
857
895
|
|
|
896
|
+
const LedgerEntryNotFoundPublic = z
|
|
897
|
+
.object({
|
|
898
|
+
code: z
|
|
899
|
+
.literal("ledger/entry_not_found")
|
|
900
|
+
.describe(
|
|
901
|
+
"No ledger entry with that reference exists on the account named. An entry on another account is answered the same way, so a reversal can never reach past the account its path names.",
|
|
902
|
+
),
|
|
903
|
+
status: z.literal(404).describe("Not Found."),
|
|
904
|
+
...publicFields,
|
|
905
|
+
})
|
|
906
|
+
.describe("A referenced ledger entry does not exist on that account (404).");
|
|
907
|
+
|
|
908
|
+
const LedgerEntryNotReversiblePublic = z
|
|
909
|
+
.object({
|
|
910
|
+
code: z
|
|
911
|
+
.literal("ledger/entry_not_reversible")
|
|
912
|
+
.describe(
|
|
913
|
+
"Only a credit or a debit reverses, and never one that is itself a reversal. A hold has release; a capture spends escrow and a transfer touches a second account, so both are refused. `params.kind` names the entry's kind, and `params.reverses` the entry a reversal reversed. Nothing was written.",
|
|
914
|
+
),
|
|
915
|
+
status: z.literal(409).describe("Conflict — the entry's kind does not reverse."),
|
|
916
|
+
...publicFields,
|
|
917
|
+
})
|
|
918
|
+
.describe("A ledger entry of a kind that does not reverse (409).");
|
|
919
|
+
|
|
920
|
+
const LedgerRefConflictPublic = z
|
|
921
|
+
.object({
|
|
922
|
+
code: z
|
|
923
|
+
.literal("ledger/ref_conflict")
|
|
924
|
+
.describe(
|
|
925
|
+
"The ref a control-plane write would be written under is already held by a different entry, so the write cannot be recorded and is not a replay either: a credit's or a debit's key already used for another account, the other act, another amount or a hold, or the derived ref of a reversal or a hold's resolution held by an unrelated entry. Nothing moved; the entry stays unreversed, or the hold stays open.",
|
|
926
|
+
),
|
|
927
|
+
status: z.literal(409).describe("Conflict — the ref belongs to another entry."),
|
|
928
|
+
...publicFields,
|
|
929
|
+
})
|
|
930
|
+
.describe("A write whose ref another entry already holds (409).");
|
|
931
|
+
|
|
858
932
|
// --- @pithy-sh/rating: skill-rating + experience tracker codes ---
|
|
859
933
|
|
|
860
934
|
const RatingUnknownAlgorithmPublic = z
|
|
@@ -921,6 +995,96 @@ const RatingRecordForbiddenPublic = z
|
|
|
921
995
|
})
|
|
922
996
|
.describe("The caller lacks the scope to record a rated outcome (403).");
|
|
923
997
|
|
|
998
|
+
// --- @pithy-sh/consent: purposes, grants and withdrawals ---
|
|
999
|
+
|
|
1000
|
+
const ConsentUnknownPurposePublic = z
|
|
1001
|
+
.object({
|
|
1002
|
+
code: z
|
|
1003
|
+
.literal("consent/unknown_purpose")
|
|
1004
|
+
.describe("No consent purpose with that id is declared by a composed capability or in `consent({ purposes })`."),
|
|
1005
|
+
status: z.literal(404).describe("Not Found."),
|
|
1006
|
+
...publicFields,
|
|
1007
|
+
})
|
|
1008
|
+
.describe("A consent purpose that is not declared (404).");
|
|
1009
|
+
|
|
1010
|
+
const ConsentStaleNoticePublic = z
|
|
1011
|
+
.object({
|
|
1012
|
+
code: z
|
|
1013
|
+
.literal("consent/stale_notice")
|
|
1014
|
+
.describe(
|
|
1015
|
+
"The grant names a notice version that is not the purpose's current one. A person agrees to the notice in force, so the screen showing an older one has to be reloaded.",
|
|
1016
|
+
),
|
|
1017
|
+
status: z.literal(409).describe("Conflict — the notice has moved on."),
|
|
1018
|
+
...publicFields,
|
|
1019
|
+
})
|
|
1020
|
+
.describe("A grant against a notice version that is not current (409).");
|
|
1021
|
+
|
|
1022
|
+
const ConsentMethodBelowMinimumPublic = z
|
|
1023
|
+
.object({
|
|
1024
|
+
code: z
|
|
1025
|
+
.literal("consent/method_below_minimum")
|
|
1026
|
+
.describe(
|
|
1027
|
+
"The grant was given by a method below the purpose's minimum — a click where the purpose needs a typed name, a drawn signature or a provider's envelope.",
|
|
1028
|
+
),
|
|
1029
|
+
status: z.literal(400).describe("Bad Request — the method is below the purpose's minimum."),
|
|
1030
|
+
...publicFields,
|
|
1031
|
+
})
|
|
1032
|
+
.describe("A grant below the purpose's minimum method (400).");
|
|
1033
|
+
|
|
1034
|
+
const ConsentWithdrawalBelowGrantPublic = z
|
|
1035
|
+
.object({
|
|
1036
|
+
code: z
|
|
1037
|
+
.literal("consent/withdrawal_below_grant")
|
|
1038
|
+
.describe(
|
|
1039
|
+
"The purpose requires a withdrawal at least at the grade of the grant it withdraws, as a HIPAA revocation must be in writing, and this one is below it.",
|
|
1040
|
+
),
|
|
1041
|
+
status: z.literal(400).describe("Bad Request — the withdrawal is below the grant's method."),
|
|
1042
|
+
...publicFields,
|
|
1043
|
+
})
|
|
1044
|
+
.describe("A withdrawal below the grade its purpose requires (400).");
|
|
1045
|
+
|
|
1046
|
+
const ConsentEvidenceMissingPublic = z
|
|
1047
|
+
.object({
|
|
1048
|
+
code: z
|
|
1049
|
+
.literal("consent/evidence_missing")
|
|
1050
|
+
.describe(
|
|
1051
|
+
"The method names evidence the request did not carry: a typed name for `typed`, a drawn image for `drawn`, a provider and envelope for `provider`, or the document a signed grant is given against.",
|
|
1052
|
+
),
|
|
1053
|
+
status: z.literal(400).describe("Bad Request — the evidence for the method is missing."),
|
|
1054
|
+
...publicFields,
|
|
1055
|
+
})
|
|
1056
|
+
.describe("A grant or withdrawal missing the evidence its method needs (400).");
|
|
1057
|
+
|
|
1058
|
+
const ConsentExpiryPassedPublic = z
|
|
1059
|
+
.object({
|
|
1060
|
+
code: z
|
|
1061
|
+
.literal("consent/expiry_passed")
|
|
1062
|
+
.describe("The grant's expiry is not in the future, so it would answer no from the moment it was recorded."),
|
|
1063
|
+
status: z.literal(400).describe("Bad Request — the expiry has already passed."),
|
|
1064
|
+
...publicFields,
|
|
1065
|
+
})
|
|
1066
|
+
.describe("A grant whose expiry has already passed (400).");
|
|
1067
|
+
|
|
1068
|
+
const ConsentDocumentNotFoundPublic = z
|
|
1069
|
+
.object({
|
|
1070
|
+
code: z.literal("consent/document_not_found").describe("No signed document with that content hash is kept."),
|
|
1071
|
+
status: z.literal(404).describe("Not Found."),
|
|
1072
|
+
...publicFields,
|
|
1073
|
+
})
|
|
1074
|
+
.describe("A signed document that is not kept (404).");
|
|
1075
|
+
|
|
1076
|
+
const ConsentEvidenceStoreMissingPublic = z
|
|
1077
|
+
.object({
|
|
1078
|
+
code: z
|
|
1079
|
+
.literal("consent/evidence_store_missing")
|
|
1080
|
+
.describe(
|
|
1081
|
+
"A drawn signature or a provider's certificate is stored in R2, and the Worker has no `CONSENT_EVIDENCE` bucket bound. A binding we never got, so the answer is in this Worker's wiring.",
|
|
1082
|
+
),
|
|
1083
|
+
status: z.literal(500).describe("Internal Server Error — the evidence bucket is not bound."),
|
|
1084
|
+
...publicFields,
|
|
1085
|
+
})
|
|
1086
|
+
.describe("The evidence bucket is not bound (500).");
|
|
1087
|
+
|
|
924
1088
|
// --- @pithy-sh/matchmaking: pairing + presence capability codes ---
|
|
925
1089
|
|
|
926
1090
|
const MatchmakingRoomNotFoundPublic = z
|
|
@@ -1525,6 +1689,54 @@ const OrganizationNominationInvalidPublic = z
|
|
|
1525
1689
|
})
|
|
1526
1690
|
.describe("No standing ownership offer this caller may accept (400).");
|
|
1527
1691
|
|
|
1692
|
+
const OrganizationLastOwnerPublic = z
|
|
1693
|
+
.object({
|
|
1694
|
+
code: z
|
|
1695
|
+
.literal("organization/last_owner")
|
|
1696
|
+
.describe(
|
|
1697
|
+
"An operator write would leave the account with nobody holding the role a transfer of ownership confers: removing or demoting its only owner. An account with no owner is the unadministrable state membership administration exists to get out of, so the way out is to force ownership onto somebody else first, which `params.ownershipRoute` names.",
|
|
1698
|
+
),
|
|
1699
|
+
status: z.literal(409).describe("Conflict — an account nobody owns is not a state to arrive at."),
|
|
1700
|
+
...publicFields,
|
|
1701
|
+
})
|
|
1702
|
+
.describe("The last owner cannot be removed or demoted (409).");
|
|
1703
|
+
|
|
1704
|
+
const OrganizationAlreadyMemberPublic = z
|
|
1705
|
+
.object({
|
|
1706
|
+
code: z
|
|
1707
|
+
.literal("organization/already_member")
|
|
1708
|
+
.describe(
|
|
1709
|
+
"An operator tried to add somebody who already holds a membership in the account. One membership per person per organization, so this is a refusal rather than a second row — and `params.role` names the role they already hold, because the next step is a role change rather than an add.",
|
|
1710
|
+
),
|
|
1711
|
+
status: z.literal(409).describe("Conflict."),
|
|
1712
|
+
...publicFields,
|
|
1713
|
+
})
|
|
1714
|
+
.describe("That person is already a member (409).");
|
|
1715
|
+
|
|
1716
|
+
const OrganizationSeatLimitReachedPublic = z
|
|
1717
|
+
.object({
|
|
1718
|
+
code: z
|
|
1719
|
+
.literal("organization/seat_limit_reached")
|
|
1720
|
+
.describe(
|
|
1721
|
+
"The account holds as many members as its seat limit allows, so another one would exceed it. `params.seatLimit` names the limit. An operator add may override it, and the override is recorded; an invitation accepted against a full account is refused until a seat frees.",
|
|
1722
|
+
),
|
|
1723
|
+
status: z.literal(409).describe("Conflict."),
|
|
1724
|
+
...publicFields,
|
|
1725
|
+
})
|
|
1726
|
+
.describe("The account has no free seat (409).");
|
|
1727
|
+
|
|
1728
|
+
const OrganizationSuspendedPublic = z
|
|
1729
|
+
.object({
|
|
1730
|
+
code: z
|
|
1731
|
+
.literal("organization/organization_suspended")
|
|
1732
|
+
.describe(
|
|
1733
|
+
"The organization this request acts in is suspended by an operator, so nobody can act in it until it is reinstated (#623). The caller's own account is not affected, and their other organizations are not either. `params.suspendedUntil`, when present, is when the suspension ends by itself, ISO-8601. Not `organization/forbidden`, because no role would let them, and not `organization/not_found`, because the caller is a proved member and already knows the organization exists.",
|
|
1734
|
+
),
|
|
1735
|
+
status: z.literal(403).describe("Forbidden — the organization may not be acted in, whoever asks."),
|
|
1736
|
+
...publicFields,
|
|
1737
|
+
})
|
|
1738
|
+
.describe("The organization is suspended (403).");
|
|
1739
|
+
|
|
1528
1740
|
// --- @pithy-sh/artifacts: Git repositories, ownership, grants and short-lived tokens ---
|
|
1529
1741
|
|
|
1530
1742
|
const ArtifactsNotFoundPublic = z
|
|
@@ -1792,6 +2004,7 @@ export const KitPublicErrorPayload = z
|
|
|
1792
2004
|
AuthSessionNotFreshPublic,
|
|
1793
2005
|
AuthAccountSuspendedPublic,
|
|
1794
2006
|
AuthAccountDeletedPublic,
|
|
2007
|
+
AuthHandoffInvalidPublic,
|
|
1795
2008
|
NotFoundPublic,
|
|
1796
2009
|
ConflictPublic,
|
|
1797
2010
|
RateLimitPublic,
|
|
@@ -1803,6 +2016,8 @@ export const KitPublicErrorPayload = z
|
|
|
1803
2016
|
UnknownWorkflowPublic,
|
|
1804
2017
|
WorkflowFailedPublic,
|
|
1805
2018
|
WebhookUnverifiedPublic,
|
|
2019
|
+
PresenceTicketInvalidPublic,
|
|
2020
|
+
PresenceRoomFullPublic,
|
|
1806
2021
|
CloudflareNotConfiguredPublic,
|
|
1807
2022
|
CloudflareRequestFailedPublic,
|
|
1808
2023
|
CloudflareInvalidResponsePublic,
|
|
@@ -1850,12 +2065,23 @@ export const KitPublicErrorPayload = z
|
|
|
1850
2065
|
LedgerInsufficientFundsPublic,
|
|
1851
2066
|
LedgerHoldNotOpenPublic,
|
|
1852
2067
|
LedgerInvalidAmountPublic,
|
|
2068
|
+
LedgerEntryNotFoundPublic,
|
|
2069
|
+
LedgerEntryNotReversiblePublic,
|
|
2070
|
+
LedgerRefConflictPublic,
|
|
1853
2071
|
RatingUnknownAlgorithmPublic,
|
|
1854
2072
|
RatingUnsupportedPlayerCountPublic,
|
|
1855
2073
|
RatingInvalidParamsPublic,
|
|
1856
2074
|
RatingGameNotFoundPublic,
|
|
1857
2075
|
RatingPoolNotFoundPublic,
|
|
1858
2076
|
RatingRecordForbiddenPublic,
|
|
2077
|
+
ConsentUnknownPurposePublic,
|
|
2078
|
+
ConsentStaleNoticePublic,
|
|
2079
|
+
ConsentMethodBelowMinimumPublic,
|
|
2080
|
+
ConsentWithdrawalBelowGrantPublic,
|
|
2081
|
+
ConsentEvidenceMissingPublic,
|
|
2082
|
+
ConsentExpiryPassedPublic,
|
|
2083
|
+
ConsentDocumentNotFoundPublic,
|
|
2084
|
+
ConsentEvidenceStoreMissingPublic,
|
|
1859
2085
|
MatchmakingRoomNotFoundPublic,
|
|
1860
2086
|
MatchmakingRoomFullPublic,
|
|
1861
2087
|
MatchmakingInvalidCodePublic,
|
|
@@ -1908,6 +2134,10 @@ export const KitPublicErrorPayload = z
|
|
|
1908
2134
|
OrganizationLastAdministratorPublic,
|
|
1909
2135
|
OrganizationSlugTakenPublic,
|
|
1910
2136
|
OrganizationNominationInvalidPublic,
|
|
2137
|
+
OrganizationLastOwnerPublic,
|
|
2138
|
+
OrganizationAlreadyMemberPublic,
|
|
2139
|
+
OrganizationSeatLimitReachedPublic,
|
|
2140
|
+
OrganizationSuspendedPublic,
|
|
1911
2141
|
ArtifactsNotFoundPublic,
|
|
1912
2142
|
ArtifactsForbiddenPublic,
|
|
1913
2143
|
ArtifactsInvalidNamePublic,
|
|
@@ -1954,6 +2184,9 @@ const AuthAccountSuspended = AuthAccountSuspendedPublic.extend(internalFields).d
|
|
|
1954
2184
|
const AuthAccountDeleted = AuthAccountDeletedPublic.extend(internalFields).describe(
|
|
1955
2185
|
AuthAccountDeletedPublic.description ?? "",
|
|
1956
2186
|
);
|
|
2187
|
+
const AuthHandoffInvalid = AuthHandoffInvalidPublic.extend(internalFields).describe(
|
|
2188
|
+
AuthHandoffInvalidPublic.description ?? "",
|
|
2189
|
+
);
|
|
1957
2190
|
const NotFound = NotFoundPublic.extend(internalFields).describe(NotFoundPublic.description ?? "");
|
|
1958
2191
|
const Conflict = ConflictPublic.extend(internalFields).describe(ConflictPublic.description ?? "");
|
|
1959
2192
|
const RateLimit = RateLimitPublic.extend(internalFields).describe(RateLimitPublic.description ?? "");
|
|
@@ -1971,6 +2204,12 @@ const WorkflowFailed = WorkflowFailedPublic.extend(internalFields).describe(Work
|
|
|
1971
2204
|
const WebhookUnverified = WebhookUnverifiedPublic.extend(internalFields).describe(
|
|
1972
2205
|
WebhookUnverifiedPublic.description ?? "",
|
|
1973
2206
|
);
|
|
2207
|
+
const PresenceTicketInvalid = PresenceTicketInvalidPublic.extend(internalFields).describe(
|
|
2208
|
+
PresenceTicketInvalidPublic.description ?? "",
|
|
2209
|
+
);
|
|
2210
|
+
const PresenceRoomFull = PresenceRoomFullPublic.extend(internalFields).describe(
|
|
2211
|
+
PresenceRoomFullPublic.description ?? "",
|
|
2212
|
+
);
|
|
1974
2213
|
const CloudflareNotConfigured = CloudflareNotConfiguredPublic.extend(internalFields).describe(
|
|
1975
2214
|
CloudflareNotConfiguredPublic.description ?? "",
|
|
1976
2215
|
);
|
|
@@ -2098,6 +2337,15 @@ const LedgerHoldNotOpen = LedgerHoldNotOpenPublic.extend(internalFields).describ
|
|
|
2098
2337
|
const LedgerInvalidAmount = LedgerInvalidAmountPublic.extend(internalFields).describe(
|
|
2099
2338
|
LedgerInvalidAmountPublic.description ?? "",
|
|
2100
2339
|
);
|
|
2340
|
+
const LedgerEntryNotFound = LedgerEntryNotFoundPublic.extend(internalFields).describe(
|
|
2341
|
+
LedgerEntryNotFoundPublic.description ?? "",
|
|
2342
|
+
);
|
|
2343
|
+
const LedgerEntryNotReversible = LedgerEntryNotReversiblePublic.extend(internalFields).describe(
|
|
2344
|
+
LedgerEntryNotReversiblePublic.description ?? "",
|
|
2345
|
+
);
|
|
2346
|
+
const LedgerRefConflict = LedgerRefConflictPublic.extend(internalFields).describe(
|
|
2347
|
+
LedgerRefConflictPublic.description ?? "",
|
|
2348
|
+
);
|
|
2101
2349
|
const RatingUnknownAlgorithm = RatingUnknownAlgorithmPublic.extend(internalFields).describe(
|
|
2102
2350
|
RatingUnknownAlgorithmPublic.description ?? "",
|
|
2103
2351
|
);
|
|
@@ -2116,6 +2364,30 @@ const RatingPoolNotFound = RatingPoolNotFoundPublic.extend(internalFields).descr
|
|
|
2116
2364
|
const RatingRecordForbidden = RatingRecordForbiddenPublic.extend(internalFields).describe(
|
|
2117
2365
|
RatingRecordForbiddenPublic.description ?? "",
|
|
2118
2366
|
);
|
|
2367
|
+
const ConsentUnknownPurpose = ConsentUnknownPurposePublic.extend(internalFields).describe(
|
|
2368
|
+
ConsentUnknownPurposePublic.description ?? "",
|
|
2369
|
+
);
|
|
2370
|
+
const ConsentStaleNotice = ConsentStaleNoticePublic.extend(internalFields).describe(
|
|
2371
|
+
ConsentStaleNoticePublic.description ?? "",
|
|
2372
|
+
);
|
|
2373
|
+
const ConsentMethodBelowMinimum = ConsentMethodBelowMinimumPublic.extend(internalFields).describe(
|
|
2374
|
+
ConsentMethodBelowMinimumPublic.description ?? "",
|
|
2375
|
+
);
|
|
2376
|
+
const ConsentWithdrawalBelowGrant = ConsentWithdrawalBelowGrantPublic.extend(internalFields).describe(
|
|
2377
|
+
ConsentWithdrawalBelowGrantPublic.description ?? "",
|
|
2378
|
+
);
|
|
2379
|
+
const ConsentEvidenceMissing = ConsentEvidenceMissingPublic.extend(internalFields).describe(
|
|
2380
|
+
ConsentEvidenceMissingPublic.description ?? "",
|
|
2381
|
+
);
|
|
2382
|
+
const ConsentExpiryPassed = ConsentExpiryPassedPublic.extend(internalFields).describe(
|
|
2383
|
+
ConsentExpiryPassedPublic.description ?? "",
|
|
2384
|
+
);
|
|
2385
|
+
const ConsentDocumentNotFound = ConsentDocumentNotFoundPublic.extend(internalFields).describe(
|
|
2386
|
+
ConsentDocumentNotFoundPublic.description ?? "",
|
|
2387
|
+
);
|
|
2388
|
+
const ConsentEvidenceStoreMissing = ConsentEvidenceStoreMissingPublic.extend(internalFields).describe(
|
|
2389
|
+
ConsentEvidenceStoreMissingPublic.description ?? "",
|
|
2390
|
+
);
|
|
2119
2391
|
const MatchmakingRoomNotFound = MatchmakingRoomNotFoundPublic.extend(internalFields).describe(
|
|
2120
2392
|
MatchmakingRoomNotFoundPublic.description ?? "",
|
|
2121
2393
|
);
|
|
@@ -2304,6 +2576,18 @@ const OrganizationSlugTaken = OrganizationSlugTakenPublic.extend(internalFields)
|
|
|
2304
2576
|
const OrganizationNominationInvalid = OrganizationNominationInvalidPublic.extend(internalFields).describe(
|
|
2305
2577
|
OrganizationNominationInvalidPublic.description ?? "",
|
|
2306
2578
|
);
|
|
2579
|
+
const OrganizationLastOwner = OrganizationLastOwnerPublic.extend(internalFields).describe(
|
|
2580
|
+
OrganizationLastOwnerPublic.description ?? "",
|
|
2581
|
+
);
|
|
2582
|
+
const OrganizationAlreadyMember = OrganizationAlreadyMemberPublic.extend(internalFields).describe(
|
|
2583
|
+
OrganizationAlreadyMemberPublic.description ?? "",
|
|
2584
|
+
);
|
|
2585
|
+
const OrganizationSeatLimitReached = OrganizationSeatLimitReachedPublic.extend(internalFields).describe(
|
|
2586
|
+
OrganizationSeatLimitReachedPublic.description ?? "",
|
|
2587
|
+
);
|
|
2588
|
+
const OrganizationSuspended = OrganizationSuspendedPublic.extend(internalFields).describe(
|
|
2589
|
+
OrganizationSuspendedPublic.description ?? "",
|
|
2590
|
+
);
|
|
2307
2591
|
|
|
2308
2592
|
const ArtifactsNotFound = ArtifactsNotFoundPublic.extend(internalFields).describe(
|
|
2309
2593
|
ArtifactsNotFoundPublic.description ?? "",
|
|
@@ -2353,6 +2637,7 @@ export const KitErrorPayload = z
|
|
|
2353
2637
|
AuthSessionNotFresh,
|
|
2354
2638
|
AuthAccountSuspended,
|
|
2355
2639
|
AuthAccountDeleted,
|
|
2640
|
+
AuthHandoffInvalid,
|
|
2356
2641
|
NotFound,
|
|
2357
2642
|
Conflict,
|
|
2358
2643
|
RateLimit,
|
|
@@ -2364,6 +2649,8 @@ export const KitErrorPayload = z
|
|
|
2364
2649
|
UnknownWorkflow,
|
|
2365
2650
|
WorkflowFailed,
|
|
2366
2651
|
WebhookUnverified,
|
|
2652
|
+
PresenceTicketInvalid,
|
|
2653
|
+
PresenceRoomFull,
|
|
2367
2654
|
CloudflareNotConfigured,
|
|
2368
2655
|
CloudflareRequestFailed,
|
|
2369
2656
|
CloudflareInvalidResponse,
|
|
@@ -2411,12 +2698,23 @@ export const KitErrorPayload = z
|
|
|
2411
2698
|
LedgerInsufficientFunds,
|
|
2412
2699
|
LedgerHoldNotOpen,
|
|
2413
2700
|
LedgerInvalidAmount,
|
|
2701
|
+
LedgerEntryNotFound,
|
|
2702
|
+
LedgerEntryNotReversible,
|
|
2703
|
+
LedgerRefConflict,
|
|
2414
2704
|
RatingUnknownAlgorithm,
|
|
2415
2705
|
RatingUnsupportedPlayerCount,
|
|
2416
2706
|
RatingInvalidParams,
|
|
2417
2707
|
RatingGameNotFound,
|
|
2418
2708
|
RatingPoolNotFound,
|
|
2419
2709
|
RatingRecordForbidden,
|
|
2710
|
+
ConsentUnknownPurpose,
|
|
2711
|
+
ConsentStaleNotice,
|
|
2712
|
+
ConsentMethodBelowMinimum,
|
|
2713
|
+
ConsentWithdrawalBelowGrant,
|
|
2714
|
+
ConsentEvidenceMissing,
|
|
2715
|
+
ConsentExpiryPassed,
|
|
2716
|
+
ConsentDocumentNotFound,
|
|
2717
|
+
ConsentEvidenceStoreMissing,
|
|
2420
2718
|
MatchmakingRoomNotFound,
|
|
2421
2719
|
MatchmakingRoomFull,
|
|
2422
2720
|
MatchmakingInvalidCode,
|
|
@@ -2469,6 +2767,10 @@ export const KitErrorPayload = z
|
|
|
2469
2767
|
OrganizationLastAdministrator,
|
|
2470
2768
|
OrganizationSlugTaken,
|
|
2471
2769
|
OrganizationNominationInvalid,
|
|
2770
|
+
OrganizationLastOwner,
|
|
2771
|
+
OrganizationAlreadyMember,
|
|
2772
|
+
OrganizationSeatLimitReached,
|
|
2773
|
+
OrganizationSuspended,
|
|
2472
2774
|
ArtifactsNotFound,
|
|
2473
2775
|
ArtifactsForbidden,
|
|
2474
2776
|
ArtifactsInvalidName,
|
package/src/error/pithyError.ts
CHANGED
|
@@ -192,6 +192,48 @@ export class WebhookUnverifiedError extends PithyError {
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
/**
|
|
196
|
+
* One code for every way a presence socket's ticket fails — missing, forged, expired, spent, or minted for
|
|
197
|
+
* another room. The step goes in `detail`, which the codec strips: a caller holding somebody else's ticket
|
|
198
|
+
* learns only that it no longer works.
|
|
199
|
+
*/
|
|
200
|
+
export class PresenceTicketInvalidError extends PithyError {
|
|
201
|
+
declare readonly payload: Extract<ErrorPayload, { code: "core/presence_ticket_invalid" }>;
|
|
202
|
+
|
|
203
|
+
constructor(args: ErrorArgs = {}, options?: { cause?: unknown }) {
|
|
204
|
+
super(
|
|
205
|
+
{
|
|
206
|
+
code: "core/presence_ticket_invalid",
|
|
207
|
+
status: 401,
|
|
208
|
+
message: args.message ?? "That presence ticket is not valid.",
|
|
209
|
+
action: args.action ?? "Mint a fresh ticket and open the socket within 60 seconds.",
|
|
210
|
+
detail: args.detail,
|
|
211
|
+
params: args.params,
|
|
212
|
+
},
|
|
213
|
+
options,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/** A presence room is at the participant cap its room kind declares. */
|
|
219
|
+
export class PresenceRoomFullError extends PithyError {
|
|
220
|
+
declare readonly payload: Extract<ErrorPayload, { code: "core/presence_room_full" }>;
|
|
221
|
+
|
|
222
|
+
constructor(args: ErrorArgs = {}, options?: { cause?: unknown }) {
|
|
223
|
+
super(
|
|
224
|
+
{
|
|
225
|
+
code: "core/presence_room_full",
|
|
226
|
+
status: 409,
|
|
227
|
+
message: args.message ?? "That room is full.",
|
|
228
|
+
action: args.action,
|
|
229
|
+
detail: args.detail,
|
|
230
|
+
params: args.params,
|
|
231
|
+
},
|
|
232
|
+
options,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
195
237
|
export class ForbiddenError extends PithyError {
|
|
196
238
|
declare readonly payload: Extract<ErrorPayload, { code: "auth/forbidden" }>;
|
|
197
239
|
|
package/src/http/routeSpec.ts
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
import type { MiddlewareHandler } from "hono";
|
|
5
5
|
import type { z } from "zod";
|
|
6
|
+
import type { PithyHonoEnv } from "../capability/capability";
|
|
7
|
+
import { ForbiddenError, UnauthorizedError } from "../error/pithyError";
|
|
6
8
|
import type { VerificationStrategy } from "./verification";
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -43,6 +45,24 @@ export interface RouteResponse {
|
|
|
43
45
|
/** The HTTP methods an `app.all` route is documented under. OpenAPI has no "any method". */
|
|
44
46
|
export type DocumentedMethod = "get" | "post" | "put" | "patch" | "delete" | "head" | "options";
|
|
45
47
|
|
|
48
|
+
/**
|
|
49
|
+
* What a tool does beyond reading, which every non-`GET` tool must say (`docs/AGENT-ACCESS.md` §4).
|
|
50
|
+
*
|
|
51
|
+
* **A route is a tool only when it says so, and a non-`GET` says so louder.** One that sends mail, charges a card or
|
|
52
|
+
* deletes something is a tool an agent can call in a loop, so the effect is not inferred from the method: it is
|
|
53
|
+
* declared, it sets the tool's MCP annotations, it is written into the tool's description, and it is counted on the
|
|
54
|
+
* consent screen beside its capability.
|
|
55
|
+
*/
|
|
56
|
+
export const TOOL_EFFECTS = ["writes", "sends", "charges", "deletes"] as const;
|
|
57
|
+
export type ToolEffect = (typeof TOOL_EFFECTS)[number];
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* A route's opt-in to the app's MCP endpoint. `true` is a read, and only a `GET` may say it; anything else declares
|
|
61
|
+
* its {@link ToolEffect}. `createBackend` refuses a composition where either half is wrong — `describeRoute` cannot
|
|
62
|
+
* see the method it is mounted under, so the composition is the first place the pair can be checked.
|
|
63
|
+
*/
|
|
64
|
+
export type RouteTool = true | { readonly effect: ToolEffect };
|
|
65
|
+
|
|
46
66
|
/** What a route is for, how its caller is verified, and what it returns. */
|
|
47
67
|
export interface RouteSpec {
|
|
48
68
|
/** One sentence, in the brand voice. The operation's title in the contract. */
|
|
@@ -64,14 +84,64 @@ export interface RouteSpec {
|
|
|
64
84
|
readonly responses: Readonly<Record<number, z.ZodType | RouteResponse>>;
|
|
65
85
|
/** For an `app.all` route only: the methods it is documented under. */
|
|
66
86
|
readonly methods?: readonly DocumentedMethod[];
|
|
87
|
+
/**
|
|
88
|
+
* The power a caller's role must hold to reach this route at all. **Declaring it installs the gate**: the
|
|
89
|
+
* same middleware that carries this spec refuses a caller whose acting organization's role does not hold it, so
|
|
90
|
+
* what the MCP endpoint filters `tools/list` on and what the route enforces are one value and cannot drift.
|
|
91
|
+
*
|
|
92
|
+
* A route whose access depends on the record — its owner may, a manager may — declares the power that lets a
|
|
93
|
+
* member reach it at all, and keeps its in-handler check. Absent, the route is gated by its other guards alone,
|
|
94
|
+
* and a tool for it is offered to every signed-in user the endpoint admits.
|
|
95
|
+
*/
|
|
96
|
+
readonly power?: string;
|
|
97
|
+
/**
|
|
98
|
+
* The route's permanent name within its capability, e.g. `threads.reply`. Its MCP tool is
|
|
99
|
+
* `<capability>_<operation>`, through the one normalizer the control-plane server's tools use. Unique within a
|
|
100
|
+
* capability, and never renamed once published: an agent references a tool by name.
|
|
101
|
+
*/
|
|
102
|
+
readonly operation?: string;
|
|
103
|
+
/**
|
|
104
|
+
* The route's opt-in to the app's MCP endpoint. Absent, the route is not a tool. See {@link RouteTool}.
|
|
105
|
+
*/
|
|
106
|
+
readonly tool?: RouteTool;
|
|
67
107
|
}
|
|
68
108
|
|
|
69
|
-
/**
|
|
109
|
+
/**
|
|
110
|
+
* Declare what a route is for, how its caller is verified, and what it returns. See {@link RouteSpec}.
|
|
111
|
+
*
|
|
112
|
+
* With a {@link RouteSpec.power} it is also the route's power gate, read off the acting-organization seam the way
|
|
113
|
+
* every capability outside tenancy asks it. It sits first on the route line, so it answers an anonymous caller
|
|
114
|
+
* itself rather than assuming a guard below it will: a 401, because signing in might help, where a role that does
|
|
115
|
+
* not hold the power is a 403.
|
|
116
|
+
*/
|
|
70
117
|
export function describeRoute(spec: RouteSpec): MiddlewareHandler {
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
118
|
+
const { power } = spec;
|
|
119
|
+
const middleware: MiddlewareHandler<PithyHonoEnv> =
|
|
120
|
+
power === undefined
|
|
121
|
+
? async (_c, next) => {
|
|
122
|
+
await next();
|
|
123
|
+
}
|
|
124
|
+
: async (c, next) => {
|
|
125
|
+
if (!c.var.auth) {
|
|
126
|
+
throw new UnauthorizedError({
|
|
127
|
+
message: "Authentication required.",
|
|
128
|
+
action: "Sign in and retry with a valid session or bearer token.",
|
|
129
|
+
detail: `describeRoute(power: ${power}) ran with no signed-in caller`,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
const acting = await c.var.actingOrganization();
|
|
133
|
+
if (acting === null || !acting.roleAllows(power)) {
|
|
134
|
+
throw new ForbiddenError({
|
|
135
|
+
message: `Your role does not allow \`${power}\`.`,
|
|
136
|
+
detail:
|
|
137
|
+
acting === null
|
|
138
|
+
? `no organization is in force for user ${c.var.auth.userId}, so ${power} is not held`
|
|
139
|
+
: `the role in organization ${acting.organizationId} does not hold ${power}`,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
await next();
|
|
143
|
+
};
|
|
144
|
+
return Object.assign(middleware as MiddlewareHandler, { [ROUTE_SPEC]: spec });
|
|
75
145
|
}
|
|
76
146
|
|
|
77
147
|
/** The spec a {@link describeRoute} middleware carries, or `undefined` for any other handler. */
|
package/src/http/validation.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-License-Identifier: MIT
|
|
3
3
|
|
|
4
4
|
import { zValidator } from "@hono/zod-validator";
|
|
5
|
-
import type { ValidationTargets } from "hono";
|
|
5
|
+
import type { Context, MiddlewareHandler, ValidationTargets } from "hono";
|
|
6
6
|
import type { z } from "zod";
|
|
7
7
|
import { fromZodError } from "../error/pithyError";
|
|
8
8
|
|
|
@@ -70,12 +70,44 @@ export interface RequestContract {
|
|
|
70
70
|
export function validate<Target extends keyof ValidationTargets, Schema extends z.ZodType>(
|
|
71
71
|
target: Target,
|
|
72
72
|
schema: Schema,
|
|
73
|
+
onInvalid?: InvalidRequestListener,
|
|
73
74
|
) {
|
|
74
|
-
const middleware = zValidator(target, schema, validationHook);
|
|
75
75
|
const contract: RequestContract = { target, schema };
|
|
76
|
-
return Object.assign(
|
|
76
|
+
if (!onInvalid) return Object.assign(zValidator(target, schema, validationHook), { [REQUEST_CONTRACT]: contract });
|
|
77
|
+
// What each refused request sent, keyed by its context, so the listener is handed the input without
|
|
78
|
+
// reading the request raw — which no route may do.
|
|
79
|
+
const refusedInput = new WeakMap<Context, unknown>();
|
|
80
|
+
const middleware = zValidator(target, schema, (outcome: ValidationOutcome & { data?: unknown }, c: Context) => {
|
|
81
|
+
if (!outcome.success) refusedInput.set(c, outcome.data);
|
|
82
|
+
validationHook(outcome);
|
|
83
|
+
});
|
|
84
|
+
// Only a throw from the validator itself is a refusal of the request. Once `next` runs, a throw is the
|
|
85
|
+
// handler's, and is the handler's to record.
|
|
86
|
+
const listened: MiddlewareHandler = async (c, next) => {
|
|
87
|
+
let reached = false;
|
|
88
|
+
try {
|
|
89
|
+
return await middleware(c, async () => {
|
|
90
|
+
reached = true;
|
|
91
|
+
await next();
|
|
92
|
+
});
|
|
93
|
+
} catch (error) {
|
|
94
|
+
if (!reached) await onInvalid(c, error, refusedInput.get(c));
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
return Object.assign(listened as typeof middleware, { [REQUEST_CONTRACT]: contract });
|
|
77
99
|
}
|
|
78
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Told when {@link validate} refuses a request — a body that does not parse, or one that fails the schema —
|
|
103
|
+
* before the refusal is thrown. A route whose every attempt must be on the audit trail records the refusal
|
|
104
|
+
* here. It cannot turn the refusal into anything else: the error is thrown after it returns, and a listener
|
|
105
|
+
* that throws replaces it. `input` is what the request sent for the validated part, as it arrived; it is
|
|
106
|
+
* `undefined` when there was nothing to read, as for a body that is not JSON. Input validated by an earlier
|
|
107
|
+
* {@link validate} on the same route is readable with `c.req.valid(target)`.
|
|
108
|
+
*/
|
|
109
|
+
export type InvalidRequestListener = (c: Context, error: unknown, input: unknown) => Promise<void> | void;
|
|
110
|
+
|
|
79
111
|
/** The contract a {@link validate} middleware carries, or `undefined` for any other handler. */
|
|
80
112
|
export function requestContractOf(handler: unknown): RequestContract | undefined {
|
|
81
113
|
if (typeof handler !== "function") return undefined;
|
package/src/http/verification.ts
CHANGED
|
@@ -11,7 +11,9 @@ import { z } from "zod";
|
|
|
11
11
|
*/
|
|
12
12
|
export const VerificationStrategy = z
|
|
13
13
|
.union([
|
|
14
|
-
z
|
|
14
|
+
z
|
|
15
|
+
.literal("bearer")
|
|
16
|
+
.describe("A session token via Authorization: Bearer, rotated before it expires; validated by @pithy-sh/auth."),
|
|
15
17
|
z.literal("session").describe("Cookie-based web session, CSRF-protected; validated by @pithy-sh/auth."),
|
|
16
18
|
z
|
|
17
19
|
.literal("signed-webhook")
|
package/src/i18n/translator.ts
CHANGED
|
@@ -90,7 +90,8 @@ export interface TranslatorInput {
|
|
|
90
90
|
readonly formattingLocale?: string;
|
|
91
91
|
/**
|
|
92
92
|
* The catalogs to walk, most-specific first. `@pithy-sh/i18n` passes adopter-locale, adopter-default,
|
|
93
|
-
* kit-locale,
|
|
93
|
+
* kit-locale, composed-locale, composed-default, composed English; a copied screen passes its own baked
|
|
94
|
+
* English and nothing else.
|
|
94
95
|
*/
|
|
95
96
|
readonly layers: readonly (MessageCatalog | undefined)[];
|
|
96
97
|
}
|