@jini-ai/cms 0.3.11 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/README.md +47 -19
  3. package/dist/content-types/agent-tools.d.ts +3 -56
  4. package/dist/content-types/agent-tools.js +22 -6
  5. package/dist/content-types/cleanup.d.ts +18 -13
  6. package/dist/content-types/cleanup.js +16 -11
  7. package/dist/content-types/errors.d.ts +57 -24
  8. package/dist/content-types/errors.js +56 -39
  9. package/dist/content-types/field-defs.d.ts +8 -4
  10. package/dist/content-types/field-defs.js +19 -14
  11. package/dist/content-types/index-provisioning.d.ts +61 -47
  12. package/dist/content-types/index-provisioning.js +90 -66
  13. package/dist/content-types/index.d.ts +4 -3
  14. package/dist/content-types/lifecycle-dispatch.d.ts +11 -5
  15. package/dist/content-types/lifecycle-dispatch.js +5 -4
  16. package/dist/content-types/lifecycle.d.ts +23 -18
  17. package/dist/content-types/lifecycle.js +71 -64
  18. package/dist/content-types/repo.memory.d.ts +5 -4
  19. package/dist/content-types/repo.memory.js +3 -2
  20. package/dist/content-types/tool-registrations.d.ts +6 -8
  21. package/dist/content-types/tool-registrations.js +24 -28
  22. package/dist/content-types/types.d.ts +17 -13
  23. package/dist/content-types/types.js +11 -5
  24. package/dist/content-types/write-service.d.ts +20 -22
  25. package/dist/content-types/write-service.js +78 -75
  26. package/dist/core/authorization.d.ts +15 -0
  27. package/dist/core/authorization.js +2 -0
  28. package/dist/core/commands/change-set.d.ts +15 -7
  29. package/dist/core/commands/command.d.ts +45 -26
  30. package/dist/core/commands/command.js +73 -63
  31. package/dist/core/entity-liveness.d.ts +11 -7
  32. package/dist/core/entity-liveness.js +5 -4
  33. package/dist/core/index.d.ts +12 -5
  34. package/dist/core/index.js +10 -4
  35. package/dist/core/ports.d.ts +25 -24
  36. package/dist/core/ports.js +1 -0
  37. package/dist/core/tools/args.d.ts +49 -0
  38. package/dist/core/tools/args.js +46 -0
  39. package/dist/core/tools/index.d.ts +3 -0
  40. package/dist/core/tools/index.js +3 -0
  41. package/dist/entries/agent-tools.d.ts +1 -73
  42. package/dist/entries/agent-tools.js +19 -13
  43. package/dist/entries/errors.d.ts +28 -14
  44. package/dist/entries/errors.js +17 -11
  45. package/dist/entries/field-validation.d.ts +5 -3
  46. package/dist/entries/field-validation.js +7 -5
  47. package/dist/entries/index.d.ts +2 -2
  48. package/dist/entries/lifecycle-dispatch.d.ts +5 -2
  49. package/dist/entries/lifecycle-dispatch.js +2 -1
  50. package/dist/entries/list.d.ts +4 -2
  51. package/dist/entries/list.js +4 -3
  52. package/dist/entries/repo.memory.d.ts +12 -10
  53. package/dist/entries/repo.memory.js +11 -10
  54. package/dist/entries/tool-registrations.d.ts +6 -8
  55. package/dist/entries/tool-registrations.js +42 -41
  56. package/dist/entries/types.d.ts +0 -7
  57. package/dist/entries/write-service.d.ts +28 -29
  58. package/dist/entries/write-service.js +114 -105
  59. package/dist/http/settings/cms-adapter.d.ts +20 -0
  60. package/dist/http/settings/cms-adapter.js +124 -0
  61. package/dist/http/settings/contracts.d.ts +135 -0
  62. package/dist/http/settings/contracts.js +2 -0
  63. package/dist/http/settings/http.d.ts +10 -0
  64. package/dist/http/settings/http.js +211 -0
  65. package/dist/http/settings/index.d.ts +5 -0
  66. package/dist/http/settings/index.js +4 -0
  67. package/dist/http/settings/shared.d.ts +68 -0
  68. package/dist/http/settings/shared.js +54 -0
  69. package/dist/http/settings/stream.d.ts +24 -0
  70. package/dist/http/settings/stream.js +147 -0
  71. package/dist/media/agent-tools.d.ts +1 -66
  72. package/dist/media/agent-tools.js +5 -1
  73. package/dist/media/blob-gc-lock.d.ts +6 -2
  74. package/dist/media/blob-gc-lock.js +4 -2
  75. package/dist/media/blob-gc.d.ts +64 -51
  76. package/dist/media/blob-gc.js +62 -52
  77. package/dist/media/blob-key.d.ts +1 -1
  78. package/dist/media/content-type-sniffer.d.ts +3 -1
  79. package/dist/media/content-type-sniffer.js +1 -1
  80. package/dist/media/html-attributes.d.ts +9 -5
  81. package/dist/media/html-attributes.js +8 -6
  82. package/dist/media/image-transformer.js +1 -1
  83. package/dist/media/image-transformer.sharp.d.ts +6 -0
  84. package/dist/media/image-transformer.sharp.js +12 -6
  85. package/dist/media/import/fetch-image.d.ts +24 -0
  86. package/dist/media/import/fetch-image.js +137 -0
  87. package/dist/media/import/index.d.ts +3 -0
  88. package/dist/media/import/index.js +3 -0
  89. package/dist/media/import/ports.d.ts +38 -0
  90. package/dist/media/index.d.ts +7 -1
  91. package/dist/media/index.js +1 -0
  92. package/dist/media/media-service.d.ts +14 -10
  93. package/dist/media/media-service.js +57 -52
  94. package/dist/media/ports.d.ts +3 -2
  95. package/dist/media/rendition-service.d.ts +3 -3
  96. package/dist/media/rendition-service.js +38 -37
  97. package/dist/media/repo.memory.d.ts +18 -7
  98. package/dist/media/repo.memory.js +12 -6
  99. package/dist/media/tool-registrations.d.ts +16 -15
  100. package/dist/media/tool-registrations.js +84 -72
  101. package/dist/media/transform-lock.d.ts +22 -12
  102. package/dist/media/transform-lock.js +14 -13
  103. package/dist/media/transform-registry.d.ts +3 -3
  104. package/dist/media/transform-registry.js +19 -18
  105. package/dist/media/transform-types.d.ts +8 -3
  106. package/dist/media/transform-types.js +10 -5
  107. package/dist/media/types.d.ts +21 -4
  108. package/dist/media/types.js +15 -2
  109. package/dist/navigation/agent-tools.d.ts +1 -80
  110. package/dist/navigation/agent-tools.js +15 -3
  111. package/dist/navigation/contracts.d.ts +1 -1
  112. package/dist/navigation/index.d.ts +2 -2
  113. package/dist/navigation/menu-service.d.ts +57 -40
  114. package/dist/navigation/menu-service.js +80 -69
  115. package/dist/navigation/ports.d.ts +1 -1
  116. package/dist/navigation/read-model.d.ts +3 -1
  117. package/dist/navigation/read-model.js +2 -2
  118. package/dist/navigation/reconcile.d.ts +2 -2
  119. package/dist/navigation/reconcile.js +2 -1
  120. package/dist/navigation/repo.memory.d.ts +7 -3
  121. package/dist/navigation/repo.memory.js +4 -2
  122. package/dist/navigation/resolver.d.ts +4 -1
  123. package/dist/navigation/resolver.js +1 -1
  124. package/dist/navigation/tool-registrations.d.ts +6 -8
  125. package/dist/navigation/tool-registrations.js +44 -42
  126. package/dist/navigation/types.d.ts +1 -1
  127. package/dist/presentation/presentation.d.ts +11 -3
  128. package/dist/presentation/presentation.js +13 -6
  129. package/dist/presentation/repo.memory.d.ts +6 -2
  130. package/dist/presentation/repo.memory.js +3 -2
  131. package/dist/settings/agent-tools.d.ts +2 -75
  132. package/dist/settings/agent-tools.js +49 -45
  133. package/dist/settings/agent-value-write-tools.d.ts +22 -0
  134. package/dist/settings/agent-value-write-tools.js +154 -0
  135. package/dist/settings/agent-writable-preferences.js +8 -20
  136. package/dist/settings/agent-write-denylist.d.ts +19 -0
  137. package/dist/settings/agent-write-denylist.js +15 -0
  138. package/dist/settings/change-feed.d.ts +11 -2
  139. package/dist/settings/change-feed.js +4 -4
  140. package/dist/settings/definitions-dispatch.d.ts +8 -3
  141. package/dist/settings/definitions-dispatch.js +5 -5
  142. package/dist/settings/dictionaries/index.d.ts +5 -2
  143. package/dist/settings/dictionaries/index.js +2 -2
  144. package/dist/settings/dictionaries/settings-dialog.ar.js +0 -1
  145. package/dist/settings/dictionaries/settings-dialog.bn.js +0 -1
  146. package/dist/settings/dictionaries/settings-dialog.de.js +0 -1
  147. package/dist/settings/dictionaries/settings-dialog.es.js +0 -1
  148. package/dist/settings/dictionaries/settings-dialog.fa.js +0 -1
  149. package/dist/settings/dictionaries/settings-dialog.fr.js +0 -1
  150. package/dist/settings/dictionaries/settings-dialog.hi.js +0 -1
  151. package/dist/settings/dictionaries/settings-dialog.hu.js +0 -1
  152. package/dist/settings/dictionaries/settings-dialog.id.js +0 -1
  153. package/dist/settings/dictionaries/settings-dialog.it.js +0 -1
  154. package/dist/settings/dictionaries/settings-dialog.ja.js +0 -1
  155. package/dist/settings/dictionaries/settings-dialog.ko.js +0 -1
  156. package/dist/settings/dictionaries/settings-dialog.pl.js +0 -1
  157. package/dist/settings/dictionaries/settings-dialog.pt-BR.js +0 -1
  158. package/dist/settings/dictionaries/settings-dialog.ru.js +0 -1
  159. package/dist/settings/dictionaries/settings-dialog.th.js +0 -1
  160. package/dist/settings/dictionaries/settings-dialog.tr.js +0 -1
  161. package/dist/settings/dictionaries/settings-dialog.uk.js +0 -1
  162. package/dist/settings/dictionaries/settings-dialog.ur.js +0 -1
  163. package/dist/settings/dictionaries/settings-dialog.zh-CN.js +0 -1
  164. package/dist/settings/dictionaries/settings-dialog.zh-TW.js +0 -1
  165. package/dist/settings/ensure-definitions.d.ts +5 -5
  166. package/dist/settings/errors.d.ts +7 -1
  167. package/dist/settings/errors.js +7 -1
  168. package/dist/settings/index.d.ts +4 -1
  169. package/dist/settings/index.js +1 -0
  170. package/dist/settings/ports.d.ts +6 -5
  171. package/dist/settings/principal-lookup.d.ts +9 -0
  172. package/dist/settings/principal-lookup.js +2 -0
  173. package/dist/settings/purge-service.d.ts +5 -4
  174. package/dist/settings/purge-service.js +3 -2
  175. package/dist/settings/settings.d.ts +22 -7
  176. package/dist/settings/settings.js +47 -26
  177. package/dist/settings/tool-registrations.d.ts +25 -32
  178. package/dist/settings/tool-registrations.js +66 -56
  179. package/dist/settings/types.d.ts +1 -1
  180. package/dist/settings/ui-tab-definitions.d.ts +1 -1
  181. package/dist/settings/write-service.d.ts +32 -26
  182. package/dist/settings/write-service.js +26 -20
  183. package/dist/taxonomy/agent-tools.d.ts +1 -66
  184. package/dist/taxonomy/agent-tools.js +25 -15
  185. package/dist/taxonomy/content-lookup.js +1 -1
  186. package/dist/taxonomy/index.d.ts +2 -2
  187. package/dist/taxonomy/merge-term.d.ts +7 -4
  188. package/dist/taxonomy/merge-term.js +7 -5
  189. package/dist/taxonomy/repo.memory.d.ts +42 -19
  190. package/dist/taxonomy/repo.memory.js +14 -12
  191. package/dist/taxonomy/validation-chain.d.ts +39 -18
  192. package/dist/taxonomy/validation-chain.js +35 -25
  193. package/dist/taxonomy/write-service.d.ts +103 -44
  194. package/dist/taxonomy/write-service.js +221 -179
  195. package/dist/trash/adapters/record-store.d.ts +52 -0
  196. package/dist/trash/adapters/record-store.js +36 -0
  197. package/dist/trash/cursor.d.ts +20 -0
  198. package/dist/trash/cursor.js +36 -0
  199. package/dist/trash/follow-ups.d.ts +76 -0
  200. package/dist/trash/follow-ups.js +46 -0
  201. package/dist/trash/index.d.ts +8 -0
  202. package/dist/trash/index.js +8 -0
  203. package/dist/trash/ports.d.ts +308 -0
  204. package/dist/trash/ports.js +2 -0
  205. package/dist/trash/repo.memory.d.ts +50 -0
  206. package/dist/trash/repo.memory.js +114 -0
  207. package/dist/trash/sweeper.d.ts +77 -0
  208. package/dist/trash/sweeper.js +127 -0
  209. package/dist/trash/write-service.d.ts +100 -0
  210. package/dist/trash/write-service.js +242 -0
  211. package/dist/workspace/agent-tools.d.ts +1 -59
  212. package/dist/workspace/agent-tools.js +27 -12
  213. package/dist/workspace/create.d.ts +31 -6
  214. package/dist/workspace/create.js +18 -5
  215. package/dist/workspace/delete.d.ts +18 -13
  216. package/dist/workspace/delete.js +20 -12
  217. package/dist/workspace/index.d.ts +1 -1
  218. package/dist/workspace/repo.memory.d.ts +19 -4
  219. package/dist/workspace/repo.memory.js +26 -4
  220. package/dist/workspace/tool-registrations.d.ts +2 -2
  221. package/dist/workspace/tool-registrations.js +13 -13
  222. package/dist/workspace/update.d.ts +6 -5
  223. package/dist/workspace/update.js +9 -8
  224. package/package.json +44 -38
  225. package/dist/identity/admin-crud-service.d.ts +0 -280
  226. package/dist/identity/admin-crud-service.js +0 -468
  227. package/dist/identity/agent-tool-input.d.ts +0 -58
  228. package/dist/identity/agent-tool-input.js +0 -126
  229. package/dist/identity/agent-tools.d.ts +0 -101
  230. package/dist/identity/agent-tools.js +0 -290
  231. package/dist/identity/auth-service.d.ts +0 -118
  232. package/dist/identity/auth-service.js +0 -170
  233. package/dist/identity/authorize.d.ts +0 -90
  234. package/dist/identity/authorize.js +0 -94
  235. package/dist/identity/grant-service.d.ts +0 -198
  236. package/dist/identity/grant-service.js +0 -361
  237. package/dist/identity/hasher.d.ts +0 -39
  238. package/dist/identity/hasher.js +0 -39
  239. package/dist/identity/index.d.ts +0 -62
  240. package/dist/identity/index.js +0 -54
  241. package/dist/identity/password-policy.d.ts +0 -57
  242. package/dist/identity/password-policy.js +0 -66
  243. package/dist/identity/permission-migrations.d.ts +0 -86
  244. package/dist/identity/permission-migrations.js +0 -67
  245. package/dist/identity/permissions.d.ts +0 -35
  246. package/dist/identity/permissions.js +0 -603
  247. package/dist/identity/ports.d.ts +0 -201
  248. package/dist/identity/repo.memory.d.ts +0 -164
  249. package/dist/identity/repo.memory.js +0 -224
  250. package/dist/identity/seed.d.ts +0 -54
  251. package/dist/identity/seed.js +0 -429
  252. package/dist/identity/tool-registrations.d.ts +0 -50
  253. package/dist/identity/tool-registrations.js +0 -419
  254. package/dist/identity/types.d.ts +0 -185
  255. package/dist/identity/types.js +0 -64
  256. package/dist/identity/username.d.ts +0 -12
  257. package/dist/identity/username.js +0 -14
  258. /package/dist/{identity → media/import}/ports.js +0 -0
@@ -30,41 +30,45 @@ import { ToolInputError } from "@jini-ai/core";
30
30
  * marker above.
31
31
  */
32
32
  export class ForbiddenError extends ToolInputError {
33
- constructor(message) {
34
- super(message);
33
+ constructor({ message }, _optional = {}) {
34
+ super({ message });
35
35
  this.name = "ForbiddenError";
36
36
  }
37
37
  }
38
- /** CIC U-002-B1 guard 1 — `key`/field-name grammar gate `^[a-z][a-z0-9_]{0,63}$` (U-001-B2). */
38
+ /** guard 1 — `key`/field-name grammar gate `^[a-z][a-z0-9_]{0,63}$`. See docs/decisions/DR-001-safe-schema-and-index-transitions.md. */
39
39
  export class InvalidKeyGrammarError extends ToolInputError {
40
- constructor(message) {
41
- super(message);
40
+ constructor(requiredArgs, optionalArgs = {}) {
41
+ const { message } = requiredArgs;
42
+ super({ message: message });
42
43
  this.name = "InvalidKeyGrammarError";
43
44
  }
44
45
  }
45
- /** CIC U-002-B1 guard 2 — `key` is one of the permanently reserved legacy `posts` keys. */
46
+ /** guard 2 — `key` is one of the permanently reserved legacy `posts` keys. See docs/decisions/DR-001-safe-schema-and-index-transitions.md. */
46
47
  export class ReservedContentTypeKeyError extends ToolInputError {
47
- constructor(message) {
48
- super(message);
48
+ constructor(requiredArgs, optionalArgs = {}) {
49
+ const { message } = requiredArgs;
50
+ super({ message: message });
49
51
  this.name = "ReservedContentTypeKeyError";
50
52
  }
51
53
  }
52
- /** CIC U-002-B1 guard 3 — a field name fails the identifier grammar gate. */
54
+ /** guard 3 — a field name fails the identifier grammar gate. See docs/decisions/DR-001-safe-schema-and-index-transitions.md. */
53
55
  export class InvalidFieldNameGrammarError extends ToolInputError {
54
- constructor(message) {
55
- super(message);
56
+ constructor(requiredArgs, optionalArgs = {}) {
57
+ const { message } = requiredArgs;
58
+ super({ message: message });
56
59
  this.name = "InvalidFieldNameGrammarError";
57
60
  }
58
61
  }
59
- /** CIC U-001-B1 / U-002-B1 guard 4 — a field `kind` is not one of the closed field-kind enum. */
62
+ /** guard 4 — a field `kind` is not one of the closed field-kind enum. See docs/decisions/DR-001-safe-schema-and-index-transitions.md. */
60
63
  export class InvalidFieldKindError extends ToolInputError {
61
- constructor(message) {
62
- super(message);
64
+ constructor(requiredArgs, optionalArgs = {}) {
65
+ const { message } = requiredArgs;
66
+ super({ message: message });
63
67
  this.name = "InvalidFieldKindError";
64
68
  }
65
69
  }
66
70
  /**
67
- * CIC U-002-B1 guard 4b — a field declares a STORAGE-ONLY `kind` (`json`) together with
71
+ * guard 4b — a field declares a STORAGE-ONLY `kind` (`json`) together with
68
72
  * `queryable: true`. The kind itself is legal and the field may be declared and written; what is
69
73
  * rejected is the pairing, because a storage-only kind has no `CAST` target and therefore no index
70
74
  * to provision.
@@ -77,10 +81,12 @@ export class InvalidFieldKindError extends ToolInputError {
77
81
  * `400 VALIDATION_ERROR` with no coordinated change, and the relationship is honest — this IS a
78
82
  * rejection of the field's kind, in the context the kind was used. `.name` still distinguishes it
79
83
  * for any caller that wants the finer signal.
84
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
80
85
  */
81
86
  export class StorageOnlyFieldNotQueryableError extends InvalidFieldKindError {
82
- constructor(message) {
83
- super(message);
87
+ constructor(requiredArgs, optionalArgs = {}) {
88
+ const { message } = requiredArgs;
89
+ super({ message: message });
84
90
  this.name = "StorageOnlyFieldNotQueryableError";
85
91
  }
86
92
  }
@@ -89,7 +95,7 @@ export class StorageOnlyFieldNotQueryableError extends InvalidFieldKindError {
89
95
  * shape the `ContentTypeFieldDef[]` contract does not describe at all (a non-array, a non-object
90
96
  * element, a missing/mistyped `name`/`required`/`queryable`, or an unrecognized key).
91
97
  *
92
- * Distinct from the five CIC U-002-B1 guard errors on purpose: those judge a well-formed field
98
+ * Distinct from the five guard errors on purpose: those judge a well-formed field
93
99
  * definition against a domain rule, and they remain the sole owners of the grammar, kind-enum and
94
100
  * queryable-cap decisions. This one fires strictly earlier, at the untrusted-input boundary
95
101
  * (`field-defs.ts`), for payloads the guards could not have judged without either crashing or
@@ -97,33 +103,37 @@ export class StorageOnlyFieldNotQueryableError extends InvalidFieldKindError {
97
103
  *
98
104
  * `violation.received` names the offending value's TYPE, never the value — a field payload can
99
105
  * carry operator content, and this message reaches both an HTTP client and a model.
106
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
100
107
  */
101
108
  export class InvalidFieldShapeError extends ToolInputError {
102
109
  code = "VALIDATION_ERROR";
103
110
  violation;
104
111
  constructor(violation) {
105
- super(`${violation.path} must be ${violation.expected}, received ${violation.received}`);
112
+ super({ message: `${violation.path} must be ${violation.expected}, received ${violation.received}` });
106
113
  this.name = "InvalidFieldShapeError";
107
114
  this.violation = violation;
108
115
  }
109
116
  }
110
- /** CIC U-002-B1 guard 5 — more than the per-type cap of `queryable` fields were submitted. */
117
+ /** guard 5 — more than the per-type cap of `queryable` fields were submitted. See docs/decisions/DR-001-safe-schema-and-index-transitions.md. */
111
118
  export class QueryableFieldCapExceededError extends ToolInputError {
112
- constructor(message) {
113
- super(message);
119
+ constructor(requiredArgs, optionalArgs = {}) {
120
+ const { message } = requiredArgs;
121
+ super({ message: message });
114
122
  this.name = "QueryableFieldCapExceededError";
115
123
  }
116
124
  }
117
- /** CIC U-004-B1 — `expectedVersion` did not match the current row's version (OCC conflict). */
125
+ /** — `expectedVersion` did not match the current row's version (OCC conflict). See docs/decisions/DR-001-safe-schema-and-index-transitions.md. */
118
126
  export class VersionConflictError extends ToolInputError {
119
- constructor(message) {
120
- super(message);
127
+ constructor(requiredArgs, optionalArgs = {}) {
128
+ const { message } = requiredArgs;
129
+ super({ message: message });
121
130
  this.name = "VersionConflictError";
122
131
  }
123
132
  }
124
133
  export class ContentTypeNotFoundError extends ToolInputError {
125
- constructor(message) {
126
- super(message);
134
+ constructor(requiredArgs, optionalArgs = {}) {
135
+ const { message } = requiredArgs;
136
+ super({ message: message });
127
137
  this.name = "CONTENT_TYPE_NOT_FOUND";
128
138
  }
129
139
  }
@@ -131,17 +141,20 @@ export class ContentTypeNotFoundError extends ToolInputError {
131
141
  * Row 7 (web-high fix plan, 2026-09-24) — `registerContentType` loaded no existing row before
132
142
  * saving, so two concurrent first-widget creates (or a caller retrying an existing key) could
133
143
  * silently overwrite the current fields, and registering a tombstoned key could resurrect it
134
- * (INV-06 forbids any transition out of tombstone, including via a fresh register). Thrown when
144
+ * ( forbids any transition out of tombstone, including via a fresh register). Thrown when
135
145
  * `deps.repo.findByKey` already returns a row for the key, whether that row is active/deprecated
136
146
  * or tombstoned — `tombstoned` distinguishes the two so a caller/HTTP route can give the right
137
147
  * guidance (retry with update-fields, vs. the key is permanently gone).
148
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
138
149
  */
139
150
  export class ContentTypeAlreadyExistsError extends ToolInputError {
140
151
  tombstoned;
141
- constructor(key, tombstoned) {
142
- super(tombstoned
143
- ? `content type '${key}' was permanently deleted; its key can't be reused (INV-06)`
144
- : `content type '${key}' already exists; use collections_content_type_update_fields to change its fields`);
152
+ constructor(requiredArgs, optionalArgs = {}) {
153
+ const { key, tombstoned } = requiredArgs;
154
+ super({ message: tombstoned
155
+ // See docs/decisions/DR-001-safe-schema-and-index-transitions.md for the invariant behind this refusal; keep external identifiers out of caller-facing messages.
156
+ ? `content type '${key}' was permanently deleted; its key can't be reused`
157
+ : `content type '${key}' already exists; use collections_content_type_update_fields to change its fields` });
145
158
  this.name = "ContentTypeAlreadyExistsError";
146
159
  this.tombstoned = tombstoned;
147
160
  }
@@ -150,23 +163,27 @@ export class ContentTypeAlreadyExistsError extends ToolInputError {
150
163
  export class ValidationError extends ToolInputError {
151
164
  code = "VALIDATION_ERROR";
152
165
  details;
153
- constructor(message, reason) {
154
- super(message);
166
+ constructor(requiredArgs, optionalArgs = {}) {
167
+ const { message, reason } = requiredArgs;
168
+ super({ message: message });
155
169
  this.name = "VALIDATION_ERROR";
156
170
  this.details = { reason };
157
171
  }
158
172
  }
159
- /** REQ-09..12 lifecycle state-machine guard rejection (INV-06 terminal-tombstone, EC-09 deprecate-first). */
173
+ /**..12 lifecycle state-machine guard rejection ( terminal-tombstone, deprecate-first). See docs/decisions/DR-001-safe-schema-and-index-transitions.md. */
160
174
  export class ContentTypeLifecycleError extends ToolInputError {
161
- constructor(message) {
162
- super(message);
175
+ constructor(requiredArgs, optionalArgs = {}) {
176
+ const { message } = requiredArgs;
177
+ super({ message: message });
163
178
  this.name = "ContentTypeLifecycleError";
164
179
  }
165
180
  }
166
- /** REQ-20 `planCleanup` eligibility-gate rejection; `reason` is one of a closed, ordered set. */
181
+ /** `planCleanup` eligibility-gate rejection; `reason` is one of a closed, ordered set. See docs/decisions/DR-001-safe-schema-and-index-transitions.md. */
167
182
  export class CleanupNotEligibleError extends Error {
168
183
  reason;
169
- constructor(reason, message) {
184
+ constructor(requiredArgs, optionalArgs = {}) {
185
+ const { reason } = requiredArgs;
186
+ const { message } = optionalArgs;
170
187
  super(message ?? `cleanup is not eligible: ${reason}`);
171
188
  this.name = "CleanupNotEligibleError";
172
189
  this.reason = reason;
@@ -1,10 +1,11 @@
1
- import { type ContentTypeFieldDef, type Result } from "./types.js";
1
+ import { type Result } from "@jini-ai/core/primitives";
2
+ import { type ContentTypeFieldDef } from "./types.js";
2
3
  /**
3
4
  * Validates an untrusted value against the `ContentTypeFieldDef[]` contract, returning either the
4
5
  * verified array or the first structural violation found.
5
6
  *
6
7
  * Stops at the first violation rather than collecting all of them, matching the
7
- * stop-at-first-failure convention CIC U-002-B1 already establishes for the domain guard chain
8
+ * stop-at-first-failure convention already establishes for the domain guard chain
8
9
  * this function feeds.
9
10
  *
10
11
  * @param value - The untrusted `fields` payload: a parsed JSON body's property, or an agent tool's
@@ -17,9 +18,12 @@ import { type ContentTypeFieldDef, type Result } from "./types.js";
17
18
  * @complexity O(f·k) time with f = element count (bounded by {@link MAX_FIELD_DEFS}) and k = 4
18
19
  * fixed keys, so effectively O(f); O(f) space for the returned array.
19
20
  * @example
20
- * const parsed = parseContentTypeFieldDefs([{ name: "servings", kind: "integer", required: false, queryable: true }]);
21
+ * const parsed = parseContentTypeFieldDefs({ value: [{ name: "servings", kind: "integer", required: false, queryable: true }] });
21
22
  * if (!parsed.ok) return { ok: false, error: parsed.error };
22
23
  * @overallScore 100
24
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
23
25
  */
24
- export declare function parseContentTypeFieldDefs(value: unknown): Result<ContentTypeFieldDef[], Error>;
26
+ export declare function parseContentTypeFieldDefs(requiredArgs: {
27
+ value: unknown;
28
+ }, optionalArgs?: Record<string, never>): Result<ContentTypeFieldDef[], Error>;
25
29
  //# sourceMappingURL=field-defs.d.ts.map
@@ -10,22 +10,22 @@
10
10
  * validation, which left three real gaps:
11
11
  *
12
12
  * 1. `required` and `queryable` were never type-checked anywhere in the codebase, so
13
- * `queryable: "yes"` counted as queryable (`write-service.ts`'s `countQueryableFields` filters
14
- * on truthiness) and `required: "maybe"` was persisted verbatim into the stored record and its
15
- * revision `stateJson`. That is a data-integrity gap, not merely a sloppy contract.
13
+ * `queryable: "yes"` counted as queryable (`write-service.ts`'s `countQueryableFields` filters
14
+ * on truthiness) and `required: "maybe"` was persisted verbatim into the stored record and its
15
+ * revision `stateJson`. That is a data-integrity gap, not merely a sloppy contract.
16
16
  * 2. A non-object element (`fields: [null]`) made the field-name grammar guard throw a bare
17
- * `TypeError` on `field.name` instead of returning a typed rejection — a 500 on the HTTP path
18
- * and an opaque `'failed'` tool execution on the agent path.
17
+ * `TypeError` on `field.name` instead of returning a typed rejection — a 500 on the HTTP path
18
+ * and an opaque `'failed'` tool execution on the agent path.
19
19
  * 3. A misspelled key (`queryible: true`) was silently dropped rather than reported, so a caller
20
- * got a field that was quietly non-queryable with no indication why.
20
+ * got a field that was quietly non-queryable with no indication why.
21
21
  *
22
22
  * Division of responsibility (deliberate, and the reason this module is narrow):
23
23
  * this module owns STRUCTURE only — array-ness, element object-ness, the four keys and their
24
24
  * types. It does NOT own the domain rules. The field-name grammar gate, the reserved-key check and
25
- * the queryable-field cap stay solely in `write-service.ts`'s CIC U-002-B1 guard chain, whose
25
+ * the queryable-field cap stay solely in `write-service.ts`'s guard chain, whose
26
26
  * fixed order (`key grammar -> reserved-key -> field-name grammar -> field-kind -> queryable-cap`)
27
27
  * and stop-at-first-failure behavior are pinned by
28
- * `__tests__/unit/write-service.register.unit.test.ts` (AC-38). Duplicating any of those here
28
+ * `__tests__/unit/write-service.register.unit.test.ts`. Duplicating any of those here
29
29
  * would either reorder that chain for boundary callers or create a second source of truth for a
30
30
  * rule that must have exactly one definition.
31
31
  *
@@ -38,8 +38,10 @@
38
38
  * Architectural role:
39
39
  * `features/content-types` domain logic. Pure — no I/O, no clock, no repo. Depends only on this
40
40
  * package's own `types.ts` and `errors.ts`.
41
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
41
42
  */
42
43
  import { InvalidFieldKindError, InvalidFieldShapeError } from "./errors.js";
44
+ import {} from "@jini-ai/core/primitives";
43
45
  import { isContentTypeFieldKind } from "./types.js";
44
46
  /**
45
47
  * The complete, closed key set of a `ContentTypeFieldDef`. Any other key is rejected rather than
@@ -78,7 +80,7 @@ function isPlainObject(value) {
78
80
  * verified array or the first structural violation found.
79
81
  *
80
82
  * Stops at the first violation rather than collecting all of them, matching the
81
- * stop-at-first-failure convention CIC U-002-B1 already establishes for the domain guard chain
83
+ * stop-at-first-failure convention already establishes for the domain guard chain
82
84
  * this function feeds.
83
85
  *
84
86
  * @param value - The untrusted `fields` payload: a parsed JSON body's property, or an agent tool's
@@ -91,11 +93,13 @@ function isPlainObject(value) {
91
93
  * @complexity O(f·k) time with f = element count (bounded by {@link MAX_FIELD_DEFS}) and k = 4
92
94
  * fixed keys, so effectively O(f); O(f) space for the returned array.
93
95
  * @example
94
- * const parsed = parseContentTypeFieldDefs([{ name: "servings", kind: "integer", required: false, queryable: true }]);
96
+ * const parsed = parseContentTypeFieldDefs({ value: [{ name: "servings", kind: "integer", required: false, queryable: true }] });
95
97
  * if (!parsed.ok) return { ok: false, error: parsed.error };
96
98
  * @overallScore 100
99
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
97
100
  */
98
- export function parseContentTypeFieldDefs(value) {
101
+ export function parseContentTypeFieldDefs(requiredArgs, optionalArgs = {}) {
102
+ const { value } = requiredArgs;
99
103
  if (!Array.isArray(value)) {
100
104
  return { ok: false, error: new InvalidFieldShapeError({ path: "fields", expected: "an array", received: describeType(value) }) };
101
105
  }
@@ -147,9 +151,10 @@ function parseOneFieldDef(element, at) {
147
151
  if (typeof element.kind !== "string") {
148
152
  return { ok: false, error: new InvalidFieldShapeError({ path: `${at}.kind`, expected: "a string", received: describeType(element.kind) }) };
149
153
  }
150
- if (!isContentTypeFieldKind(element.kind)) {
151
- return { ok: false, error: new InvalidFieldKindError(`field '${element.name}' has kind '${element.kind}', not one of the closed field-kind enum`) };
154
+ const kind = { value: element.kind };
155
+ if (!isContentTypeFieldKind(kind)) {
156
+ return { ok: false, error: new InvalidFieldKindError({ message: `field '${element.name}' has kind '${element.kind}', not one of the closed field-kind enum` }) };
152
157
  }
153
- return { ok: true, value: { name: element.name, kind: element.kind, required: element.required, queryable: element.queryable } };
158
+ return { ok: true, value: { name: element.name, kind: kind.value, required: element.required, queryable: element.queryable } };
154
159
  }
155
160
  //# sourceMappingURL=field-defs.js.map
@@ -1,47 +1,47 @@
1
1
  import { type ContentTypeFieldKind, type IndexableFieldKind } from "./types.js";
2
2
  /**
3
- * @file CIC U-001 — the `kind`->`CAST` fixed lookup table, the identifier grammar
3
+ * @file the `kind`->`CAST` fixed lookup table, the identifier grammar
4
4
  * gate, the workspace-scoped queryable-index naming scheme, and the before/after index-transition
5
5
  * resolver (grammar-and-workspace-scoping folds).
6
6
  *
7
7
  * Purpose:
8
8
  * THIS IS THE HIGHEST-SECURITY-SEVERITY MODULE IN THE 5-PACKAGE PIPELINE — every value that ends
9
- * up inside a `CREATE INDEX ... CAST(json_extract(fields,'$.ext.{ns}.{field}') AS {type})`
9
+ * up inside a `CREATE INDEX... CAST(json_extract(fields,'$.ext.{ns}.{field}') AS {type})`
10
10
  * statement is produced here, and only here:
11
- * - `mapFieldKindToCast` (U-001-B1). STATE THE INVARIANT PRECISELY, because an earlier version
12
- * of this comment did not and the imprecision was itself a hazard: it said "a fixed, hardcoded
13
- * 5-entry table", which reads as though the ENTRY COUNT were the defense. It is not. Neither
14
- * the number of keys nor the number of distinct values is the security boundary.
11
+ * - `mapFieldKindToCast`. STATE THE INVARIANT PRECISELY, because an earlier version
12
+ * of this comment did not and the imprecision was itself a hazard: it said "a fixed, hardcoded
13
+ * 5-entry table", which reads as though the ENTRY COUNT were the defense. It is not. Neither
14
+ * the number of keys nor the number of distinct values is the security boundary.
15
15
  *
16
- * THE DEFENSE IS: this function returns a VALUE FROM THE TABLE and never returns, echoes, or
17
- * interpolates its own ARGUMENT. The function has exactly one `return`, and it is a table
18
- * lookup. Therefore the set of strings that can reach a `CAST(... AS {type})` position is
19
- * exactly the set of string literals written into `KIND_TO_CAST_LITERAL` in this source file —
20
- * compile-time constants, every one — no matter what an operator, an agent, or an attacker
21
- * supplies as `kind`. A 50-entry table of literals would be exactly as safe as a 5-entry one.
16
+ * THE DEFENSE IS: this function returns a VALUE FROM THE TABLE and never returns, echoes, or
17
+ * interpolates its own ARGUMENT. The function has exactly one `return`, and it is a table
18
+ * lookup. Therefore the set of strings that can reach a `CAST(... AS {type})` position is
19
+ * exactly the set of string literals written into `KIND_TO_CAST_LITERAL` in this source file —
20
+ * compile-time constants, every one — no matter what an operator, an agent, or an attacker
21
+ * supplies as `kind`. A 50-entry table of literals would be exactly as safe as a 5-entry one.
22
22
  *
23
- * What follows from that, and what a maintainer actually needs to know:
24
- * * Adding a KEY whose value is an existing literal cannot widen the DDL alphabet. It is not
25
- * a security event and does not need to be feared as one. (`relation: "TEXT"` is exactly
26
- * this: `"TEXT"` was already present twice.)
27
- * * Adding a new VALUE does widen it, and must be reviewed as a DDL change.
28
- * * Returning, concatenating, or template-interpolating `kind` itself — or reading the table
29
- * with a fallback such as `?? kind` — BREAKS the invariant outright. That is the edit to
30
- * refuse, and it is the one the old "5-entry" phrasing gave no way to recognise.
31
- * The reachable-value set is pinned executably by `HISTORICAL_DDL_ALPHABET` in
32
- * `__tests__/field-kind-widening.test.ts`, so this claim is a failing test and not only prose.
23
+ * What follows from that, and what a maintainer actually needs to know:
24
+ * * Adding a KEY whose value is an existing literal cannot widen the DDL alphabet. It is not
25
+ * a security event and does not need to be feared as one. (`relation: "TEXT"` is exactly
26
+ * this: `"TEXT"` was already present twice.)
27
+ * * Adding a new VALUE does widen it, and must be reviewed as a DDL change.
28
+ * * Returning, concatenating, or template-interpolating `kind` itself — or reading the table
29
+ * with a fallback such as `?? kind` — BREAKS the invariant outright. That is the edit to
30
+ * refuse, and it is the one the old "5-entry" phrasing gave no way to recognise.
31
+ * The reachable-value set is pinned executably by `HISTORICAL_DDL_ALPHABET` in
32
+ * `__tests__/field-kind-widening.test.ts`, so this claim is a failing test and not only prose.
33
33
  *
34
- * Degraded failure mode, stated so the blast radius is known: if every runtime guard below
35
- * were deleted, a storage-only kind would reach the table and `KIND_TO_CAST_LITERAL["json"]`
36
- * would evaluate to `undefined` — a SQL syntax error and a loud broken feature, never an
37
- * operator-controlled string. Total guard removal degrades this module to unavailable, not to
38
- * injectable. That is the property worth preserving through any future change.
39
- * - `validateIdentifierGrammar`/`buildQueryableFieldIndexName` gate every `key`/field name
40
- * through `^[a-z][a-z0-9_]{0,63}$` before it can reach an index-name segment or JSON-path
41
- * literal (U-001-B2), and join grammar-gated segments with `/` — a delimiter outside the
42
- * grammar's own alphabet `[a-z0-9_]`, closing the namespace-injectivity collision class
43
- * (U-001-B3) — and fold in a workspace-derived segment so two workspaces defining the same
44
- * `(key, field)` pair never collide on index identity.
34
+ * Degraded failure mode, stated so the blast radius is known: if every runtime guard below
35
+ * were deleted, a storage-only kind would reach the table and `KIND_TO_CAST_LITERAL["json"]`
36
+ * would evaluate to `undefined` — a SQL syntax error and a loud broken feature, never an
37
+ * operator-controlled string. Total guard removal degrades this module to unavailable, not to
38
+ * injectable. That is the property worth preserving through any future change.
39
+ * - `validateIdentifierGrammar`/`buildQueryableFieldIndexName` gate every `key`/field name
40
+ * through `^[a-z][a-z0-9_]{0,63}$` before it can reach an index-name segment or JSON-path
41
+ * literal, and join grammar-gated segments with `/` — a delimiter outside the
42
+ * grammar's own alphabet `[a-z0-9_]`, closing the namespace-injectivity collision class
43
+ * — and fold in a workspace-derived segment so two workspaces defining the same
44
+ * `(key, field)` pair never collide on index identity.
45
45
  *
46
46
  * How it relates to the project:
47
47
  * `resolveFieldIndexTransition` deliberately still ACCEPTS a storage-only kind on its `none` and
@@ -51,35 +51,40 @@ import { type ContentTypeFieldKind, type IndexableFieldKind } from "./types.js";
51
51
  *
52
52
  * `write-service.ts`'s `registerContentType`/`updateContentTypeFields` call
53
53
  * `resolveFieldIndexTransition` once per field (never two independent kind/queryable branches —
54
- * CIC U-003-B1) and hand the result to the injected `indexProvisioner` port, which is the only
54
+ * ) and hand the result to the injected `indexProvisioner` port, which is the only
55
55
  * thing that ever issues the real `CREATE INDEX`/`DROP INDEX` DDL (this module only decides what
56
56
  * to build, never executes DDL itself).
57
57
  *
58
58
  * Architectural role:
59
- * `features/content-types` domain logic. No dependencies beyond `node:crypto` (workspace-segment
60
- * hashing) and this package's own `errors.ts`/`types.ts`.
59
+ * `features/content-types` domain logic. Workspace-segment hashing uses Web Crypto so this
60
+ * universal entry needs only standard runtime APIs and this package's own `errors.ts`/`types.ts`.
61
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
61
62
  */
62
63
  /**
63
- * U-001-B2 — the closed identifier grammar every `content_types.key` and field name must satisfy,
64
+ * — the closed identifier grammar every `content_types.key` and field name must satisfy,
64
65
  * as a pattern string so the agent-facing JSON Schemas in `agent-tools.ts` can publish the very
65
66
  * same grammar instead of restating it. A cross-cutting single-source-of-truth governance rule makes this grammar load-bearing for DDL
66
67
  * safety, so it must have exactly one definition; {@link IDENTIFIER_GRAMMAR} is compiled from this
67
68
  * string rather than written twice.
69
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
68
70
  */
69
71
  export declare const IDENTIFIER_GRAMMAR_PATTERN = "^[a-z][a-z0-9_]{0,63}$";
70
72
  /**
71
- * Structural grammar gate for a `content_types.key` or field name (U-001-B2).
73
+ * Structural grammar gate for a `content_types.key` or field name.
72
74
  *
73
75
  * @complexity O(n) in the string's length (regex match), bounded at 64 chars.
74
76
  * @overallScore 100
77
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
75
78
  */
76
- export declare function validateIdentifierGrammar(value: string): boolean;
79
+ export declare function validateIdentifierGrammar(requiredArgs: {
80
+ value: string;
81
+ }, optionalArgs?: Record<string, never>): boolean;
77
82
  /**
78
83
  * Maps an INDEXABLE field `kind` to its fixed `CAST(... AS {type})` type token. Throws
79
84
  * {@link InvalidFieldKindError} for anything that is not exactly one of `INDEXABLE_FIELD_KINDS` —
80
85
  * including a storage-only kind such as `json`, which is a legal kind to declare but has no CAST
81
86
  * target. This is a lookup, never a template, so an adversarial payload can never reach the
82
- * returned string (U-001-B1).
87
+ * returned string.
83
88
  *
84
89
  * The PARAMETER type is deliberately the wider `ContentTypeFieldKind`. Narrowing it would be a
85
90
  * breaking change for `@jini-ai/cms`'s public consumers (`content-types/index.ts` documents this
@@ -93,23 +98,31 @@ export declare function validateIdentifierGrammar(value: string): boolean;
93
98
  *
94
99
  * @complexity O(1) — a fixed-size object lookup behind a fixed-size membership test.
95
100
  * @overallScore 100
101
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
96
102
  */
97
- export declare function mapFieldKindToCast(kind: ContentTypeFieldKind): string;
103
+ export declare function mapFieldKindToCast(requiredArgs: {
104
+ kind: ContentTypeFieldKind;
105
+ }, optionalArgs?: Record<string, never>): string;
98
106
  /**
99
107
  * Builds the workspace-scoped queryable-field index identity for `(workspaceId, contentTypeKey,
100
108
  * fieldName)`. Both `contentTypeKey` and `fieldName` are grammar-gated first — a failure throws
101
- * before any index name is produced (U-001-B2). Segments are joined with `/`, a delimiter outside
109
+ * before any index name is produced. Segments are joined with `/`, a delimiter outside
102
110
  * the grammar's own alphabet `[a-z0-9_]`, so distinct `(key, name)` pairs can never collide by
103
- * boundary-shifting (U-001-B3, e.g. `("a_b","c")` vs `("a","b_c")`).
111
+ * boundary-shifting (e.g. `("a_b","c")` vs `("a","b_c")`).
112
+ *
113
+ * Returns a promise for the unchanged index identity. Grammar failures still throw
114
+ * synchronously before hashing; Web Crypto failures reject the promise. Callers must await
115
+ * the name before using it in DDL.
104
116
  *
105
- * @complexity O(1) plus two grammar checks and one SHA-256 hash.
117
+ * @complexity O(n) time and space in the UTF-8 workspace ID length, plus two grammar checks.
106
118
  * @overallScore 100
119
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
107
120
  */
108
121
  export declare function buildQueryableFieldIndexName(params: {
109
122
  workspaceId: string;
110
123
  contentTypeKey: string;
111
124
  fieldName: string;
112
- }): string;
125
+ }): Promise<string>;
113
126
  /** A field's `(kind, queryable)` pair at one side of an update call, or `undefined` if absent (new/removed). */
114
127
  export type FieldIndexState = {
115
128
  kind: ContentTypeFieldKind;
@@ -125,13 +138,14 @@ export interface FieldIndexTransition {
125
138
  newKind?: IndexableFieldKind;
126
139
  }
127
140
  /**
128
- * CIC U-003-B1 — resolves a single field's index transition from ONE before/after comparison of
141
+ * — resolves a single field's index transition from ONE before/after comparison of
129
142
  * its `(kind, queryable)` pair, never from two independent branches that each assume the other
130
143
  * property is unchanged (the bug class this closes: a field whose `kind` AND `queryable` both
131
- * change in the same call must still resolve correctly — REQ-30(b)).
144
+ * change in the same call must still resolve correctly — (b)).
132
145
  *
133
146
  * @complexity O(1) — four comparisons, one of four fixed outcomes.
134
147
  * @overallScore 100
148
+ * See docs/decisions/DR-001-safe-schema-and-index-transitions.md.
135
149
  */
136
150
  export declare function resolveFieldIndexTransition(params: {
137
151
  before: FieldIndexState;