@pithy-sh/core 0.10.0 → 0.12.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 (270) hide show
  1. package/dist/access/access.d.ts +172 -0
  2. package/dist/access/access.d.ts.map +1 -0
  3. package/dist/access/access.js +147 -0
  4. package/dist/access/acting.d.ts +49 -0
  5. package/dist/access/acting.d.ts.map +1 -0
  6. package/dist/access/acting.js +21 -0
  7. package/dist/access/policyCheck.d.ts +33 -0
  8. package/dist/access/policyCheck.d.ts.map +1 -0
  9. package/dist/access/policyCheck.js +48 -0
  10. package/dist/access/usage.d.ts +83 -0
  11. package/dist/access/usage.d.ts.map +1 -0
  12. package/dist/access/usage.js +104 -0
  13. package/dist/access/visibility.d.ts +66 -0
  14. package/dist/access/visibility.d.ts.map +1 -0
  15. package/dist/access/visibility.js +86 -0
  16. package/dist/audit/auditEvent.d.ts +5 -0
  17. package/dist/audit/auditEvent.d.ts.map +1 -1
  18. package/dist/audit/auditEvent.js +2 -0
  19. package/dist/audit/recorder.d.ts +10 -2
  20. package/dist/audit/recorder.d.ts.map +1 -1
  21. package/dist/capability/bindings.d.ts +47 -2
  22. package/dist/capability/bindings.d.ts.map +1 -1
  23. package/dist/capability/bindings.js +117 -7
  24. package/dist/capability/capability.d.ts +110 -28
  25. package/dist/capability/capability.d.ts.map +1 -1
  26. package/dist/capability/capability.js +2 -0
  27. package/dist/capability/manifest.d.ts +2 -1
  28. package/dist/capability/manifest.d.ts.map +1 -1
  29. package/dist/capability/manifest.js +1 -1
  30. package/dist/capability/purge.d.ts +80 -0
  31. package/dist/capability/purge.d.ts.map +1 -0
  32. package/dist/capability/purge.js +76 -0
  33. package/dist/capability/settings.d.ts +86 -2
  34. package/dist/capability/settings.d.ts.map +1 -1
  35. package/dist/capability/settings.js +80 -1
  36. package/dist/cli/commandCatalog.generated.d.ts +238 -24
  37. package/dist/cli/commandCatalog.generated.d.ts.map +1 -1
  38. package/dist/cli/commandCatalog.generated.js +251 -22
  39. package/dist/cli/commandFacts.d.ts +2 -1
  40. package/dist/cli/commandFacts.d.ts.map +1 -1
  41. package/dist/cli/commandFacts.js +2 -0
  42. package/dist/controlPlane/capability.d.ts.map +1 -1
  43. package/dist/controlPlane/capability.js +19 -2
  44. package/dist/controlPlane/context.d.ts +5 -0
  45. package/dist/controlPlane/context.d.ts.map +1 -1
  46. package/dist/controlPlane/context.js +3 -1
  47. package/dist/controlPlane/data/connection.d.ts +49 -12
  48. package/dist/controlPlane/data/connection.d.ts.map +1 -1
  49. package/dist/controlPlane/data/connection.js +56 -2
  50. package/dist/controlPlane/discovery/adminRoute.d.ts +29 -0
  51. package/dist/controlPlane/discovery/adminRoute.d.ts.map +1 -1
  52. package/dist/controlPlane/discovery/adminRoute.js +3 -0
  53. package/dist/controlPlane/error/errors.d.ts +4 -3
  54. package/dist/controlPlane/error/errors.d.ts.map +1 -1
  55. package/dist/controlPlane/http/cors.d.ts +4 -4
  56. package/dist/controlPlane/http/cors.js +4 -4
  57. package/dist/controlPlane/http/guard.d.ts +11 -0
  58. package/dist/controlPlane/http/guard.d.ts.map +1 -1
  59. package/dist/controlPlane/http/guard.js +17 -1
  60. package/dist/controlPlane/http/handlers.d.ts +139 -0
  61. package/dist/controlPlane/http/handlers.d.ts.map +1 -1
  62. package/dist/controlPlane/http/handlers.js +67 -4
  63. package/dist/controlPlane/http/readiness.d.ts +33 -0
  64. package/dist/controlPlane/http/readiness.d.ts.map +1 -0
  65. package/dist/controlPlane/http/readiness.js +39 -0
  66. package/dist/controlPlane/http/responses.d.ts +245 -0
  67. package/dist/controlPlane/http/responses.d.ts.map +1 -1
  68. package/dist/controlPlane/http/responses.js +101 -4
  69. package/dist/controlPlane/http/routes.d.ts +2 -0
  70. package/dist/controlPlane/http/routes.d.ts.map +1 -1
  71. package/dist/controlPlane/http/routes.js +31 -3
  72. package/dist/controlPlane/http/verify.d.ts.map +1 -1
  73. package/dist/controlPlane/http/verify.js +2 -1
  74. package/dist/controlPlane/migrationState/migrationState.d.ts +102 -0
  75. package/dist/controlPlane/migrationState/migrationState.d.ts.map +1 -0
  76. package/dist/controlPlane/migrationState/migrationState.js +142 -0
  77. package/dist/controlPlane/migrations/0003_connection_principal.d.ts +21 -0
  78. package/dist/controlPlane/migrations/0003_connection_principal.d.ts.map +1 -0
  79. package/dist/controlPlane/migrations/0003_connection_principal.js +33 -0
  80. package/dist/controlPlane/scope/scope.d.ts +23 -2
  81. package/dist/controlPlane/scope/scope.d.ts.map +1 -1
  82. package/dist/controlPlane/scope/scope.js +24 -3
  83. package/dist/createBackend.d.ts.map +1 -1
  84. package/dist/createBackend.js +9 -2
  85. package/dist/createEntrypoint.d.ts.map +1 -1
  86. package/dist/createEntrypoint.js +5 -3
  87. package/dist/crypto/envelope.d.ts +86 -0
  88. package/dist/crypto/envelope.d.ts.map +1 -0
  89. package/dist/crypto/envelope.js +129 -0
  90. package/dist/crypto/fieldKeys.d.ts +41 -0
  91. package/dist/crypto/fieldKeys.d.ts.map +1 -0
  92. package/dist/crypto/fieldKeys.js +56 -0
  93. package/dist/data/codecs.d.ts +23 -10
  94. package/dist/data/codecs.d.ts.map +1 -1
  95. package/dist/data/codecs.js +50 -36
  96. package/dist/entitlement/allowance.d.ts +25 -0
  97. package/dist/entitlement/allowance.d.ts.map +1 -0
  98. package/dist/entitlement/allowance.js +80 -0
  99. package/dist/entitlement/entitlement.d.ts +41 -0
  100. package/dist/entitlement/entitlement.d.ts.map +1 -1
  101. package/dist/entitlement/meter.d.ts +57 -0
  102. package/dist/entitlement/meter.d.ts.map +1 -0
  103. package/dist/entitlement/meter.js +13 -0
  104. package/dist/error/extend.d.ts +6 -5
  105. package/dist/error/extend.d.ts.map +1 -1
  106. package/dist/error/http.d.ts +168 -0
  107. package/dist/error/http.d.ts.map +1 -1
  108. package/dist/error/payload.d.ts +336 -0
  109. package/dist/error/payload.d.ts.map +1 -1
  110. package/dist/error/payload.js +116 -4
  111. package/dist/error/pithyError.d.ts +18 -7
  112. package/dist/error/pithyError.d.ts.map +1 -1
  113. package/dist/error/pithyError.js +6 -0
  114. package/dist/http/authContext.d.ts +7 -0
  115. package/dist/http/authContext.d.ts.map +1 -1
  116. package/dist/http/authContext.js +8 -1
  117. package/dist/http/scopeGates.d.ts +20 -0
  118. package/dist/http/scopeGates.d.ts.map +1 -0
  119. package/dist/http/scopeGates.js +36 -0
  120. package/dist/index.d.ts +1 -1
  121. package/dist/index.d.ts.map +1 -1
  122. package/dist/index.js +2 -2
  123. package/dist/logger/logger.d.ts +12 -5
  124. package/dist/logger/logger.d.ts.map +1 -1
  125. package/dist/logger/record.d.ts +98 -0
  126. package/dist/logger/record.d.ts.map +1 -1
  127. package/dist/migrations/capabilitySets.d.ts +23 -0
  128. package/dist/migrations/capabilitySets.d.ts.map +1 -0
  129. package/dist/migrations/capabilitySets.js +74 -0
  130. package/dist/migrations/registry.d.ts +26 -0
  131. package/dist/migrations/registry.d.ts.map +1 -1
  132. package/dist/migrations/registry.js +38 -7
  133. package/dist/migrations/state.d.ts +60 -0
  134. package/dist/migrations/state.d.ts.map +1 -0
  135. package/dist/migrations/state.js +46 -0
  136. package/dist/naming/feature.d.ts +27 -5
  137. package/dist/naming/feature.d.ts.map +1 -1
  138. package/dist/naming/feature.js +36 -6
  139. package/dist/naming/limits.d.ts +47 -3
  140. package/dist/naming/limits.d.ts.map +1 -1
  141. package/dist/naming/limits.js +47 -3
  142. package/dist/naming/provisionScope.d.ts +6 -0
  143. package/dist/naming/provisionScope.d.ts.map +1 -1
  144. package/dist/naming/provisionScope.js +8 -3
  145. package/dist/naming/resourceNames.d.ts +21 -2
  146. package/dist/naming/resourceNames.d.ts.map +1 -1
  147. package/dist/naming/resourceNames.js +21 -3
  148. package/dist/privacy/blindIndex.d.ts +27 -0
  149. package/dist/privacy/blindIndex.d.ts.map +1 -0
  150. package/dist/privacy/blindIndex.js +57 -0
  151. package/dist/privacy/classes.d.ts +142 -0
  152. package/dist/privacy/classes.d.ts.map +1 -0
  153. package/dist/privacy/classes.js +209 -0
  154. package/dist/privacy/classify.d.ts +336 -0
  155. package/dist/privacy/classify.d.ts.map +1 -0
  156. package/dist/privacy/classify.js +1024 -0
  157. package/dist/privacy/encrypted.d.ts +210 -0
  158. package/dist/privacy/encrypted.d.ts.map +1 -0
  159. package/dist/privacy/encrypted.js +350 -0
  160. package/dist/privacy/encryptedColumns.d.ts +64 -0
  161. package/dist/privacy/encryptedColumns.d.ts.map +1 -0
  162. package/dist/privacy/encryptedColumns.js +134 -0
  163. package/dist/privacy/fieldRotation.d.ts +34 -0
  164. package/dist/privacy/fieldRotation.d.ts.map +1 -0
  165. package/dist/privacy/fieldRotation.js +186 -0
  166. package/dist/privacy/inventory.d.ts +12 -0
  167. package/dist/privacy/inventory.d.ts.map +1 -0
  168. package/dist/privacy/inventory.js +154 -0
  169. package/dist/privacy/posture.d.ts +114 -0
  170. package/dist/privacy/posture.d.ts.map +1 -0
  171. package/dist/privacy/posture.js +136 -0
  172. package/dist/privacy/redact.d.ts +7 -0
  173. package/dist/privacy/redact.d.ts.map +1 -0
  174. package/dist/privacy/redact.js +404 -0
  175. package/dist/privacy/report.d.ts +58 -0
  176. package/dist/privacy/report.d.ts.map +1 -0
  177. package/dist/privacy/report.js +15 -0
  178. package/dist/privacy/retirement.d.ts +68 -0
  179. package/dist/privacy/retirement.d.ts.map +1 -0
  180. package/dist/privacy/retirement.js +72 -0
  181. package/dist/privacy/sealed.d.ts +87 -0
  182. package/dist/privacy/sealed.d.ts.map +1 -0
  183. package/dist/privacy/sealed.js +221 -0
  184. package/dist/privacy/types.d.ts +559 -0
  185. package/dist/privacy/types.d.ts.map +1 -0
  186. package/dist/privacy/types.js +2 -0
  187. package/dist/seed/writeD1.d.ts +7 -1
  188. package/dist/seed/writeD1.d.ts.map +1 -1
  189. package/dist/seed/writeD1.js +9 -3
  190. package/dist/seed/writeKv.d.ts +2 -0
  191. package/dist/seed/writeKv.d.ts.map +1 -1
  192. package/dist/seed/writeKv.js +6 -2
  193. package/dist/version.generated.d.ts +1 -1
  194. package/dist/version.generated.js +1 -1
  195. package/dist/worker/serviceLoopback.d.ts +36 -0
  196. package/dist/worker/serviceLoopback.d.ts.map +1 -0
  197. package/dist/worker/serviceLoopback.js +74 -0
  198. package/dist/workflow/faults.d.ts +12 -1
  199. package/dist/workflow/faults.d.ts.map +1 -1
  200. package/dist/workflow/faults.js +22 -15
  201. package/package.json +2 -2
  202. package/src/access/access.ts +298 -0
  203. package/src/access/acting.ts +59 -0
  204. package/src/access/policyCheck.ts +77 -0
  205. package/src/access/usage.ts +141 -0
  206. package/src/access/visibility.ts +109 -0
  207. package/src/audit/auditEvent.ts +4 -0
  208. package/src/audit/recorder.ts +10 -2
  209. package/src/capability/bindings.ts +159 -13
  210. package/src/capability/capability.ts +114 -29
  211. package/src/capability/purge.ts +124 -0
  212. package/src/capability/settings.ts +146 -2
  213. package/src/cli/commandCatalog.generated.ts +271 -22
  214. package/src/cli/commandFacts.ts +2 -0
  215. package/src/controlPlane/capability.ts +36 -1
  216. package/src/controlPlane/context.ts +4 -0
  217. package/src/controlPlane/data/connection.ts +90 -0
  218. package/src/controlPlane/discovery/adminRoute.ts +11 -0
  219. package/src/controlPlane/error/errors.ts +4 -3
  220. package/src/controlPlane/http/cors.ts +4 -4
  221. package/src/controlPlane/http/guard.ts +21 -0
  222. package/src/controlPlane/http/handlers.ts +98 -4
  223. package/src/controlPlane/http/readiness.ts +50 -0
  224. package/src/controlPlane/http/responses.ts +240 -2
  225. package/src/controlPlane/http/routes.ts +55 -1
  226. package/src/controlPlane/http/verify.ts +2 -0
  227. package/src/controlPlane/migrationState/migrationState.ts +200 -0
  228. package/src/controlPlane/migrations/0003_connection_principal.ts +37 -0
  229. package/src/controlPlane/scope/scope.ts +25 -2
  230. package/src/controlPlane/token/base64url.ts +1 -1
  231. package/src/createBackend.ts +28 -6
  232. package/src/createEntrypoint.ts +9 -3
  233. package/src/crypto/envelope.ts +196 -0
  234. package/src/crypto/fieldKeys.ts +76 -0
  235. package/src/data/codecs.ts +69 -37
  236. package/src/entitlement/allowance.ts +85 -0
  237. package/src/entitlement/entitlement.ts +38 -0
  238. package/src/entitlement/meter.ts +69 -0
  239. package/src/error/extend.ts +6 -5
  240. package/src/error/payload.ts +253 -4
  241. package/src/error/pithyError.ts +21 -7
  242. package/src/http/authContext.ts +13 -1
  243. package/src/http/scopeGates.ts +34 -0
  244. package/src/index.ts +2 -0
  245. package/src/logger/logger.ts +12 -5
  246. package/src/migrations/capabilitySets.ts +87 -0
  247. package/src/migrations/registry.ts +46 -2
  248. package/src/migrations/state.ts +94 -0
  249. package/src/naming/feature.ts +46 -7
  250. package/src/naming/limits.ts +35 -3
  251. package/src/naming/provisionScope.ts +19 -1
  252. package/src/naming/resourceNames.ts +52 -5
  253. package/src/privacy/blindIndex.ts +81 -0
  254. package/src/privacy/classes.ts +277 -0
  255. package/src/privacy/classify.ts +1447 -0
  256. package/src/privacy/encrypted.ts +513 -0
  257. package/src/privacy/encryptedColumns.ts +185 -0
  258. package/src/privacy/fieldRotation.ts +234 -0
  259. package/src/privacy/inventory.ts +147 -0
  260. package/src/privacy/posture.ts +205 -0
  261. package/src/privacy/redact.ts +423 -0
  262. package/src/privacy/report.ts +64 -0
  263. package/src/privacy/retirement.ts +102 -0
  264. package/src/privacy/sealed.ts +323 -0
  265. package/src/privacy/types.ts +804 -0
  266. package/src/seed/writeD1.ts +13 -4
  267. package/src/seed/writeKv.ts +6 -2
  268. package/src/version.generated.ts +1 -1
  269. package/src/worker/serviceLoopback.ts +105 -0
  270. package/src/workflow/faults.ts +51 -24
@@ -97,6 +97,16 @@ const AuthSessionNotFreshPublic = z.object({
97
97
  status: z.literal(403).describe("Forbidden — a real, current credential was presented and is not sufficient for this particular decision. Not 401, which is what a caller with no credential gets: a client that cannot tell the two apart does not know whether to re-authenticate or to retry."),
98
98
  ...publicFields
99
99
  }).describe("The session is authentic but the holder authenticated too long ago to attach a provider (403).");
100
+ const AuthAccountSuspendedPublic = z.object({
101
+ code: z.literal("auth/account_suspended").describe("The account this credential belongs to is suspended, so the request is refused whatever it carries. An operator suspended it on purpose, with a reason, and the reason is the `message`. When the suspension has an end, `params.suspendedUntil` names it as ISO-8601; a suspension past its end is no longer one, and nothing has to clear it. A separate code from `auth/forbidden` so a client can render the screen that says what happened rather than a generic refusal."),
102
+ status: z.literal(403).describe("Forbidden — the credential is genuine and the account behind it may not act. Not 401: signing in again cannot help, and a client that read it as an expired token would loop."),
103
+ ...publicFields
104
+ }).describe("The account is suspended (403).");
105
+ const AuthAccountDeletedPublic = z.object({
106
+ code: z.literal("auth/account_deleted").describe("The account this credential belongs to is deleted and inside its purge window: it cannot sign in or act, and it can still be restored until the window closes. After the purge there is no account, and the credential is simply invalid."),
107
+ status: z.literal(403).describe("Forbidden — the account exists and may not act. Not 404, because until the purge runs it can come back, and not 401, because signing in again cannot help."),
108
+ ...publicFields
109
+ }).describe("The account is deleted and awaiting its purge (403).");
100
110
  const NotFoundPublic = z.object({
101
111
  code: z.literal("core/not_found").describe("The requested resource does not exist."),
102
112
  status: z.literal(404).describe("Not Found."),
@@ -242,6 +252,16 @@ const TurnstileConfigPublic = z.object({
242
252
  status: z.literal(500).describe("Internal Server Error — a configuration fault, not a client request."),
243
253
  ...publicFields
244
254
  }).describe("The Turnstile middleware is misconfigured (500).");
255
+ const TurnstileAnalyticsWindowPublic = z.object({
256
+ code: z.literal("turnstile/analytics_window").describe("The requested challenge window reaches past what Cloudflare keeps, or is wider than one read may ask for."),
257
+ status: z.literal(400).describe("Bad Request — narrow the window or move it later."),
258
+ ...publicFields
259
+ }).describe("A Turnstile-analytics window outside Cloudflare's retention or range (400).");
260
+ const TurnstileAnalyticsUnavailablePublic = z.object({
261
+ code: z.literal("turnstile/analytics_unavailable").describe("Cloudflare does not serve Turnstile analytics to this account, so no outcome can be read."),
262
+ status: z.literal(409).describe("Conflict — the account's configuration rules the read out."),
263
+ ...publicFields
264
+ }).describe("Turnstile analytics are not served to this account (409).");
245
265
  const AuditInvalidEventPublic = z.object({
246
266
  code: z.literal("audit/invalid_event").describe("An audit event failed validation against the AuditEvent schema (bad action, outcome, or actor)."),
247
267
  status: z.literal(400).describe("Bad Request — the event did not match its schema."),
@@ -257,6 +277,11 @@ const MediaNotFoundPublic = z.object({
257
277
  status: z.literal(404).describe("Not Found."),
258
278
  ...publicFields
259
279
  }).describe("A requested media record does not exist (404).");
280
+ const MediaForbiddenPublic = z.object({
281
+ code: z.literal("media/forbidden").describe("The caller may read the media record but not change it: only its owner, acting for the record's organization, or a role holding `media:manage` there may edit, delete or re-scope it."),
282
+ status: z.literal(403).describe("Forbidden."),
283
+ ...publicFields
284
+ }).describe("The caller may read the record but not change it (403).");
260
285
  const MediaUnsupportedPublic = z.object({
261
286
  code: z.literal("media/unsupported").describe("The media type, extension, or backend is not supported for the requested operation."),
262
287
  status: z.literal(400).describe("Bad Request — the operation does not apply to this media."),
@@ -272,6 +297,16 @@ const MediaEnrichmentFailedPublic = z.object({
272
297
  status: z.literal(500).describe("Internal Server Error — an enrichment step could not complete."),
273
298
  ...publicFields
274
299
  }).describe("A media AI-enrichment step failed (500).");
300
+ const MediaAnalyticsWindowPublic = z.object({
301
+ code: z.literal("media/analytics_window").describe("The requested delivery window reaches past what Cloudflare keeps, or is wider than one read may ask for."),
302
+ status: z.literal(400).describe("Bad Request — narrow the window or move it later."),
303
+ ...publicFields
304
+ }).describe("A delivery-analytics window outside Cloudflare's retention or range (400).");
305
+ const MediaAnalyticsUnavailablePublic = z.object({
306
+ code: z.literal("media/analytics_unavailable").describe("Cloudflare does not serve the delivery analytics this read needs to this account — a Customer Metadata Boundary outside the US carries none of them."),
307
+ status: z.literal(409).describe("Conflict — the account's configuration rules the read out."),
308
+ ...publicFields
309
+ }).describe("Delivery analytics are not served to this account (409).");
275
310
  const LeaderboardBoardNotFoundPublic = z.object({
276
311
  code: z.literal("leaderboard/board_not_found").describe("No board with that key is configured. Board keys come from `pithy.config.ts`, not from the database."),
277
312
  status: z.literal(404).describe("Not Found."),
@@ -438,17 +473,17 @@ const MatchmakingNotQueuedPublic = z.object({
438
473
  ...publicFields
439
474
  }).describe("The player is not in the queue (404).");
440
475
  const StorageNotFoundPublic = z.object({
441
- code: z.literal("storage/not_found").describe("No object row matches, or the object exists but is not visible to this caller."),
476
+ code: z.literal("storage/not_found").describe("No object row matches, or the object exists but this caller may not read it."),
442
477
  status: z.literal(404).describe("Not Found."),
443
478
  ...publicFields
444
479
  }).describe("The object does not exist, or is not visible to the caller (404).");
445
480
  const StorageForbiddenPublic = z.object({
446
- code: z.literal("storage/forbidden").describe("The caller does not own the object and the object is not public."),
481
+ code: z.literal("storage/forbidden").describe("The caller may read the object but not change it: only its owner, acting for the object's organization, or a role holding `storage:manage` there may."),
447
482
  status: z.literal(403).describe("Forbidden."),
448
483
  ...publicFields
449
- }).describe("The caller is not the owner and the object is not public (403).");
484
+ }).describe("The caller may read the object but not change it (403).");
450
485
  const StorageQuotaExceededPublic = z.object({
451
- code: z.literal("storage/quota_exceeded").describe("The declared upload size would push the owner past their byte quota. Checked at init against pending and stored rows together, so concurrent inits cannot race past the limit."),
486
+ code: z.literal("storage/quota_exceeded").describe("The declared upload size would push the owner past the configured `bytesPerOwner` quota. Checked at init against pending and stored rows together, so concurrent inits cannot race past the limit. Where the `storageBytes` meter is enforced, the same refusal is `payments/quota_exceeded` (402)."),
452
487
  status: z.literal(413).describe("Content Too Large."),
453
488
  ...publicFields
454
489
  }).describe("The upload would exceed the owner's byte quota (413).");
@@ -582,6 +617,16 @@ const PaymentsSubscriptionChangeRefusedPublic = z.object({
582
617
  status: z.literal(409).describe("Conflict — the subscription's present state forbids the change asked of it."),
583
618
  ...publicFields
584
619
  }).describe("A subscription's state forbids the change asked of it (409).");
620
+ const PaymentsOverrideStalePublic = z.object({
621
+ code: z.literal("payments/override_stale").describe("A control-plane override write named a version behind the subject's override row. Two operators share one customer: both opened the same allowance, and the second would silently overwrite the first while the first believed they had succeeded. So the write is refused and nothing is written. 409, because the request is well-formed and the same request against the version it now holds would be accepted — the caller re-reads, and tries again."),
622
+ status: z.literal(409).describe("Conflict — the override changed since the caller read it."),
623
+ ...publicFields
624
+ }).describe("An override write named a stale version (409).");
625
+ const PaymentsQuotaExceededPublic = z.object({
626
+ code: z.literal("payments/quota_exceeded").describe("An enforced kit meter — emails enqueued, bytes stored, media items held — would pass the subject's effective quota for the period. Nothing was written. 402 Payment Required, because it is the honest status: the plan does not allow more and the remedy is a purchase, a bigger tier, or a number pinned for this subject from the control plane. A meter refuses and never bills — the kit does not sell overage."),
627
+ status: z.literal(402).describe("Payment Required — the plan's allowance for this period is used up."),
628
+ ...publicFields
629
+ }).describe("An enforced meter is at its quota for this period (402).");
585
630
  const ControlPlaneNotConnectedPublic = z.object({
586
631
  code: z.literal("controlplane/not_connected").describe("No management-client connection is registered for this environment. The shipped default: the seam is present and denies everything until the adopter provisions a credential. There is no backdoor."),
587
632
  status: z.literal(403).describe("Forbidden."),
@@ -642,6 +687,31 @@ const OrganizationNominationInvalidPublic = z.object({
642
687
  status: z.literal(400).describe("Bad Request — no offer this caller may accept."),
643
688
  ...publicFields
644
689
  }).describe("No standing ownership offer this caller may accept (400).");
690
+ const ArtifactsNotFoundPublic = z.object({
691
+ 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
+ status: z.literal(404).describe("Not Found."),
693
+ ...publicFields
694
+ }).describe("No such repository, or none this caller may see — the same answer for both (404).");
695
+ const ArtifactsForbiddenPublic = z.object({
696
+ code: z.literal("artifacts/forbidden").describe("The caller can see the repository and may not do this to it: a grant holder asking for what only an owner may do, or a member of an organization whose role lacks the configured `managePower`. A 403 rather than the 404 above, because by then the caller already knows the repository exists."),
697
+ status: z.literal(403).describe("Forbidden."),
698
+ ...publicFields
699
+ }).describe("The caller may see this repository and may not do this (403).");
700
+ const ArtifactsInvalidNamePublic = z.object({
701
+ code: z.literal("artifacts/invalid_name").describe("A supplied repository name is outside Cloudflare's charset or the 2-to-63 cap. Refused and never shortened: a name somebody chose is in every clone URL, and a silently different one is a repository nobody can find."),
702
+ status: z.literal(400).describe("Bad Request."),
703
+ ...publicFields
704
+ }).describe("A repository name breaks the naming rule (400).");
705
+ const ArtifactsNameTakenPublic = z.object({
706
+ code: z.literal("artifacts/name_taken").describe("The owner already holds a repository with that display name, or a supplied physical name is already in the namespace. The second happens only where the adopter supplies names, so uniqueness is theirs."),
707
+ status: z.literal(409).describe("Conflict."),
708
+ ...publicFields
709
+ }).describe("That repository name is already in use (409).");
710
+ const ArtifactsInvalidConfigPublic = z.object({
711
+ code: z.literal("artifacts/invalid_config").describe("The capability's configuration cannot be honored: a `tokenTtlSeconds` above the ceiling, or `organization` composed with no `managePower` named. Raised at boot, so a mistake fails on deploy rather than at the first mint."),
712
+ status: z.literal(400).describe("Bad Request — the configuration is malformed."),
713
+ ...publicFields
714
+ }).describe("The artifacts configuration is invalid (400).");
645
715
  const SupportNotFoundPublic = z.object({
646
716
  code: z.literal("support/not_found").describe("A requested support thread, message, or attachment does not exist."),
647
717
  status: z.literal(404).describe("Not Found."),
@@ -737,6 +807,8 @@ const KitPublicErrorPayload = z.discriminatedUnion("code", [
737
807
  ForbiddenPublic,
738
808
  AuthProviderUnavailablePublic,
739
809
  AuthSessionNotFreshPublic,
810
+ AuthAccountSuspendedPublic,
811
+ AuthAccountDeletedPublic,
740
812
  NotFoundPublic,
741
813
  ConflictPublic,
742
814
  RateLimitPublic,
@@ -766,12 +838,17 @@ const KitPublicErrorPayload = z.discriminatedUnion("code", [
766
838
  TurnstileMissingTokenPublic,
767
839
  TurnstileFailedPublic,
768
840
  TurnstileConfigPublic,
841
+ TurnstileAnalyticsWindowPublic,
842
+ TurnstileAnalyticsUnavailablePublic,
769
843
  AuditInvalidEventPublic,
770
844
  AuditWriteFailedPublic,
771
845
  MediaNotFoundPublic,
846
+ MediaForbiddenPublic,
772
847
  MediaUnsupportedPublic,
773
848
  MediaStorageFailedPublic,
774
849
  MediaEnrichmentFailedPublic,
850
+ MediaAnalyticsWindowPublic,
851
+ MediaAnalyticsUnavailablePublic,
775
852
  LeaderboardBoardNotFoundPublic,
776
853
  LeaderboardEntryNotFoundPublic,
777
854
  LeaderboardScoreRejectedPublic,
@@ -834,6 +911,8 @@ const KitPublicErrorPayload = z.discriminatedUnion("code", [
834
911
  PaymentsEntitlementNotInCatalogPublic,
835
912
  PaymentsSubjectUnresolvedPublic,
836
913
  PaymentsSubscriptionChangeRefusedPublic,
914
+ PaymentsOverrideStalePublic,
915
+ PaymentsQuotaExceededPublic,
837
916
  ControlPlaneNotConnectedPublic,
838
917
  ControlPlaneInvalidCredentialPublic,
839
918
  ControlPlaneInsufficientScopePublic,
@@ -846,6 +925,11 @@ const KitPublicErrorPayload = z.discriminatedUnion("code", [
846
925
  OrganizationLastAdministratorPublic,
847
926
  OrganizationSlugTakenPublic,
848
927
  OrganizationNominationInvalidPublic,
928
+ ArtifactsNotFoundPublic,
929
+ ArtifactsForbiddenPublic,
930
+ ArtifactsInvalidNamePublic,
931
+ ArtifactsNameTakenPublic,
932
+ ArtifactsInvalidConfigPublic,
849
933
  SupportNotFoundPublic,
850
934
  SupportInvalidCategoryPublic,
851
935
  SupportUnparseableMessagePublic,
@@ -871,6 +955,8 @@ const InvalidToken = InvalidTokenPublic.extend(internalFields).describe(InvalidT
871
955
  const Forbidden = ForbiddenPublic.extend(internalFields).describe(ForbiddenPublic.description ?? "");
872
956
  const AuthProviderUnavailable = AuthProviderUnavailablePublic.extend(internalFields).describe(AuthProviderUnavailablePublic.description ?? "");
873
957
  const AuthSessionNotFresh = AuthSessionNotFreshPublic.extend(internalFields).describe(AuthSessionNotFreshPublic.description ?? "");
958
+ const AuthAccountSuspended = AuthAccountSuspendedPublic.extend(internalFields).describe(AuthAccountSuspendedPublic.description ?? "");
959
+ const AuthAccountDeleted = AuthAccountDeletedPublic.extend(internalFields).describe(AuthAccountDeletedPublic.description ?? "");
874
960
  const NotFound = NotFoundPublic.extend(internalFields).describe(NotFoundPublic.description ?? "");
875
961
  const Conflict = ConflictPublic.extend(internalFields).describe(ConflictPublic.description ?? "");
876
962
  const RateLimit = RateLimitPublic.extend(internalFields).describe(RateLimitPublic.description ?? "");
@@ -900,12 +986,17 @@ const EmailSendFailed = EmailSendFailedPublic.extend(internalFields).describe(Em
900
986
  const TurnstileMissingToken = TurnstileMissingTokenPublic.extend(internalFields).describe(TurnstileMissingTokenPublic.description ?? "");
901
987
  const TurnstileFailed = TurnstileFailedPublic.extend(internalFields).describe(TurnstileFailedPublic.description ?? "");
902
988
  const TurnstileConfig = TurnstileConfigPublic.extend(internalFields).describe(TurnstileConfigPublic.description ?? "");
989
+ const TurnstileAnalyticsWindow = TurnstileAnalyticsWindowPublic.extend(internalFields).describe(TurnstileAnalyticsWindowPublic.description ?? "");
990
+ const TurnstileAnalyticsUnavailable = TurnstileAnalyticsUnavailablePublic.extend(internalFields).describe(TurnstileAnalyticsUnavailablePublic.description ?? "");
903
991
  const AuditInvalidEvent = AuditInvalidEventPublic.extend(internalFields).describe(AuditInvalidEventPublic.description ?? "");
904
992
  const AuditWriteFailed = AuditWriteFailedPublic.extend(internalFields).describe(AuditWriteFailedPublic.description ?? "");
905
993
  const MediaNotFound = MediaNotFoundPublic.extend(internalFields).describe(MediaNotFoundPublic.description ?? "");
994
+ const MediaForbidden = MediaForbiddenPublic.extend(internalFields).describe(MediaForbiddenPublic.description ?? "");
906
995
  const MediaUnsupported = MediaUnsupportedPublic.extend(internalFields).describe(MediaUnsupportedPublic.description ?? "");
907
996
  const MediaStorageFailed = MediaStorageFailedPublic.extend(internalFields).describe(MediaStorageFailedPublic.description ?? "");
908
997
  const MediaEnrichmentFailed = MediaEnrichmentFailedPublic.extend(internalFields).describe(MediaEnrichmentFailedPublic.description ?? "");
998
+ const MediaAnalyticsWindow = MediaAnalyticsWindowPublic.extend(internalFields).describe(MediaAnalyticsWindowPublic.description ?? "");
999
+ const MediaAnalyticsUnavailable = MediaAnalyticsUnavailablePublic.extend(internalFields).describe(MediaAnalyticsUnavailablePublic.description ?? "");
909
1000
  const LeaderboardBoardNotFound = LeaderboardBoardNotFoundPublic.extend(internalFields).describe(LeaderboardBoardNotFoundPublic.description ?? "");
910
1001
  const LeaderboardEntryNotFound = LeaderboardEntryNotFoundPublic.extend(internalFields).describe(LeaderboardEntryNotFoundPublic.description ?? "");
911
1002
  const LeaderboardScoreRejected = LeaderboardScoreRejectedPublic.extend(internalFields).describe(LeaderboardScoreRejectedPublic.description ?? "");
@@ -968,6 +1059,8 @@ const PaymentsDiscountInvalid = PaymentsDiscountInvalidPublic.extend(internalFie
968
1059
  const PaymentsEntitlementNotInCatalog = PaymentsEntitlementNotInCatalogPublic.extend(internalFields).describe(PaymentsEntitlementNotInCatalogPublic.description ?? "");
969
1060
  const PaymentsSubjectUnresolved = PaymentsSubjectUnresolvedPublic.extend(internalFields).describe(PaymentsSubjectUnresolvedPublic.description ?? "");
970
1061
  const PaymentsSubscriptionChangeRefused = PaymentsSubscriptionChangeRefusedPublic.extend(internalFields).describe(PaymentsSubscriptionChangeRefusedPublic.description ?? "");
1062
+ const PaymentsOverrideStale = PaymentsOverrideStalePublic.extend(internalFields).describe(PaymentsOverrideStalePublic.description ?? "");
1063
+ const PaymentsQuotaExceeded = PaymentsQuotaExceededPublic.extend(internalFields).describe(PaymentsQuotaExceededPublic.description ?? "");
971
1064
  const ControlPlaneNotConnected = ControlPlaneNotConnectedPublic.extend(internalFields).describe(ControlPlaneNotConnectedPublic.description ?? "");
972
1065
  const ControlPlaneInvalidCredential = ControlPlaneInvalidCredentialPublic.extend(internalFields).describe(ControlPlaneInvalidCredentialPublic.description ?? "");
973
1066
  const ControlPlaneInsufficientScope = ControlPlaneInsufficientScopePublic.extend(internalFields).describe(ControlPlaneInsufficientScopePublic.description ?? "");
@@ -990,6 +1083,11 @@ const OrganizationInvitationInvalid = OrganizationInvitationInvalidPublic.extend
990
1083
  const OrganizationLastAdministrator = OrganizationLastAdministratorPublic.extend(internalFields).describe(OrganizationLastAdministratorPublic.description ?? "");
991
1084
  const OrganizationSlugTaken = OrganizationSlugTakenPublic.extend(internalFields).describe(OrganizationSlugTakenPublic.description ?? "");
992
1085
  const OrganizationNominationInvalid = OrganizationNominationInvalidPublic.extend(internalFields).describe(OrganizationNominationInvalidPublic.description ?? "");
1086
+ const ArtifactsNotFound = ArtifactsNotFoundPublic.extend(internalFields).describe(ArtifactsNotFoundPublic.description ?? "");
1087
+ const ArtifactsForbidden = ArtifactsForbiddenPublic.extend(internalFields).describe(ArtifactsForbiddenPublic.description ?? "");
1088
+ const ArtifactsInvalidName = ArtifactsInvalidNamePublic.extend(internalFields).describe(ArtifactsInvalidNamePublic.description ?? "");
1089
+ const ArtifactsNameTaken = ArtifactsNameTakenPublic.extend(internalFields).describe(ArtifactsNameTakenPublic.description ?? "");
1090
+ const ArtifactsInvalidConfig = ArtifactsInvalidConfigPublic.extend(internalFields).describe(ArtifactsInvalidConfigPublic.description ?? "");
993
1091
  const SupportNotFound = SupportNotFoundPublic.extend(internalFields).describe(SupportNotFoundPublic.description ?? "");
994
1092
  const SupportInvalidCategory = SupportInvalidCategoryPublic.extend(internalFields).describe(SupportInvalidCategoryPublic.description ?? "");
995
1093
  const SupportUnparseableMessage = SupportUnparseableMessagePublic.extend(internalFields).describe(SupportUnparseableMessagePublic.description ?? "");
@@ -1010,6 +1108,8 @@ const KitErrorPayload = z.discriminatedUnion("code", [
1010
1108
  Forbidden,
1011
1109
  AuthProviderUnavailable,
1012
1110
  AuthSessionNotFresh,
1111
+ AuthAccountSuspended,
1112
+ AuthAccountDeleted,
1013
1113
  NotFound,
1014
1114
  Conflict,
1015
1115
  RateLimit,
@@ -1039,12 +1139,17 @@ const KitErrorPayload = z.discriminatedUnion("code", [
1039
1139
  TurnstileMissingToken,
1040
1140
  TurnstileFailed,
1041
1141
  TurnstileConfig,
1142
+ TurnstileAnalyticsWindow,
1143
+ TurnstileAnalyticsUnavailable,
1042
1144
  AuditInvalidEvent,
1043
1145
  AuditWriteFailed,
1044
1146
  MediaNotFound,
1147
+ MediaForbidden,
1045
1148
  MediaUnsupported,
1046
1149
  MediaStorageFailed,
1047
1150
  MediaEnrichmentFailed,
1151
+ MediaAnalyticsWindow,
1152
+ MediaAnalyticsUnavailable,
1048
1153
  LeaderboardBoardNotFound,
1049
1154
  LeaderboardEntryNotFound,
1050
1155
  LeaderboardScoreRejected,
@@ -1107,6 +1212,8 @@ const KitErrorPayload = z.discriminatedUnion("code", [
1107
1212
  PaymentsEntitlementNotInCatalog,
1108
1213
  PaymentsSubjectUnresolved,
1109
1214
  PaymentsSubscriptionChangeRefused,
1215
+ PaymentsOverrideStale,
1216
+ PaymentsQuotaExceeded,
1110
1217
  ControlPlaneNotConnected,
1111
1218
  ControlPlaneInvalidCredential,
1112
1219
  ControlPlaneInsufficientScope,
@@ -1119,6 +1226,11 @@ const KitErrorPayload = z.discriminatedUnion("code", [
1119
1226
  OrganizationLastAdministrator,
1120
1227
  OrganizationSlugTaken,
1121
1228
  OrganizationNominationInvalid,
1229
+ ArtifactsNotFound,
1230
+ ArtifactsForbidden,
1231
+ ArtifactsInvalidName,
1232
+ ArtifactsNameTaken,
1233
+ ArtifactsInvalidConfig,
1122
1234
  SupportNotFound,
1123
1235
  SupportInvalidCategory,
1124
1236
  SupportUnparseableMessage,
@@ -2,6 +2,7 @@
2
2
  // SPDX-License-Identifier: MIT
3
3
  import type { z } from "zod";
4
4
  import type { MessageParams } from "../i18n/catalog";
5
+ import type { UnmarkedString } from "../privacy/types";
5
6
  import type { ValidationIssue } from "./payload";
6
7
  import { ErrorPayload } from "./payload";
7
8
  /**
@@ -15,18 +16,28 @@ import { ErrorPayload } from "./payload";
15
16
  */
16
17
  export declare class PithyError extends Error {
17
18
  readonly payload: ErrorPayload;
18
- constructor(payload: ErrorPayload, options?: {
19
+ /**
20
+ * `message`, `action` and `detail` are each an {@link UnmarkedString} here and on every subclass's arguments
21
+ * (#132): a value marked with a privacy class is refused at compile time, because all three ride into every log
22
+ * line and audit row that carries this error. A template literal is a plain `string`, so interpolation is not caught — see
23
+ * `privacy/types.ts` for exactly what is.
24
+ */
25
+ constructor(payload: ErrorPayload & {
26
+ message: UnmarkedString;
27
+ action?: UnmarkedString | undefined;
28
+ detail?: UnmarkedString | undefined;
29
+ }, options?: {
19
30
  cause?: unknown;
20
31
  });
21
32
  }
22
33
  /** Variable parts every subclass accepts; the `code`/`status` are fixed by the subclass. */
23
34
  interface ErrorArgs {
24
- /** Override the public, safe-to-expose message. Defaults to a per-code summary. */
25
- message?: string;
26
- /** A remediation hint (CLI action line). */
27
- action?: string;
28
- /** Internal context for logs + audit. Never serialized to clients. */
29
- detail?: string;
35
+ /** Override the public, safe-to-expose message. Defaults to a per-code summary. Never a privacy-marked value. */
36
+ message?: UnmarkedString;
37
+ /** A remediation hint (CLI action line). Never a privacy-marked value. */
38
+ action?: UnmarkedString;
39
+ /** Internal context for logs + audit. Never serialized to clients, and never a privacy-marked value (#132). */
40
+ detail?: UnmarkedString;
30
41
  /**
31
42
  * Values a translating client interpolates into its own wording for this code. Client-facing, so —
32
43
  * unlike `action` and `detail` — these cross the boundary with `message`. The `code` is the catalog
@@ -1 +1 @@
1
- {"version":3,"file":"pithyError.d.ts","sourceRoot":"","sources":["../../src/error/pithyError.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pithyError.d.ts","sourceRoot":"","sources":["../../src/error/pithyError.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC;;;;;;;;GAQG;AACH,qBAAa,UAAW,SAAQ,KAAK;IACnC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAE/B;;;;;OAKG;IACH,YACE,OAAO,EAAE,YAAY,GAAG;QACtB,OAAO,EAAE,cAAc,CAAC;QACxB,MAAM,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;QACpC,MAAM,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;KACrC,EACD,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAM9B;CACF;AAED,4FAA4F;AAC5F,UAAU,SAAS;IACjB,iHAAiH;IACjH,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,+GAA+G;IAC/G,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB;;;;OAIG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,0BAA0B,CAAA;KAAE,CAAC,CAAC;IAEtF,YAAY,IAAI,GAAE,SAAS,GAAG;QAAE,MAAM,CAAC,EAAE,eAAe,EAAE,CAAA;KAAO,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAa/F;CACF;AAED;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,UAAU;IAChD,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IAE5E,YACE,IAAI,GAAE,SAAS,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;KAAO,EAC5E,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAe9B;CACF;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,UAAU;IACrD,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,0BAA0B,CAAA;KAAE,CAAC,CAAC;IAEtF,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,UAAU;IACjD,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,sBAAsB,CAAA;KAAE,CAAC,CAAC;IAElF,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED,qBAAa,iBAAkB,SAAQ,UAAU;IAC/C,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,oBAAoB,CAAA;KAAE,CAAC,CAAC;IAEhF,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED;;;;GAIG;AACH,qBAAa,sBAAuB,SAAQ,UAAU;IACpD,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,yBAAyB,CAAA;KAAE,CAAC,CAAC;IAErF,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED,qBAAa,cAAe,SAAQ,UAAU;IAC5C,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IAE5E,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED,qBAAa,aAAc,SAAQ,UAAU;IAC3C,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,gBAAgB,CAAA;KAAE,CAAC,CAAC;IAE5E,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED,qBAAa,aAAc,SAAQ,UAAU;IAC3C,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IAE3E,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED,qBAAa,cAAe,SAAQ,UAAU;IAC5C,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,qBAAqB,CAAA;KAAE,CAAC,CAAC;IAEjF,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED,qBAAa,aAAc,SAAQ,UAAU;IAC3C,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,eAAe,CAAA;KAAE,CAAC,CAAC;IAE3E,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED;;;;;GAKG;AACH,qBAAa,aAAc,SAAQ,UAAU;IAC3C,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,sBAAsB,CAAA;KAAE,CAAC,CAAC;IAElF,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED,sGAAsG;AACtG,qBAAa,oBAAqB,SAAQ,UAAU;IAClD,SAAiB,OAAO,EAAE,OAAO,CAAC,YAAY,EAAE;QAAE,IAAI,EAAE,uBAAuB,CAAA;KAAE,CAAC,CAAC;IAEnF,YAAY,IAAI,GAAE,SAAc,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,EAY9D;CACF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,QAAQ,EAAE,IAAI,GAAE,SAAc,GAAG,eAAe,CAarF;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEhD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAGjD"}
@@ -13,6 +13,12 @@ import { ErrorPayload } from "./payload.js";
13
13
  */
14
14
  var PithyError = class extends Error {
15
15
  payload;
16
+ /**
17
+ * `message`, `action` and `detail` are each an {@link UnmarkedString} here and on every subclass's arguments
18
+ * (#132): a value marked with a privacy class is refused at compile time, because all three ride into every log
19
+ * line and audit row that carries this error. A template literal is a plain `string`, so interpolation is not caught — see
20
+ * `privacy/types.ts` for exactly what is.
21
+ */
16
22
  constructor(payload, options) {
17
23
  const parsed = ErrorPayload.parse(payload);
18
24
  super(parsed.message, options);
@@ -12,6 +12,13 @@ import { z } from "zod";
12
12
  * stored choice outrank their device's `Accept-Language`. That link read `c.var.locale` at first,
13
13
  * which nothing ever wrote, so it silently contributed nothing and the chain degraded to
14
14
  * `param → cookie → header → default` while the docs said otherwise.
15
+ *
16
+ * **`scopes` answers one question: did this request come from the adopter's own trusted backend, or from a
17
+ * device?** The name reads like a grant to the user, and it is not one. Tenancy roles went to `c.var.acting`
18
+ * with `@pithy-sh/organization`; management access is the control plane's, with its own credential and its
19
+ * own scope type. What is left is an attestation about the caller, which `@pithy-sh/auth`'s `resolveScopes`
20
+ * makes on every request from something the request proves — a service binding, a verified client
21
+ * certificate, a short-lived token bound to this origin — and never from anything it merely says (#560).
15
22
  */
16
23
  export declare const AuthContext: z.ZodObject<{
17
24
  userId: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"authContext.d.ts","sourceRoot":"","sources":["../../src/http/authContext.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,WAAW;;;;;;iBAeiE,CAAC;AAC1F,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC"}
1
+ {"version":3,"file":"authContext.d.ts","sourceRoot":"","sources":["../../src/http/authContext.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,WAAW;;;;;;iBAoBiE,CAAC;AAC1F,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC"}
@@ -14,11 +14,18 @@ import { z } from "zod";
14
14
  * stored choice outrank their device's `Accept-Language`. That link read `c.var.locale` at first,
15
15
  * which nothing ever wrote, so it silently contributed nothing and the chain degraded to
16
16
  * `param → cookie → header → default` while the docs said otherwise.
17
+ *
18
+ * **`scopes` answers one question: did this request come from the adopter's own trusted backend, or from a
19
+ * device?** The name reads like a grant to the user, and it is not one. Tenancy roles went to `c.var.acting`
20
+ * with `@pithy-sh/organization`; management access is the control plane's, with its own credential and its
21
+ * own scope type. What is left is an attestation about the caller, which `@pithy-sh/auth`'s `resolveScopes`
22
+ * makes on every request from something the request proves — a service binding, a verified client
23
+ * certificate, a short-lived token bound to this origin — and never from anything it merely says (#560).
17
24
  */
18
25
  const AuthContext = z.object({
19
26
  userId: z.string().describe("ID of the authenticated user (populated by @pithy-sh/auth)."),
20
27
  sessionId: z.string().describe("ID of the active session this request belongs to."),
21
- scopes: z.array(z.string()).default([]).describe("Permission scopes granted to this session."),
28
+ scopes: z.array(z.string()).default([]).describe("Attestations about the caller, not permissions granted to the user: what this request's caller was established to be — the adopter's own trusted backend, say — by the `resolveScopes` seam on `@pithy-sh/auth`, resolved per request and never cached. Empty when no resolver is configured. Tenancy roles are not here; they are `c.var.acting`."),
22
29
  locale: Locale.nullish().describe("The reader's own stored language, from `pithy_auth_users.locale`; null or absent when they have never chosen."),
23
30
  authenticatedAt: z.date().nullish().describe("When the holder of this session last actually authenticated — a sign-in, never a rotation, which carries the value forward unchanged. It rides here for the same reason `locale` does: the session lookup has already loaded the row, so a gate that needs it should not pay for a second read. Distinct from the session's own `createdAt`, which `/token/rotate` stamps fresh and is therefore resettable by anyone holding a stolen refresh token. Null or absent for a session written before the column existed, and for a Worker whose auth capability predates it.")
24
31
  }).describe("Per-request authenticated identity; the seam other capabilities depend on.");
@@ -0,0 +1,20 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import { Hono } from "hono";
4
+ import type { PithyHonoEnv, ScopeGate } from "../capability/capability";
5
+ /**
6
+ * **A capability's scope gates, read off its own routes rather than listed beside them (#560).**
7
+ *
8
+ * `Capability.scopeGates` is what `pithy doctor` names when nothing composed fills `AuthContext.scopes`.
9
+ * A list written out by hand next to the routes is a second copy of something the routes already say: every
10
+ * gated route carries `describeRoute({ scopes })`, because that is how the OpenAPI contract learns it. So the
11
+ * registrar is run against a throwaway app and the specs are read back — the same walk `openApiDocument`
12
+ * makes over a composed app, and a route whose scope changes changes what this returns with it.
13
+ *
14
+ * **Only `bearer` and `session` routes.** Those are the strategies `requireAuth()` takes, so a scope on one
15
+ * is an `AuthContext` scope. A `control-plane` route also names scopes, and they are a different credential
16
+ * entirely — a signed management token with its own type, never `c.var.auth` — so naming one here would tell
17
+ * an adopter to configure a resolver that could never open it.
18
+ */
19
+ export declare function scopeGatesOf(register: (app: Hono<PithyHonoEnv>) => void): ScopeGate[];
20
+ //# sourceMappingURL=scopeGates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scopeGates.d.ts","sourceRoot":"","sources":["../../src/http/scopeGates.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAGxE;;;;;;;;;;;;;GAaG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,YAAY,CAAC,KAAK,IAAI,GAAG,SAAS,EAAE,CAYrF"}
@@ -0,0 +1,36 @@
1
+ // SPDX-FileCopyrightText: 2026 Pithy
2
+ // SPDX-License-Identifier: MIT
3
+ import { routeSpecOf } from "./routeSpec.js";
4
+ import { Hono } from "hono";
5
+ //#region src/http/scopeGates.ts
6
+ /**
7
+ * **A capability's scope gates, read off its own routes rather than listed beside them (#560).**
8
+ *
9
+ * `Capability.scopeGates` is what `pithy doctor` names when nothing composed fills `AuthContext.scopes`.
10
+ * A list written out by hand next to the routes is a second copy of something the routes already say: every
11
+ * gated route carries `describeRoute({ scopes })`, because that is how the OpenAPI contract learns it. So the
12
+ * registrar is run against a throwaway app and the specs are read back — the same walk `openApiDocument`
13
+ * makes over a composed app, and a route whose scope changes changes what this returns with it.
14
+ *
15
+ * **Only `bearer` and `session` routes.** Those are the strategies `requireAuth()` takes, so a scope on one
16
+ * is an `AuthContext` scope. A `control-plane` route also names scopes, and they are a different credential
17
+ * entirely — a signed management token with its own type, never `c.var.auth` — so naming one here would tell
18
+ * an adopter to configure a resolver that could never open it.
19
+ */
20
+ function scopeGatesOf(register) {
21
+ const app = new Hono();
22
+ register(app);
23
+ const gates = [];
24
+ for (const route of app.routes) {
25
+ const spec = routeSpecOf(route.handler);
26
+ if (!spec?.scopes || spec.scopes.length === 0) continue;
27
+ if (![spec.verification].flat().some((strategy) => strategy === "bearer" || strategy === "session")) continue;
28
+ for (const scope of spec.scopes) gates.push({
29
+ scope,
30
+ route: `${route.method} ${route.path}`
31
+ });
32
+ }
33
+ return gates;
34
+ }
35
+ //#endregion
36
+ export { scopeGatesOf };
package/dist/index.d.ts CHANGED
@@ -28,7 +28,7 @@ export { type AdminRouteDrift, missingAdminRoutes } from "./controlPlane/discove
28
28
  export { type CapabilityHealth, type CapabilityHealthInput, type CapabilityHealthSource, capabilityHealthSources, defineCapabilityHealth, readCapabilityHealth, } from "./controlPlane/discovery/health";
29
29
  export { CapabilityHealthReport, type CapabilityHealthWire, HealthCountNominal, HealthNominal, type HealthStanding, HealthSummary, HealthSummaryKey, HealthSummaryValue, HealthValueCost, HealthValueKind, healthAttention, healthReport, healthWire, type NamedHealthValue, namedHealthValues, standingOf, } from "./controlPlane/discovery/healthSummary";
30
30
  export { requireControlPlane } from "./controlPlane/http/guard";
31
- export { ANY_VERIFIED_CALLER, type ControlPlaneRequirement, ControlPlaneScope, KEYS_ROTATE_SCOPE, MANIFEST_READ_SCOPE, SEAM_SCOPES, } from "./controlPlane/scope/scope";
31
+ export { ANY_VERIFIED_CALLER, type ControlPlaneRequirement, ControlPlaneScope, KEYS_ROTATE_SCOPE, MANIFEST_READ_SCOPE, MIGRATIONS_READ_SCOPE, PRIVACY_READ_SCOPE, SEAM_SCOPES, } from "./controlPlane/scope/scope";
32
32
  export { exportPublicJwk, type MintControlPlaneToken, mintControlPlaneToken } from "./controlPlane/token/mint";
33
33
  export { CONTROL_PLANE_HEADER, CONTROL_PLANE_VERSION_CREATED_HEADER, CONTROL_PLANE_VERSION_HEADER, type WorkerBuild, workerBuildChanged, } from "./controlPlane/wire";
34
34
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,KAAK,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACtG,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,YAAY,EACZ,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACzG,OAAO,EACL,+BAA+B,EAC/B,KAAK,oBAAoB,EACzB,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAIpC,OAAO,EACL,UAAU,EACV,KAAK,gBAAgB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,wBAAwB,GAC9B,MAAM,qCAAqC,CAAC;AAK7C,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,6BAA6B,EAClC,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,iBAAiB,GAClB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,KAAK,eAAe,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAQ1F,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,kBAAkB,EAClB,aAAa,EACb,KAAK,cAAc,EACnB,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,eAAe,EACf,YAAY,EACZ,UAAU,EACV,KAAK,gBAAgB,EACrB,iBAAiB,EACjB,UAAU,GACX,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EACL,mBAAmB,EACnB,KAAK,uBAAuB,EAC5B,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,GACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAI/G,OAAO,EACL,oBAAoB,EACpB,oCAAoC,EACpC,4BAA4B,EAC5B,KAAK,WAAW,EAChB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,KAAK,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AACtG,OAAO,EACL,wBAAwB,EACxB,4BAA4B,EAC5B,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,YAAY,EACZ,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AACzG,OAAO,EACL,+BAA+B,EAC/B,KAAK,oBAAoB,EACzB,oBAAoB,GACrB,MAAM,4BAA4B,CAAC;AAIpC,OAAO,EACL,UAAU,EACV,KAAK,gBAAgB,EACrB,qBAAqB,EACrB,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,wBAAwB,GAC9B,MAAM,qCAAqC,CAAC;AAK7C,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,6BAA6B,EAClC,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,iBAAiB,GAClB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,KAAK,eAAe,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAQ1F,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,uBAAuB,EACvB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,sBAAsB,EACtB,KAAK,oBAAoB,EACzB,kBAAkB,EAClB,aAAa,EACb,KAAK,cAAc,EACnB,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,eAAe,EACf,YAAY,EACZ,UAAU,EACV,KAAK,gBAAgB,EACrB,iBAAiB,EACjB,UAAU,GACX,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EACL,mBAAmB,EACnB,KAAK,uBAAuB,EAC5B,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,WAAW,GACZ,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,KAAK,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAI/G,OAAO,EACL,oBAAoB,EACpB,oCAAoC,EACpC,4BAA4B,EAC5B,KAAK,WAAW,EAChB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
- import { ANY_VERIFIED_CALLER, ControlPlaneScope, KEYS_ROTATE_SCOPE, MANIFEST_READ_SCOPE, SEAM_SCOPES } from "./controlPlane/scope/scope.js";
3
+ import { ANY_VERIFIED_CALLER, ControlPlaneScope, KEYS_ROTATE_SCOPE, MANIFEST_READ_SCOPE, MIGRATIONS_READ_SCOPE, PRIVACY_READ_SCOPE, SEAM_SCOPES } from "./controlPlane/scope/scope.js";
4
4
  import { ControlPlaneConfig } from "./controlPlane/config/config.js";
5
5
  import { ControlPlaneConnection, Ed25519PublicJwk, RegisteredKey } from "./controlPlane/data/connection.js";
6
6
  import { CONTROL_PLANE_CONNECTIONS_TABLE, controlPlaneDatabase } from "./controlPlane/data/tables.js";
@@ -16,4 +16,4 @@ import { CONTROL_PLANE_KV_BINDING } from "./controlPlane/replay/kvGuard.js";
16
16
  import { CONTROLPLANE_MIGRATION_ORDER, controlplane, isControlPlaneCapability } from "./controlPlane/capability.js";
17
17
  import { missingAdminRoutes } from "./controlPlane/discovery/drift.js";
18
18
  import { exportPublicJwk, mintControlPlaneToken } from "./controlPlane/token/mint.js";
19
- export { ANY_VERIFIED_CALLER, AdminRoute, CONTROLPLANE_MIGRATION_ORDER, CONTROL_PLANE_CONNECTIONS_TABLE, CONTROL_PLANE_HEADER, CONTROL_PLANE_KV_BINDING, CONTROL_PLANE_VERSION_CREATED_HEADER, CONTROL_PLANE_VERSION_HEADER, CapabilityDeclaration, CapabilityDescriptor, CapabilityHealthReport, ControlPlaneAuditActions, ControlPlaneConfig, ControlPlaneConnection, ControlPlaneContext, ControlPlaneManifest, ControlPlaneScope, Ed25519PublicJwk, HealthCountNominal, HealthNominal, HealthSummary, HealthSummaryKey, HealthSummaryValue, HealthValueCost, HealthValueKind, KEYS_ROTATE_SCOPE, MANIFEST_READ_SCOPE, ManifestConfigKey, ManifestConfigValue, ManifestConfigValues, RegisteredKey, SEAM_SCOPES, capabilityHealthSources, controlPlaneDatabase, controlplane, defineCapabilityHealth, defineManifestConfig, exportPublicJwk, healthAttention, healthReport, healthWire, isControlPlaneCapability, mintControlPlaneToken, missingAdminRoutes, namedConfigValues, namedHealthValues, readCapabilityHealth, requireControlPlane, standingOf, workerBuildChanged };
19
+ export { ANY_VERIFIED_CALLER, AdminRoute, CONTROLPLANE_MIGRATION_ORDER, CONTROL_PLANE_CONNECTIONS_TABLE, CONTROL_PLANE_HEADER, CONTROL_PLANE_KV_BINDING, CONTROL_PLANE_VERSION_CREATED_HEADER, CONTROL_PLANE_VERSION_HEADER, CapabilityDeclaration, CapabilityDescriptor, CapabilityHealthReport, ControlPlaneAuditActions, ControlPlaneConfig, ControlPlaneConnection, ControlPlaneContext, ControlPlaneManifest, ControlPlaneScope, Ed25519PublicJwk, HealthCountNominal, HealthNominal, HealthSummary, HealthSummaryKey, HealthSummaryValue, HealthValueCost, HealthValueKind, KEYS_ROTATE_SCOPE, MANIFEST_READ_SCOPE, MIGRATIONS_READ_SCOPE, ManifestConfigKey, ManifestConfigValue, ManifestConfigValues, PRIVACY_READ_SCOPE, RegisteredKey, SEAM_SCOPES, capabilityHealthSources, controlPlaneDatabase, controlplane, defineCapabilityHealth, defineManifestConfig, exportPublicJwk, healthAttention, healthReport, healthWire, isControlPlaneCapability, mintControlPlaneToken, missingAdminRoutes, namedConfigValues, namedHealthValues, readCapabilityHealth, requireControlPlane, standingOf, workerBuildChanged };
@@ -1,5 +1,6 @@
1
1
  // SPDX-FileCopyrightText: 2026 Pithy
2
2
  // SPDX-License-Identifier: MIT
3
+ import type { Loggable, UnmarkedString } from "../privacy/types";
3
4
  import { type LogFields, type LogLevel, type LogRecord } from "./record";
4
5
  /**
5
6
  * The `Logger` seam. Four levels, each taking a message plus **structured fields** (not a formatted
@@ -11,22 +12,28 @@ import { type LogFields, type LogLevel, type LogRecord } from "./record";
11
12
  * The reserved `error` field on any call may carry a `PithyError` or `ErrorPayload` — the engine lifts
12
13
  * it into the record's `error`, `detail` and all. A log is internal; this is the inverse of the HTTP
13
14
  * codec, which strips `detail`. The logger must never be wired to a client-facing surface.
15
+ *
16
+ * **A value marked with a privacy class does not compile here** (#132). Every method takes `F & Loggable<F>`,
17
+ * so a field holding a `pii()`/`phi()`/`secret()`/`pci()` value — the value itself, or one inside an object or
18
+ * an array, to the depth `privacy/types.ts` states — is refused at that key, and `redact(Schema, value)` is the
19
+ * way through. The message and a child's name take `UnmarkedString`, so `log.info(user.email)` is refused too. `LogFields` the schema stays permissive: a record that reaches a sink at runtime still parses,
20
+ * because a brand is a type and a parsed log line has none.
14
21
  */
15
22
  export interface Logger {
16
23
  /** Dev-time diagnostics. Dropped unless the logger's level is `debug`. */
17
- debug(msg: string, fields?: LogFields): void;
24
+ debug<F extends LogFields = LogFields>(msg: UnmarkedString, fields?: F & Loggable<F>): void;
18
25
  /** Normal operational events. */
19
- info(msg: string, fields?: LogFields): void;
26
+ info<F extends LogFields = LogFields>(msg: UnmarkedString, fields?: F & Loggable<F>): void;
20
27
  /** A recoverable problem worth attention. */
21
- warn(msg: string, fields?: LogFields): void;
28
+ warn<F extends LogFields = LogFields>(msg: UnmarkedString, fields?: F & Loggable<F>): void;
22
29
  /** A failure that was observed. Pass `{ error }` (a PithyError) to carry its full payload. */
23
- error(msg: string, fields?: LogFields): void;
30
+ error<F extends LogFields = LogFields>(msg: UnmarkedString, fields?: F & Loggable<F>): void;
24
31
  /**
25
32
  * A namespaced sub-logger. `name` composes as `parent:child`; bound `fields` merge into every record
26
33
  * the child emits. Omit `name` (pass `undefined`) to bind fields only — how request-correlation
27
34
  * attaches `request`/`method`/`path` without renaming the logger.
28
35
  */
29
- child(name?: string, fields?: LogFields): Logger;
36
+ child<F extends LogFields = LogFields>(name?: UnmarkedString, fields?: F & Loggable<F>): Logger;
30
37
  }
31
38
  /** A sink receives a finished {@link LogRecord}. Adapters supply one; the engine builds records and calls it. */
32
39
  export type LogSink = (record: LogRecord) => void;
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/logger/logger.ts"],"names":[],"mappings":"AAKA,OAAO,EAAmB,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1F;;;;;;;;;;GAUG;AACH,MAAM,WAAW,MAAM;IACrB,0EAA0E;IAC1E,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7C,iCAAiC;IACjC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5C,6CAA6C;IAC7C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC5C,8FAA8F;IAC9F,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAC7C;;;;OAIG;IACH,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;CAClD;AAED,iHAAiH;AACjH,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;AAElD,2GAA2G;AAC3G,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,KAAK,EAAE,QAAQ,CAAC;IAChB,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAoED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAQjE;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,MAMxB,CAAC"}
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/logger/logger.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAmB,KAAK,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1F;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,MAAM;IACrB,0EAA0E;IAC1E,KAAK,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC5F,iCAAiC;IACjC,IAAI,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC3F,6CAA6C;IAC7C,IAAI,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC3F,8FAA8F;IAC9F,KAAK,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAAE,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAC5F;;;;OAIG;IACH,KAAK,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,EAAE,IAAI,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;CACjG;AAED,iHAAiH;AACjH,MAAM,MAAM,OAAO,GAAG,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI,CAAC;AAElD,2GAA2G;AAC3G,MAAM,WAAW,mBAAmB;IAClC,mDAAmD;IACnD,KAAK,EAAE,QAAQ,CAAC;IAChB,iCAAiC;IACjC,IAAI,EAAE,OAAO,CAAC;IACd,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wDAAwD;IACxD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAoED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAQjE;AAED;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,MAMxB,CAAC"}