@wildo-ai/saas-models 1.1.2 → 1.1.3

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 (410) hide show
  1. package/dist/esm/applications/applications-context.schemas.d.ts +14 -10
  2. package/dist/esm/applications/applications-context.schemas.d.ts.map +1 -1
  3. package/dist/esm/applications/applications.shared.resources-config.schemas.d.ts.map +1 -1
  4. package/dist/esm/applications/applications.shared.resources-config.schemas.js +4 -3
  5. package/dist/esm/applications/applications.shared.resources-config.schemas.js.map +1 -1
  6. package/dist/esm/billing/billing-configuration.shared.schemas.d.ts +0 -4
  7. package/dist/esm/billing/billing-configuration.shared.schemas.d.ts.map +1 -1
  8. package/dist/esm/billing/billing-configuration.shared.schemas.js +59 -17
  9. package/dist/esm/billing/billing-configuration.shared.schemas.js.map +1 -1
  10. package/dist/esm/billing/billing-enums.shared.schemas.d.ts +77 -21
  11. package/dist/esm/billing/billing-enums.shared.schemas.d.ts.map +1 -1
  12. package/dist/esm/billing/billing-enums.shared.schemas.js +85 -23
  13. package/dist/esm/billing/billing-enums.shared.schemas.js.map +1 -1
  14. package/dist/esm/billing/billing-types.shared.schemas.d.ts +3 -3
  15. package/dist/esm/billing/price.shared.schemas.d.ts.map +1 -1
  16. package/dist/esm/billing/price.shared.schemas.js +7 -1
  17. package/dist/esm/billing/price.shared.schemas.js.map +1 -1
  18. package/dist/esm/billing/product-behavior-policy.shared.schemas.d.ts.map +1 -1
  19. package/dist/esm/billing/product-behavior-policy.shared.schemas.js +52 -11
  20. package/dist/esm/billing/product-behavior-policy.shared.schemas.js.map +1 -1
  21. package/dist/esm/billing/product-definition.shared.schemas.d.ts +2 -2
  22. package/dist/esm/billing/product.shared.resources-config.schemas.d.ts +2 -2
  23. package/dist/esm/billing/product.shared.schemas.d.ts +2 -2
  24. package/dist/esm/billing/product.shared.schemas.d.ts.map +1 -1
  25. package/dist/esm/billing/product.shared.schemas.js +7 -3
  26. package/dist/esm/billing/product.shared.schemas.js.map +1 -1
  27. package/dist/esm/billing/subscription.shared.resources-config.schemas.d.ts +1 -1
  28. package/dist/esm/billing/subscription.shared.resources-config.schemas.d.ts.map +1 -1
  29. package/dist/esm/billing/subscription.shared.resources-config.schemas.js +15 -1
  30. package/dist/esm/billing/subscription.shared.resources-config.schemas.js.map +1 -1
  31. package/dist/esm/billing/usage-record.shared.schemas.d.ts +7 -3
  32. package/dist/esm/billing/usage-record.shared.schemas.d.ts.map +1 -1
  33. package/dist/esm/billing/usage-record.shared.schemas.js +22 -3
  34. package/dist/esm/billing/usage-record.shared.schemas.js.map +1 -1
  35. package/dist/esm/companion/provider-discovery.shared.schemas.d.ts +69 -2
  36. package/dist/esm/companion/provider-discovery.shared.schemas.d.ts.map +1 -1
  37. package/dist/esm/companion/provider-discovery.shared.schemas.js +20 -1
  38. package/dist/esm/companion/provider-discovery.shared.schemas.js.map +1 -1
  39. package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.d.ts +85 -0
  40. package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.d.ts.map +1 -0
  41. package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.js +157 -0
  42. package/dist/esm/compliance/audit-trails/application-audit-logs.shared.resources-config.schemas.js.map +1 -0
  43. package/dist/esm/compliance/audit-trails/audit-trail-config.shared.schemas.d.ts +23 -0
  44. package/dist/esm/compliance/audit-trails/audit-trail-config.shared.schemas.d.ts.map +1 -1
  45. package/dist/esm/compliance/audit-trails/audit-trail-config.shared.schemas.js +56 -0
  46. package/dist/esm/compliance/audit-trails/audit-trail-config.shared.schemas.js.map +1 -1
  47. package/dist/esm/compliance/audit-trails/auditable-events.shared.schema.d.ts +480 -20
  48. package/dist/esm/compliance/audit-trails/auditable-events.shared.schema.d.ts.map +1 -1
  49. package/dist/esm/compliance/audit-trails/auditable-events.shared.schema.js +547 -23
  50. package/dist/esm/compliance/audit-trails/auditable-events.shared.schema.js.map +1 -1
  51. package/dist/esm/compliance/audit-trails/security-audit-event-envelope.shared.schema.d.ts.map +1 -1
  52. package/dist/esm/compliance/audit-trails/security-audit-event-envelope.shared.schema.js +82 -3
  53. package/dist/esm/compliance/audit-trails/security-audit-event-envelope.shared.schema.js.map +1 -1
  54. package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.d.ts +31 -30
  55. package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.d.ts.map +1 -1
  56. package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.js +98 -3
  57. package/dist/esm/compliance/privacy/operating-jurisdictions.shared.schemas.js.map +1 -1
  58. package/dist/esm/compliance/privacy/privacy.shared.schemas.d.ts +17 -0
  59. package/dist/esm/compliance/privacy/privacy.shared.schemas.d.ts.map +1 -1
  60. package/dist/esm/compliance/privacy/privacy.shared.schemas.js +27 -4
  61. package/dist/esm/compliance/privacy/privacy.shared.schemas.js.map +1 -1
  62. package/dist/esm/compliance/privacy/redaction.shared.schemas.d.ts +82 -29
  63. package/dist/esm/compliance/privacy/redaction.shared.schemas.d.ts.map +1 -1
  64. package/dist/esm/compliance/privacy/redaction.shared.schemas.js +95 -29
  65. package/dist/esm/compliance/privacy/redaction.shared.schemas.js.map +1 -1
  66. package/dist/esm/compliance/privacy/subject-export.shared.schemas.d.ts.map +1 -1
  67. package/dist/esm/compliance/privacy/subject-export.shared.schemas.js +12 -5
  68. package/dist/esm/compliance/privacy/subject-export.shared.schemas.js.map +1 -1
  69. package/dist/esm/config/analytics-value-moments.shared.schemas.d.ts +21 -0
  70. package/dist/esm/config/analytics-value-moments.shared.schemas.d.ts.map +1 -1
  71. package/dist/esm/config/analytics-value-moments.shared.schemas.js +20 -0
  72. package/dist/esm/config/analytics-value-moments.shared.schemas.js.map +1 -1
  73. package/dist/esm/config/app-configuration-shared.shared.schemas.d.ts +7 -5
  74. package/dist/esm/config/app-configuration-shared.shared.schemas.d.ts.map +1 -1
  75. package/dist/esm/config/auth-config-resolution.shared.utils.d.ts +8 -1
  76. package/dist/esm/config/auth-config-resolution.shared.utils.d.ts.map +1 -1
  77. package/dist/esm/config/auth-config-resolution.shared.utils.js +29 -0
  78. package/dist/esm/config/auth-config-resolution.shared.utils.js.map +1 -1
  79. package/dist/esm/config/entity-identity-config.shared.schemas.d.ts +95 -17
  80. package/dist/esm/config/entity-identity-config.shared.schemas.d.ts.map +1 -1
  81. package/dist/esm/config/entity-identity-config.shared.schemas.js +86 -8
  82. package/dist/esm/config/entity-identity-config.shared.schemas.js.map +1 -1
  83. package/dist/esm/config/frontend/chart-definition.shared.schemas.d.ts +12 -12
  84. package/dist/esm/errors/errors.custom-message-ref.shared.definitions.d.ts +28 -0
  85. package/dist/esm/errors/errors.custom-message-ref.shared.definitions.d.ts.map +1 -1
  86. package/dist/esm/errors/errors.custom-message-ref.shared.definitions.js +28 -0
  87. package/dist/esm/errors/errors.custom-message-ref.shared.definitions.js.map +1 -1
  88. package/dist/esm/external-data/external-data-pipeline.shared.schemas.d.ts +45 -12
  89. package/dist/esm/external-data/external-data-pipeline.shared.schemas.d.ts.map +1 -1
  90. package/dist/esm/external-data/external-data-pipeline.shared.schemas.js.map +1 -1
  91. package/dist/esm/external-providers/engine-capabilities.shared.schemas.d.ts +103 -58
  92. package/dist/esm/external-providers/engine-capabilities.shared.schemas.d.ts.map +1 -1
  93. package/dist/esm/external-providers/engine-capabilities.shared.schemas.js +176 -15
  94. package/dist/esm/external-providers/engine-capabilities.shared.schemas.js.map +1 -1
  95. package/dist/esm/external-providers/engine-capability-resolution-mode.shared.d.ts +15 -3
  96. package/dist/esm/external-providers/engine-capability-resolution-mode.shared.d.ts.map +1 -1
  97. package/dist/esm/external-providers/engine-capability-resolution-mode.shared.js +32 -5
  98. package/dist/esm/external-providers/engine-capability-resolution-mode.shared.js.map +1 -1
  99. package/dist/esm/external-providers/frontend-bootstrap.shared.schemas.d.ts +83 -7
  100. package/dist/esm/external-providers/frontend-bootstrap.shared.schemas.d.ts.map +1 -1
  101. package/dist/esm/external-providers/frontend-capability-public-config.shared.schemas.d.ts +59 -0
  102. package/dist/esm/external-providers/frontend-capability-public-config.shared.schemas.d.ts.map +1 -0
  103. package/dist/esm/external-providers/frontend-capability-public-config.shared.schemas.js +61 -0
  104. package/dist/esm/external-providers/frontend-capability-public-config.shared.schemas.js.map +1 -0
  105. package/dist/esm/external-providers/frontend-capability-runtime.shared.types.d.ts +97 -0
  106. package/dist/esm/external-providers/frontend-capability-runtime.shared.types.d.ts.map +1 -0
  107. package/dist/esm/external-providers/frontend-capability-runtime.shared.types.js +41 -0
  108. package/dist/esm/external-providers/frontend-capability-runtime.shared.types.js.map +1 -0
  109. package/dist/esm/external-providers/frontend-provider-entry.shared.schemas.d.ts +148 -2
  110. package/dist/esm/external-providers/frontend-provider-entry.shared.schemas.d.ts.map +1 -1
  111. package/dist/esm/external-providers/frontend-provider-entry.shared.schemas.js +56 -1
  112. package/dist/esm/external-providers/frontend-provider-entry.shared.schemas.js.map +1 -1
  113. package/dist/esm/external-providers/provider-capability.shared.schemas.d.ts +5 -28
  114. package/dist/esm/external-providers/provider-capability.shared.schemas.d.ts.map +1 -1
  115. package/dist/esm/external-providers/provider-capability.shared.schemas.js +4 -2
  116. package/dist/esm/external-providers/provider-capability.shared.schemas.js.map +1 -1
  117. package/dist/esm/external-providers/provider-compliance-profile.shared.schemas.d.ts +18 -8
  118. package/dist/esm/external-providers/provider-compliance-profile.shared.schemas.d.ts.map +1 -1
  119. package/dist/esm/external-providers/provider-compliance-profile.shared.schemas.js +9 -4
  120. package/dist/esm/external-providers/provider-compliance-profile.shared.schemas.js.map +1 -1
  121. package/dist/esm/external-providers/provider-frontend-surface.shared.schemas.d.ts +338 -0
  122. package/dist/esm/external-providers/provider-frontend-surface.shared.schemas.d.ts.map +1 -0
  123. package/dist/esm/external-providers/provider-frontend-surface.shared.schemas.js +332 -0
  124. package/dist/esm/external-providers/provider-frontend-surface.shared.schemas.js.map +1 -0
  125. package/dist/esm/external-providers/provider-metadata.shared.schemas.d.ts +178 -9
  126. package/dist/esm/external-providers/provider-metadata.shared.schemas.d.ts.map +1 -1
  127. package/dist/esm/external-providers/provider-metadata.shared.schemas.js +181 -9
  128. package/dist/esm/external-providers/provider-metadata.shared.schemas.js.map +1 -1
  129. package/dist/esm/external-providers/provider-protocol.shared.schemas.d.ts +7 -5
  130. package/dist/esm/external-providers/provider-protocol.shared.schemas.d.ts.map +1 -1
  131. package/dist/esm/external-providers/provider-protocol.shared.schemas.js +7 -5
  132. package/dist/esm/external-providers/provider-protocol.shared.schemas.js.map +1 -1
  133. package/dist/esm/external-providers/provider-tier-rule.shared.utils.d.ts +40 -0
  134. package/dist/esm/external-providers/provider-tier-rule.shared.utils.d.ts.map +1 -0
  135. package/dist/esm/external-providers/provider-tier-rule.shared.utils.js +80 -0
  136. package/dist/esm/external-providers/provider-tier-rule.shared.utils.js.map +1 -0
  137. package/dist/esm/features/core-feature-definitions.shared.d.ts.map +1 -1
  138. package/dist/esm/features/core-feature-definitions.shared.js +7 -1
  139. package/dist/esm/features/core-feature-definitions.shared.js.map +1 -1
  140. package/dist/esm/features/feature-builders.shared.d.ts +32 -0
  141. package/dist/esm/features/feature-builders.shared.d.ts.map +1 -1
  142. package/dist/esm/features/feature-builders.shared.js +32 -0
  143. package/dist/esm/features/feature-builders.shared.js.map +1 -1
  144. package/dist/esm/files/file-upload-grant.shared.schemas.d.ts +14 -2
  145. package/dist/esm/files/file-upload-grant.shared.schemas.d.ts.map +1 -1
  146. package/dist/esm/files/file-upload-grant.shared.schemas.js +44 -5
  147. package/dist/esm/files/file-upload-grant.shared.schemas.js.map +1 -1
  148. package/dist/esm/files/files.shared.schemas.d.ts +15 -8
  149. package/dist/esm/files/files.shared.schemas.d.ts.map +1 -1
  150. package/dist/esm/files/files.shared.schemas.js +15 -8
  151. package/dist/esm/files/files.shared.schemas.js.map +1 -1
  152. package/dist/esm/flows-actors/actors.shared.schemas.d.ts.map +1 -1
  153. package/dist/esm/flows-actors/actors.shared.schemas.js +3 -2
  154. package/dist/esm/flows-actors/actors.shared.schemas.js.map +1 -1
  155. package/dist/esm/flows-actors/agents.shared.schemas.d.ts +54 -5
  156. package/dist/esm/flows-actors/agents.shared.schemas.d.ts.map +1 -1
  157. package/dist/esm/flows-actors/agents.shared.schemas.js.map +1 -1
  158. package/dist/esm/flows-actors/apps-blueprint/apps-blueprint.shared.schemas.d.ts +6 -6
  159. package/dist/esm/flows-actors/deliberation.shared.schemas.d.ts +0 -3
  160. package/dist/esm/flows-actors/deliberation.shared.schemas.d.ts.map +1 -1
  161. package/dist/esm/flows-actors/deliberation.shared.schemas.js +0 -5
  162. package/dist/esm/flows-actors/deliberation.shared.schemas.js.map +1 -1
  163. package/dist/esm/flows-actors/flows-actors-execution.shared.schemas.d.ts +14 -0
  164. package/dist/esm/flows-actors/flows-actors-execution.shared.schemas.d.ts.map +1 -1
  165. package/dist/esm/flows-actors/flows-actors-execution.shared.schemas.js +40 -3
  166. package/dist/esm/flows-actors/flows-actors-execution.shared.schemas.js.map +1 -1
  167. package/dist/esm/flows-actors/flows-actors.commons.shared.schemas.d.ts +19 -0
  168. package/dist/esm/flows-actors/flows-actors.commons.shared.schemas.d.ts.map +1 -1
  169. package/dist/esm/flows-actors/flows-actors.commons.shared.schemas.js +33 -0
  170. package/dist/esm/flows-actors/flows-actors.commons.shared.schemas.js.map +1 -1
  171. package/dist/esm/flows-actors/flows-actors.io.shared.schemas.d.ts +14 -9
  172. package/dist/esm/flows-actors/flows-actors.io.shared.schemas.d.ts.map +1 -1
  173. package/dist/esm/flows-actors/flows-actors.io.shared.schemas.js +14 -9
  174. package/dist/esm/flows-actors/flows-actors.io.shared.schemas.js.map +1 -1
  175. package/dist/esm/flows-actors/flows-actors.system.shared.schemas.d.ts.map +1 -1
  176. package/dist/esm/flows-actors/flows-actors.system.shared.schemas.js +3 -2
  177. package/dist/esm/flows-actors/flows-actors.system.shared.schemas.js.map +1 -1
  178. package/dist/esm/flows-actors/flows.shared.schemas.d.ts.map +1 -1
  179. package/dist/esm/flows-actors/flows.shared.schemas.js +3 -2
  180. package/dist/esm/flows-actors/flows.shared.schemas.js.map +1 -1
  181. package/dist/esm/flows-actors/mcp-servers.shared.schemas.d.ts +128 -0
  182. package/dist/esm/flows-actors/mcp-servers.shared.schemas.d.ts.map +1 -0
  183. package/dist/esm/flows-actors/mcp-servers.shared.schemas.js +142 -0
  184. package/dist/esm/flows-actors/mcp-servers.shared.schemas.js.map +1 -0
  185. package/dist/esm/flows-actors/meta-workflows/budget-authority.meta-workflows.shared.schemas.d.ts +0 -3
  186. package/dist/esm/flows-actors/meta-workflows/budget-authority.meta-workflows.shared.schemas.d.ts.map +1 -1
  187. package/dist/esm/flows-actors/meta-workflows/budget-authority.meta-workflows.shared.schemas.js +1 -4
  188. package/dist/esm/flows-actors/meta-workflows/budget-authority.meta-workflows.shared.schemas.js.map +1 -1
  189. package/dist/esm/flows-actors/meta-workflows/context-selection.meta-workflows.shared.schemas.d.ts +0 -16
  190. package/dist/esm/flows-actors/meta-workflows/context-selection.meta-workflows.shared.schemas.d.ts.map +1 -1
  191. package/dist/esm/flows-actors/meta-workflows/context-selection.meta-workflows.shared.schemas.js +1 -17
  192. package/dist/esm/flows-actors/meta-workflows/context-selection.meta-workflows.shared.schemas.js.map +1 -1
  193. package/dist/esm/flows-actors/meta-workflows/decisions.meta-workflows.shared.schemas.d.ts +3 -3
  194. package/dist/esm/flows-actors/meta-workflows/decisions.meta-workflows.shared.schemas.js +3 -3
  195. package/dist/esm/flows-actors/meta-workflows/decisions.meta-workflows.shared.schemas.js.map +1 -1
  196. package/dist/esm/flows-actors/meta-workflows/execution-binding-common.meta-workflows.shared.schemas.d.ts +2 -8
  197. package/dist/esm/flows-actors/meta-workflows/execution-binding-common.meta-workflows.shared.schemas.d.ts.map +1 -1
  198. package/dist/esm/flows-actors/meta-workflows/execution-binding-common.meta-workflows.shared.schemas.js +4 -15
  199. package/dist/esm/flows-actors/meta-workflows/execution-binding-common.meta-workflows.shared.schemas.js.map +1 -1
  200. package/dist/esm/guidance/guidance-state.shared.utils.d.ts.map +1 -1
  201. package/dist/esm/guidance/guidance-state.shared.utils.js +1 -0
  202. package/dist/esm/guidance/guidance-state.shared.utils.js.map +1 -1
  203. package/dist/esm/guidance/progression-state.shared.resources-config.schemas.d.ts +8 -0
  204. package/dist/esm/guidance/progression-state.shared.resources-config.schemas.d.ts.map +1 -1
  205. package/dist/esm/guidance/progression-state.shared.schemas.d.ts +46 -0
  206. package/dist/esm/guidance/progression-state.shared.schemas.d.ts.map +1 -1
  207. package/dist/esm/guidance/progression-state.shared.schemas.js +49 -0
  208. package/dist/esm/guidance/progression-state.shared.schemas.js.map +1 -1
  209. package/dist/esm/http-api-binding/http-api-binding.shared.schemas.d.ts +320 -50
  210. package/dist/esm/http-api-binding/http-api-binding.shared.schemas.d.ts.map +1 -1
  211. package/dist/esm/http-api-binding/http-api-binding.shared.schemas.js +137 -36
  212. package/dist/esm/http-api-binding/http-api-binding.shared.schemas.js.map +1 -1
  213. package/dist/esm/index.d.ts +9 -0
  214. package/dist/esm/index.d.ts.map +1 -1
  215. package/dist/esm/index.js +9 -0
  216. package/dist/esm/index.js.map +1 -1
  217. package/dist/esm/notifications/email/email-template-registry.shared.schemas.d.ts +11 -2
  218. package/dist/esm/notifications/email/email-template-registry.shared.schemas.d.ts.map +1 -1
  219. package/dist/esm/notifications/email/email-template-registry.shared.schemas.js.map +1 -1
  220. package/dist/esm/notifications/email/email-template.shared.enums.d.ts +15 -0
  221. package/dist/esm/notifications/email/email-template.shared.enums.d.ts.map +1 -1
  222. package/dist/esm/notifications/email/email-template.shared.enums.js +15 -0
  223. package/dist/esm/notifications/email/email-template.shared.enums.js.map +1 -1
  224. package/dist/esm/notifications/m2m/webhook-config.shared.resources-config.schemas.d.ts +1 -0
  225. package/dist/esm/notifications/m2m/webhook-config.shared.resources-config.schemas.d.ts.map +1 -1
  226. package/dist/esm/notifications/m2m/webhook-config.shared.resources-config.schemas.js +19 -0
  227. package/dist/esm/notifications/m2m/webhook-config.shared.resources-config.schemas.js.map +1 -1
  228. package/dist/esm/notifications/m2m/webhook-config.shared.schemas.d.ts +30 -0
  229. package/dist/esm/notifications/m2m/webhook-config.shared.schemas.d.ts.map +1 -1
  230. package/dist/esm/notifications/m2m/webhook-config.shared.schemas.js +65 -1
  231. package/dist/esm/notifications/m2m/webhook-config.shared.schemas.js.map +1 -1
  232. package/dist/esm/notifications/notification-badges.core.definitions.d.ts +6 -4
  233. package/dist/esm/notifications/notification-badges.core.definitions.d.ts.map +1 -1
  234. package/dist/esm/notifications/notification-badges.core.definitions.js +6 -4
  235. package/dist/esm/notifications/notification-badges.core.definitions.js.map +1 -1
  236. package/dist/esm/notifications/notification-badges.schemas.d.ts +167 -5
  237. package/dist/esm/notifications/notification-badges.schemas.d.ts.map +1 -1
  238. package/dist/esm/notifications/notification-badges.schemas.js +191 -6
  239. package/dist/esm/notifications/notification-badges.schemas.js.map +1 -1
  240. package/dist/esm/notifications/notifications.shared.schemas.d.ts +107 -0
  241. package/dist/esm/notifications/notifications.shared.schemas.d.ts.map +1 -1
  242. package/dist/esm/notifications/notifications.shared.schemas.js +149 -1
  243. package/dist/esm/notifications/notifications.shared.schemas.js.map +1 -1
  244. package/dist/esm/organizations/organization-notifications.shared.schemas.d.ts.map +1 -1
  245. package/dist/esm/organizations/organization-notifications.shared.schemas.js +22 -1
  246. package/dist/esm/organizations/organization-notifications.shared.schemas.js.map +1 -1
  247. package/dist/esm/organizations/organization-preferences.shared.schemas.d.ts +26 -0
  248. package/dist/esm/organizations/organization-preferences.shared.schemas.d.ts.map +1 -1
  249. package/dist/esm/organizations/organization-preferences.shared.schemas.js +25 -0
  250. package/dist/esm/organizations/organization-preferences.shared.schemas.js.map +1 -1
  251. package/dist/esm/organizations/organization-profile.shared.schemas.d.ts +25 -0
  252. package/dist/esm/organizations/organization-profile.shared.schemas.d.ts.map +1 -1
  253. package/dist/esm/organizations/organization-profile.shared.schemas.js +42 -17
  254. package/dist/esm/organizations/organization-profile.shared.schemas.js.map +1 -1
  255. package/dist/esm/organizations/organization-unit-narrowing.shared.d.ts +3 -2
  256. package/dist/esm/organizations/organization-unit-narrowing.shared.d.ts.map +1 -1
  257. package/dist/esm/organizations/organization-unit-narrowing.shared.js +9 -2
  258. package/dist/esm/organizations/organization-unit-narrowing.shared.js.map +1 -1
  259. package/dist/esm/organizations/organizations.shared.resources-config.schemas.d.ts.map +1 -1
  260. package/dist/esm/organizations/organizations.shared.resources-config.schemas.js +18 -3
  261. package/dist/esm/organizations/organizations.shared.resources-config.schemas.js.map +1 -1
  262. package/dist/esm/public-runtime/index.d.ts +49 -2
  263. package/dist/esm/public-runtime/index.d.ts.map +1 -1
  264. package/dist/esm/public-runtime/index.js +48 -1
  265. package/dist/esm/public-runtime/index.js.map +1 -1
  266. package/dist/esm/queue/jobs.shared.resources-config.schemas.d.ts +6 -5
  267. package/dist/esm/queue/jobs.shared.resources-config.schemas.d.ts.map +1 -1
  268. package/dist/esm/queue/jobs.shared.resources-config.schemas.js +6 -5
  269. package/dist/esm/queue/jobs.shared.resources-config.schemas.js.map +1 -1
  270. package/dist/esm/queue/jobs.shared.schemas.d.ts +16 -3
  271. package/dist/esm/queue/jobs.shared.schemas.d.ts.map +1 -1
  272. package/dist/esm/queue/jobs.shared.schemas.js +16 -3
  273. package/dist/esm/queue/jobs.shared.schemas.js.map +1 -1
  274. package/dist/esm/requests/manual-controllers-routes-documentation.d.ts +137 -0
  275. package/dist/esm/requests/manual-controllers-routes-documentation.d.ts.map +1 -0
  276. package/dist/esm/requests/manual-controllers-routes-documentation.js +1201 -0
  277. package/dist/esm/requests/manual-controllers-routes-documentation.js.map +1 -0
  278. package/dist/esm/requests/manual-controllers-routes-urls.d.ts +67 -0
  279. package/dist/esm/requests/manual-controllers-routes-urls.d.ts.map +1 -1
  280. package/dist/esm/requests/manual-controllers-routes-urls.js +78 -0
  281. package/dist/esm/requests/manual-controllers-routes-urls.js.map +1 -1
  282. package/dist/esm/requests/rate-limits.shared.schemas.d.ts +11 -1
  283. package/dist/esm/requests/rate-limits.shared.schemas.d.ts.map +1 -1
  284. package/dist/esm/requests/rate-limits.shared.schemas.js +11 -1
  285. package/dist/esm/requests/rate-limits.shared.schemas.js.map +1 -1
  286. package/dist/esm/requests/websocket.shared.schemas.d.ts +27 -4
  287. package/dist/esm/requests/websocket.shared.schemas.d.ts.map +1 -1
  288. package/dist/esm/requests/websocket.shared.schemas.js +35 -0
  289. package/dist/esm/requests/websocket.shared.schemas.js.map +1 -1
  290. package/dist/esm/resources/resources-config.shared.factory.d.ts +1 -0
  291. package/dist/esm/resources/resources-config.shared.factory.d.ts.map +1 -1
  292. package/dist/esm/resources/resources-config.shared.factory.js +105 -20
  293. package/dist/esm/resources/resources-config.shared.factory.js.map +1 -1
  294. package/dist/esm/resources/resources-config.shared.schemas.d.ts +254 -72
  295. package/dist/esm/resources/resources-config.shared.schemas.d.ts.map +1 -1
  296. package/dist/esm/resources/resources-config.shared.schemas.js.map +1 -1
  297. package/dist/esm/resources/resources-registry.shared.core.definitions.d.ts.map +1 -1
  298. package/dist/esm/resources/resources-registry.shared.core.definitions.js +97 -5
  299. package/dist/esm/resources/resources-registry.shared.core.definitions.js.map +1 -1
  300. package/dist/esm/resources/resources-relationships.shared.factory.d.ts.map +1 -1
  301. package/dist/esm/resources/resources-relationships.shared.factory.js +15 -0
  302. package/dist/esm/resources/resources-relationships.shared.factory.js.map +1 -1
  303. package/dist/esm/resources/resources.shared.core.definitions.d.ts +37 -0
  304. package/dist/esm/resources/resources.shared.core.definitions.d.ts.map +1 -1
  305. package/dist/esm/resources/resources.shared.core.definitions.js +51 -0
  306. package/dist/esm/resources/resources.shared.core.definitions.js.map +1 -1
  307. package/dist/esm/resources/resources.shared.schemas.d.ts +11 -2
  308. package/dist/esm/resources/resources.shared.schemas.d.ts.map +1 -1
  309. package/dist/esm/resources/resources.shared.schemas.js +34 -3
  310. package/dist/esm/resources/resources.shared.schemas.js.map +1 -1
  311. package/dist/esm/resources/utils/field-value-disclosure.utils.d.ts +51 -0
  312. package/dist/esm/resources/utils/field-value-disclosure.utils.d.ts.map +1 -0
  313. package/dist/esm/resources/utils/field-value-disclosure.utils.js +53 -0
  314. package/dist/esm/resources/utils/field-value-disclosure.utils.js.map +1 -0
  315. package/dist/esm/resources/utils/resources-summary.utils.d.ts +16 -2
  316. package/dist/esm/resources/utils/resources-summary.utils.d.ts.map +1 -1
  317. package/dist/esm/resources/utils/resources-summary.utils.js +19 -5
  318. package/dist/esm/resources/utils/resources-summary.utils.js.map +1 -1
  319. package/dist/esm/resources/utils/shared-persistence-collection.utils.d.ts.map +1 -1
  320. package/dist/esm/resources/utils/shared-persistence-collection.utils.js +11 -0
  321. package/dist/esm/resources/utils/shared-persistence-collection.utils.js.map +1 -1
  322. package/dist/esm/runtime/domain-module.shared.definitions.d.ts +25 -0
  323. package/dist/esm/runtime/domain-module.shared.definitions.d.ts.map +1 -1
  324. package/dist/esm/runtime/domain-module.shared.definitions.js.map +1 -1
  325. package/dist/esm/security/api-keys/api-keys-application.shared.resources-config.schemas.d.ts +1 -0
  326. package/dist/esm/security/api-keys/api-keys-application.shared.resources-config.schemas.d.ts.map +1 -1
  327. package/dist/esm/security/api-keys/api-keys-application.shared.resources-config.schemas.js +38 -0
  328. package/dist/esm/security/api-keys/api-keys-application.shared.resources-config.schemas.js.map +1 -1
  329. package/dist/esm/security/api-keys/api-keys-organization.shared.resources-config.schemas.d.ts +1 -0
  330. package/dist/esm/security/api-keys/api-keys-organization.shared.resources-config.schemas.d.ts.map +1 -1
  331. package/dist/esm/security/api-keys/api-keys-organization.shared.resources-config.schemas.js +38 -0
  332. package/dist/esm/security/api-keys/api-keys-organization.shared.resources-config.schemas.js.map +1 -1
  333. package/dist/esm/security/authentications/authentication.shared.dto.schemas.d.ts +4 -11
  334. package/dist/esm/security/authentications/authentication.shared.dto.schemas.d.ts.map +1 -1
  335. package/dist/esm/security/authentications/authentication.shared.dto.schemas.js +0 -1
  336. package/dist/esm/security/authentications/authentication.shared.dto.schemas.js.map +1 -1
  337. package/dist/esm/security/authentications/authentication.shared.schemas.d.ts +84 -5
  338. package/dist/esm/security/authentications/authentication.shared.schemas.d.ts.map +1 -1
  339. package/dist/esm/security/authentications/authentication.shared.schemas.js +83 -3
  340. package/dist/esm/security/authentications/authentication.shared.schemas.js.map +1 -1
  341. package/dist/esm/security/authentications/registration.shared.dto.schemas.d.ts +1 -0
  342. package/dist/esm/security/authentications/registration.shared.dto.schemas.d.ts.map +1 -1
  343. package/dist/esm/security/authentications/registration.shared.dto.schemas.js +11 -0
  344. package/dist/esm/security/authentications/registration.shared.dto.schemas.js.map +1 -1
  345. package/dist/esm/security/authentications/scim/scim-provisioning-config.shared.schemas.d.ts +15 -0
  346. package/dist/esm/security/authentications/scim/scim-provisioning-config.shared.schemas.d.ts.map +1 -1
  347. package/dist/esm/security/authentications/scim/scim-provisioning-config.shared.schemas.js +21 -4
  348. package/dist/esm/security/authentications/scim/scim-provisioning-config.shared.schemas.js.map +1 -1
  349. package/dist/esm/security/authentications/sso/sso-config.shared.resources-config.schemas.d.ts +61 -1
  350. package/dist/esm/security/authentications/sso/sso-config.shared.resources-config.schemas.d.ts.map +1 -1
  351. package/dist/esm/security/authentications/sso/sso-config.shared.resources-config.schemas.js +208 -6
  352. package/dist/esm/security/authentications/sso/sso-config.shared.resources-config.schemas.js.map +1 -1
  353. package/dist/esm/security/authentications/sso/sso-config.shared.schemas.d.ts +37 -27
  354. package/dist/esm/security/authentications/sso/sso-config.shared.schemas.d.ts.map +1 -1
  355. package/dist/esm/security/authentications/sso/sso-config.shared.schemas.js +134 -12
  356. package/dist/esm/security/authentications/sso/sso-config.shared.schemas.js.map +1 -1
  357. package/dist/esm/security/authentications/sso/sso-connection.shared.schemas.d.ts +0 -6
  358. package/dist/esm/security/authentications/sso/sso-connection.shared.schemas.d.ts.map +1 -1
  359. package/dist/esm/security/authentications/sso/sso-connection.shared.schemas.js +17 -8
  360. package/dist/esm/security/authentications/sso/sso-connection.shared.schemas.js.map +1 -1
  361. package/dist/esm/security/authorizations/platform-access-grants.shared.resources-config.schemas.d.ts.map +1 -1
  362. package/dist/esm/security/authorizations/platform-access-grants.shared.resources-config.schemas.js +27 -0
  363. package/dist/esm/security/authorizations/platform-access-grants.shared.resources-config.schemas.js.map +1 -1
  364. package/dist/esm/security/authorizations/platform-access-grants.shared.schemas.d.ts +52 -7
  365. package/dist/esm/security/authorizations/platform-access-grants.shared.schemas.d.ts.map +1 -1
  366. package/dist/esm/security/authorizations/platform-access-grants.shared.schemas.js +45 -8
  367. package/dist/esm/security/authorizations/platform-access-grants.shared.schemas.js.map +1 -1
  368. package/dist/esm/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.d.ts +31 -0
  369. package/dist/esm/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.d.ts.map +1 -0
  370. package/dist/esm/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.js +198 -0
  371. package/dist/esm/security/connected-accounts/provider-credentials-organization.shared.resources-config.schemas.js.map +1 -0
  372. package/dist/esm/security/connected-accounts/provider-credentials-user.shared.resources-config.schemas.d.ts +31 -0
  373. package/dist/esm/security/connected-accounts/provider-credentials-user.shared.resources-config.schemas.d.ts.map +1 -0
  374. package/dist/esm/security/connected-accounts/provider-credentials-user.shared.resources-config.schemas.js +191 -0
  375. package/dist/esm/security/connected-accounts/provider-credentials-user.shared.resources-config.schemas.js.map +1 -0
  376. package/dist/esm/security/connected-accounts/provider-credentials.shared.schemas.d.ts +250 -0
  377. package/dist/esm/security/connected-accounts/provider-credentials.shared.schemas.d.ts.map +1 -0
  378. package/dist/esm/security/connected-accounts/provider-credentials.shared.schemas.js +486 -0
  379. package/dist/esm/security/connected-accounts/provider-credentials.shared.schemas.js.map +1 -0
  380. package/dist/esm/security/oauth-clients/oauth-clients-application.shared.resources-config.schemas.d.ts +4 -1
  381. package/dist/esm/security/oauth-clients/oauth-clients-application.shared.resources-config.schemas.d.ts.map +1 -1
  382. package/dist/esm/security/oauth-clients/oauth-clients-application.shared.resources-config.schemas.js +29 -0
  383. package/dist/esm/security/oauth-clients/oauth-clients-application.shared.resources-config.schemas.js.map +1 -1
  384. package/dist/esm/security/oauth-clients/oauth-clients-organization.shared.resources-config.schemas.d.ts +4 -1
  385. package/dist/esm/security/oauth-clients/oauth-clients-organization.shared.resources-config.schemas.d.ts.map +1 -1
  386. package/dist/esm/security/oauth-clients/oauth-clients-organization.shared.resources-config.schemas.js +29 -0
  387. package/dist/esm/security/oauth-clients/oauth-clients-organization.shared.resources-config.schemas.js.map +1 -1
  388. package/dist/esm/security/oauth-clients/oauth-clients.shared.schemas.d.ts +6 -0
  389. package/dist/esm/security/oauth-clients/oauth-clients.shared.schemas.d.ts.map +1 -1
  390. package/dist/esm/security/oauth-clients/oauth-clients.shared.schemas.js +31 -0
  391. package/dist/esm/security/oauth-clients/oauth-clients.shared.schemas.js.map +1 -1
  392. package/dist/esm/security/oauth-clients/oauth-consent-grants.shared.schemas.d.ts +13 -0
  393. package/dist/esm/security/oauth-clients/oauth-consent-grants.shared.schemas.d.ts.map +1 -1
  394. package/dist/esm/security/oauth-clients/oauth-consent-grants.shared.schemas.js +24 -3
  395. package/dist/esm/security/oauth-clients/oauth-consent-grants.shared.schemas.js.map +1 -1
  396. package/dist/esm/users/user-preferences.shared.resources-config.schemas.d.ts +4 -4
  397. package/dist/esm/users/user-self-preferences.shared.resources-config.schemas.d.ts +4 -4
  398. package/dist/esm/users/user-self.shared.resources-config.schemas.d.ts.map +1 -1
  399. package/dist/esm/users/user-self.shared.resources-config.schemas.js +33 -3
  400. package/dist/esm/users/user-self.shared.resources-config.schemas.js.map +1 -1
  401. package/dist/esm/users/users.shared.resources-config.schemas.d.ts +17 -1
  402. package/dist/esm/users/users.shared.resources-config.schemas.d.ts.map +1 -1
  403. package/dist/esm/users/users.shared.resources-config.schemas.js +136 -5
  404. package/dist/esm/users/users.shared.resources-config.schemas.js.map +1 -1
  405. package/dist/esm/users/users.shared.schemas.d.ts +43 -12
  406. package/dist/esm/users/users.shared.schemas.d.ts.map +1 -1
  407. package/dist/esm/users/users.shared.schemas.js +38 -7
  408. package/dist/esm/users/users.shared.schemas.js.map +1 -1
  409. package/dist/tsconfig.build.tsbuildinfo +1 -1
  410. package/package.json +4 -4
@@ -25,6 +25,37 @@ function normalizeScopes(scope) {
25
25
  // defineFeature() — Boolean Feature Builder
26
26
  // =====================================================
27
27
  /**
28
+ * @wildo_source:part:start saas.models.features.definition-builders facet:layer:shared facet:audience:app-developer
29
+ *
30
+ * Declaring what an application can SELL or gate on. Two builders, from `@wildo-ai/saas-models`:
31
+ * `defineFeature` for a boolean capability, `defineLimitFeature` for a numeric allowance.
32
+ *
33
+ * A product in the billing catalogue then grants them through `grantedFeatures` / `grantedLimits`,
34
+ * and any surface gates on the identifier with `requiredFeatures` — a resource operation, a view, a
35
+ * chart, a navigation item, a settings section.
36
+ *
37
+ * ## Two things that decide whether the gate actually fires
38
+ *
39
+ * (`limitSemantic` is the third and is covered by the product-definitions skill's own guidance —
40
+ * the default `FLOOR` is an entitlement the tenant is ALLOWED, and a consumption CAP needs `CEILING`.)
41
+ *
42
+ * - **`countResource` is the one-call form.** It registers a limit check on that resource's CREATE
43
+ * automatically, so "at most ten projects per organisation" is one declaration rather than a
44
+ * definition plus a hand-written gate. A limit declared WITHOUT counting cannot be checked
45
+ * automatically: `checkLimit` REFUSES rather than guessing at a remaining quota, and the caller
46
+ * must pass a counting override or measure consumption itself. That is the right answer for a
47
+ * quantity that is not a row count — a sum of tokens, for instance.
48
+ * - **`rateLimit` on a definition is RESERVED and ignored by the gate.** A time-windowed allowance
49
+ * like "one hundred calls an hour" is not expressible here at all; abuse throttling is a separate
50
+ * mechanism with its own declaration.
51
+ *
52
+ * ## Granting a capability does not configure it
53
+ *
54
+ * An entitlement says the tenant MAY have the thing. Single sign-on entitles an organisation to
55
+ * register an identity provider; somebody still has to register one. The same holds for provisioning
56
+ * tokens, export destinations and webhook endpoints — so a plan that grants one of these still needs
57
+ * an onboarding step behind it.
58
+ *
28
59
  * Simple boolean feature builder.
29
60
  *
30
61
  * @example
@@ -106,4 +137,5 @@ export function defineLimitFeature(identifier, options) {
106
137
  }
107
138
  return definition;
108
139
  }
140
+ /** @wildo_source:part:end saas.models.features.definition-builders */
109
141
  //# sourceMappingURL=feature-builders.shared.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"feature-builders.shared.js","sourceRoot":"","sources":["../../../../src/features/feature-builders.shared.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,gBAAgB,GAMjB,MAAM,qCAAqC,CAAC;AAE7C,wDAAwD;AACxD,iCAAiC;AACjC,wDAAwD;AAExD;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;AAajF,wDAAwD;AACxD,sBAAsB;AACtB,wDAAwD;AAExD,SAAS,eAAe,CAAC,KAAoD;IAC3E,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,wDAAwD;AACxD,4CAA4C;AAC5C,wDAAwD;AAExD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,aAAa,CAC3B,UAAkB,EAClB,OAKC;IAED,OAAO;QACL,UAAU;QACV,SAAS,EAAE,gBAAgB,CAAC,OAAO;QACnC,gBAAgB,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC;QAChD,YAAY,EAAE,OAAO,CAAC,cAAc,IAAI,KAAK;QAC7C,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,EAAE;QACxC,cAAc,EAAE,OAAO,CAAC,cAAc;KACvC,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,+CAA+C;AAC/C,wDAAwD;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAkB,EAClB,OAsBC;IAED,8FAA8F;IAC9F,MAAM,QAAQ,GACZ,OAAO,CAAC,QAAQ;QAChB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEhF,MAAM,UAAU,GAAsC;QACpD,UAAU;QACV,SAAS,EAAE,gBAAgB,CAAC,KAAK;QACjC,gBAAgB,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC;QAChD,YAAY,EAAE,OAAO,CAAC,OAAO;QAC7B,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,EAAE;QACxC,6FAA6F;QAC7F,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,QAAQ;QACR,cAAc,EAAE,OAAO,CAAC,cAAc;KACvC,CAAC;IAEF,kFAAkF;IAClF,IAAI,OAAO,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;QACvD,UAAU,CAAC,yBAAyB,CAAC,GAAG;YACtC,aAAa,EAAE,OAAO,CAAC,aAAa;SACrC,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC","sourcesContent":["/**\n * Feature Builder Utilities\n *\n * DX-oriented builder functions for defining features.\n * These handle boilerplate: scope normalization, default values, counting config generation.\n * Custom app developers should use these instead of raw FeatureDefinition objects.\n */\n\nimport { ResourcePrimaryScope } from '../resources/resources.shared.schemas';\nimport {\n FeatureValueType,\n FEATURES_UNLIMITED,\n FeatureLimitSemantic,\n type FeatureDefinition,\n type FeatureUnavailabilityOverride,\n type LimitCountingConfig,\n} from './feature-definition.shared.schemas';\n\n// =====================================================\n// Internal: Auto-register marker\n// =====================================================\n\n/**\n * Internal marker symbol for limit features that should auto-register\n * a limitCheck on the counted resource's CREATE operation.\n * Used by FeatureDefinitionRegistryBackendService at startup.\n */\nexport const AUTO_REGISTER_LIMIT_CHECK = Symbol.for('AUTO_REGISTER_LIMIT_CHECK');\n\n/**\n * Extended FeatureDefinition with auto-register metadata.\n * This is the internal type returned by defineLimitFeature when countResource is provided.\n */\nexport type FeatureDefinitionWithAutoRegister = FeatureDefinition & {\n [AUTO_REGISTER_LIMIT_CHECK]?: {\n /** Resource type whose CREATE operation should get a limitCheck for this feature */\n countResource: string;\n };\n};\n\n// =====================================================\n// Scope Normalization\n// =====================================================\n\nfunction normalizeScopes(scope: ResourcePrimaryScope | ResourcePrimaryScope[]): ResourcePrimaryScope[] {\n return Array.isArray(scope) ? scope : [scope];\n}\n\n// =====================================================\n// defineFeature() — Boolean Feature Builder\n// =====================================================\n\n/**\n * Simple boolean feature builder.\n *\n * @example\n * defineFeature('AI_ASSISTANT', { scope: ResourcePrimaryScope.ORGANIZATIONS })\n *\n * @example\n * defineFeature('PREMIUM_THEMES', {\n * scope: ResourcePrimaryScope.USER_SELF,\n * unavailability: {\n * behavior: FeatureUnavailabilityBehavior.UPGRADE_PROMPT,\n * },\n * })\n */\nexport function defineFeature(\n identifier: string,\n options: {\n scope: ResourcePrimaryScope | ResourcePrimaryScope[];\n defaultEnabled?: boolean;\n dependencies?: string[];\n unavailability?: FeatureUnavailabilityOverride;\n }\n): FeatureDefinition {\n return {\n identifier,\n valueType: FeatureValueType.BOOLEAN,\n applicableScopes: normalizeScopes(options.scope),\n defaultValue: options.defaultEnabled ?? false,\n dependencies: options.dependencies ?? [],\n unavailability: options.unavailability,\n };\n}\n\n// =====================================================\n// defineLimitFeature() — Limit Feature Builder\n// =====================================================\n\n/**\n * Limit feature builder with auto-wiring support.\n *\n * Key DX improvement: when `countResource` is provided, the engine\n * auto-registers a `limitChecks` entry on the CREATE operation of the\n * referenced resource at startup (via FeatureDefinitionRegistryBackendService).\n *\n * This means: to add \"max 10 projects per org\", write ONE call and the\n * gate is automatically enforced. No need to manually add limitChecks on\n * the resource's operation variant.\n *\n * @example\n * defineLimitFeature('MAX_PROJECTS', {\n * scope: ResourcePrimaryScope.ORGANIZATIONS,\n * default: 5,\n * countResource: CustomShared_ResourceType.PROJECTS,\n * })\n * // Equivalent to manually defining:\n * // { identifier: 'MAX_PROJECTS', valueType: LIMIT, applicableScopes: [ORGANIZATIONS],\n * // defaultValue: 5, counting: { resourceType: 'PROJECTS' } }\n * // + adding limitChecks: [{ featureId: 'MAX_PROJECTS' }] on PROJECTS.CREATE variant\n *\n * @example\n * defineLimitFeature('MAX_STORAGE_GB', {\n * scope: ResourcePrimaryScope.ORGANIZATIONS,\n * default: 10,\n * counting: {\n * resourceType: 'FILES',\n * aggregate: { field: 'sizeBytes', operation: AggregationOperation.SUM },\n * },\n * })\n */\nexport function defineLimitFeature(\n identifier: string,\n options: {\n scope: ResourcePrimaryScope | ResourcePrimaryScope[];\n default: number;\n /**\n * How this limit COMPOSES when several sources supply a value (see {@link FeatureLimitSemantic}).\n * Omit for the default `FLOOR` — an entitlement the tenant is ALLOWED, where most-permissive\n * wins and add-ons stack upward (`MAX_MEMBERS`, `MAX_API_KEYS`).\n *\n * Pass `CEILING` for a consumption CAP the tenant may not exceed: most-RESTRICTIVE wins, and\n * `FEATURES_UNLIMITED` means \"no ceiling\" so it yields to any finite grant. Without it a cap is\n * inexpressible — under FLOOR an unlimited default absorbs every finite plan grant, so the cap\n * silently never engages.\n */\n limitSemantic?: FeatureLimitSemantic;\n /** Resource to count. Auto-registers a limitCheck on CREATE for this resource. */\n countResource?: string;\n /** Advanced: filter + aggregation for counting (overrides simple resource count) */\n counting?: LimitCountingConfig;\n /** If true, skip auto-registration of limitChecks on the resource's CREATE operation */\n skipAutoRegister?: boolean;\n dependencies?: string[];\n unavailability?: FeatureUnavailabilityOverride;\n }\n): FeatureDefinitionWithAutoRegister {\n // Build counting config: explicit counting takes precedence, then countResource, then nothing\n const counting: LimitCountingConfig | undefined =\n options.counting ??\n (options.countResource ? { resourceType: options.countResource } : undefined);\n\n const definition: FeatureDefinitionWithAutoRegister = {\n identifier,\n valueType: FeatureValueType.LIMIT,\n applicableScopes: normalizeScopes(options.scope),\n defaultValue: options.default,\n dependencies: options.dependencies ?? [],\n // Omitted ⇒ absent on the definition ⇒ read as FLOOR, so every existing caller is unchanged.\n ...(options.limitSemantic ? { limitSemantic: options.limitSemantic } : {}),\n counting,\n unavailability: options.unavailability,\n };\n\n // Add auto-register marker for limit features with countResource (unless skipped)\n if (options.countResource && !options.skipAutoRegister) {\n definition[AUTO_REGISTER_LIMIT_CHECK] = {\n countResource: options.countResource,\n };\n }\n\n return definition;\n}\n"]}
1
+ {"version":3,"file":"feature-builders.shared.js","sourceRoot":"","sources":["../../../../src/features/feature-builders.shared.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,gBAAgB,GAMjB,MAAM,qCAAqC,CAAC;AAE7C,wDAAwD;AACxD,iCAAiC;AACjC,wDAAwD;AAExD;;;;GAIG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;AAajF,wDAAwD;AACxD,sBAAsB;AACtB,wDAAwD;AAExD,SAAS,eAAe,CAAC,KAAoD;IAC3E,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,wDAAwD;AACxD,4CAA4C;AAC5C,wDAAwD;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,MAAM,UAAU,aAAa,CAC3B,UAAkB,EAClB,OAKC;IAED,OAAO;QACL,UAAU;QACV,SAAS,EAAE,gBAAgB,CAAC,OAAO;QACnC,gBAAgB,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC;QAChD,YAAY,EAAE,OAAO,CAAC,cAAc,IAAI,KAAK;QAC7C,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,EAAE;QACxC,cAAc,EAAE,OAAO,CAAC,cAAc;KACvC,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,+CAA+C;AAC/C,wDAAwD;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,UAAU,kBAAkB,CAChC,UAAkB,EAClB,OAsBC;IAED,8FAA8F;IAC9F,MAAM,QAAQ,GACZ,OAAO,CAAC,QAAQ;QAChB,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAEhF,MAAM,UAAU,GAAsC;QACpD,UAAU;QACV,SAAS,EAAE,gBAAgB,CAAC,KAAK;QACjC,gBAAgB,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC;QAChD,YAAY,EAAE,OAAO,CAAC,OAAO;QAC7B,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,EAAE;QACxC,6FAA6F;QAC7F,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,QAAQ;QACR,cAAc,EAAE,OAAO,CAAC,cAAc;KACvC,CAAC;IAEF,kFAAkF;IAClF,IAAI,OAAO,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;QACvD,UAAU,CAAC,yBAAyB,CAAC,GAAG;YACtC,aAAa,EAAE,OAAO,CAAC,aAAa;SACrC,CAAC;IACJ,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AACD,sEAAsE","sourcesContent":["/**\n * Feature Builder Utilities\n *\n * DX-oriented builder functions for defining features.\n * These handle boilerplate: scope normalization, default values, counting config generation.\n * Custom app developers should use these instead of raw FeatureDefinition objects.\n */\n\nimport { ResourcePrimaryScope } from '../resources/resources.shared.schemas';\nimport {\n FeatureValueType,\n FEATURES_UNLIMITED,\n FeatureLimitSemantic,\n type FeatureDefinition,\n type FeatureUnavailabilityOverride,\n type LimitCountingConfig,\n} from './feature-definition.shared.schemas';\n\n// =====================================================\n// Internal: Auto-register marker\n// =====================================================\n\n/**\n * Internal marker symbol for limit features that should auto-register\n * a limitCheck on the counted resource's CREATE operation.\n * Used by FeatureDefinitionRegistryBackendService at startup.\n */\nexport const AUTO_REGISTER_LIMIT_CHECK = Symbol.for('AUTO_REGISTER_LIMIT_CHECK');\n\n/**\n * Extended FeatureDefinition with auto-register metadata.\n * This is the internal type returned by defineLimitFeature when countResource is provided.\n */\nexport type FeatureDefinitionWithAutoRegister = FeatureDefinition & {\n [AUTO_REGISTER_LIMIT_CHECK]?: {\n /** Resource type whose CREATE operation should get a limitCheck for this feature */\n countResource: string;\n };\n};\n\n// =====================================================\n// Scope Normalization\n// =====================================================\n\nfunction normalizeScopes(scope: ResourcePrimaryScope | ResourcePrimaryScope[]): ResourcePrimaryScope[] {\n return Array.isArray(scope) ? scope : [scope];\n}\n\n// =====================================================\n// defineFeature() — Boolean Feature Builder\n// =====================================================\n\n/**\n * @wildo_source:part:start saas.models.features.definition-builders facet:layer:shared facet:audience:app-developer\n *\n * Declaring what an application can SELL or gate on. Two builders, from `@wildo-ai/saas-models`:\n * `defineFeature` for a boolean capability, `defineLimitFeature` for a numeric allowance.\n *\n * A product in the billing catalogue then grants them through `grantedFeatures` / `grantedLimits`,\n * and any surface gates on the identifier with `requiredFeatures` — a resource operation, a view, a\n * chart, a navigation item, a settings section.\n *\n * ## Two things that decide whether the gate actually fires\n *\n * (`limitSemantic` is the third and is covered by the product-definitions skill's own guidance —\n * the default `FLOOR` is an entitlement the tenant is ALLOWED, and a consumption CAP needs `CEILING`.)\n *\n * - **`countResource` is the one-call form.** It registers a limit check on that resource's CREATE\n * automatically, so \"at most ten projects per organisation\" is one declaration rather than a\n * definition plus a hand-written gate. A limit declared WITHOUT counting cannot be checked\n * automatically: `checkLimit` REFUSES rather than guessing at a remaining quota, and the caller\n * must pass a counting override or measure consumption itself. That is the right answer for a\n * quantity that is not a row count — a sum of tokens, for instance.\n * - **`rateLimit` on a definition is RESERVED and ignored by the gate.** A time-windowed allowance\n * like \"one hundred calls an hour\" is not expressible here at all; abuse throttling is a separate\n * mechanism with its own declaration.\n *\n * ## Granting a capability does not configure it\n *\n * An entitlement says the tenant MAY have the thing. Single sign-on entitles an organisation to\n * register an identity provider; somebody still has to register one. The same holds for provisioning\n * tokens, export destinations and webhook endpoints — so a plan that grants one of these still needs\n * an onboarding step behind it.\n *\n * Simple boolean feature builder.\n *\n * @example\n * defineFeature('AI_ASSISTANT', { scope: ResourcePrimaryScope.ORGANIZATIONS })\n *\n * @example\n * defineFeature('PREMIUM_THEMES', {\n * scope: ResourcePrimaryScope.USER_SELF,\n * unavailability: {\n * behavior: FeatureUnavailabilityBehavior.UPGRADE_PROMPT,\n * },\n * })\n */\nexport function defineFeature(\n identifier: string,\n options: {\n scope: ResourcePrimaryScope | ResourcePrimaryScope[];\n defaultEnabled?: boolean;\n dependencies?: string[];\n unavailability?: FeatureUnavailabilityOverride;\n }\n): FeatureDefinition {\n return {\n identifier,\n valueType: FeatureValueType.BOOLEAN,\n applicableScopes: normalizeScopes(options.scope),\n defaultValue: options.defaultEnabled ?? false,\n dependencies: options.dependencies ?? [],\n unavailability: options.unavailability,\n };\n}\n\n// =====================================================\n// defineLimitFeature() — Limit Feature Builder\n// =====================================================\n\n/**\n * Limit feature builder with auto-wiring support.\n *\n * Key DX improvement: when `countResource` is provided, the engine\n * auto-registers a `limitChecks` entry on the CREATE operation of the\n * referenced resource at startup (via FeatureDefinitionRegistryBackendService).\n *\n * This means: to add \"max 10 projects per org\", write ONE call and the\n * gate is automatically enforced. No need to manually add limitChecks on\n * the resource's operation variant.\n *\n * @example\n * defineLimitFeature('MAX_PROJECTS', {\n * scope: ResourcePrimaryScope.ORGANIZATIONS,\n * default: 5,\n * countResource: CustomShared_ResourceType.PROJECTS,\n * })\n * // Equivalent to manually defining:\n * // { identifier: 'MAX_PROJECTS', valueType: LIMIT, applicableScopes: [ORGANIZATIONS],\n * // defaultValue: 5, counting: { resourceType: 'PROJECTS' } }\n * // + adding limitChecks: [{ featureId: 'MAX_PROJECTS' }] on PROJECTS.CREATE variant\n *\n * @example\n * defineLimitFeature('MAX_STORAGE_GB', {\n * scope: ResourcePrimaryScope.ORGANIZATIONS,\n * default: 10,\n * counting: {\n * resourceType: 'FILES',\n * aggregate: { field: 'sizeBytes', operation: AggregationOperation.SUM },\n * },\n * })\n */\nexport function defineLimitFeature(\n identifier: string,\n options: {\n scope: ResourcePrimaryScope | ResourcePrimaryScope[];\n default: number;\n /**\n * How this limit COMPOSES when several sources supply a value (see {@link FeatureLimitSemantic}).\n * Omit for the default `FLOOR` — an entitlement the tenant is ALLOWED, where most-permissive\n * wins and add-ons stack upward (`MAX_MEMBERS`, `MAX_API_KEYS`).\n *\n * Pass `CEILING` for a consumption CAP the tenant may not exceed: most-RESTRICTIVE wins, and\n * `FEATURES_UNLIMITED` means \"no ceiling\" so it yields to any finite grant. Without it a cap is\n * inexpressible — under FLOOR an unlimited default absorbs every finite plan grant, so the cap\n * silently never engages.\n */\n limitSemantic?: FeatureLimitSemantic;\n /** Resource to count. Auto-registers a limitCheck on CREATE for this resource. */\n countResource?: string;\n /** Advanced: filter + aggregation for counting (overrides simple resource count) */\n counting?: LimitCountingConfig;\n /** If true, skip auto-registration of limitChecks on the resource's CREATE operation */\n skipAutoRegister?: boolean;\n dependencies?: string[];\n unavailability?: FeatureUnavailabilityOverride;\n }\n): FeatureDefinitionWithAutoRegister {\n // Build counting config: explicit counting takes precedence, then countResource, then nothing\n const counting: LimitCountingConfig | undefined =\n options.counting ??\n (options.countResource ? { resourceType: options.countResource } : undefined);\n\n const definition: FeatureDefinitionWithAutoRegister = {\n identifier,\n valueType: FeatureValueType.LIMIT,\n applicableScopes: normalizeScopes(options.scope),\n defaultValue: options.default,\n dependencies: options.dependencies ?? [],\n // Omitted ⇒ absent on the definition ⇒ read as FLOOR, so every existing caller is unchanged.\n ...(options.limitSemantic ? { limitSemantic: options.limitSemantic } : {}),\n counting,\n unavailability: options.unavailability,\n };\n\n // Add auto-register marker for limit features with countResource (unless skipped)\n if (options.countResource && !options.skipAutoRegister) {\n definition[AUTO_REGISTER_LIMIT_CHECK] = {\n countResource: options.countResource,\n };\n }\n\n return definition;\n}\n/** @wildo_source:part:end saas.models.features.definition-builders */\n"]}
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { FileUploaderEntityType } from '@wildo-ai/zod-decorators';
2
3
  import { CoreResourceOperation } from '../resources/resources.shared.core.definitions';
3
4
  import { FileStatus } from './files.shared.schemas';
4
5
  /**
@@ -64,7 +65,7 @@ export declare const FileUploadGrantMetadataSchema: z.ZodObject<{
64
65
  [K in FileUploadGrantOperation]: K;
65
66
  }>;
66
67
  minter: z.ZodObject<{
67
- entityType: z.ZodString;
68
+ entityType: z.ZodEnum<typeof FileUploaderEntityType>;
68
69
  id: z.ZodString;
69
70
  }>;
70
71
  uploadUrl: z.ZodString;
@@ -135,9 +136,20 @@ export declare const FileUploadGrantStatusSchema: z.ZodObject<{
135
136
  }>>;
136
137
  }>;
137
138
  export type FileUploadGrantStatus = z.infer<typeof FileUploadGrantStatusSchema>;
138
- /** Body accepted by both mint doors. */
139
+ /**
140
+ * Body accepted by both mint doors.
141
+ *
142
+ * The three optional file facts mirror what the MCP File Objects proposal has a client declare when
143
+ * it asks to upload (`name`, `mimeType`, `size`): declaring them lets the server refuse a file the
144
+ * field would never accept BEFORE handing out a link, instead of at redemption when the link is
145
+ * already spent. They are advisory for the upload itself — the bytes are validated on receipt
146
+ * regardless — and a declaration that later disagrees with the bytes is refused on receipt too.
147
+ */
139
148
  export declare const FileUploadGrantMintRequestSchema: z.ZodObject<{
140
149
  expiresInMinutes: z.ZodOptional<z.ZodNumber>;
150
+ name: z.ZodOptional<z.ZodString>;
151
+ mimeType: z.ZodOptional<z.ZodString>;
152
+ size: z.ZodOptional<z.ZodNumber>;
141
153
  }>;
142
154
  export type FileUploadGrantMintRequest = z.infer<typeof FileUploadGrantMintRequestSchema>;
143
155
  /** @wildo_source:part:end saas.models.file-upload-grant */
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload-grant.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../src/files/file-upload-grant.shared.schemas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"file-upload-grant.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../src/files/file-upload-grant.shared.schemas.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { FileUploaderEntityType } from '@wildo-ai/zod-decorators';
2
3
  import { CoreResourceOperation } from '../resources/resources.shared.core.definitions.js';
3
4
  import { FileStatus } from './files.shared.schemas.js';
4
5
  /**
@@ -62,11 +63,35 @@ export const FileUploadGrantMetadataSchema = z.object({
62
63
  operation: FileUploadGrantOperationSchema,
63
64
  /**
64
65
  * Who minted — recorded so the uploaded file is attributed to a PERSON or MACHINE, not to the
65
- * grant. `entityType` is a `FileUploaderEntityType` value; kept as a string here because the
66
- * uploader enum lives in `zod-decorators`, upstream of this package.
66
+ * grant.
67
+ *
68
+ * `entityType` is the ENUM, not a string. It was `z.string().min(1)` until 2026-09-08, with the
69
+ * stated reason that "the uploader enum lives in `zod-decorators`, upstream of this package" —
70
+ * which is exactly backwards: upstream is what a package MAY import, and this one already does.
71
+ * `files.shared.schemas.ts` in this very directory imports `FileUploaderEntityType` from
72
+ * `@wildo-ai/zod-decorators`, re-exports it, and writes `z.enum(FileUploaderEntityType)` on the
73
+ * FILES row's own `uploadedByEntityType`. So the vocabulary was one import away the whole time and
74
+ * the metadata's copy of the same field was the only one left open.
75
+ *
76
+ * What the enum buys: `metadata` is an UNTYPED bag on the token row, so nothing between the write
77
+ * and the read guarantees its shape — the read is the only place that can. Every reader here goes
78
+ * through `FileUploadGrantMetadataSchema.safeParse`, so an out-of-vocabulary entity type now makes
79
+ * the whole metadata unparseable and the redemption path refuses the grant instead of casting the
80
+ * value into `FileUploaderPrincipal` and carrying it three layers to `validateUploadedByEntityType`.
81
+ *
82
+ * NOT narrowed to the three values `mint` can actually produce (mint refuses an anonymous and a
83
+ * token-borne minter, so `ANONYMOUS_USER` is unreachable): that refusal is a MINT policy, enforced
84
+ * and explained at mint, and re-encoding it here would put half a policy in a schema that cannot
85
+ * say why. The vocabulary of this field is the vocabulary of the principal it names.
86
+ */
87
+ minter: z.object({ entityType: z.enum(FileUploaderEntityType), id: z.string().min(1) }),
88
+ /**
89
+ * The concrete upload URL the grant was minted for. Two jobs, and the second one is why it must be
90
+ * absolute: the status read hands it to the drop page, AND the redemption path compares its PATH
91
+ * against the route the token is presented on (`assertGrantMatchesRoute`). Until 2026-09-08 it was
92
+ * recorded and never read back, so a grant bound to one concrete route could be redeemed on any
93
+ * other route reaching the same (resource, field, operation, row).
67
94
  */
68
- minter: z.object({ entityType: z.string().min(1), id: z.string().min(1) }),
69
- /** The concrete upload URL the grant was minted for — recorded so the status read can hand it to the drop page. */
70
95
  uploadUrl: z.string().url(),
71
96
  /** Written after a successful redemption; absent until then. */
72
97
  producedFileId: z.string().min(1).optional(),
@@ -128,9 +153,23 @@ export const FileUploadGrantStatusSchema = z.object({
128
153
  /** `null` until redeemed, or when the post-redemption write-back failed (re-read the resource instead). */
129
154
  file: z.object({ fileId: z.string().min(1), status: z.enum(FileStatus) }).nullable(),
130
155
  });
131
- /** Body accepted by both mint doors. */
156
+ /**
157
+ * Body accepted by both mint doors.
158
+ *
159
+ * The three optional file facts mirror what the MCP File Objects proposal has a client declare when
160
+ * it asks to upload (`name`, `mimeType`, `size`): declaring them lets the server refuse a file the
161
+ * field would never accept BEFORE handing out a link, instead of at redemption when the link is
162
+ * already spent. They are advisory for the upload itself — the bytes are validated on receipt
163
+ * regardless — and a declaration that later disagrees with the bytes is refused on receipt too.
164
+ */
132
165
  export const FileUploadGrantMintRequestSchema = z.object({
133
166
  expiresInMinutes: z.number().int().min(1).max(FILE_UPLOAD_GRANT_ABSOLUTE_MAX_MINUTES).optional(),
167
+ /** The file name the caller intends to upload; used for the curl example and checked against nothing else. */
168
+ name: z.string().min(1).max(255).optional(),
169
+ /** Declared MIME type; refused at mint when the field does not accept it. */
170
+ mimeType: z.string().min(1).max(255).optional(),
171
+ /** Declared size in bytes; refused at mint when above the field's maximum. */
172
+ size: z.number().int().positive().optional(),
134
173
  }).strict();
135
174
  /** @wildo_source:part:end saas.models.file-upload-grant */
136
175
  //# sourceMappingURL=file-upload-grant.shared.schemas.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"file-upload-grant.shared.schemas.js","sourceRoot":"","sources":["../../../../src/files/file-upload-grant.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from 'zod';\nimport { CoreResourceOperation } from '../resources/resources.shared.core.definitions';\nimport { FileStatus } from './files.shared.schemas';\n\n/**\n * File upload grant — the shared contract between the two mint doors (REST, MCP), the upload route,\n * the status read, and the browser drop page (issue #312).\n *\n * A grant is a single-use consumable token. Nothing durable is created at mint but the token: an\n * abandoned grant leaves a dead token and nothing else. The upload itself goes through the resource's\n * EXISTING file-upload route, authenticated by the grant alone, and the ordinary authorizer decides.\n */\n\n/**\n * Public frontend route the browser drop page lives on; the token follows as the next path segment\n * (`/upload-grant/<token>`). Declared HERE so the backend (which builds `uploadPageUrl`) and the\n * frontend (which mounts the route) read one source — the backend cannot import frontend route\n * constants.\n */\nexport const FILE_UPLOAD_GRANT_PAGE_PATH = '/upload-grant';\n\n/** @wildo_source:part:start saas.models.file-upload-grant facet:layer:shared facet:family:files\n *\n * Lifetime bounds of an upload grant, in minutes. The ceiling is fixed by the framework and enforced\n * when the grant is minted — a request above it is REFUSED, never clamped, so a caller that asked for\n * two hours learns from an error that the bound is sixty minutes rather than from an expiry it did not\n * expect. The bound is the framework's to own because the grant is designed to leave the trust\n * boundary: it lands in an AI agent's transcript, a model provider's logs, a shell history.\n */\nexport const FILE_UPLOAD_GRANT_DEFAULT_MINUTES = 15;\nexport const FILE_UPLOAD_GRANT_ABSOLUTE_MAX_MINUTES = 60;\n\n/**\n * Which write the grant is for. A grant minted on the CREATE upload route uploads a file that a\n * later CREATE will reference; one minted on the UPDATE route (`…/{resourceId}/files/<field>`) is\n * bound to that row. The two routes authorize differently, so a grant may not cross from one to the\n * other — the upload middleware checks this against the route it is presented on.\n */\nexport const FILE_UPLOAD_GRANT_OPERATIONS = [CoreResourceOperation.CREATE, CoreResourceOperation.UPDATE] as const;\nexport type FileUploadGrantOperation = (typeof FILE_UPLOAD_GRANT_OPERATIONS)[number];\n/** Derived from `CoreResourceOperation` — the named source — rather than a second enum spelling the same two words. */\nexport const FileUploadGrantOperationSchema: z.ZodEnum<{ [K in FileUploadGrantOperation]: K }> = z.enum(FILE_UPLOAD_GRANT_OPERATIONS);\n\n/**\n * Lifecycle of a grant as the status read reports it. Derived from the token row — `isConsumed`,\n * `expiresAt`, `revokedAt` — never stored, so it cannot drift from the row.\n */\nexport enum FileUploadGrantState {\n /** Minted, unexpired, unrevoked, not yet redeemed: an upload will be accepted. */\n PENDING = 'pending',\n /** Redeemed by exactly one upload. `file` names what it produced when the write-back succeeded. */\n REDEEMED = 'redeemed',\n /** Past `expiresAt` without being redeemed. Mint a new one. */\n EXPIRED = 'expired',\n /** Revoked by the minter or an administrator before redemption. */\n REVOKED = 'revoked',\n}\nexport const FileUploadGrantStateSchema: z.ZodEnum<typeof FileUploadGrantState> = z.enum(FileUploadGrantState);\n\n/**\n * The `metadata` a FILE_UPLOAD_GRANT token carries — the ROUTE binding, as opposed to the identity\n * the typed token fields carry. The upload middleware reads this; the execution-context creator\n * deliberately does not.\n */\nexport const FileUploadGrantMetadataSchema: z.ZodObject<{\n fieldName: z.ZodString;\n operation: z.ZodEnum<{ [K in FileUploadGrantOperation]: K }>;\n minter: z.ZodObject<{ entityType: z.ZodString; id: z.ZodString }>;\n uploadUrl: z.ZodString;\n producedFileId: z.ZodOptional<z.ZodString>;\n}> = z.object({\n /** The `z_file()` field the upload lands on, as authored (dotted for nested fields). */\n fieldName: z.string().min(1),\n operation: FileUploadGrantOperationSchema,\n /**\n * Who minted — recorded so the uploaded file is attributed to a PERSON or MACHINE, not to the\n * grant. `entityType` is a `FileUploaderEntityType` value; kept as a string here because the\n * uploader enum lives in `zod-decorators`, upstream of this package.\n */\n minter: z.object({ entityType: z.string().min(1), id: z.string().min(1) }),\n /** The concrete upload URL the grant was minted for — recorded so the status read can hand it to the drop page. */\n uploadUrl: z.string().url(),\n /** Written after a successful redemption; absent until then. */\n producedFileId: z.string().min(1).optional(),\n});\nexport type FileUploadGrantMetadata = z.infer<typeof FileUploadGrantMetadataSchema>;\n\n/**\n * What a mint returns — identical on the REST door and the MCP tool. Two affordances for one\n * token: `uploadCommand` for a caller that can execute, `uploadPageUrl` for one that must hand a\n * human a link. The token appears in `uploadHeader.value` and inside both commands and the page URL;\n * it is the credential and cannot be omitted. It never appears in any audit row.\n */\nexport const FileUploadGrantSchema: z.ZodObject<{\n grantId: z.ZodString;\n state: z.ZodEnum<typeof FileUploadGrantState>;\n expiresAt: z.ZodString;\n singleUse: z.ZodLiteral<true>;\n target: z.ZodObject<{\n resourceType: z.ZodString;\n fieldName: z.ZodString;\n operation: z.ZodEnum<{ [K in FileUploadGrantOperation]: K }>;\n resourceId: z.ZodNullable<z.ZodString>;\n }>;\n constraints: z.ZodObject<{\n maxBytes: z.ZodNumber;\n allowedMimeTypes: z.ZodArray<z.ZodString>;\n }>;\n uploadUrl: z.ZodString;\n uploadHeader: z.ZodObject<{ name: z.ZodString; value: z.ZodString }>;\n uploadCommand: z.ZodString;\n uploadCommandPowerShell: z.ZodString;\n uploadPageUrl: z.ZodNullable<z.ZodString>;\n statusUrl: z.ZodString;\n note: z.ZodString;\n}> = z.object({\n grantId: z.string().min(1),\n state: FileUploadGrantStateSchema,\n expiresAt: z.string().datetime(),\n singleUse: z.literal(true),\n target: z.object({\n resourceType: z.string().min(1),\n fieldName: z.string().min(1),\n operation: FileUploadGrantOperationSchema,\n resourceId: z.string().min(1).nullable(),\n }),\n /** From the field's own constraint resolver — the same one the upload enforces, so the two cannot disagree. */\n constraints: z.object({\n maxBytes: z.number().int().positive(),\n /** Empty means every type is accepted. */\n allowedMimeTypes: z.array(z.string()),\n }),\n uploadUrl: z.string().url(),\n /** The credential travels in a HEADER on the curl form: paths are logged by every proxy, headers are not. */\n uploadHeader: z.object({ name: z.string().min(1), value: z.string().min(1) }),\n /** No `-f`: on a refusal the JSON error body is the only thing that tells the caller why. */\n uploadCommand: z.string().min(1),\n /** In PowerShell `curl` aliases Invoke-WebRequest, which does not understand `-F`; the real binary is `curl.exe`. */\n uploadCommandPowerShell: z.string().min(1),\n /** `null` when the application declares no frontend service — a headless API has no page to hand a human. */\n uploadPageUrl: z.string().url().nullable(),\n statusUrl: z.string().url(),\n note: z.string().min(1),\n});\nexport type FileUploadGrant = z.infer<typeof FileUploadGrantSchema>;\n\n/**\n * What the public status read returns. The token is the credential, so the read is unauthenticated\n * and returns only what the drop page needs to render and the agent needs to learn the `fileId`:\n * never the file's name (the status URL may be pasted around).\n */\nexport const FileUploadGrantStatusSchema: z.ZodObject<{\n grantId: z.ZodString;\n state: z.ZodEnum<typeof FileUploadGrantState>;\n expiresAt: z.ZodString;\n target: z.ZodObject<{\n resourceType: z.ZodString;\n fieldName: z.ZodString;\n operation: z.ZodEnum<{ [K in FileUploadGrantOperation]: K }>;\n resourceId: z.ZodNullable<z.ZodString>;\n }>;\n constraints: z.ZodObject<{ maxBytes: z.ZodNumber; allowedMimeTypes: z.ZodArray<z.ZodString> }>;\n uploadUrl: z.ZodString;\n uploadHeaderName: z.ZodString;\n file: z.ZodNullable<z.ZodObject<{ fileId: z.ZodString; status: z.ZodEnum<typeof FileStatus> }>>;\n}> = z.object({\n grantId: z.string().min(1),\n state: FileUploadGrantStateSchema,\n expiresAt: z.string().datetime(),\n target: z.object({\n resourceType: z.string().min(1),\n fieldName: z.string().min(1),\n operation: FileUploadGrantOperationSchema,\n resourceId: z.string().min(1).nullable(),\n }),\n constraints: z.object({ maxBytes: z.number().int().positive(), allowedMimeTypes: z.array(z.string()) }),\n uploadUrl: z.string().url(),\n /** The page sets this header itself; the token it already holds is the value. */\n uploadHeaderName: z.string().min(1),\n /** `null` until redeemed, or when the post-redemption write-back failed (re-read the resource instead). */\n file: z.object({ fileId: z.string().min(1), status: z.enum(FileStatus) }).nullable(),\n});\nexport type FileUploadGrantStatus = z.infer<typeof FileUploadGrantStatusSchema>;\n\n/** Body accepted by both mint doors. */\nexport const FileUploadGrantMintRequestSchema: z.ZodObject<{ expiresInMinutes: z.ZodOptional<z.ZodNumber> }> = z.object({\n expiresInMinutes: z.number().int().min(1).max(FILE_UPLOAD_GRANT_ABSOLUTE_MAX_MINUTES).optional(),\n}).strict();\nexport type FileUploadGrantMintRequest = z.infer<typeof FileUploadGrantMintRequestSchema>;\n/** @wildo_source:part:end saas.models.file-upload-grant */\n"]}
1
+ {"version":3,"file":"file-upload-grant.shared.schemas.js","sourceRoot":"","sources":["../../../../src/files/file-upload-grant.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gDAAgD,CAAC;AACvF,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;;;;;;GAOG;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,eAAe,CAAC;AAE3D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAG,EAAE,CAAC;AACpD,MAAM,CAAC,MAAM,sCAAsC,GAAG,EAAE,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,CAAC,MAAM,CAAU,CAAC;AAElH,uHAAuH;AACvH,MAAM,CAAC,MAAM,8BAA8B,GAAsD,CAAC,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;AAEtI;;;GAGG;AACH,MAAM,CAAN,IAAY,oBASX;AATD,WAAY,oBAAoB;IAC9B,kFAAkF;IAClF,2CAAmB,CAAA;IACnB,mGAAmG;IACnG,6CAAqB,CAAA;IACrB,+DAA+D;IAC/D,2CAAmB,CAAA;IACnB,mEAAmE;IACnE,2CAAmB,CAAA;AACrB,CAAC,EATW,oBAAoB,KAApB,oBAAoB,QAS/B;AACD,MAAM,CAAC,MAAM,0BAA0B,GAA2C,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;AAE/G;;;;GAIG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAMrC,CAAC,CAAC,MAAM,CAAC;IACZ,wFAAwF;IACxF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5B,SAAS,EAAE,8BAA8B;IACzC;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IACvF;;;;;;OAMG;IACH,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC3B,gEAAgE;IAChE,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CAC7C,CAAC,CAAC;AAGH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAsB7B,CAAC,CAAC,MAAM,CAAC;IACZ,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,KAAK,EAAE,0BAA0B;IACjC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IAC1B,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5B,SAAS,EAAE,8BAA8B;QACzC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;KACzC,CAAC;IACF,+GAA+G;IAC/G,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC;QACpB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;QACrC,0CAA0C;QAC1C,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;KACtC,CAAC;IACF,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC3B,6GAA6G;IAC7G,YAAY,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7E,6FAA6F;IAC7F,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAChC,qHAAqH;IACrH,uBAAuB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1C,6GAA6G;IAC7G,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IAC1C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC3B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CACxB,CAAC,CAAC;AAGH;;;;GAIG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAcnC,CAAC,CAAC,MAAM,CAAC;IACZ,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1B,KAAK,EAAE,0BAA0B;IACjC,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAChC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;QACf,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QAC5B,SAAS,EAAE,8BAA8B;QACzC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;KACzC,CAAC;IACF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,EAAE,gBAAgB,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;IACvG,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IAC3B,iFAAiF;IACjF,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACnC,2GAA2G;IAC3G,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;CACrF,CAAC,CAAC;AAGH;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAKxC,CAAC,CAAC,MAAM,CAAC;IACZ,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC,QAAQ,EAAE;IAChG,8GAA8G;IAC9G,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAC3C,6EAA6E;IAC7E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;IAC/C,8EAA8E;IAC9E,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;CAC7C,CAAC,CAAC,MAAM,EAAE,CAAC;AAEZ,2DAA2D","sourcesContent":["import { z } from 'zod';\nimport { FileUploaderEntityType } from '@wildo-ai/zod-decorators';\nimport { CoreResourceOperation } from '../resources/resources.shared.core.definitions';\nimport { FileStatus } from './files.shared.schemas';\n\n/**\n * File upload grant — the shared contract between the two mint doors (REST, MCP), the upload route,\n * the status read, and the browser drop page (issue #312).\n *\n * A grant is a single-use consumable token. Nothing durable is created at mint but the token: an\n * abandoned grant leaves a dead token and nothing else. The upload itself goes through the resource's\n * EXISTING file-upload route, authenticated by the grant alone, and the ordinary authorizer decides.\n */\n\n/**\n * Public frontend route the browser drop page lives on; the token follows as the next path segment\n * (`/upload-grant/<token>`). Declared HERE so the backend (which builds `uploadPageUrl`) and the\n * frontend (which mounts the route) read one source — the backend cannot import frontend route\n * constants.\n */\nexport const FILE_UPLOAD_GRANT_PAGE_PATH = '/upload-grant';\n\n/** @wildo_source:part:start saas.models.file-upload-grant facet:layer:shared facet:family:files\n *\n * Lifetime bounds of an upload grant, in minutes. The ceiling is fixed by the framework and enforced\n * when the grant is minted — a request above it is REFUSED, never clamped, so a caller that asked for\n * two hours learns from an error that the bound is sixty minutes rather than from an expiry it did not\n * expect. The bound is the framework's to own because the grant is designed to leave the trust\n * boundary: it lands in an AI agent's transcript, a model provider's logs, a shell history.\n */\nexport const FILE_UPLOAD_GRANT_DEFAULT_MINUTES = 15;\nexport const FILE_UPLOAD_GRANT_ABSOLUTE_MAX_MINUTES = 60;\n\n/**\n * Which write the grant is for. A grant minted on the CREATE upload route uploads a file that a\n * later CREATE will reference; one minted on the UPDATE route (`…/{resourceId}/files/<field>`) is\n * bound to that row. The two routes authorize differently, so a grant may not cross from one to the\n * other — the upload middleware checks this against the route it is presented on.\n */\nexport const FILE_UPLOAD_GRANT_OPERATIONS = [CoreResourceOperation.CREATE, CoreResourceOperation.UPDATE] as const;\nexport type FileUploadGrantOperation = (typeof FILE_UPLOAD_GRANT_OPERATIONS)[number];\n/** Derived from `CoreResourceOperation` — the named source — rather than a second enum spelling the same two words. */\nexport const FileUploadGrantOperationSchema: z.ZodEnum<{ [K in FileUploadGrantOperation]: K }> = z.enum(FILE_UPLOAD_GRANT_OPERATIONS);\n\n/**\n * Lifecycle of a grant as the status read reports it. Derived from the token row — `isConsumed`,\n * `expiresAt`, `revokedAt` — never stored, so it cannot drift from the row.\n */\nexport enum FileUploadGrantState {\n /** Minted, unexpired, unrevoked, not yet redeemed: an upload will be accepted. */\n PENDING = 'pending',\n /** Redeemed by exactly one upload. `file` names what it produced when the write-back succeeded. */\n REDEEMED = 'redeemed',\n /** Past `expiresAt` without being redeemed. Mint a new one. */\n EXPIRED = 'expired',\n /** Revoked by the minter or an administrator before redemption. */\n REVOKED = 'revoked',\n}\nexport const FileUploadGrantStateSchema: z.ZodEnum<typeof FileUploadGrantState> = z.enum(FileUploadGrantState);\n\n/**\n * The `metadata` a FILE_UPLOAD_GRANT token carries — the ROUTE binding, as opposed to the identity\n * the typed token fields carry. The upload middleware reads this; the execution-context creator\n * deliberately does not.\n */\nexport const FileUploadGrantMetadataSchema: z.ZodObject<{\n fieldName: z.ZodString;\n operation: z.ZodEnum<{ [K in FileUploadGrantOperation]: K }>;\n minter: z.ZodObject<{ entityType: z.ZodEnum<typeof FileUploaderEntityType>; id: z.ZodString }>;\n uploadUrl: z.ZodString;\n producedFileId: z.ZodOptional<z.ZodString>;\n}> = z.object({\n /** The `z_file()` field the upload lands on, as authored (dotted for nested fields). */\n fieldName: z.string().min(1),\n operation: FileUploadGrantOperationSchema,\n /**\n * Who minted — recorded so the uploaded file is attributed to a PERSON or MACHINE, not to the\n * grant.\n *\n * `entityType` is the ENUM, not a string. It was `z.string().min(1)` until 2026-09-08, with the\n * stated reason that \"the uploader enum lives in `zod-decorators`, upstream of this package\" —\n * which is exactly backwards: upstream is what a package MAY import, and this one already does.\n * `files.shared.schemas.ts` in this very directory imports `FileUploaderEntityType` from\n * `@wildo-ai/zod-decorators`, re-exports it, and writes `z.enum(FileUploaderEntityType)` on the\n * FILES row's own `uploadedByEntityType`. So the vocabulary was one import away the whole time and\n * the metadata's copy of the same field was the only one left open.\n *\n * What the enum buys: `metadata` is an UNTYPED bag on the token row, so nothing between the write\n * and the read guarantees its shape — the read is the only place that can. Every reader here goes\n * through `FileUploadGrantMetadataSchema.safeParse`, so an out-of-vocabulary entity type now makes\n * the whole metadata unparseable and the redemption path refuses the grant instead of casting the\n * value into `FileUploaderPrincipal` and carrying it three layers to `validateUploadedByEntityType`.\n *\n * NOT narrowed to the three values `mint` can actually produce (mint refuses an anonymous and a\n * token-borne minter, so `ANONYMOUS_USER` is unreachable): that refusal is a MINT policy, enforced\n * and explained at mint, and re-encoding it here would put half a policy in a schema that cannot\n * say why. The vocabulary of this field is the vocabulary of the principal it names.\n */\n minter: z.object({ entityType: z.enum(FileUploaderEntityType), id: z.string().min(1) }),\n /**\n * The concrete upload URL the grant was minted for. Two jobs, and the second one is why it must be\n * absolute: the status read hands it to the drop page, AND the redemption path compares its PATH\n * against the route the token is presented on (`assertGrantMatchesRoute`). Until 2026-09-08 it was\n * recorded and never read back, so a grant bound to one concrete route could be redeemed on any\n * other route reaching the same (resource, field, operation, row).\n */\n uploadUrl: z.string().url(),\n /** Written after a successful redemption; absent until then. */\n producedFileId: z.string().min(1).optional(),\n});\nexport type FileUploadGrantMetadata = z.infer<typeof FileUploadGrantMetadataSchema>;\n\n/**\n * What a mint returns — identical on the REST door and the MCP tool. Two affordances for one\n * token: `uploadCommand` for a caller that can execute, `uploadPageUrl` for one that must hand a\n * human a link. The token appears in `uploadHeader.value` and inside both commands and the page URL;\n * it is the credential and cannot be omitted. It never appears in any audit row.\n */\nexport const FileUploadGrantSchema: z.ZodObject<{\n grantId: z.ZodString;\n state: z.ZodEnum<typeof FileUploadGrantState>;\n expiresAt: z.ZodString;\n singleUse: z.ZodLiteral<true>;\n target: z.ZodObject<{\n resourceType: z.ZodString;\n fieldName: z.ZodString;\n operation: z.ZodEnum<{ [K in FileUploadGrantOperation]: K }>;\n resourceId: z.ZodNullable<z.ZodString>;\n }>;\n constraints: z.ZodObject<{\n maxBytes: z.ZodNumber;\n allowedMimeTypes: z.ZodArray<z.ZodString>;\n }>;\n uploadUrl: z.ZodString;\n uploadHeader: z.ZodObject<{ name: z.ZodString; value: z.ZodString }>;\n uploadCommand: z.ZodString;\n uploadCommandPowerShell: z.ZodString;\n uploadPageUrl: z.ZodNullable<z.ZodString>;\n statusUrl: z.ZodString;\n note: z.ZodString;\n}> = z.object({\n grantId: z.string().min(1),\n state: FileUploadGrantStateSchema,\n expiresAt: z.string().datetime(),\n singleUse: z.literal(true),\n target: z.object({\n resourceType: z.string().min(1),\n fieldName: z.string().min(1),\n operation: FileUploadGrantOperationSchema,\n resourceId: z.string().min(1).nullable(),\n }),\n /** From the field's own constraint resolver — the same one the upload enforces, so the two cannot disagree. */\n constraints: z.object({\n maxBytes: z.number().int().positive(),\n /** Empty means every type is accepted. */\n allowedMimeTypes: z.array(z.string()),\n }),\n uploadUrl: z.string().url(),\n /** The credential travels in a HEADER on the curl form: paths are logged by every proxy, headers are not. */\n uploadHeader: z.object({ name: z.string().min(1), value: z.string().min(1) }),\n /** No `-f`: on a refusal the JSON error body is the only thing that tells the caller why. */\n uploadCommand: z.string().min(1),\n /** In PowerShell `curl` aliases Invoke-WebRequest, which does not understand `-F`; the real binary is `curl.exe`. */\n uploadCommandPowerShell: z.string().min(1),\n /** `null` when the application declares no frontend service — a headless API has no page to hand a human. */\n uploadPageUrl: z.string().url().nullable(),\n statusUrl: z.string().url(),\n note: z.string().min(1),\n});\nexport type FileUploadGrant = z.infer<typeof FileUploadGrantSchema>;\n\n/**\n * What the public status read returns. The token is the credential, so the read is unauthenticated\n * and returns only what the drop page needs to render and the agent needs to learn the `fileId`:\n * never the file's name (the status URL may be pasted around).\n */\nexport const FileUploadGrantStatusSchema: z.ZodObject<{\n grantId: z.ZodString;\n state: z.ZodEnum<typeof FileUploadGrantState>;\n expiresAt: z.ZodString;\n target: z.ZodObject<{\n resourceType: z.ZodString;\n fieldName: z.ZodString;\n operation: z.ZodEnum<{ [K in FileUploadGrantOperation]: K }>;\n resourceId: z.ZodNullable<z.ZodString>;\n }>;\n constraints: z.ZodObject<{ maxBytes: z.ZodNumber; allowedMimeTypes: z.ZodArray<z.ZodString> }>;\n uploadUrl: z.ZodString;\n uploadHeaderName: z.ZodString;\n file: z.ZodNullable<z.ZodObject<{ fileId: z.ZodString; status: z.ZodEnum<typeof FileStatus> }>>;\n}> = z.object({\n grantId: z.string().min(1),\n state: FileUploadGrantStateSchema,\n expiresAt: z.string().datetime(),\n target: z.object({\n resourceType: z.string().min(1),\n fieldName: z.string().min(1),\n operation: FileUploadGrantOperationSchema,\n resourceId: z.string().min(1).nullable(),\n }),\n constraints: z.object({ maxBytes: z.number().int().positive(), allowedMimeTypes: z.array(z.string()) }),\n uploadUrl: z.string().url(),\n /** The page sets this header itself; the token it already holds is the value. */\n uploadHeaderName: z.string().min(1),\n /** `null` until redeemed, or when the post-redemption write-back failed (re-read the resource instead). */\n file: z.object({ fileId: z.string().min(1), status: z.enum(FileStatus) }).nullable(),\n});\nexport type FileUploadGrantStatus = z.infer<typeof FileUploadGrantStatusSchema>;\n\n/**\n * Body accepted by both mint doors.\n *\n * The three optional file facts mirror what the MCP File Objects proposal has a client declare when\n * it asks to upload (`name`, `mimeType`, `size`): declaring them lets the server refuse a file the\n * field would never accept BEFORE handing out a link, instead of at redemption when the link is\n * already spent. They are advisory for the upload itself — the bytes are validated on receipt\n * regardless — and a declaration that later disagrees with the bytes is refused on receipt too.\n */\nexport const FileUploadGrantMintRequestSchema: z.ZodObject<{\n expiresInMinutes: z.ZodOptional<z.ZodNumber>;\n name: z.ZodOptional<z.ZodString>;\n mimeType: z.ZodOptional<z.ZodString>;\n size: z.ZodOptional<z.ZodNumber>;\n}> = z.object({\n expiresInMinutes: z.number().int().min(1).max(FILE_UPLOAD_GRANT_ABSOLUTE_MAX_MINUTES).optional(),\n /** The file name the caller intends to upload; used for the curl example and checked against nothing else. */\n name: z.string().min(1).max(255).optional(),\n /** Declared MIME type; refused at mint when the field does not accept it. */\n mimeType: z.string().min(1).max(255).optional(),\n /** Declared size in bytes; refused at mint when above the field's maximum. */\n size: z.number().int().positive().optional(),\n}).strict();\nexport type FileUploadGrantMintRequest = z.infer<typeof FileUploadGrantMintRequestSchema>;\n/** @wildo_source:part:end saas.models.file-upload-grant */\n"]}
@@ -83,14 +83,21 @@ export declare function parseFileServeVariant(raw: unknown): FileServeVariant;
83
83
  * to CLEAN / INFECTED / QUARANTINED. `SCANNING`, `INFECTED` and `QUARANTINED` are absent from this
84
84
  * set and therefore blocked, which is the post-scan half of the original Wave 1 note.
85
85
  *
86
- * ⚠️ `UPLOADED` is still admitted, and that is the OPEN question this comment used to hide behind
87
- * "scanning is not enforced yet". Two reasons it is not simply a leftover, and neither is settled:
88
- * scanning is opt-in per field (`shouldScan` reads the field's `fileMetadata`), so an unscanned
89
- * file legitimately terminates at UPLOADED and removing it from this set would make every such
90
- * field undownloadable; and `initiateScan` is fired without being awaited, so even for a scanned
91
- * field there is a window between the upload committing and the status reaching SCANNING in which
92
- * the bytes are servable. Closing that window is a behaviour change with its own decision — see
93
- * the tracker not something to infer from this comment.
86
+ * `UPLOADED` IS admitted, and that is correct rather than a leftover but only because of where
87
+ * the scan gate now sits. Scanning is opt-in per field (`shouldScan` reads the field's
88
+ * `fileMetadata`), so an unscanned file legitimately terminates at UPLOADED and removing it from
89
+ * this set would make every such field undownloadable.
90
+ *
91
+ * The window that used to sit behind that reasoning is CLOSED (#433, 2026-09-08). A file whose
92
+ * field requires a scan never sits at UPLOADED at all: `resource-file-upload-handler` now AWAITS
93
+ * `initiateScan` — which awaits the UPLOADED -> SCANNING transition and only then fires the scan
94
+ * pipeline — BEFORE the upload response is sent. Previously it was fired afterwards without being
95
+ * awaited, so the bytes were servable for the gap between the upload committing and the transition
96
+ * landing.
97
+ *
98
+ * So the invariant this set relies on is external to it: **a required scan reaches SCANNING before
99
+ * anyone learns the upload succeeded.** Do not restore a fire-and-forget scan initiation, and do
100
+ * not add UPLOADED-adjacent statuses here without asking which side of that gate they fall on.
94
101
  */
95
102
  export declare const FILE_DOWNLOADABLE_STATUSES: ReadonlySet<FileStatus>;
96
103
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"files.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../src/files/files.shared.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACtI,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAG7E,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACvF,YAAY,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEtE;;;;;;;;;;;;GAYG;AACH,oBAAY,UAAU;IACpB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IAEjB,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,WAAW,gBAAgB;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,oBAAY,gBAAgB;IAC1B,QAAQ,aAAa;IACrB,SAAS,cAAc;CACxB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAIpE;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,UAAU,CAK7D,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,+BAA+B,EAAE,WAAW,CAAC,UAAU,CAElE,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,aAAa,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,UAAU,CAOxD,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,UAAU,EAAE,CAAC,CAWvF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,UAAU,CAGzD,CAAC;AAGH,eAAO,MAAM,mBAAmB,iHAItB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAyBpE,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAqBV;AAuGD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BrB,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,GAAG,qBAAqB,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,qGAAqG;IACrG,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"files.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../src/files/files.shared.schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,KAAK,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AACtI,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAG7E,YAAY,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AACvF,YAAY,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAEtE;;;;;;;;;;;;GAYG;AACH,oBAAY,UAAU;IACpB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IACjB,OAAO,YAAY;IACnB,QAAQ,aAAa;IACrB,MAAM,WAAW;IAEjB,QAAQ,aAAa;IACrB,KAAK,UAAU;IACf,QAAQ,aAAa;IACrB,WAAW,gBAAgB;CAC5B;AAED;;;;;;;;;;;;GAYG;AACH,oBAAY,gBAAgB;IAC1B,QAAQ,aAAa;IACrB,SAAS,cAAc;CACxB;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,gBAAgB,CAIpE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,0BAA0B,EAAE,WAAW,CAAC,UAAU,CAK7D,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,+BAA+B,EAAE,WAAW,CAAC,UAAU,CAElE,CAAC;AAEH;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,aAAa,CAAC;AAEvD;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,WAAW,CAAC,UAAU,CAOxD,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,EAAE,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,SAAS,UAAU,EAAE,CAAC,CAWvF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,eAAO,MAAM,sBAAsB,EAAE,WAAW,CAAC,UAAU,CAGzD,CAAC;AAGH,eAAO,MAAM,mBAAmB,iHAItB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAyBpE,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,YAAY,EAAE,gBAAgB,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAqBV;AAuGD,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6BrB,CAAC;AACH,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,GAAG,qBAAqB,CAAC;AAEtE;;;GAGG;AACH,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,gBAAgB,CAAC;IAC/B,qGAAqG;IACrG,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB"}
@@ -88,14 +88,21 @@ export function parseFileServeVariant(raw) {
88
88
  * to CLEAN / INFECTED / QUARANTINED. `SCANNING`, `INFECTED` and `QUARANTINED` are absent from this
89
89
  * set and therefore blocked, which is the post-scan half of the original Wave 1 note.
90
90
  *
91
- * ⚠️ `UPLOADED` is still admitted, and that is the OPEN question this comment used to hide behind
92
- * "scanning is not enforced yet". Two reasons it is not simply a leftover, and neither is settled:
93
- * scanning is opt-in per field (`shouldScan` reads the field's `fileMetadata`), so an unscanned
94
- * file legitimately terminates at UPLOADED and removing it from this set would make every such
95
- * field undownloadable; and `initiateScan` is fired without being awaited, so even for a scanned
96
- * field there is a window between the upload committing and the status reaching SCANNING in which
97
- * the bytes are servable. Closing that window is a behaviour change with its own decision — see
98
- * the tracker not something to infer from this comment.
91
+ * `UPLOADED` IS admitted, and that is correct rather than a leftover but only because of where
92
+ * the scan gate now sits. Scanning is opt-in per field (`shouldScan` reads the field's
93
+ * `fileMetadata`), so an unscanned file legitimately terminates at UPLOADED and removing it from
94
+ * this set would make every such field undownloadable.
95
+ *
96
+ * The window that used to sit behind that reasoning is CLOSED (#433, 2026-09-08). A file whose
97
+ * field requires a scan never sits at UPLOADED at all: `resource-file-upload-handler` now AWAITS
98
+ * `initiateScan` — which awaits the UPLOADED -> SCANNING transition and only then fires the scan
99
+ * pipeline — BEFORE the upload response is sent. Previously it was fired afterwards without being
100
+ * awaited, so the bytes were servable for the gap between the upload committing and the transition
101
+ * landing.
102
+ *
103
+ * So the invariant this set relies on is external to it: **a required scan reaches SCANNING before
104
+ * anyone learns the upload succeeded.** Do not restore a fire-and-forget scan initiation, and do
105
+ * not add UPLOADED-adjacent statuses here without asking which side of that gate they fall on.
99
106
  */
100
107
  export const FILE_DOWNLOADABLE_STATUSES = new Set([
101
108
  FileStatus.UPLOADED,
@@ -1 +1 @@
1
- {"version":3,"file":"files.shared.schemas.js","sourceRoot":"","sources":["../../../../src/files/files.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Files Shared Schemas\n *\n * Reusable schemas for file uploads and file handling.\n *\n * ## Scope Model\n *\n * Files use a **segregated scope model** where scope identifiers are separate fields\n * (not hierarchical). A file belongs to exactly one primary scope:\n * - APPLICATION: App-level shared files (e.g., branding assets)\n * - ORGANIZATIONS: Org-scoped files (e.g., org documents)\n * - USER_SELF: User-private files owned by a single user (NO org — USER_SELF and\n * ORGANIZATIONS are independent primary-scope axes; `applicationId` is the bucket anchor)\n *\n * `ANONYMOUS` is intentionally excluded from the file contract for now. The\n * file layer does not yet define anonymous upload, storage, and access semantics\n * end to end, so file resources fail closed instead of pretending support.\n *\n * Scope is **derived from the parent resource's resourcePrimaryScope** when linking.\n * Access rights are **inherited from the z_file() field** on the parent resource.\n *\n * Note: FileMetadata is defined in @wildo-ai/zod-decorators\n */\n\nimport { z } from 'zod';\nimport { PersonalDataCategory } from '../compliance/privacy/personal-data-category.shared.schemas';\nimport { FileDisplayNature, FileStorageAccepted, FileUploaderEntityType, type FileUploaderOwnership } from '@wildo-ai/zod-decorators';\nimport { ResourcePrimaryScope } from '../resources/resources.shared.schemas';\n\n// Re-export FileMetadata from zod-decorators for convenience\nexport type { FileMetadata } from '@wildo-ai/zod-decorators';\nexport { FileUploaderEntityType, FileStorageAccepted } from '@wildo-ai/zod-decorators';\nexport type { FileUploaderOwnership } from '@wildo-ai/zod-decorators';\n\n/**\n * File status lifecycle enum\n *\n * NOTE — no extraction/indexing members. `EXTRACTING` / `EXTRACTED` / `INDEXED` were removed\n * 2026-08-26 with the resource-native RAG reshape (plan `resource-rag-capability`, Phase 1):\n * text extraction and embedding state are per-FIELD, per-CHUNK facts, and the RAG chunk rows\n * (Phase 2's derived-data tier, keyed `(resourceType, resourceId, fieldName, chunkIndex)` with a\n * NULLABLE `vector` as the \"needs embedding\" ledger) carry them. A single file-level status could\n * never say WHICH field's corpus was current — it was the wrong shape, not merely unused — and\n * `INDEXED` had already shipped one false claim (written to mean \"text was copied\", read as\n * \"searchable\": https://github.com/wildo-ai/wildo-ai/issues/46). The file lifecycle now ends at\n * upload/scan/link/erasure concerns, which really are per-file.\n */\nexport enum FileStatus {\n PENDING = 'pending',\n UPLOADED = 'uploaded',\n LINKED = 'linked',\n DELETED = 'deleted',\n ORPHANED = 'orphaned',\n FAILED = 'failed',\n\n SCANNING = 'scanning',\n CLEAN = 'clean',\n INFECTED = 'infected',\n QUARANTINED = 'quarantined',\n}\n\n/**\n * Rendition of a file's bytes requested from the serve route via `?variant=`.\n *\n * - `ORIGINAL` — the stored bytes, unchanged (the default when the param is absent).\n * - `THUMBNAIL` — a small, downscaled `webp` derived on the fly for preview surfaces\n * (nav avatar, list/card image) so a preview never pulls a multi-MB original. Only\n * raster images are eligible; for any other file the serve route transparently\n * falls back to the original bytes.\n *\n * This is the WIRE CONTRACT for the serve route's `variant` query parameter — shared\n * by the frontend (which builds `?variant=thumbnail` preview URLs) and the backend\n * serve route (which parses it). Keep the string values stable across releases.\n */\nexport enum FileServeVariant {\n ORIGINAL = 'original',\n THUMBNAIL = 'thumbnail',\n}\n\n/**\n * Parse an untrusted `?variant=` query value into a {@link FileServeVariant}.\n * Absent or unrecognized values fall back to `ORIGINAL` (fail-safe: an unknown\n * variant serves the untransformed bytes rather than erroring).\n */\nexport function parseFileServeVariant(raw: unknown): FileServeVariant {\n return raw === FileServeVariant.THUMBNAIL\n ? FileServeVariant.THUMBNAIL\n : FileServeVariant.ORIGINAL;\n}\n\n/**\n * Statuses in which a file's bytes are safe to serve for download.\n *\n * AV scanning IS wired: `FileScanningBackendService` is bound in the container and the resource\n * upload handler calls `shouldScan` then `initiateScan`, so a scanned file moves through SCANNING\n * to CLEAN / INFECTED / QUARANTINED. `SCANNING`, `INFECTED` and `QUARANTINED` are absent from this\n * set and therefore blocked, which is the post-scan half of the original Wave 1 note.\n *\n * ⚠️ `UPLOADED` is still admitted, and that is the OPEN question this comment used to hide behind\n * \"scanning is not enforced yet\". Two reasons it is not simply a leftover, and neither is settled:\n * scanning is opt-in per field (`shouldScan` reads the field's `fileMetadata`), so an unscanned\n * file legitimately terminates at UPLOADED and removing it from this set would make every such\n * field undownloadable; and `initiateScan` is fired without being awaited, so even for a scanned\n * field there is a window between the upload committing and the status reaching SCANNING in which\n * the bytes are servable. Closing that window is a behaviour change with its own decision — see\n * the tracker — not something to infer from this comment.\n */\nexport const FILE_DOWNLOADABLE_STATUSES: ReadonlySet<FileStatus> = new Set([\n FileStatus.UPLOADED,\n FileStatus.LINKED,\n FileStatus.ORPHANED,\n FileStatus.CLEAN,\n]);\n\n/**\n * Statuses in which a file's own METADATA must no longer be disclosed on the GLOBAL\n * `GET /files/:fileId/metadata` route (gate **G-FILE**).\n *\n * Blocking the BYTES is not enough. A privacy erasure marks the file `DELETED`, but physical cleanup\n * is a batch that runs much later — so between the two, `originalFilename` (`passport-jane-doe.pdf`)\n * and `uploadedBy` stayed readable by any member of the file's scope. \"Erased\" that leaves the\n * filename readable for weeks is not erased.\n *\n * DELIBERATELY NARROWER than {@link FILE_BLOCKED_STATUSES}: `PENDING`, `SCANNING`, `FAILED` and\n * `INFECTED` files are not servable either, but their metadata IS the diagnostic surface an uploader\n * legitimately polls (\"upload failed\", \"scan in progress\"). Withholding those would break upload UX\n * while protecting nothing — none of them is an erasure outcome. `DELETED` is the terminal state (it\n * has no outgoing transition in {@link FILE_STATUS_TRANSITIONS}) and the one an erasure produces.\n */\nexport const FILE_METADATA_WITHHELD_STATUSES: ReadonlySet<FileStatus> = new Set([\n FileStatus.DELETED,\n]);\n\n/**\n * Value written over a file's `filename` / `originalFilename` when the file is erased for privacy.\n *\n * Both fields are REQUIRED (`z.string().min(1)`), so an erasure cannot null them without a schema\n * reshape; overwriting with one shared, non-identifying constant erases the personal data while\n * keeping the row valid, greppable and obviously-erased in logs and admin surfaces. Deliberately a\n * fixed constant rather than a per-file token: two erased files must not be distinguishable by name.\n */\nexport const ERASED_FILE_NAME_PLACEHOLDER = '[erased]';\n\n/**\n * Statuses that represent terminal or non-servable states.\n * Files in these states must not be served for download.\n */\nexport const FILE_BLOCKED_STATUSES: ReadonlySet<FileStatus> = new Set([\n FileStatus.PENDING,\n FileStatus.DELETED,\n FileStatus.FAILED,\n FileStatus.SCANNING,\n FileStatus.INFECTED,\n FileStatus.QUARANTINED,\n]);\n\n/**\n * Valid lifecycle transitions.\n *\n * Each key is a source status; the value is the set of statuses it can\n * transition to. Any transition not listed here is invalid.\n */\nexport const FILE_STATUS_TRANSITIONS: Readonly<Record<FileStatus, readonly FileStatus[]>> = {\n [FileStatus.PENDING]: [FileStatus.UPLOADED, FileStatus.FAILED],\n [FileStatus.UPLOADED]: [FileStatus.LINKED, FileStatus.SCANNING, FileStatus.ORPHANED, FileStatus.DELETED, FileStatus.FAILED],\n [FileStatus.SCANNING]: [FileStatus.CLEAN, FileStatus.INFECTED, FileStatus.FAILED],\n [FileStatus.CLEAN]: [FileStatus.LINKED, FileStatus.ORPHANED, FileStatus.DELETED],\n [FileStatus.INFECTED]: [FileStatus.QUARANTINED, FileStatus.DELETED],\n [FileStatus.QUARANTINED]: [FileStatus.DELETED],\n [FileStatus.LINKED]: [FileStatus.ORPHANED, FileStatus.DELETED],\n [FileStatus.ORPHANED]: [FileStatus.LINKED, FileStatus.DELETED],\n [FileStatus.DELETED]: [],\n [FileStatus.FAILED]: [FileStatus.DELETED],\n};\n\n/**\n * Statuses from which a file may be LINKED to a resource field — the set the link-time checks\n * (`FileOperationHandlerBackendService.validateFileFieldsForCreate/Update`,\n * `FilesBackendService.linkFileToResource`) consult.\n *\n * ## Why this set exists (issue #320)\n *\n * Those checks used to compare against the literal `FileStatus.UPLOADED`, while\n * {@link FILE_STATUS_TRANSITIONS} — the authority on what a status MEANS — already allowed\n * `CLEAN → LINKED`. So a file the scanner had just certified safe was refused at the one moment it was\n * needed, with an error naming `UPLOADED` as the expected state, and whether a scanned file could be\n * attached at all depended on how fast the caller was relative to the scanner. Two `$in` queries in\n * `FilesBackendService` had meanwhile grown their own `[UPLOADED, CLEAN]` pairs — three copies of one\n * answer, one of them wrong. This is the single copy.\n *\n * ## Derived-CHECKED against the map, not computed from it\n *\n * Every member here has `LINKED` among its outgoing transitions (pinned by\n * `files.shared.status-sets.test.ts`), so this set can never admit a transition the map forbids.\n * It is nonetheless written out rather than computed, because the map is a superset of what linking\n * should admit today:\n *\n * - `ORPHANED → LINKED` is legal in the map (a re-link after the parent was deleted with the file\n * kept) and is DELIBERATELY NOT admitted here. Re-linking an orphan is a distinct capability with\n * its own questions — whose scope does the file re-enter, what happens to its old key — and\n * admitting it as a side effect of fixing the `CLEAN` refusal would decide those questions by\n * accident. The pin asserts this exclusion by name so widening it is a choice, not drift.\n * - `SCANNING` is absent because the map forbids `SCANNING → LINKED`: a file whose scan is in\n * flight is not yet known to be safe. The link path names that case with\n * `FILE_SCAN_IN_PROGRESS` so the caller learns to retry, rather than the generic refusal.\n */\nexport const FILE_LINKABLE_STATUSES: ReadonlySet<FileStatus> = new Set([\n FileStatus.UPLOADED,\n FileStatus.CLEAN,\n]);\n\n\nexport const FILE_PRIMARY_SCOPES = [\n ResourcePrimaryScope.APPLICATION,\n ResourcePrimaryScope.ORGANIZATIONS,\n ResourcePrimaryScope.USER_SELF,\n] as const;\n\nexport type FilePrimaryScope = (typeof FILE_PRIMARY_SCOPES)[number];\n\nfunction hasFileScopeIdentifierValue(value: string | undefined): boolean {\n return typeof value === 'string' && value.trim() !== '';\n}\n\nfunction validateUploaderPair(\n file: {\n uploadedBy?: string;\n uploadedByEntityType?: FileUploaderEntityType;\n },\n ctx: z.RefinementCtx,\n): void {\n const hasUploadedBy = hasFileScopeIdentifierValue(file.uploadedBy);\n const hasUploadedByEntityType = file.uploadedByEntityType !== undefined;\n\n if (hasUploadedBy !== hasUploadedByEntityType) {\n ctx.addIssue({\n code: 'custom',\n path: hasUploadedBy ? ['uploadedByEntityType'] : ['uploadedBy'],\n message: 'uploadedBy and uploadedByEntityType must either both be set or both be omitted',\n });\n }\n}\n\nexport function validateFileScopeIdentifiers(scope: {\n primaryScope: FilePrimaryScope;\n applicationId: string;\n organizationId?: string;\n userId?: string;\n}): boolean {\n const hasApplicationId = hasFileScopeIdentifierValue(scope.applicationId);\n const hasOrganizationId = hasFileScopeIdentifierValue(scope.organizationId);\n const hasUserId = hasFileScopeIdentifierValue(scope.userId);\n\n switch (scope.primaryScope) {\n case ResourcePrimaryScope.APPLICATION:\n return hasApplicationId && !hasOrganizationId && !hasUserId;\n case ResourcePrimaryScope.ORGANIZATIONS:\n // applicationId is always required (tenant isolation); organizationId is the scope discriminator.\n return hasApplicationId && hasOrganizationId && !hasUserId;\n case ResourcePrimaryScope.USER_SELF:\n // Primary scopes are a SEPARATION OF CONCERN: USER_SELF and ORGANIZATIONS are\n // independent axes. A user's self-owned file is user-owned, NOT org-owned —\n // `userId` is the scope discriminator and `applicationId` is the tenant/bucket\n // anchor. `organizationId` MUST be absent (a present org would conflate the two\n // scopes). Fail closed on any org value.\n return hasApplicationId && hasUserId && !hasOrganizationId;\n default:\n return false;\n }\n}\n\n/**\n * File resource schema\n *\n * Stores file metadata and links files to resources.\n * Files are stored via app-managed storage providers (MinIO/S3, local directory, etc.),\n * this schema tracks metadata only.\n *\n * ## Storage Identity Convention\n * `storageProvider` + `storageRef` are the persisted routing truth used to\n * reach the active storage backend. `storageKey` remains framework metadata\n * that captures the file's derived scope path for bookkeeping, diagnostics,\n * and future storage contract evolution.\n *\n * `storageKey` includes scope path derived from primaryScope:\n * - APPLICATION: `app/{applicationId}/{fileId}`\n * - ORGANIZATIONS: `org/{organizationId}/{fileId}`\n * - USER_SELF: `user/{userId}/{fileId}` (owner is the user; no org segment)\n */\nconst FileSchemaBase = z.object({\n fileId: z.string().min(1).isPrimaryKey().isSummaryField(),\n\n // ========== File Metadata ==========\n // USER_CONTENT on both names. A filename is chosen by the person and routinely IS the personal\n // datum — \"scan-2026-medical.pdf\" discloses a special category before the file is opened. The\n // file's BYTES are not a field here (this resource is metadata over object storage), so this is the\n // only place the content axis can be declared at all.\n filename: z.string().min(1).isDBIndexed().isSummaryField().dataCategories(PersonalDataCategory.USER_CONTENT),\n originalFilename: z.string().min(1).isSummaryField().dataCategories(PersonalDataCategory.USER_CONTENT),\n mimeType: z.string().min(1).isDBIndexed().isSummaryField(),\n size: z.number().min(0).isSummaryField(),\n extension: z.string().optional(),\n checksum: z.string().optional().isDBIndexed(),\n\n // ========== Storage ==========\n // `storageProvider` + `storageRef` are the persisted backend-routing truth.\n storageProvider: z.enum(FileStorageAccepted).optional().isDBIndexed(),\n storageRef: z.string().min(1).optional().isDBIndexed(),\n // `storageKey` is still scoped metadata, not the storage backend handle. It embeds the\n // file identity (`_id`, surfaced as the `fileId` virtual), so it is derived + persisted\n // AFTER the row is created (insert-first) — hence optional at create time. `createFile`\n // sets it once `_id` exists, and `linkFileToResource` re-derives it when the file's scope\n // is finalized.\n storageKey: z.string().min(1).optional().isDBIndexed(),\n url: z.url().optional(), // Cached URL (may be presigned)\n\n // ========== Status & Lifecycle ==========\n status: z.enum(FileStatus).default(FileStatus.PENDING).isDBIndexed().isSummaryField(),\n\n // ========== Nature-specific Metadata ==========\n // Inferred from MIME type or set by analysis services (F4-03)\n // Resolved display nature (IMAGE/VIDEO/AUDIO/DOCUMENT/GENERIC) — NOT the schema-level FileNature.\n // Set by resolveFileDisplayNature() during upload or inferred from MIME type in toMetadataResponse().\n // Schema declares FileNature (e.g., PDF, OFFICE), but the DB stores the resolved FileDisplayNature.\n nature: z.enum(FileDisplayNature).optional().isDBIndexed(),\n // Image-specific\n width: z.number().positive().optional(),\n height: z.number().positive().optional(),\n thumbnailUrl: z.url().optional(),\n // Video/Audio-specific (populated by IFileVideoAnalyzer / IFileAudioAnalyzer)\n duration: z.number().positive().optional(), // Duration in seconds\n // Document-specific (populated by IFileDocumentAnalyzer)\n pageCount: z.number().positive().optional(),\n\n // ========== Resource Linking ==========\n // When linked, scope is derived from parent resource's resourcePrimaryScope\n linkedResourceType: z.string().optional().isDBIndexed(),\n linkedResourceId: z.string().optional().isDBIndexed(),\n linkedFieldName: z.string().optional(),\n\n // ========== Primary Scope ==========\n // Derived from parent resource's resourcePrimaryScope when linking\n // Determines access control and storage path\n primaryScope: z.enum(FILE_PRIMARY_SCOPES).optional().isDBIndexed(),\n\n // ========== Scope Identifiers ==========\n // applicationId is ALWAYS set (from execution context at creation time) — it is the\n // top-level tenant isolation field present on every file record regardless of primaryScope.\n // organizationId and userId are populated only when the file's primaryScope requires them.\n\n applicationId: z.string().isDBIndexed(),\n\n // ORGANIZATIONS scope: org-scoped files. Set ONLY for ORGANIZATIONS-scoped files —\n // never for USER_SELF (the two scopes are independent axes, separation of concern).\n organizationId: z.string().optional().isDBIndexed(),\n\n // USER_SELF scope: user-private files owned by one user. Set ONLY for USER_SELF-scoped\n // files; the owner is the user (no org). `applicationId` is the tenant/bucket anchor.\n userId: z.string().optional().isDBIndexed(),\n\n // ========== Upload Metadata ==========\n // The uploader principal is persisted as a raw id + type pair only.\n // Any richer label/entity hydration is intentionally client-driven.\n uploadedBy: z.string().trim().min(1).optional().isDBIndexed(),\n uploadedByEntityType: z.enum(FileUploaderEntityType).optional().isDBIndexed(),\n\n // ========== Timestamps ==========\n uploadedAt: z.date().default(() => new Date()).isDBIndexed().isSummaryField().excludeFromCreate().excludeFromUpdate(),\n updatedAt: z.date().default(() => new Date()).isDBIndexed().excludeFromCreate().excludeFromUpdate(),\n deletedAt: z.date().optional().isDBIndexed().excludeFromCreate(),\n});\n\nexport const FileSchema = FileSchemaBase.superRefine((file, ctx) => {\n validateUploaderPair(file, ctx);\n\n if (!file.primaryScope) {\n // Pre-link state: applicationId is always present (set from execution context at upload time),\n // but organizationId/userId must not be set without a primaryScope discriminator.\n if (hasFileScopeIdentifierValue(file.organizationId) || hasFileScopeIdentifierValue(file.userId)) {\n ctx.addIssue({\n code: 'custom',\n path: ['primaryScope'],\n message: 'primaryScope is required when organizationId or userId are present',\n });\n }\n return;\n }\n\n if (!validateFileScopeIdentifiers({\n primaryScope: file.primaryScope,\n applicationId: file.applicationId,\n organizationId: file.organizationId,\n userId: file.userId,\n })) {\n ctx.addIssue({\n code: 'custom',\n path: ['primaryScope'],\n message: 'File scope identifiers must match the declared primaryScope',\n });\n }\n\n});\nexport type File = z.infer<typeof FileSchema> & FileUploaderOwnership;\n\n/**\n * Scope identifiers for file access control.\n * Populated based on primaryScope when file is created/linked.\n */\nexport interface FileScopeIdentifiers {\n primaryScope: FilePrimaryScope;\n /** Always required — top-level tenant isolation key, set from execution context at file creation. */\n applicationId: string;\n organizationId?: string;\n userId?: string;\n}\n"]}
1
+ {"version":3,"file":"files.shared.schemas.js","sourceRoot":"","sources":["../../../../src/files/files.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Files Shared Schemas\n *\n * Reusable schemas for file uploads and file handling.\n *\n * ## Scope Model\n *\n * Files use a **segregated scope model** where scope identifiers are separate fields\n * (not hierarchical). A file belongs to exactly one primary scope:\n * - APPLICATION: App-level shared files (e.g., branding assets)\n * - ORGANIZATIONS: Org-scoped files (e.g., org documents)\n * - USER_SELF: User-private files owned by a single user (NO org — USER_SELF and\n * ORGANIZATIONS are independent primary-scope axes; `applicationId` is the bucket anchor)\n *\n * `ANONYMOUS` is intentionally excluded from the file contract for now. The\n * file layer does not yet define anonymous upload, storage, and access semantics\n * end to end, so file resources fail closed instead of pretending support.\n *\n * Scope is **derived from the parent resource's resourcePrimaryScope** when linking.\n * Access rights are **inherited from the z_file() field** on the parent resource.\n *\n * Note: FileMetadata is defined in @wildo-ai/zod-decorators\n */\n\nimport { z } from 'zod';\nimport { PersonalDataCategory } from '../compliance/privacy/personal-data-category.shared.schemas';\nimport { FileDisplayNature, FileStorageAccepted, FileUploaderEntityType, type FileUploaderOwnership } from '@wildo-ai/zod-decorators';\nimport { ResourcePrimaryScope } from '../resources/resources.shared.schemas';\n\n// Re-export FileMetadata from zod-decorators for convenience\nexport type { FileMetadata } from '@wildo-ai/zod-decorators';\nexport { FileUploaderEntityType, FileStorageAccepted } from '@wildo-ai/zod-decorators';\nexport type { FileUploaderOwnership } from '@wildo-ai/zod-decorators';\n\n/**\n * File status lifecycle enum\n *\n * NOTE — no extraction/indexing members. `EXTRACTING` / `EXTRACTED` / `INDEXED` were removed\n * 2026-08-26 with the resource-native RAG reshape (plan `resource-rag-capability`, Phase 1):\n * text extraction and embedding state are per-FIELD, per-CHUNK facts, and the RAG chunk rows\n * (Phase 2's derived-data tier, keyed `(resourceType, resourceId, fieldName, chunkIndex)` with a\n * NULLABLE `vector` as the \"needs embedding\" ledger) carry them. A single file-level status could\n * never say WHICH field's corpus was current — it was the wrong shape, not merely unused — and\n * `INDEXED` had already shipped one false claim (written to mean \"text was copied\", read as\n * \"searchable\": https://github.com/wildo-ai/wildo-ai/issues/46). The file lifecycle now ends at\n * upload/scan/link/erasure concerns, which really are per-file.\n */\nexport enum FileStatus {\n PENDING = 'pending',\n UPLOADED = 'uploaded',\n LINKED = 'linked',\n DELETED = 'deleted',\n ORPHANED = 'orphaned',\n FAILED = 'failed',\n\n SCANNING = 'scanning',\n CLEAN = 'clean',\n INFECTED = 'infected',\n QUARANTINED = 'quarantined',\n}\n\n/**\n * Rendition of a file's bytes requested from the serve route via `?variant=`.\n *\n * - `ORIGINAL` — the stored bytes, unchanged (the default when the param is absent).\n * - `THUMBNAIL` — a small, downscaled `webp` derived on the fly for preview surfaces\n * (nav avatar, list/card image) so a preview never pulls a multi-MB original. Only\n * raster images are eligible; for any other file the serve route transparently\n * falls back to the original bytes.\n *\n * This is the WIRE CONTRACT for the serve route's `variant` query parameter — shared\n * by the frontend (which builds `?variant=thumbnail` preview URLs) and the backend\n * serve route (which parses it). Keep the string values stable across releases.\n */\nexport enum FileServeVariant {\n ORIGINAL = 'original',\n THUMBNAIL = 'thumbnail',\n}\n\n/**\n * Parse an untrusted `?variant=` query value into a {@link FileServeVariant}.\n * Absent or unrecognized values fall back to `ORIGINAL` (fail-safe: an unknown\n * variant serves the untransformed bytes rather than erroring).\n */\nexport function parseFileServeVariant(raw: unknown): FileServeVariant {\n return raw === FileServeVariant.THUMBNAIL\n ? FileServeVariant.THUMBNAIL\n : FileServeVariant.ORIGINAL;\n}\n\n/**\n * Statuses in which a file's bytes are safe to serve for download.\n *\n * AV scanning IS wired: `FileScanningBackendService` is bound in the container and the resource\n * upload handler calls `shouldScan` then `initiateScan`, so a scanned file moves through SCANNING\n * to CLEAN / INFECTED / QUARANTINED. `SCANNING`, `INFECTED` and `QUARANTINED` are absent from this\n * set and therefore blocked, which is the post-scan half of the original Wave 1 note.\n *\n * `UPLOADED` IS admitted, and that is correct rather than a leftover — but only because of where\n * the scan gate now sits. Scanning is opt-in per field (`shouldScan` reads the field's\n * `fileMetadata`), so an unscanned file legitimately terminates at UPLOADED and removing it from\n * this set would make every such field undownloadable.\n *\n * The window that used to sit behind that reasoning is CLOSED (#433, 2026-09-08). A file whose\n * field requires a scan never sits at UPLOADED at all: `resource-file-upload-handler` now AWAITS\n * `initiateScan` — which awaits the UPLOADED -> SCANNING transition and only then fires the scan\n * pipeline — BEFORE the upload response is sent. Previously it was fired afterwards without being\n * awaited, so the bytes were servable for the gap between the upload committing and the transition\n * landing.\n *\n * So the invariant this set relies on is external to it: **a required scan reaches SCANNING before\n * anyone learns the upload succeeded.** Do not restore a fire-and-forget scan initiation, and do\n * not add UPLOADED-adjacent statuses here without asking which side of that gate they fall on.\n */\nexport const FILE_DOWNLOADABLE_STATUSES: ReadonlySet<FileStatus> = new Set([\n FileStatus.UPLOADED,\n FileStatus.LINKED,\n FileStatus.ORPHANED,\n FileStatus.CLEAN,\n]);\n\n/**\n * Statuses in which a file's own METADATA must no longer be disclosed on the GLOBAL\n * `GET /files/:fileId/metadata` route (gate **G-FILE**).\n *\n * Blocking the BYTES is not enough. A privacy erasure marks the file `DELETED`, but physical cleanup\n * is a batch that runs much later — so between the two, `originalFilename` (`passport-jane-doe.pdf`)\n * and `uploadedBy` stayed readable by any member of the file's scope. \"Erased\" that leaves the\n * filename readable for weeks is not erased.\n *\n * DELIBERATELY NARROWER than {@link FILE_BLOCKED_STATUSES}: `PENDING`, `SCANNING`, `FAILED` and\n * `INFECTED` files are not servable either, but their metadata IS the diagnostic surface an uploader\n * legitimately polls (\"upload failed\", \"scan in progress\"). Withholding those would break upload UX\n * while protecting nothing — none of them is an erasure outcome. `DELETED` is the terminal state (it\n * has no outgoing transition in {@link FILE_STATUS_TRANSITIONS}) and the one an erasure produces.\n */\nexport const FILE_METADATA_WITHHELD_STATUSES: ReadonlySet<FileStatus> = new Set([\n FileStatus.DELETED,\n]);\n\n/**\n * Value written over a file's `filename` / `originalFilename` when the file is erased for privacy.\n *\n * Both fields are REQUIRED (`z.string().min(1)`), so an erasure cannot null them without a schema\n * reshape; overwriting with one shared, non-identifying constant erases the personal data while\n * keeping the row valid, greppable and obviously-erased in logs and admin surfaces. Deliberately a\n * fixed constant rather than a per-file token: two erased files must not be distinguishable by name.\n */\nexport const ERASED_FILE_NAME_PLACEHOLDER = '[erased]';\n\n/**\n * Statuses that represent terminal or non-servable states.\n * Files in these states must not be served for download.\n */\nexport const FILE_BLOCKED_STATUSES: ReadonlySet<FileStatus> = new Set([\n FileStatus.PENDING,\n FileStatus.DELETED,\n FileStatus.FAILED,\n FileStatus.SCANNING,\n FileStatus.INFECTED,\n FileStatus.QUARANTINED,\n]);\n\n/**\n * Valid lifecycle transitions.\n *\n * Each key is a source status; the value is the set of statuses it can\n * transition to. Any transition not listed here is invalid.\n */\nexport const FILE_STATUS_TRANSITIONS: Readonly<Record<FileStatus, readonly FileStatus[]>> = {\n [FileStatus.PENDING]: [FileStatus.UPLOADED, FileStatus.FAILED],\n [FileStatus.UPLOADED]: [FileStatus.LINKED, FileStatus.SCANNING, FileStatus.ORPHANED, FileStatus.DELETED, FileStatus.FAILED],\n [FileStatus.SCANNING]: [FileStatus.CLEAN, FileStatus.INFECTED, FileStatus.FAILED],\n [FileStatus.CLEAN]: [FileStatus.LINKED, FileStatus.ORPHANED, FileStatus.DELETED],\n [FileStatus.INFECTED]: [FileStatus.QUARANTINED, FileStatus.DELETED],\n [FileStatus.QUARANTINED]: [FileStatus.DELETED],\n [FileStatus.LINKED]: [FileStatus.ORPHANED, FileStatus.DELETED],\n [FileStatus.ORPHANED]: [FileStatus.LINKED, FileStatus.DELETED],\n [FileStatus.DELETED]: [],\n [FileStatus.FAILED]: [FileStatus.DELETED],\n};\n\n/**\n * Statuses from which a file may be LINKED to a resource field — the set the link-time checks\n * (`FileOperationHandlerBackendService.validateFileFieldsForCreate/Update`,\n * `FilesBackendService.linkFileToResource`) consult.\n *\n * ## Why this set exists (issue #320)\n *\n * Those checks used to compare against the literal `FileStatus.UPLOADED`, while\n * {@link FILE_STATUS_TRANSITIONS} — the authority on what a status MEANS — already allowed\n * `CLEAN → LINKED`. So a file the scanner had just certified safe was refused at the one moment it was\n * needed, with an error naming `UPLOADED` as the expected state, and whether a scanned file could be\n * attached at all depended on how fast the caller was relative to the scanner. Two `$in` queries in\n * `FilesBackendService` had meanwhile grown their own `[UPLOADED, CLEAN]` pairs — three copies of one\n * answer, one of them wrong. This is the single copy.\n *\n * ## Derived-CHECKED against the map, not computed from it\n *\n * Every member here has `LINKED` among its outgoing transitions (pinned by\n * `files.shared.status-sets.test.ts`), so this set can never admit a transition the map forbids.\n * It is nonetheless written out rather than computed, because the map is a superset of what linking\n * should admit today:\n *\n * - `ORPHANED → LINKED` is legal in the map (a re-link after the parent was deleted with the file\n * kept) and is DELIBERATELY NOT admitted here. Re-linking an orphan is a distinct capability with\n * its own questions — whose scope does the file re-enter, what happens to its old key — and\n * admitting it as a side effect of fixing the `CLEAN` refusal would decide those questions by\n * accident. The pin asserts this exclusion by name so widening it is a choice, not drift.\n * - `SCANNING` is absent because the map forbids `SCANNING → LINKED`: a file whose scan is in\n * flight is not yet known to be safe. The link path names that case with\n * `FILE_SCAN_IN_PROGRESS` so the caller learns to retry, rather than the generic refusal.\n */\nexport const FILE_LINKABLE_STATUSES: ReadonlySet<FileStatus> = new Set([\n FileStatus.UPLOADED,\n FileStatus.CLEAN,\n]);\n\n\nexport const FILE_PRIMARY_SCOPES = [\n ResourcePrimaryScope.APPLICATION,\n ResourcePrimaryScope.ORGANIZATIONS,\n ResourcePrimaryScope.USER_SELF,\n] as const;\n\nexport type FilePrimaryScope = (typeof FILE_PRIMARY_SCOPES)[number];\n\nfunction hasFileScopeIdentifierValue(value: string | undefined): boolean {\n return typeof value === 'string' && value.trim() !== '';\n}\n\nfunction validateUploaderPair(\n file: {\n uploadedBy?: string;\n uploadedByEntityType?: FileUploaderEntityType;\n },\n ctx: z.RefinementCtx,\n): void {\n const hasUploadedBy = hasFileScopeIdentifierValue(file.uploadedBy);\n const hasUploadedByEntityType = file.uploadedByEntityType !== undefined;\n\n if (hasUploadedBy !== hasUploadedByEntityType) {\n ctx.addIssue({\n code: 'custom',\n path: hasUploadedBy ? ['uploadedByEntityType'] : ['uploadedBy'],\n message: 'uploadedBy and uploadedByEntityType must either both be set or both be omitted',\n });\n }\n}\n\nexport function validateFileScopeIdentifiers(scope: {\n primaryScope: FilePrimaryScope;\n applicationId: string;\n organizationId?: string;\n userId?: string;\n}): boolean {\n const hasApplicationId = hasFileScopeIdentifierValue(scope.applicationId);\n const hasOrganizationId = hasFileScopeIdentifierValue(scope.organizationId);\n const hasUserId = hasFileScopeIdentifierValue(scope.userId);\n\n switch (scope.primaryScope) {\n case ResourcePrimaryScope.APPLICATION:\n return hasApplicationId && !hasOrganizationId && !hasUserId;\n case ResourcePrimaryScope.ORGANIZATIONS:\n // applicationId is always required (tenant isolation); organizationId is the scope discriminator.\n return hasApplicationId && hasOrganizationId && !hasUserId;\n case ResourcePrimaryScope.USER_SELF:\n // Primary scopes are a SEPARATION OF CONCERN: USER_SELF and ORGANIZATIONS are\n // independent axes. A user's self-owned file is user-owned, NOT org-owned —\n // `userId` is the scope discriminator and `applicationId` is the tenant/bucket\n // anchor. `organizationId` MUST be absent (a present org would conflate the two\n // scopes). Fail closed on any org value.\n return hasApplicationId && hasUserId && !hasOrganizationId;\n default:\n return false;\n }\n}\n\n/**\n * File resource schema\n *\n * Stores file metadata and links files to resources.\n * Files are stored via app-managed storage providers (MinIO/S3, local directory, etc.),\n * this schema tracks metadata only.\n *\n * ## Storage Identity Convention\n * `storageProvider` + `storageRef` are the persisted routing truth used to\n * reach the active storage backend. `storageKey` remains framework metadata\n * that captures the file's derived scope path for bookkeeping, diagnostics,\n * and future storage contract evolution.\n *\n * `storageKey` includes scope path derived from primaryScope:\n * - APPLICATION: `app/{applicationId}/{fileId}`\n * - ORGANIZATIONS: `org/{organizationId}/{fileId}`\n * - USER_SELF: `user/{userId}/{fileId}` (owner is the user; no org segment)\n */\nconst FileSchemaBase = z.object({\n fileId: z.string().min(1).isPrimaryKey().isSummaryField(),\n\n // ========== File Metadata ==========\n // USER_CONTENT on both names. A filename is chosen by the person and routinely IS the personal\n // datum — \"scan-2026-medical.pdf\" discloses a special category before the file is opened. The\n // file's BYTES are not a field here (this resource is metadata over object storage), so this is the\n // only place the content axis can be declared at all.\n filename: z.string().min(1).isDBIndexed().isSummaryField().dataCategories(PersonalDataCategory.USER_CONTENT),\n originalFilename: z.string().min(1).isSummaryField().dataCategories(PersonalDataCategory.USER_CONTENT),\n mimeType: z.string().min(1).isDBIndexed().isSummaryField(),\n size: z.number().min(0).isSummaryField(),\n extension: z.string().optional(),\n checksum: z.string().optional().isDBIndexed(),\n\n // ========== Storage ==========\n // `storageProvider` + `storageRef` are the persisted backend-routing truth.\n storageProvider: z.enum(FileStorageAccepted).optional().isDBIndexed(),\n storageRef: z.string().min(1).optional().isDBIndexed(),\n // `storageKey` is still scoped metadata, not the storage backend handle. It embeds the\n // file identity (`_id`, surfaced as the `fileId` virtual), so it is derived + persisted\n // AFTER the row is created (insert-first) — hence optional at create time. `createFile`\n // sets it once `_id` exists, and `linkFileToResource` re-derives it when the file's scope\n // is finalized.\n storageKey: z.string().min(1).optional().isDBIndexed(),\n url: z.url().optional(), // Cached URL (may be presigned)\n\n // ========== Status & Lifecycle ==========\n status: z.enum(FileStatus).default(FileStatus.PENDING).isDBIndexed().isSummaryField(),\n\n // ========== Nature-specific Metadata ==========\n // Inferred from MIME type or set by analysis services (F4-03)\n // Resolved display nature (IMAGE/VIDEO/AUDIO/DOCUMENT/GENERIC) — NOT the schema-level FileNature.\n // Set by resolveFileDisplayNature() during upload or inferred from MIME type in toMetadataResponse().\n // Schema declares FileNature (e.g., PDF, OFFICE), but the DB stores the resolved FileDisplayNature.\n nature: z.enum(FileDisplayNature).optional().isDBIndexed(),\n // Image-specific\n width: z.number().positive().optional(),\n height: z.number().positive().optional(),\n thumbnailUrl: z.url().optional(),\n // Video/Audio-specific (populated by IFileVideoAnalyzer / IFileAudioAnalyzer)\n duration: z.number().positive().optional(), // Duration in seconds\n // Document-specific (populated by IFileDocumentAnalyzer)\n pageCount: z.number().positive().optional(),\n\n // ========== Resource Linking ==========\n // When linked, scope is derived from parent resource's resourcePrimaryScope\n linkedResourceType: z.string().optional().isDBIndexed(),\n linkedResourceId: z.string().optional().isDBIndexed(),\n linkedFieldName: z.string().optional(),\n\n // ========== Primary Scope ==========\n // Derived from parent resource's resourcePrimaryScope when linking\n // Determines access control and storage path\n primaryScope: z.enum(FILE_PRIMARY_SCOPES).optional().isDBIndexed(),\n\n // ========== Scope Identifiers ==========\n // applicationId is ALWAYS set (from execution context at creation time) — it is the\n // top-level tenant isolation field present on every file record regardless of primaryScope.\n // organizationId and userId are populated only when the file's primaryScope requires them.\n\n applicationId: z.string().isDBIndexed(),\n\n // ORGANIZATIONS scope: org-scoped files. Set ONLY for ORGANIZATIONS-scoped files —\n // never for USER_SELF (the two scopes are independent axes, separation of concern).\n organizationId: z.string().optional().isDBIndexed(),\n\n // USER_SELF scope: user-private files owned by one user. Set ONLY for USER_SELF-scoped\n // files; the owner is the user (no org). `applicationId` is the tenant/bucket anchor.\n userId: z.string().optional().isDBIndexed(),\n\n // ========== Upload Metadata ==========\n // The uploader principal is persisted as a raw id + type pair only.\n // Any richer label/entity hydration is intentionally client-driven.\n uploadedBy: z.string().trim().min(1).optional().isDBIndexed(),\n uploadedByEntityType: z.enum(FileUploaderEntityType).optional().isDBIndexed(),\n\n // ========== Timestamps ==========\n uploadedAt: z.date().default(() => new Date()).isDBIndexed().isSummaryField().excludeFromCreate().excludeFromUpdate(),\n updatedAt: z.date().default(() => new Date()).isDBIndexed().excludeFromCreate().excludeFromUpdate(),\n deletedAt: z.date().optional().isDBIndexed().excludeFromCreate(),\n});\n\nexport const FileSchema = FileSchemaBase.superRefine((file, ctx) => {\n validateUploaderPair(file, ctx);\n\n if (!file.primaryScope) {\n // Pre-link state: applicationId is always present (set from execution context at upload time),\n // but organizationId/userId must not be set without a primaryScope discriminator.\n if (hasFileScopeIdentifierValue(file.organizationId) || hasFileScopeIdentifierValue(file.userId)) {\n ctx.addIssue({\n code: 'custom',\n path: ['primaryScope'],\n message: 'primaryScope is required when organizationId or userId are present',\n });\n }\n return;\n }\n\n if (!validateFileScopeIdentifiers({\n primaryScope: file.primaryScope,\n applicationId: file.applicationId,\n organizationId: file.organizationId,\n userId: file.userId,\n })) {\n ctx.addIssue({\n code: 'custom',\n path: ['primaryScope'],\n message: 'File scope identifiers must match the declared primaryScope',\n });\n }\n\n});\nexport type File = z.infer<typeof FileSchema> & FileUploaderOwnership;\n\n/**\n * Scope identifiers for file access control.\n * Populated based on primaryScope when file is created/linked.\n */\nexport interface FileScopeIdentifiers {\n primaryScope: FilePrimaryScope;\n /** Always required — top-level tenant isolation key, set from execution context at file creation. */\n applicationId: string;\n organizationId?: string;\n userId?: string;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"actors.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../src/flows-actors/actors.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAmG,oBAAoB,EAAG,MAAM,sCAAsC,CAAC;AAe9K,oBAAY,mBAAmB;IAC7B,WAAW,gBAAgB;IAC3B,YAAY,iBAAiB;IAC7B,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,iBAAiB,sBAAsB;IACvC,cAAc,mBAAmB;CAClC;AAGD,oBAAY,mBAAmB;IAC7B,OAAO,YAAY;IACnB,cAAc,mBAAmB;IACjC,iBAAiB,sBAAsB;CACxC;AAED,eAAO,MAAM,WAAW;;;;;;;iBAOtB,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAMhD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAS5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAO5D,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8BtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
1
+ {"version":3,"file":"actors.shared.schemas.d.ts","sourceRoot":"","sources":["../../../../src/flows-actors/actors.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,kBAAkB,EAA6B,MAAM,uCAAuC,CAAC;AACtG,OAAO,EAAmG,oBAAoB,EAAG,MAAM,sCAAsC,CAAC;AAe9K,oBAAY,mBAAmB;IAC7B,WAAW,gBAAgB;IAC3B,YAAY,iBAAiB;IAC7B,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,QAAQ,aAAa;IACrB,iBAAiB,sBAAsB;IACvC,cAAc,mBAAmB;CAClC;AAGD,oBAAY,mBAAmB;IAC7B,OAAO,YAAY;IACnB,cAAc,mBAAmB;IACjC,iBAAiB,sBAAsB;CACxC;AAED,eAAO,MAAM,WAAW;;;;;;;iBAOtB,CAAC;AACH,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAMhD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAS5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAO5D,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA+BtC,CAAC;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { z } from "zod";
2
2
  import { WildoError_BackendSchema } from "../errors/errors.shared.schemas.js";
3
- import { FlowsActors_Status } from "./flows-actors.commons.shared.schemas.js";
3
+ import { FlowsActors_Status, describeFlowsActorsStatus } from "./flows-actors.commons.shared.schemas.js";
4
4
  import { FlowActorSystem_BaseSchema, FlowActorSystem_ErrorStates_Schema, FlowActorSystem_ExecutionSchema, FlowActorSystem_Kind, } from "./flows-actors.system.shared.schemas.js";
5
5
  import { Actors_Task_Schema, Actors_Walkthrough_Schema, ActorsSystem_ExecutionPlan_Schema } from "./tasks.actors.shared.schemas.js";
6
6
  //===============================================================
@@ -73,7 +73,8 @@ export const ActorSystem_ExecutionSchema = FlowActorSystem_ExecutionSchema.exten
73
73
  status: z.enum(FlowsActors_Status),
74
74
  updatedAt: z.iso.datetime(),
75
75
  statusChanges: z.array(z.object({
76
- status: z.enum(FlowsActors_Status),
76
+ status: z.enum(FlowsActors_Status)
77
+ .describe(describeFlowsActorsStatus("The state this run moved into at `timestamp`. The list is the run's history, oldest first.")),
77
78
  timestamp: z.iso.datetime(),
78
79
  })),
79
80
  }).array(),
@@ -1 +1 @@
1
- {"version":3,"file":"actors.shared.schemas.js","sourceRoot":"","sources":["../../../../src/flows-actors/actors.shared.schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,0BAA0B,EAAE,kCAAkC,EAAE,+BAA+B,EAAE,oBAAoB,GAAG,MAAM,sCAAsC,CAAC;AAC9K,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,iCAAiC,EAAE,MAAM,+BAA+B,CAAC;AAGjI,iEAAiE;AACjE,SAAS;AACT,WAAW;AACX,gEAAgE;AAChE,kEAAkE;AAClE,iEAAiE;AACjE,sEAAsE;AACtE,mEAAmE;AACnE,iEAAiE;AAGjE,MAAM,CAAN,IAAY,mBAQX;AARD,WAAY,mBAAmB;IAC7B,kDAA2B,CAAA;IAC3B,oDAA6B,CAAA;IAC7B,4CAAqB,CAAA;IACrB,4CAAqB,CAAA;IACrB,4CAAqB,CAAA;IACrB,8DAAuC,CAAA;IACvC,wDAAiC,CAAA;AACnC,CAAC,EARW,mBAAmB,KAAnB,mBAAmB,QAQ9B;AAGD,MAAM,CAAN,IAAY,mBAIX;AAJD,WAAY,mBAAmB;IAC7B,0CAAmB,CAAA;IACnB,wDAAiC,CAAA;IACjC,8DAAuC,CAAA;AACzC,CAAC,EAJW,mBAAmB,KAAnB,mBAAmB,QAI9B;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC;IACzC,aAAa,EAAE,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC;IAC1C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC/B,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC/B,CAAC,CAAC;AAGH,iEAAiE;AACjE,gBAAgB;AAChB,iEAAiE;AAEjE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,0BAA0B,CAAC,MAAM,CAAC;IACjE;;;;;OAKG;IACH,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC;IAC3C,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC;CAC3C,CAAC,CAAC;AAIH,iEAAiE;AACjE,0BAA0B;AAC1B,iEAAiE;AAEjE,MAAM,CAAC,MAAM,2BAA2B,GAAG,+BAA+B,CAAC,MAAM,CAAC;IAChF,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC;IAE3C,IAAI,EAAE,iCAAiC,CAAC,QAAQ,EAAE;IAClD,WAAW,EAAE,yBAAyB,CAAC,QAAQ,EAAE;IACjD,eAAe,EAAE,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC;IAE5C,oBAAoB,EAAE,CAAC,CAAC,MAAM,CAAC;QAC7B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;QAClB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC;QAClC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;QAC3B,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;YAC9B,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC;YAClC,SAAS,EAAE,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE;SAC5B,CAAC,CAAC;KACJ,CAAC,CAAC,KAAK,EAAE;IAEV;;;;;OAKG;IACH,WAAW,EAAG,kCAAkC,CAAC,MAAM,CAAC;QACtD,UAAU,EAAE,wBAAwB,CAAC,MAAM,CAAC;YAC1C,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;YACrB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC7B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;SAClC,CAAC,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;KACtB,CAAC,CAAC,QAAQ,EAAE;CACd,CAAC,CAAC","sourcesContent":["import { z } from \"zod\";\n\nimport { WildoError_BackendSchema } from \"../errors/errors.shared.schemas\";\nimport { FlowsActors_Status } from \"./flows-actors.commons.shared.schemas\";\nimport { FlowActorSystem_BaseSchema, FlowActorSystem_ErrorStates_Schema, FlowActorSystem_ExecutionSchema, FlowActorSystem_Kind, } from \"./flows-actors.system.shared.schemas\";\nimport { Actors_Task_Schema, Actors_Walkthrough_Schema, ActorsSystem_ExecutionPlan_Schema } from \"./tasks.actors.shared.schemas\";\n\n\n//===============================================================\n// Actor\n// --------\n// Actors are reactive components that subscribe to event topics\n// and respond with automated processing. They enable event-driven\n// architecture by processing messages asynchronously, supporting\n// batch processing, filtering, and various error handling strategies.\n// Actors can emit new events, creating event chains and workflows.\n//===============================================================\n\n\nexport enum Actor_Role_Category {\n COORDINATOR = \"coordinator\",\n TASK_PLANNER = \"task_planner\",\n OPERATOR = \"operator\",\n ANALYZER = \"analyzer\",\n REVIEWER = \"reviewer\",\n HUMAN_IN_THE_LOOP = \"human_in_the_loop\",\n FLOW_EXECUTION = \"flow_execution\"\n}\n\n\nexport enum Actor_ExecutionMode {\n AGENTIC = \"agentic\",\n FLOW_EXECUTION = \"flow_execution\",\n HUMAN_INTERACTION = \"human_interaction\",\n}\n\nexport const ActorSchema = z.object({\n ref: z.string().min(1),\n displayName: z.string().min(1),\n roleCategory: z.enum(Actor_Role_Category),\n executionMode: z.enum(Actor_ExecutionMode),\n agentRef: z.string().optional(),\n flowRef: z.string().optional(),\n});\nexport type Actor = z.infer<typeof ActorSchema>;\n\n//===============================================================\n// Actor System\n//===============================================================\n\n/**\n * The ACTOR specialization of the system base — the schema that OWNS a system's\n * actor list. `actors` is declared here and in no other system schema: the base\n * cannot declare it, because a FLOW system has no actors. (Unrelated `actors`\n * members exist on the TASK schemas; those point at one actor, they are not a\n * system's roster.)\n *\n * An actor system must therefore be parsed with this schema, or one derived\n * from it. Parsing one with `FlowActorSystem_BaseSchema` strips `actors`\n * silently — see the warning there.\n */\nexport const ActorSystemSchema = FlowActorSystem_BaseSchema.extend({\n /**\n * Narrows the inherited `kind` discriminant to ACTOR. The historical shape\n * added a separate `type` field here while every consumer (backend registry,\n * execution schemas, flows counterpart) discriminates on `kind` — fixed\n * 2026-07-02 (meta-workflows Step 0 hygiene; no `.type` consumer existed).\n */\n kind: z.literal(FlowActorSystem_Kind.ACTOR),\n actors: z.array(z.lazy(() => ActorSchema)),\n});\nexport type ActorSystem = z.infer<typeof ActorSystemSchema>;\n\n\n//===============================================================\n// Actor System Execution\n//===============================================================\n\nexport const ActorSystem_ExecutionSchema = FlowActorSystem_ExecutionSchema.extend({\n kind: z.literal(FlowActorSystem_Kind.ACTOR),\n\n plan: ActorsSystem_ExecutionPlan_Schema.optional(),\n walkthrough: Actors_Walkthrough_Schema.optional(),\n standaloneTasks: z.array(Actors_Task_Schema),\n\n standaloneTaskStates: z.object({\n taskId: z.string(),\n status: z.enum(FlowsActors_Status),\n updatedAt: z.iso.datetime(),\n statusChanges: z.array(z.object({\n status: z.enum(FlowsActors_Status),\n timestamp: z.iso.datetime(),\n })),\n }).array(),\n\n /**\n * Overrides the base `errorItems` with the actor-execution-scoped variant\n * (adds taskId/planStepId locators). Historically this extension used a\n * divergent `errors` key coexisting with the base `errorItems` — aligned\n * 2026-07-02 (meta-workflows Step 0 hygiene; the field had no consumers).\n */\n errorStates : FlowActorSystem_ErrorStates_Schema.extend({\n errorItems: WildoError_BackendSchema.extend({\n systemRef: z.string(),\n taskId: z.string().optional(),\n planStepId: z.string().optional(),\n }).array().optional(),\n }).optional(),\n});\nexport type ActorSystem_Execution = z.infer<typeof ActorSystem_ExecutionSchema>;\n"]}
1
+ {"version":3,"file":"actors.shared.schemas.js","sourceRoot":"","sources":["../../../../src/flows-actors/actors.shared.schemas.ts"],"names":[],"mappings":"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","sourcesContent":["import { z } from \"zod\";\n\nimport { WildoError_BackendSchema } from \"../errors/errors.shared.schemas\";\nimport { FlowsActors_Status, describeFlowsActorsStatus } from \"./flows-actors.commons.shared.schemas\";\nimport { FlowActorSystem_BaseSchema, FlowActorSystem_ErrorStates_Schema, FlowActorSystem_ExecutionSchema, FlowActorSystem_Kind, } from \"./flows-actors.system.shared.schemas\";\nimport { Actors_Task_Schema, Actors_Walkthrough_Schema, ActorsSystem_ExecutionPlan_Schema } from \"./tasks.actors.shared.schemas\";\n\n\n//===============================================================\n// Actor\n// --------\n// Actors are reactive components that subscribe to event topics\n// and respond with automated processing. They enable event-driven\n// architecture by processing messages asynchronously, supporting\n// batch processing, filtering, and various error handling strategies.\n// Actors can emit new events, creating event chains and workflows.\n//===============================================================\n\n\nexport enum Actor_Role_Category {\n COORDINATOR = \"coordinator\",\n TASK_PLANNER = \"task_planner\",\n OPERATOR = \"operator\",\n ANALYZER = \"analyzer\",\n REVIEWER = \"reviewer\",\n HUMAN_IN_THE_LOOP = \"human_in_the_loop\",\n FLOW_EXECUTION = \"flow_execution\"\n}\n\n\nexport enum Actor_ExecutionMode {\n AGENTIC = \"agentic\",\n FLOW_EXECUTION = \"flow_execution\",\n HUMAN_INTERACTION = \"human_interaction\",\n}\n\nexport const ActorSchema = z.object({\n ref: z.string().min(1),\n displayName: z.string().min(1),\n roleCategory: z.enum(Actor_Role_Category),\n executionMode: z.enum(Actor_ExecutionMode),\n agentRef: z.string().optional(),\n flowRef: z.string().optional(),\n});\nexport type Actor = z.infer<typeof ActorSchema>;\n\n//===============================================================\n// Actor System\n//===============================================================\n\n/**\n * The ACTOR specialization of the system base — the schema that OWNS a system's\n * actor list. `actors` is declared here and in no other system schema: the base\n * cannot declare it, because a FLOW system has no actors. (Unrelated `actors`\n * members exist on the TASK schemas; those point at one actor, they are not a\n * system's roster.)\n *\n * An actor system must therefore be parsed with this schema, or one derived\n * from it. Parsing one with `FlowActorSystem_BaseSchema` strips `actors`\n * silently — see the warning there.\n */\nexport const ActorSystemSchema = FlowActorSystem_BaseSchema.extend({\n /**\n * Narrows the inherited `kind` discriminant to ACTOR. The historical shape\n * added a separate `type` field here while every consumer (backend registry,\n * execution schemas, flows counterpart) discriminates on `kind` — fixed\n * 2026-07-02 (meta-workflows Step 0 hygiene; no `.type` consumer existed).\n */\n kind: z.literal(FlowActorSystem_Kind.ACTOR),\n actors: z.array(z.lazy(() => ActorSchema)),\n});\nexport type ActorSystem = z.infer<typeof ActorSystemSchema>;\n\n\n//===============================================================\n// Actor System Execution\n//===============================================================\n\nexport const ActorSystem_ExecutionSchema = FlowActorSystem_ExecutionSchema.extend({\n kind: z.literal(FlowActorSystem_Kind.ACTOR),\n\n plan: ActorsSystem_ExecutionPlan_Schema.optional(),\n walkthrough: Actors_Walkthrough_Schema.optional(),\n standaloneTasks: z.array(Actors_Task_Schema),\n\n standaloneTaskStates: z.object({\n taskId: z.string(),\n status: z.enum(FlowsActors_Status),\n updatedAt: z.iso.datetime(),\n statusChanges: z.array(z.object({\n status: z.enum(FlowsActors_Status)\n .describe(describeFlowsActorsStatus(\"The state this run moved into at `timestamp`. The list is the run's history, oldest first.\")),\n timestamp: z.iso.datetime(),\n })),\n }).array(),\n\n /**\n * Overrides the base `errorItems` with the actor-execution-scoped variant\n * (adds taskId/planStepId locators). Historically this extension used a\n * divergent `errors` key coexisting with the base `errorItems` — aligned\n * 2026-07-02 (meta-workflows Step 0 hygiene; the field had no consumers).\n */\n errorStates : FlowActorSystem_ErrorStates_Schema.extend({\n errorItems: WildoError_BackendSchema.extend({\n systemRef: z.string(),\n taskId: z.string().optional(),\n planStepId: z.string().optional(),\n }).array().optional(),\n }).optional(),\n});\nexport type ActorSystem_Execution = z.infer<typeof ActorSystem_ExecutionSchema>;\n"]}