@pithy-sh/core 0.12.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/audit/composed.d.ts +18 -0
  2. package/dist/audit/composed.d.ts.map +1 -0
  3. package/dist/audit/composed.js +28 -0
  4. package/dist/capability/capability.d.ts +11 -0
  5. package/dist/capability/capability.d.ts.map +1 -1
  6. package/dist/capability/purge.d.ts +43 -1
  7. package/dist/capability/purge.d.ts.map +1 -1
  8. package/dist/capability/purge.js +58 -3
  9. package/dist/cli/commandCatalog.generated.d.ts +1 -1
  10. package/dist/cli/commandCatalog.generated.d.ts.map +1 -1
  11. package/dist/cli/commandCatalog.generated.js +6 -0
  12. package/dist/controlPlane/http/guard.d.ts.map +1 -1
  13. package/dist/controlPlane/http/guard.js +40 -1
  14. package/dist/createEntrypoint.d.ts +7 -1
  15. package/dist/createEntrypoint.d.ts.map +1 -1
  16. package/dist/createEntrypoint.js +15 -5
  17. package/dist/error/http.d.ts +48 -0
  18. package/dist/error/http.d.ts.map +1 -1
  19. package/dist/error/payload.d.ts +96 -0
  20. package/dist/error/payload.d.ts.map +1 -1
  21. package/dist/error/payload.js +32 -0
  22. package/dist/http/validation.d.ts +11 -2
  23. package/dist/http/validation.d.ts.map +1 -1
  24. package/dist/http/validation.js +20 -3
  25. package/dist/logger/record.d.ts +28 -0
  26. package/dist/logger/record.d.ts.map +1 -1
  27. package/dist/version.generated.d.ts +1 -1
  28. package/dist/version.generated.js +1 -1
  29. package/package.json +1 -1
  30. package/src/audit/composed.ts +30 -0
  31. package/src/capability/capability.ts +11 -0
  32. package/src/capability/purge.ts +66 -3
  33. package/src/cli/commandCatalog.generated.ts +6 -0
  34. package/src/controlPlane/http/guard.ts +60 -1
  35. package/src/createEntrypoint.ts +17 -2
  36. package/src/error/payload.ts +68 -0
  37. package/src/http/validation.ts +35 -3
  38. package/src/version.generated.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/error/http.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/error/http.ts"],"names":[],"mappings":"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"}
@@ -660,6 +660,26 @@ export declare const KitPublicErrorPayload: z.ZodDiscriminatedUnion<[z.ZodObject
660
660
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
661
661
  code: z.ZodLiteral<"organization/nomination_invalid">;
662
662
  status: z.ZodLiteral<400>;
663
+ }, z.core.$strip>, z.ZodObject<{
664
+ message: z.ZodString;
665
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
666
+ code: z.ZodLiteral<"organization/last_owner">;
667
+ status: z.ZodLiteral<409>;
668
+ }, z.core.$strip>, z.ZodObject<{
669
+ message: z.ZodString;
670
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
671
+ code: z.ZodLiteral<"organization/already_member">;
672
+ status: z.ZodLiteral<409>;
673
+ }, z.core.$strip>, z.ZodObject<{
674
+ message: z.ZodString;
675
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
676
+ code: z.ZodLiteral<"organization/seat_limit_reached">;
677
+ status: z.ZodLiteral<409>;
678
+ }, z.core.$strip>, z.ZodObject<{
679
+ message: z.ZodString;
680
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
681
+ code: z.ZodLiteral<"organization/organization_suspended">;
682
+ status: z.ZodLiteral<403>;
663
683
  }, z.core.$strip>, z.ZodObject<{
664
684
  message: z.ZodString;
665
685
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
@@ -1660,6 +1680,34 @@ export declare const KitErrorPayload: z.ZodDiscriminatedUnion<[z.ZodObject<{
1660
1680
  detail: z.ZodOptional<z.ZodString>;
1661
1681
  code: z.ZodLiteral<"organization/nomination_invalid">;
1662
1682
  status: z.ZodLiteral<400>;
1683
+ }, z.core.$strip>, z.ZodObject<{
1684
+ message: z.ZodString;
1685
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
1686
+ action: z.ZodOptional<z.ZodString>;
1687
+ detail: z.ZodOptional<z.ZodString>;
1688
+ code: z.ZodLiteral<"organization/last_owner">;
1689
+ status: z.ZodLiteral<409>;
1690
+ }, z.core.$strip>, z.ZodObject<{
1691
+ message: z.ZodString;
1692
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
1693
+ action: z.ZodOptional<z.ZodString>;
1694
+ detail: z.ZodOptional<z.ZodString>;
1695
+ code: z.ZodLiteral<"organization/already_member">;
1696
+ status: z.ZodLiteral<409>;
1697
+ }, z.core.$strip>, z.ZodObject<{
1698
+ message: z.ZodString;
1699
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
1700
+ action: z.ZodOptional<z.ZodString>;
1701
+ detail: z.ZodOptional<z.ZodString>;
1702
+ code: z.ZodLiteral<"organization/seat_limit_reached">;
1703
+ status: z.ZodLiteral<409>;
1704
+ }, z.core.$strip>, z.ZodObject<{
1705
+ message: z.ZodString;
1706
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
1707
+ action: z.ZodOptional<z.ZodString>;
1708
+ detail: z.ZodOptional<z.ZodString>;
1709
+ code: z.ZodLiteral<"organization/organization_suspended">;
1710
+ status: z.ZodLiteral<403>;
1663
1711
  }, z.core.$strip>, z.ZodObject<{
1664
1712
  message: z.ZodString;
1665
1713
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
@@ -2467,6 +2515,26 @@ export declare const PublicErrorPayload: z.ZodUnion<readonly [z.ZodDiscriminated
2467
2515
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
2468
2516
  code: z.ZodLiteral<"organization/nomination_invalid">;
2469
2517
  status: z.ZodLiteral<400>;
2518
+ }, z.core.$strip>, z.ZodObject<{
2519
+ message: z.ZodString;
2520
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
2521
+ code: z.ZodLiteral<"organization/last_owner">;
2522
+ status: z.ZodLiteral<409>;
2523
+ }, z.core.$strip>, z.ZodObject<{
2524
+ message: z.ZodString;
2525
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
2526
+ code: z.ZodLiteral<"organization/already_member">;
2527
+ status: z.ZodLiteral<409>;
2528
+ }, z.core.$strip>, z.ZodObject<{
2529
+ message: z.ZodString;
2530
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
2531
+ code: z.ZodLiteral<"organization/seat_limit_reached">;
2532
+ status: z.ZodLiteral<409>;
2533
+ }, z.core.$strip>, z.ZodObject<{
2534
+ message: z.ZodString;
2535
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
2536
+ code: z.ZodLiteral<"organization/organization_suspended">;
2537
+ status: z.ZodLiteral<403>;
2470
2538
  }, z.core.$strip>, z.ZodObject<{
2471
2539
  message: z.ZodString;
2472
2540
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
@@ -3483,6 +3551,34 @@ export declare const ErrorPayload: z.ZodUnion<readonly [z.ZodDiscriminatedUnion<
3483
3551
  detail: z.ZodOptional<z.ZodString>;
3484
3552
  code: z.ZodLiteral<"organization/nomination_invalid">;
3485
3553
  status: z.ZodLiteral<400>;
3554
+ }, z.core.$strip>, z.ZodObject<{
3555
+ message: z.ZodString;
3556
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
3557
+ action: z.ZodOptional<z.ZodString>;
3558
+ detail: z.ZodOptional<z.ZodString>;
3559
+ code: z.ZodLiteral<"organization/last_owner">;
3560
+ status: z.ZodLiteral<409>;
3561
+ }, z.core.$strip>, z.ZodObject<{
3562
+ message: z.ZodString;
3563
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
3564
+ action: z.ZodOptional<z.ZodString>;
3565
+ detail: z.ZodOptional<z.ZodString>;
3566
+ code: z.ZodLiteral<"organization/already_member">;
3567
+ status: z.ZodLiteral<409>;
3568
+ }, z.core.$strip>, z.ZodObject<{
3569
+ message: z.ZodString;
3570
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
3571
+ action: z.ZodOptional<z.ZodString>;
3572
+ detail: z.ZodOptional<z.ZodString>;
3573
+ code: z.ZodLiteral<"organization/seat_limit_reached">;
3574
+ status: z.ZodLiteral<409>;
3575
+ }, z.core.$strip>, z.ZodObject<{
3576
+ message: z.ZodString;
3577
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
3578
+ action: z.ZodOptional<z.ZodString>;
3579
+ detail: z.ZodOptional<z.ZodString>;
3580
+ code: z.ZodLiteral<"organization/organization_suspended">;
3581
+ status: z.ZodLiteral<403>;
3486
3582
  }, z.core.$strip>, z.ZodObject<{
3487
3583
  message: z.ZodString;
3488
3584
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
@@ -1 +1 @@
1
- {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/error/payload.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;GAQG;AAEH,uFAAuF;AACvF,eAAO,MAAM,eAAe;;;;iBAQqD,CAAC;AAClF,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAstD9D;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAsJiE,CAAC;AAsZpG;;;;GAIG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2BAsJ2E,CAAC;AACxG,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;AAqBnD,yFAAyF;AACzF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/D;AA4CD,qGAAqG;AACrG,MAAM,MAAM,cAAc,GAAG,YAAY,SAAS,GAAG,MAAM,MAAM,IAAI,MAAM,EAAE,GAAG,MAAM,GAAG,KAAK,CAAC;AAc/F;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,6FASC,CAAC;AAChC,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAgBnE;;;GAGG;AACH,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAEuE,CAAC;AACvG,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEpE,8GAA8G;AAC9G,eAAO,MAAM,oBAAoB;;;;;;;iBAEhC,CAAC;AACF,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE;;;;GAIG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAItB,CAAC;AACJ,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD,mGAAmG;AACnG,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC"}
1
+ {"version":3,"file":"payload.d.ts","sourceRoot":"","sources":["../../src/error/payload.ts"],"names":[],"mappings":"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"}
@@ -687,6 +687,26 @@ const OrganizationNominationInvalidPublic = z.object({
687
687
  status: z.literal(400).describe("Bad Request — no offer this caller may accept."),
688
688
  ...publicFields
689
689
  }).describe("No standing ownership offer this caller may accept (400).");
690
+ const OrganizationLastOwnerPublic = z.object({
691
+ code: z.literal("organization/last_owner").describe("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."),
692
+ status: z.literal(409).describe("Conflict — an account nobody owns is not a state to arrive at."),
693
+ ...publicFields
694
+ }).describe("The last owner cannot be removed or demoted (409).");
695
+ const OrganizationAlreadyMemberPublic = z.object({
696
+ code: z.literal("organization/already_member").describe("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."),
697
+ status: z.literal(409).describe("Conflict."),
698
+ ...publicFields
699
+ }).describe("That person is already a member (409).");
700
+ const OrganizationSeatLimitReachedPublic = z.object({
701
+ code: z.literal("organization/seat_limit_reached").describe("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."),
702
+ status: z.literal(409).describe("Conflict."),
703
+ ...publicFields
704
+ }).describe("The account has no free seat (409).");
705
+ const OrganizationSuspendedPublic = z.object({
706
+ code: z.literal("organization/organization_suspended").describe("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."),
707
+ status: z.literal(403).describe("Forbidden — the organization may not be acted in, whoever asks."),
708
+ ...publicFields
709
+ }).describe("The organization is suspended (403).");
690
710
  const ArtifactsNotFoundPublic = z.object({
691
711
  code: z.literal("artifacts/not_found").describe("No such repository, **or** one the caller holds no grant on and does not own. One code for both, byte for byte: a repository's name is in its clone URL, and a refusal that told the two apart would hand it over. Also what the credential route answers for a repository with remote access off. Which it was survives in `detail`, which the HTTP codec strips."),
692
712
  status: z.literal(404).describe("Not Found."),
@@ -925,6 +945,10 @@ const KitPublicErrorPayload = z.discriminatedUnion("code", [
925
945
  OrganizationLastAdministratorPublic,
926
946
  OrganizationSlugTakenPublic,
927
947
  OrganizationNominationInvalidPublic,
948
+ OrganizationLastOwnerPublic,
949
+ OrganizationAlreadyMemberPublic,
950
+ OrganizationSeatLimitReachedPublic,
951
+ OrganizationSuspendedPublic,
928
952
  ArtifactsNotFoundPublic,
929
953
  ArtifactsForbiddenPublic,
930
954
  ArtifactsInvalidNamePublic,
@@ -1083,6 +1107,10 @@ const OrganizationInvitationInvalid = OrganizationInvitationInvalidPublic.extend
1083
1107
  const OrganizationLastAdministrator = OrganizationLastAdministratorPublic.extend(internalFields).describe(OrganizationLastAdministratorPublic.description ?? "");
1084
1108
  const OrganizationSlugTaken = OrganizationSlugTakenPublic.extend(internalFields).describe(OrganizationSlugTakenPublic.description ?? "");
1085
1109
  const OrganizationNominationInvalid = OrganizationNominationInvalidPublic.extend(internalFields).describe(OrganizationNominationInvalidPublic.description ?? "");
1110
+ const OrganizationLastOwner = OrganizationLastOwnerPublic.extend(internalFields).describe(OrganizationLastOwnerPublic.description ?? "");
1111
+ const OrganizationAlreadyMember = OrganizationAlreadyMemberPublic.extend(internalFields).describe(OrganizationAlreadyMemberPublic.description ?? "");
1112
+ const OrganizationSeatLimitReached = OrganizationSeatLimitReachedPublic.extend(internalFields).describe(OrganizationSeatLimitReachedPublic.description ?? "");
1113
+ const OrganizationSuspended = OrganizationSuspendedPublic.extend(internalFields).describe(OrganizationSuspendedPublic.description ?? "");
1086
1114
  const ArtifactsNotFound = ArtifactsNotFoundPublic.extend(internalFields).describe(ArtifactsNotFoundPublic.description ?? "");
1087
1115
  const ArtifactsForbidden = ArtifactsForbiddenPublic.extend(internalFields).describe(ArtifactsForbiddenPublic.description ?? "");
1088
1116
  const ArtifactsInvalidName = ArtifactsInvalidNamePublic.extend(internalFields).describe(ArtifactsInvalidNamePublic.description ?? "");
@@ -1226,6 +1254,10 @@ const KitErrorPayload = z.discriminatedUnion("code", [
1226
1254
  OrganizationLastAdministrator,
1227
1255
  OrganizationSlugTaken,
1228
1256
  OrganizationNominationInvalid,
1257
+ OrganizationLastOwner,
1258
+ OrganizationAlreadyMember,
1259
+ OrganizationSeatLimitReached,
1260
+ OrganizationSuspended,
1229
1261
  ArtifactsNotFound,
1230
1262
  ArtifactsForbidden,
1231
1263
  ArtifactsInvalidName,
@@ -1,6 +1,6 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
- import type { ValidationTargets } from "hono";
3
+ import type { Context, MiddlewareHandler, ValidationTargets } from "hono";
4
4
  import type { z } from "zod";
5
5
  /**
6
6
  * How a route declares what it accepts. Its sibling {@link ./verification.VerificationStrategy}
@@ -60,12 +60,21 @@ export interface RequestContract {
60
60
  * app.post(path, requireAuth(), validate("param", BoardParam), validate("json", SubmitScoreBody), handler);
61
61
  * ```
62
62
  */
63
- export declare function validate<Target extends keyof ValidationTargets, Schema extends z.ZodType>(target: Target, schema: Schema): import("hono").MiddlewareHandler<import("hono").Env, string, {
63
+ export declare function validate<Target extends keyof ValidationTargets, Schema extends z.ZodType>(target: Target, schema: Schema, onInvalid?: InvalidRequestListener): MiddlewareHandler<import("hono").Env, string, {
64
64
  in: (undefined extends (Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>> ? z.core.input<Schema> : never) ? true : false) extends true ? { [K in Target]?: ([Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>> ? z.core.input<Schema> : never] extends [ValidationTargets[K]] ? ValidationTargets[K] & (Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>> ? z.core.input<Schema> : never) : import("hono/validator").InferInput<Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>> ? z.core.input<Schema> : never, K, import("hono/types").ParsedFormValue>) | undefined; } : { [K in Target]: [Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>> ? z.core.input<Schema> : never] extends [ValidationTargets[K]] ? ValidationTargets[K] & (Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>> ? z.core.input<Schema> : never) : import("hono/validator").InferInput<Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").input<Schema> : Schema extends z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>> ? z.core.input<Schema> : never, K, import("hono/types").ParsedFormValue>; };
65
65
  out: { [K in Target]: Schema extends import("zod/v3").ZodType<any, import("zod/v3").ZodTypeDef, any> ? import("zod/v3").output<Schema> : Schema extends z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>> ? z.infer<Schema> : never; };
66
66
  }, never> & {
67
67
  [REQUEST_CONTRACT]: RequestContract;
68
68
  };
69
+ /**
70
+ * Told when {@link validate} refuses a request — a body that does not parse, or one that fails the schema —
71
+ * before the refusal is thrown. A route whose every attempt must be on the audit trail records the refusal
72
+ * here. It cannot turn the refusal into anything else: the error is thrown after it returns, and a listener
73
+ * that throws replaces it. `input` is what the request sent for the validated part, as it arrived; it is
74
+ * `undefined` when there was nothing to read, as for a body that is not JSON. Input validated by an earlier
75
+ * {@link validate} on the same route is readable with `c.req.valid(target)`.
76
+ */
77
+ export type InvalidRequestListener = (c: Context, error: unknown, input: unknown) => Promise<void> | void;
69
78
  /** The contract a {@link validate} middleware carries, or `undefined` for any other handler. */
70
79
  export declare function requestContractOf(handler: unknown): RequestContract | undefined;
71
80
  //# sourceMappingURL=validation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/http/validation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAA;CAAE,CAAC;AAEhG;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAG/D;AAED,6GAA6G;AAC7G,eAAO,MAAM,gBAAgB,eAAsC,CAAC;AAEpE,4GAA4G;AAC5G,MAAM,WAAW,eAAe;IAC9B,kGAAkG;IAClG,QAAQ,CAAC,MAAM,EAAE,MAAM,iBAAiB,CAAC;IACzC,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,MAAM,SAAS,MAAM,iBAAiB,EAAE,MAAM,SAAS,CAAC,CAAC,OAAO,EACvF,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM;;;;;EAKf;AAED,gGAAgG;AAChG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAG/E"}
1
+ {"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/http/validation.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC1E,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAG7B;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAA;CAAE,CAAC;AAEhG;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAG/D;AAED,6GAA6G;AAC7G,eAAO,MAAM,gBAAgB,eAAsC,CAAC;AAEpE,4GAA4G;AAC5G,MAAM,WAAW,eAAe;IAC9B,kGAAkG;IAClG,QAAQ,CAAC,MAAM,EAAE,MAAM,iBAAiB,CAAC;IACzC,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CAAC,MAAM,SAAS,MAAM,iBAAiB,EAAE,MAAM,SAAS,CAAC,CAAC,OAAO,EACvF,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,sBAAsB;;;;;EA0BnC;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;AAE1G,gGAAgG;AAChG,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAG/E"}
@@ -23,13 +23,30 @@ const REQUEST_CONTRACT = Symbol.for("pithy.requestContract");
23
23
  * app.post(path, requireAuth(), validate("param", BoardParam), validate("json", SubmitScoreBody), handler);
24
24
  * ```
25
25
  */
26
- function validate(target, schema) {
27
- const middleware = zValidator(target, schema, validationHook);
26
+ function validate(target, schema, onInvalid) {
28
27
  const contract = {
29
28
  target,
30
29
  schema
31
30
  };
32
- return Object.assign(middleware, { [REQUEST_CONTRACT]: contract });
31
+ if (!onInvalid) return Object.assign(zValidator(target, schema, validationHook), { [REQUEST_CONTRACT]: contract });
32
+ const refusedInput = /* @__PURE__ */ new WeakMap();
33
+ const middleware = zValidator(target, schema, (outcome, c) => {
34
+ if (!outcome.success) refusedInput.set(c, outcome.data);
35
+ validationHook(outcome);
36
+ });
37
+ const listened = async (c, next) => {
38
+ let reached = false;
39
+ try {
40
+ return await middleware(c, async () => {
41
+ reached = true;
42
+ await next();
43
+ });
44
+ } catch (error) {
45
+ if (!reached) await onInvalid(c, error, refusedInput.get(c));
46
+ throw error;
47
+ }
48
+ };
49
+ return Object.assign(listened, { [REQUEST_CONTRACT]: contract });
33
50
  }
34
51
  /** The contract a {@link validate} middleware carries, or `undefined` for any other handler. */
35
52
  function requestContractOf(handler) {
@@ -933,6 +933,34 @@ export declare const LogRecord: z.ZodObject<{
933
933
  detail: z.ZodOptional<z.ZodString>;
934
934
  code: z.ZodLiteral<"organization/nomination_invalid">;
935
935
  status: z.ZodLiteral<400>;
936
+ }, z.core.$strip>, z.ZodObject<{
937
+ message: z.ZodString;
938
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
939
+ action: z.ZodOptional<z.ZodString>;
940
+ detail: z.ZodOptional<z.ZodString>;
941
+ code: z.ZodLiteral<"organization/last_owner">;
942
+ status: z.ZodLiteral<409>;
943
+ }, z.core.$strip>, z.ZodObject<{
944
+ message: z.ZodString;
945
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
946
+ action: z.ZodOptional<z.ZodString>;
947
+ detail: z.ZodOptional<z.ZodString>;
948
+ code: z.ZodLiteral<"organization/already_member">;
949
+ status: z.ZodLiteral<409>;
950
+ }, z.core.$strip>, z.ZodObject<{
951
+ message: z.ZodString;
952
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
953
+ action: z.ZodOptional<z.ZodString>;
954
+ detail: z.ZodOptional<z.ZodString>;
955
+ code: z.ZodLiteral<"organization/seat_limit_reached">;
956
+ status: z.ZodLiteral<409>;
957
+ }, z.core.$strip>, z.ZodObject<{
958
+ message: z.ZodString;
959
+ params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
960
+ action: z.ZodOptional<z.ZodString>;
961
+ detail: z.ZodOptional<z.ZodString>;
962
+ code: z.ZodLiteral<"organization/organization_suspended">;
963
+ status: z.ZodLiteral<403>;
936
964
  }, z.core.$strip>, z.ZodObject<{
937
965
  message: z.ZodString;
938
966
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
@@ -1 +1 @@
1
- {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/logger/record.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;GAKG;AAEH,4GAA4G;AAC5G,eAAO,MAAM,QAAQ;;;;;EAE4F,CAAC;AAClH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAgD,CAAC;AAEtG;;;;GAIG;AACH,eAAO,MAAM,SAAS,wCAEsF,CAAC;AAC7G,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAW+E,CAAC;AACtG,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;AAmBnD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAMzD"}
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../src/logger/record.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;GAKG;AAEH,4GAA4G;AAC5G,eAAO,MAAM,QAAQ;;;;;EAE4F,CAAC;AAClH,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEjD;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAgD,CAAC;AAEtG;;;;GAIG;AACH,eAAO,MAAM,SAAS,wCAEsF,CAAC;AAC7G,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;AAEnD;;;;;GAKG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAW+E,CAAC;AACtG,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;AAmBnD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAMzD"}
@@ -3,5 +3,5 @@
3
3
  /** This package's npm name — the join key against a release feed. */
4
4
  export declare const PACKAGE_NAME = "@pithy-sh/core";
5
5
  /** This package's version, stamped from its own package.json at generation time. */
6
- export declare const PACKAGE_VERSION = "0.12.0";
6
+ export declare const PACKAGE_VERSION = "0.13.0";
7
7
  //# sourceMappingURL=version.generated.d.ts.map
@@ -4,6 +4,6 @@
4
4
  /** This package's npm name — the join key against a release feed. */
5
5
  const PACKAGE_NAME = "@pithy-sh/core";
6
6
  /** This package's version, stamped from its own package.json at generation time. */
7
- const PACKAGE_VERSION = "0.12.0";
7
+ const PACKAGE_VERSION = "0.13.0";
8
8
  //#endregion
9
9
  export { PACKAGE_NAME, PACKAGE_VERSION };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pithy-sh/core",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -0,0 +1,30 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+
4
+ import type { Capability } from "../capability/capability";
5
+ import { type AuditEmit, noopEmit } from "./recorder";
6
+
7
+ /**
8
+ * The audit recorder for code with no request — a Workflow step (#622).
9
+ *
10
+ * A route records through `c.var.emit`. A Workflow has no `c`: the runtime constructs it with `env` and nothing
11
+ * else. So it finds the composed capability that declares {@link Capability.auditRecorder} — `@pithy-sh/audit`
12
+ * — and records through that, built over this run's env. With none composed it is {@link noopEmit}, exactly as
13
+ * `c.var.emit` is in a Worker that composes no audit, so a step can always record without asking first.
14
+ *
15
+ * **Non-fatal, whatever the recorder does.** The contract says a recorder never throws; this holds a recorder
16
+ * to it rather than trusting it, because what a step records has already happened and a throw here would turn
17
+ * it into a retried step.
18
+ */
19
+ export function composedAuditEmit(capabilities: readonly Capability[], env: Record<string, unknown>): AuditEmit {
20
+ const provider = capabilities.find((capability) => capability.auditRecorder !== undefined);
21
+ if (!provider?.auditRecorder) return noopEmit;
22
+ const record = provider.auditRecorder(env);
23
+ return async (event) => {
24
+ try {
25
+ await record(event);
26
+ } catch {
27
+ // The recorder broke its own contract. The event is lost, and the step it recorded stands.
28
+ }
29
+ };
30
+ }
@@ -633,6 +633,17 @@ export interface Capability<
633
633
  * capability that declares one (e.g. `@pithy-sh/email`'s bounce/complaint handler).
634
634
  */
635
635
  email?: CapabilityEmailHandler;
636
+ /**
637
+ * The audit recorder this capability provides **for code that has no request** — a Workflow step, which the
638
+ * runtime constructs with `env` and nothing else (#622). `@pithy-sh/audit` declares it; nothing else does.
639
+ *
640
+ * A route records through `c.var.emit`, which the same capability's middleware fills, and keeps doing that.
641
+ * This is the other door, for the purge that erases a deleted account: it runs in a Workflow and still owes
642
+ * the trail its event. `../audit/composed.ts` finds it among the composed capabilities, so a capability that
643
+ * audits from a step imports no audit package — principle 4, the same reason `c.var.emit` is a seam. Built
644
+ * from the env per call, like the request recorder is built per request. Non-fatal by the same contract.
645
+ */
646
+ auditRecorder?: (env: Record<string, unknown>) => AuditEmit;
636
647
  /**
637
648
  * Named D1 databases this capability contributes tables to (database name → {@link DatabaseSpec}).
638
649
  * `createBackend` merges every capability's slices per database (via `composeDatabases`) and serves
@@ -23,6 +23,14 @@ import { ValidationError } from "../error/pithyError";
23
23
  * a step is retried after a failure that may have come after its rows were already gone, and erasing
24
24
  * nothing must then succeed.
25
25
  *
26
+ * ## The same contribution answers an export (#622)
27
+ *
28
+ * An access request arrives before an erasure, not after. So a contribution may also say what this capability
29
+ * holds about the subject, on the read side: `export` answers one JSON object, and the control plane's export
30
+ * route assembles one document from every composed contribution, in the same order the purge runs them. A
31
+ * contribution with no `export` is listed as holding rows it did not say how to export, which is the honest
32
+ * answer and the one an operator can act on.
33
+ *
26
34
  * ## An adopter declares one too
27
35
  *
28
36
  * On their own `app` capability, for their own tables, with the same types. The contract is exported for
@@ -31,12 +39,13 @@ import { ValidationError } from "../error/pithyError";
31
39
 
32
40
  /**
33
41
  * The kinds of subject a purge erases. Closed, so a typo is refused where it is written rather than becoming
34
- * a contribution no purge ever asks for. `organization` joins when organization state does (#623).
42
+ * a contribution no purge ever asks for. `organization` joined with organization state (#623): a capability
43
+ * holding rows scoped to a tenant declares one for it, and the organization purge runs it.
35
44
  */
36
45
  export const PurgeSubject = z
37
- .enum(["user"])
46
+ .enum(["user", "organization"])
38
47
  .describe(
39
- "The kind of subject a purge erases. `user` is one person's account in `@pithy-sh/auth`, identified by its user id.",
48
+ "The kind of subject a purge erases. `user` is one person's account in `@pithy-sh/auth`, identified by its user id. `organization` is one tenant in `@pithy-sh/organization`, identified by its organization id.",
40
49
  );
41
50
  export type PurgeSubject = z.output<typeof PurgeSubject>;
42
51
 
@@ -63,6 +72,13 @@ export interface PurgeContribution {
63
72
  * and only this step.
64
73
  */
65
74
  readonly erase: (context: PurgeContext) => Promise<void>;
75
+ /**
76
+ * What this capability holds about the subject, as one JSON object — the read side of `erase` (#622). It
77
+ * answers an access request, so it carries the subject's own data and never a credential: no session token,
78
+ * no provider token, no push token. Optional: a contribution without one is listed in the export as rows it
79
+ * erases and did not say how to export. A throw costs this capability's entry, never the document.
80
+ */
81
+ readonly export?: (context: PurgeContext) => Promise<Record<string, unknown>>;
66
82
  }
67
83
 
68
84
  /** One step of a purge: which capability it runs, and the contribution that capability declared. */
@@ -101,6 +117,12 @@ export function assertPurgeContributions(capability: string, contributions: read
101
117
  action: "Say in one sentence what it erases. The purge records it with the step.",
102
118
  });
103
119
  }
120
+ if (contribution.export !== undefined && typeof contribution.export !== "function") {
121
+ throw new ValidationError({
122
+ message: `The ${capability} capability's ${subject.data} purge has an export that is not a function.`,
123
+ action: "Give it an `export` that answers what this capability holds about the subject, or leave it out.",
124
+ });
125
+ }
104
126
  if (typeof contribution.erase !== "function") {
105
127
  throw new ValidationError({
106
128
  message: `The ${capability} capability's ${subject.data} purge has no erase function.`,
@@ -122,3 +144,44 @@ export function purgeSteps(
122
144
  }
123
145
  return steps;
124
146
  }
147
+
148
+ /** What one step's export answered: its data, that it declared none, or that it could not be read. */
149
+ export type PurgeExportEntry =
150
+ | {
151
+ readonly capability: string;
152
+ readonly summary: string;
153
+ readonly state: "exported";
154
+ readonly data: Record<string, unknown>;
155
+ }
156
+ | { readonly capability: string; readonly summary: string; readonly state: "not_exported" }
157
+ | { readonly capability: string; readonly summary: string; readonly state: "unavailable" };
158
+
159
+ /** Whether an export answered what the contract promises: one plain object. */
160
+ function isRecord(value: unknown): value is Record<string, unknown> {
161
+ return typeof value === "object" && value !== null && !Array.isArray(value);
162
+ }
163
+
164
+ /**
165
+ * Read every step's export for one subject — the export document's body, in step order (#622).
166
+ *
167
+ * **Each read is guarded on its own and they run concurrently**, the shape the user pane's sub-reads have
168
+ * (#380): one capability whose table will not read costs its own entry as `unavailable`, and the rest of the
169
+ * document still answers the request. What the read threw is not carried — it names a query and a table, and
170
+ * the document crosses a trust boundary. An answer that is not one object is `unavailable` too, because the
171
+ * document promises an object per capability and a client validates it.
172
+ */
173
+ export async function purgeExports(steps: readonly PurgeStep[], context: PurgeContext): Promise<PurgeExportEntry[]> {
174
+ return Promise.all(
175
+ steps.map(async ({ step, contribution }): Promise<PurgeExportEntry> => {
176
+ const base = { capability: step, summary: contribution.summary };
177
+ const read = contribution.export;
178
+ if (read === undefined) return { ...base, state: "not_exported" };
179
+ try {
180
+ const data = await read(context);
181
+ return isRecord(data) ? { ...base, state: "exported", data } : { ...base, state: "unavailable" };
182
+ } catch {
183
+ return { ...base, state: "unavailable" };
184
+ }
185
+ }),
186
+ );
187
+ }
@@ -903,6 +903,12 @@ export const COMMANDS = {
903
903
  "accountReinstated",
904
904
  "deletionScheduled",
905
905
  "deletionComplete",
906
+ "organizationMemberAdded",
907
+ "organizationMemberRemoved",
908
+ "organizationOwnershipTransferred",
909
+ "organizationSuspended",
910
+ "organizationReinstated",
911
+ "organizationDeletionScheduled",
906
912
  "operationalNotice",
907
913
  "newsletter",
908
914
  "leadCapture",
@@ -186,7 +186,21 @@ export function requireControlPlane(requirement: ControlPlaneRequirement): Middl
186
186
  },
187
187
  c.var.log,
188
188
  );
189
- await next();
189
+ // A handler can refuse a call the gate's requirement let through — an operator roster write that
190
+ // would move the owning role is refused `controlplane/insufficient_scope`, naming the ownership route,
191
+ // even on a connection granted `organization:ownership:transfer`, because a token exercises the one
192
+ // scope it was minted for — and it refuses it itself, past this gate. That refusal is still a blocked attempt, and the trail must
193
+ // say so: `call_allowed` alone would hide a credential probing for the grant it lacks.
194
+ //
195
+ // Both paths, as the organization routes' refusal recorder reads them: a throw that reaches here, and
196
+ // `c.error`, which is where Hono's `compose` leaves a downstream throw it rendered through `onError`.
197
+ try {
198
+ await next();
199
+ } catch (error) {
200
+ await auditHandlerDenial(c, requirement, context, error);
201
+ throw error;
202
+ }
203
+ await auditHandlerDenial(c, requirement, context, c.error);
190
204
  };
191
205
  (guard as unknown as Record<symbol, unknown>)[CONTROL_PLANE_GUARD] = true;
192
206
  return guard;
@@ -245,6 +259,51 @@ async function auditDenial(
245
259
  );
246
260
  }
247
261
 
262
+ /**
263
+ * Record a scope refusal a handler raised after the gate let the call in.
264
+ *
265
+ * Only `controlplane/insufficient_scope`: every other refusal past the gate is the handler's own to
266
+ * record, and a 404 or a validation error is not a credential reaching beyond its grant. The same row as
267
+ * {@link auditDenial}, with two differences that follow from the call having been verified: the actor is
268
+ * the proven subject and its connection, and `refusedBy` says the gate passed it — `required` is the
269
+ * gate's requirement, which this call met; what it lacked is in the log, with the rest of `detail`.
270
+ */
271
+ async function auditHandlerDenial(
272
+ c: Parameters<MiddlewareHandler<PithyHonoEnv>>[0],
273
+ requirement: ControlPlaneRequirement,
274
+ context: ControlPlaneContext,
275
+ cause: unknown,
276
+ ): Promise<void> {
277
+ // Read by its code, not `instanceof`: a capability that throws it may hold its own copy of this module,
278
+ // and a refusal that slipped past a class check would be exactly the unaudited attempt this exists for.
279
+ const code = (cause as { payload?: { code?: unknown } } | null)?.payload?.code;
280
+ if (code !== "controlplane/insufficient_scope") return;
281
+ await safeEmit(
282
+ c.var.emit,
283
+ {
284
+ action: ControlPlaneAuditActions.callDenied,
285
+ outcome: "denied",
286
+ severity: "warning",
287
+ actorType: "control-plane",
288
+ actorId: context.subject,
289
+ resourceType: "controlplane_connection",
290
+ resourceId: context.connectionId,
291
+ requestId: c.req.header("cf-ray"),
292
+ ip: c.req.header("cf-connecting-ip"),
293
+ userAgent: c.req.header("user-agent"),
294
+ metadata: {
295
+ reason: code,
296
+ required: String(requirement),
297
+ refusedBy: "handler",
298
+ connectionId: context.connectionId,
299
+ method: c.req.method,
300
+ path: c.req.path,
301
+ },
302
+ },
303
+ c.var.log,
304
+ );
305
+ }
306
+
248
307
  /**
249
308
  * The step that connects a management client, as this deployed Worker can name it: with its own environment when
250
309
  * it knows it, and never with a Worker — it cannot know the `apps/` directory that provisioned it (#711).