@jini-ai/cms 0.3.5 → 0.3.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -17
- package/dist/content-types/agent-tools.d.ts.map +1 -1
- package/dist/content-types/agent-tools.js +1 -1
- package/dist/content-types/agent-tools.js.map +1 -1
- package/dist/content-types/errors.d.ts +19 -1
- package/dist/content-types/errors.d.ts.map +1 -1
- package/dist/content-types/errors.js +22 -1
- package/dist/content-types/errors.js.map +1 -1
- package/dist/content-types/index-provisioning.d.ts +56 -10
- package/dist/content-types/index-provisioning.d.ts.map +1 -1
- package/dist/content-types/index-provisioning.js +86 -13
- package/dist/content-types/index-provisioning.js.map +1 -1
- package/dist/content-types/index.d.ts +15 -3
- package/dist/content-types/index.d.ts.map +1 -1
- package/dist/content-types/index.js +14 -2
- package/dist/content-types/index.js.map +1 -1
- package/dist/content-types/lifecycle.js +3 -3
- package/dist/content-types/lifecycle.js.map +1 -1
- package/dist/content-types/types.d.ts +64 -3
- package/dist/content-types/types.d.ts.map +1 -1
- package/dist/content-types/types.js +67 -3
- package/dist/content-types/types.js.map +1 -1
- package/dist/content-types/write-service.d.ts +18 -3
- package/dist/content-types/write-service.d.ts.map +1 -1
- package/dist/content-types/write-service.js +28 -2
- package/dist/content-types/write-service.js.map +1 -1
- package/dist/core/ports.d.ts +12 -2
- package/dist/core/ports.d.ts.map +1 -1
- package/dist/entries/field-validation.d.ts.map +1 -1
- package/dist/entries/field-validation.js +96 -1
- package/dist/entries/field-validation.js.map +1 -1
- package/dist/entries/write-service.d.ts +14 -0
- package/dist/entries/write-service.d.ts.map +1 -1
- package/dist/entries/write-service.js +2 -2
- package/dist/entries/write-service.js.map +1 -1
- package/dist/identity/admin-crud-service.d.ts +28 -0
- package/dist/identity/admin-crud-service.d.ts.map +1 -1
- package/dist/identity/admin-crud-service.js +30 -0
- package/dist/identity/admin-crud-service.js.map +1 -1
- package/dist/identity/auth-service.d.ts +32 -1
- package/dist/identity/auth-service.d.ts.map +1 -1
- package/dist/identity/auth-service.js +44 -15
- package/dist/identity/auth-service.js.map +1 -1
- package/dist/identity/index.d.ts +4 -1
- package/dist/identity/index.d.ts.map +1 -1
- package/dist/identity/index.js +4 -1
- package/dist/identity/index.js.map +1 -1
- package/dist/identity/seed.d.ts +14 -2
- package/dist/identity/seed.d.ts.map +1 -1
- package/dist/identity/seed.js +197 -45
- package/dist/identity/seed.js.map +1 -1
- package/dist/media/content-type-sniffer.d.ts +1 -1
- package/dist/media/content-type-sniffer.d.ts.map +1 -1
- package/dist/media/content-type-sniffer.js +52 -4
- package/dist/media/content-type-sniffer.js.map +1 -1
- package/dist/media/html-attributes.d.ts +90 -0
- package/dist/media/html-attributes.d.ts.map +1 -0
- package/dist/media/html-attributes.js +161 -0
- package/dist/media/html-attributes.js.map +1 -0
- package/dist/media/image-transformer.sharp.d.ts +35 -1
- package/dist/media/image-transformer.sharp.d.ts.map +1 -1
- package/dist/media/image-transformer.sharp.js +44 -2
- package/dist/media/image-transformer.sharp.js.map +1 -1
- package/dist/media/index.d.ts +2 -1
- package/dist/media/index.d.ts.map +1 -1
- package/dist/media/index.js +2 -1
- package/dist/media/index.js.map +1 -1
- package/dist/media/media-service.d.ts +60 -1
- package/dist/media/media-service.d.ts.map +1 -1
- package/dist/media/media-service.js +212 -5
- package/dist/media/media-service.js.map +1 -1
- package/dist/media/ports.d.ts +6 -0
- package/dist/media/ports.d.ts.map +1 -1
- package/dist/media/rendition-service.d.ts +7 -1
- package/dist/media/rendition-service.d.ts.map +1 -1
- package/dist/media/rendition-service.js +10 -4
- package/dist/media/rendition-service.js.map +1 -1
- package/dist/media/repo.memory.d.ts +4 -0
- package/dist/media/repo.memory.d.ts.map +1 -1
- package/dist/media/repo.memory.js +3 -0
- package/dist/media/repo.memory.js.map +1 -1
- package/dist/media/types.d.ts +26 -0
- package/dist/media/types.d.ts.map +1 -1
- package/dist/media/types.js.map +1 -1
- package/dist/navigation/agent-tools.d.ts.map +1 -1
- package/dist/navigation/agent-tools.js +8 -1
- package/dist/navigation/agent-tools.js.map +1 -1
- package/dist/navigation/index.d.ts +10 -1
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +10 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/navigation/menu-service.d.ts +60 -4
- package/dist/navigation/menu-service.d.ts.map +1 -1
- package/dist/navigation/menu-service.js +106 -8
- package/dist/navigation/menu-service.js.map +1 -1
- package/package.json +1 -1
|
@@ -14,20 +14,81 @@
|
|
|
14
14
|
* is that enum's single source of truth so the write-service's validation and the index
|
|
15
15
|
* provisioner's CAST-mapping can never drift apart.
|
|
16
16
|
*
|
|
17
|
+
* The enum is SPLIT rather than flat (2026-09-05): a kind is either INDEXABLE — it may carry
|
|
18
|
+
* `queryable: true` and therefore may reach `mapFieldKindToCast` — or STORAGE-ONLY, stored
|
|
19
|
+
* verbatim in `fieldsJson` and never indexed, sorted, or filtered on. The split is what keeps the
|
|
20
|
+
* CAST table's exhaustiveness compiler-enforced without forcing a CAST target to be invented for a
|
|
21
|
+
* kind that has none; see `index-provisioning.ts`'s `KIND_TO_CAST_LITERAL`.
|
|
22
|
+
*
|
|
17
23
|
* Architectural role:
|
|
18
24
|
* `features/content-types` domain vocabulary. No dependencies.
|
|
19
25
|
*/
|
|
20
|
-
/**
|
|
21
|
-
|
|
26
|
+
/**
|
|
27
|
+
* CIC U-001-B1 — the closed, 5-entry INDEXABLE SCALAR set. Never extend ad hoc.
|
|
28
|
+
*
|
|
29
|
+
* Unchanged since the original enum: every value that has ever reached a `CAST` literal is still
|
|
30
|
+
* here, in this order. Kept as its own constant so the "these five are the original, untouched
|
|
31
|
+
* scalars" claim is expressible in code rather than only in a comment.
|
|
32
|
+
*/
|
|
33
|
+
export declare const CONTENT_TYPE_SCALAR_KINDS: readonly ["text", "integer", "real", "boolean", "datetime"];
|
|
34
|
+
/**
|
|
35
|
+
* CIC U-001-B1 — kinds that MAY carry `queryable: true` and therefore MAY reach
|
|
36
|
+
* `mapFieldKindToCast`. Every member MUST have an entry in `index-provisioning.ts`'s
|
|
37
|
+
* `KIND_TO_CAST_LITERAL`; the compiler enforces this via `Record<IndexableFieldKind, string>`, so
|
|
38
|
+
* adding a member here fails the build until a CAST literal is supplied for it.
|
|
39
|
+
*
|
|
40
|
+
* `relation` stores a foreign entity id and shares `text`'s storage class, so its CAST target is
|
|
41
|
+
* the already-present literal `"TEXT"` — it adds a KEY to that table, never a new VALUE to the
|
|
42
|
+
* DDL alphabet.
|
|
43
|
+
*/
|
|
44
|
+
export declare const INDEXABLE_FIELD_KINDS: readonly ["text", "integer", "real", "boolean", "datetime", "relation"];
|
|
45
|
+
export type IndexableFieldKind = (typeof INDEXABLE_FIELD_KINDS)[number];
|
|
46
|
+
/**
|
|
47
|
+
* Kinds stored verbatim inside `fieldsJson` and NEVER indexed, sorted, or filtered on. A
|
|
48
|
+
* storage-only kind has no CAST target — it is not that one is hard to choose, it is that a JSON
|
|
49
|
+
* document has no scalar storage class to cast to — so `write-service.ts` rejects
|
|
50
|
+
* `queryable: true` on one before any index transition can be resolved.
|
|
51
|
+
*/
|
|
52
|
+
export declare const STORAGE_ONLY_FIELD_KINDS: readonly ["json"];
|
|
53
|
+
export type StorageOnlyFieldKind = (typeof STORAGE_ONLY_FIELD_KINDS)[number];
|
|
54
|
+
/**
|
|
55
|
+
* CIC U-001-B1 — the closed field-kind enum. UNCHANGED NAME AND MEANING for every existing
|
|
56
|
+
* consumer: it is still the complete, closed set of legal `kind` values, and
|
|
57
|
+
* {@link isContentTypeFieldKind} is still the gate for it.
|
|
58
|
+
*
|
|
59
|
+
* Member order is load-bearing, not cosmetic: the five scalars must stay first and in their
|
|
60
|
+
* original order because this array's `join("|")` is interpolated into an operator-facing error
|
|
61
|
+
* message. The spread order below preserves that; the published agent-tool schema
|
|
62
|
+
* (`agent-tools.ts`) also spreads this constant, so both widen in lockstep with no hand-copied
|
|
63
|
+
* second list to drift.
|
|
64
|
+
*/
|
|
65
|
+
export declare const CONTENT_TYPE_FIELD_KINDS: readonly ["text", "integer", "real", "boolean", "datetime", "relation", "json"];
|
|
22
66
|
export type ContentTypeFieldKind = (typeof CONTENT_TYPE_FIELD_KINDS)[number];
|
|
23
67
|
/**
|
|
24
68
|
* Type guard for {@link ContentTypeFieldKind}. The single gate every kind value must pass before
|
|
25
69
|
* it is trusted anywhere near DDL construction (`index-provisioning.ts`) or write validation.
|
|
26
70
|
*
|
|
27
|
-
* @
|
|
71
|
+
* Note the division of labour with {@link isIndexableFieldKind}: passing THIS gate means the value
|
|
72
|
+
* is a legal kind to DECLARE and STORE. It does NOT license a CAST — `mapFieldKindToCast` applies
|
|
73
|
+
* the narrower gate, because "storable" and "indexable" are no longer the same set.
|
|
74
|
+
*
|
|
75
|
+
* @complexity O(1) — a fixed-size array membership test.
|
|
28
76
|
* @overallScore 100
|
|
29
77
|
*/
|
|
30
78
|
export declare function isContentTypeFieldKind(value: unknown): value is ContentTypeFieldKind;
|
|
79
|
+
/**
|
|
80
|
+
* Type guard for {@link IndexableFieldKind} — the gate `mapFieldKindToCast` applies instead of
|
|
81
|
+
* {@link isContentTypeFieldKind}, and the gate `write-service.ts` applies to reject
|
|
82
|
+
* `queryable: true` on a storage-only kind.
|
|
83
|
+
*
|
|
84
|
+
* For all five original scalars this predicate and {@link isContentTypeFieldKind} agree exactly,
|
|
85
|
+
* which is what makes narrowing the CAST gate behavior-preserving for every input that could
|
|
86
|
+
* exist before `relation`/`json` were introduced.
|
|
87
|
+
*
|
|
88
|
+
* @complexity O(1) — a fixed-size array membership test.
|
|
89
|
+
* @overallScore 100
|
|
90
|
+
*/
|
|
91
|
+
export declare function isIndexableFieldKind(value: unknown): value is IndexableFieldKind;
|
|
31
92
|
export interface ContentTypeFieldDef {
|
|
32
93
|
name: string;
|
|
33
94
|
kind: ContentTypeFieldKind;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/content-types/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/content-types/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,6DAA8D,CAAC;AAErG;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,yEAAsD,CAAC;AAEzF,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC;AAExE;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,mBAAoB,CAAC;AAE1D,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,iFAG3B,CAAC;AAEX,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7E;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,oBAAoB,CAEpF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAEhF;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,oBAAoB,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,YAAY,GAAG,WAAW,CAAC;AAEtE,wFAAwF;AACxF,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;GAKG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEzE,iGAAiG;AACjG,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,6GAA6G;AAC7G,MAAM,MAAM,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,CAAC"}
|
|
@@ -14,19 +14,83 @@
|
|
|
14
14
|
* is that enum's single source of truth so the write-service's validation and the index
|
|
15
15
|
* provisioner's CAST-mapping can never drift apart.
|
|
16
16
|
*
|
|
17
|
+
* The enum is SPLIT rather than flat (2026-09-05): a kind is either INDEXABLE — it may carry
|
|
18
|
+
* `queryable: true` and therefore may reach `mapFieldKindToCast` — or STORAGE-ONLY, stored
|
|
19
|
+
* verbatim in `fieldsJson` and never indexed, sorted, or filtered on. The split is what keeps the
|
|
20
|
+
* CAST table's exhaustiveness compiler-enforced without forcing a CAST target to be invented for a
|
|
21
|
+
* kind that has none; see `index-provisioning.ts`'s `KIND_TO_CAST_LITERAL`.
|
|
22
|
+
*
|
|
17
23
|
* Architectural role:
|
|
18
24
|
* `features/content-types` domain vocabulary. No dependencies.
|
|
19
25
|
*/
|
|
20
|
-
/**
|
|
21
|
-
|
|
26
|
+
/**
|
|
27
|
+
* CIC U-001-B1 — the closed, 5-entry INDEXABLE SCALAR set. Never extend ad hoc.
|
|
28
|
+
*
|
|
29
|
+
* Unchanged since the original enum: every value that has ever reached a `CAST` literal is still
|
|
30
|
+
* here, in this order. Kept as its own constant so the "these five are the original, untouched
|
|
31
|
+
* scalars" claim is expressible in code rather than only in a comment.
|
|
32
|
+
*/
|
|
33
|
+
export const CONTENT_TYPE_SCALAR_KINDS = ["text", "integer", "real", "boolean", "datetime"];
|
|
34
|
+
/**
|
|
35
|
+
* CIC U-001-B1 — kinds that MAY carry `queryable: true` and therefore MAY reach
|
|
36
|
+
* `mapFieldKindToCast`. Every member MUST have an entry in `index-provisioning.ts`'s
|
|
37
|
+
* `KIND_TO_CAST_LITERAL`; the compiler enforces this via `Record<IndexableFieldKind, string>`, so
|
|
38
|
+
* adding a member here fails the build until a CAST literal is supplied for it.
|
|
39
|
+
*
|
|
40
|
+
* `relation` stores a foreign entity id and shares `text`'s storage class, so its CAST target is
|
|
41
|
+
* the already-present literal `"TEXT"` — it adds a KEY to that table, never a new VALUE to the
|
|
42
|
+
* DDL alphabet.
|
|
43
|
+
*/
|
|
44
|
+
export const INDEXABLE_FIELD_KINDS = [...CONTENT_TYPE_SCALAR_KINDS, "relation"];
|
|
45
|
+
/**
|
|
46
|
+
* Kinds stored verbatim inside `fieldsJson` and NEVER indexed, sorted, or filtered on. A
|
|
47
|
+
* storage-only kind has no CAST target — it is not that one is hard to choose, it is that a JSON
|
|
48
|
+
* document has no scalar storage class to cast to — so `write-service.ts` rejects
|
|
49
|
+
* `queryable: true` on one before any index transition can be resolved.
|
|
50
|
+
*/
|
|
51
|
+
export const STORAGE_ONLY_FIELD_KINDS = ["json"];
|
|
52
|
+
/**
|
|
53
|
+
* CIC U-001-B1 — the closed field-kind enum. UNCHANGED NAME AND MEANING for every existing
|
|
54
|
+
* consumer: it is still the complete, closed set of legal `kind` values, and
|
|
55
|
+
* {@link isContentTypeFieldKind} is still the gate for it.
|
|
56
|
+
*
|
|
57
|
+
* Member order is load-bearing, not cosmetic: the five scalars must stay first and in their
|
|
58
|
+
* original order because this array's `join("|")` is interpolated into an operator-facing error
|
|
59
|
+
* message. The spread order below preserves that; the published agent-tool schema
|
|
60
|
+
* (`agent-tools.ts`) also spreads this constant, so both widen in lockstep with no hand-copied
|
|
61
|
+
* second list to drift.
|
|
62
|
+
*/
|
|
63
|
+
export const CONTENT_TYPE_FIELD_KINDS = [
|
|
64
|
+
...INDEXABLE_FIELD_KINDS,
|
|
65
|
+
...STORAGE_ONLY_FIELD_KINDS,
|
|
66
|
+
];
|
|
22
67
|
/**
|
|
23
68
|
* Type guard for {@link ContentTypeFieldKind}. The single gate every kind value must pass before
|
|
24
69
|
* it is trusted anywhere near DDL construction (`index-provisioning.ts`) or write validation.
|
|
25
70
|
*
|
|
26
|
-
* @
|
|
71
|
+
* Note the division of labour with {@link isIndexableFieldKind}: passing THIS gate means the value
|
|
72
|
+
* is a legal kind to DECLARE and STORE. It does NOT license a CAST — `mapFieldKindToCast` applies
|
|
73
|
+
* the narrower gate, because "storable" and "indexable" are no longer the same set.
|
|
74
|
+
*
|
|
75
|
+
* @complexity O(1) — a fixed-size array membership test.
|
|
27
76
|
* @overallScore 100
|
|
28
77
|
*/
|
|
29
78
|
export function isContentTypeFieldKind(value) {
|
|
30
79
|
return typeof value === "string" && CONTENT_TYPE_FIELD_KINDS.includes(value);
|
|
31
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Type guard for {@link IndexableFieldKind} — the gate `mapFieldKindToCast` applies instead of
|
|
83
|
+
* {@link isContentTypeFieldKind}, and the gate `write-service.ts` applies to reject
|
|
84
|
+
* `queryable: true` on a storage-only kind.
|
|
85
|
+
*
|
|
86
|
+
* For all five original scalars this predicate and {@link isContentTypeFieldKind} agree exactly,
|
|
87
|
+
* which is what makes narrowing the CAST gate behavior-preserving for every input that could
|
|
88
|
+
* exist before `relation`/`json` were introduced.
|
|
89
|
+
*
|
|
90
|
+
* @complexity O(1) — a fixed-size array membership test.
|
|
91
|
+
* @overallScore 100
|
|
92
|
+
*/
|
|
93
|
+
export function isIndexableFieldKind(value) {
|
|
94
|
+
return typeof value === "string" && INDEXABLE_FIELD_KINDS.includes(value);
|
|
95
|
+
}
|
|
32
96
|
//# sourceMappingURL=types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/content-types/types.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/content-types/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,CAAU,CAAC;AAErG;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,GAAG,yBAAyB,EAAE,UAAU,CAAU,CAAC;AAIzF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,MAAM,CAAU,CAAC;AAI1D;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG;IACtC,GAAG,qBAAqB;IACxB,GAAG,wBAAwB;CACnB,CAAC;AAIX;;;;;;;;;;GAUG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,wBAA8C,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACtG,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAc;IACjD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAK,qBAA2C,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACnG,CAAC"}
|
|
@@ -10,8 +10,12 @@ import { type ActorIdentityInput, type ActorPrincipalKind, type ContentTypeField
|
|
|
10
10
|
* same-transaction row + revision write (+ watermark stamp when supplied) -> index provisioning.
|
|
11
11
|
*
|
|
12
12
|
* `registerContentType`'s CIC U-002-B1 guard order is binding, not incidental: key grammar ->
|
|
13
|
-
* reserved-key -> field-name grammar -> field-kind -> queryable-cap,
|
|
14
|
-
* first failure.
|
|
13
|
+
* reserved-key -> field-name grammar -> field-kind -> storage-only-not-queryable -> queryable-cap,
|
|
14
|
+
* evaluation stops at the first failure. The storage-only check is numbered 4b rather than
|
|
15
|
+
* renumbering 5, because the fixed order is pinned by name in the certified suite and the existing
|
|
16
|
+
* five guards keep both their relative order and their identity: 4b sits strictly between the
|
|
17
|
+
* field-kind check and the queryable-cap check, and can only fire on a field whose kind already
|
|
18
|
+
* passed guard 4. `updateContentTypeFields`'s CIC U-004-B1 additionally requires `expectedVersion`
|
|
15
19
|
* to be checked BEFORE the `fields_empty` floor and before any per-field guard, so a stale
|
|
16
20
|
* `expectedVersion` combined with `fields: []` reports `VERSION_CONFLICT`, never
|
|
17
21
|
* `VALIDATION_ERROR(fields_empty)`.
|
|
@@ -26,11 +30,22 @@ import { type ActorIdentityInput, type ActorPrincipalKind, type ContentTypeField
|
|
|
26
30
|
* `features/content-types` domain logic. Depends only on `core/ports` and this package's own
|
|
27
31
|
* `errors.ts`/`index-provisioning.ts`/`types.ts` — no adapter, no other feature.
|
|
28
32
|
*/
|
|
29
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Matches every other feature's chokepoint `AuthorizeFn` shape structurally — no shared import,
|
|
35
|
+
* kept decoupled. `entityType`/`entityId` let `registerContentType`/`updateContentTypeFields`
|
|
36
|
+
* (and `lifecycle.ts`'s three transitions, which import this same type) pass
|
|
37
|
+
* `entityType: "content-type"` — matching every fronting HTTP route's own
|
|
38
|
+
* `entityType: "content-type"` pre-check. See `entries/write-service.ts`'s identical `AuthorizeFn`
|
|
39
|
+
* doc for why an omitted `entityType` here previously denied a content-type-scoped-only grant with
|
|
40
|
+
* `resource_scope_mismatch` even though the route's pre-check allowed it, and why this chokepoint —
|
|
41
|
+
* not the route — is the one that must stay at least as expressive.
|
|
42
|
+
*/
|
|
30
43
|
export type AuthorizeFn = (params: {
|
|
31
44
|
principalId: string;
|
|
32
45
|
permission: string;
|
|
33
46
|
workspaceId: string;
|
|
47
|
+
entityType?: string | undefined;
|
|
48
|
+
entityId?: string | undefined;
|
|
34
49
|
}) => Promise<{
|
|
35
50
|
allowed: boolean;
|
|
36
51
|
reason: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-service.d.ts","sourceRoot":"","sources":["../../src/content-types/write-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"write-service.d.ts","sourceRoot":"","sources":["../../src/content-types/write-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ContentTypeNotFoundError, ForbiddenError, InvalidFieldKindError, InvalidFieldNameGrammarError, InvalidKeyGrammarError, QueryableFieldCapExceededError, ReservedContentTypeKeyError, ValidationError, VersionConflictError, } from "./errors.js";
|
|
1
|
+
import { ContentTypeNotFoundError, ForbiddenError, InvalidFieldKindError, InvalidFieldNameGrammarError, InvalidKeyGrammarError, QueryableFieldCapExceededError, ReservedContentTypeKeyError, StorageOnlyFieldNotQueryableError, ValidationError, VersionConflictError, } from "./errors.js";
|
|
2
2
|
import { resolveFieldIndexTransition, validateIdentifierGrammar } from "./index-provisioning.js";
|
|
3
|
-
import { isContentTypeFieldKind, } from "./types.js";
|
|
3
|
+
import { isContentTypeFieldKind, isIndexableFieldKind, } from "./types.js";
|
|
4
4
|
/** Reserved forever for the legacy `posts` table — an operator Collection can never take these keys. */
|
|
5
5
|
const RESERVED_CONTENT_TYPE_KEYS = new Set(["post", "page"]);
|
|
6
6
|
/** Per-type cap on `queryable` fields (queryable-index sprawl mitigation). */
|
|
@@ -21,6 +21,7 @@ export async function registerContentType(required) {
|
|
|
21
21
|
principalId: input.actorId,
|
|
22
22
|
permission: "admin.collections.manage",
|
|
23
23
|
workspaceId: input.workspaceId,
|
|
24
|
+
entityType: "content-type",
|
|
24
25
|
});
|
|
25
26
|
if (!authResult.allowed) {
|
|
26
27
|
return { ok: false, error: new ForbiddenError(`principal '${input.actorId}' cannot register a content type (${authResult.reason})`) };
|
|
@@ -45,6 +46,18 @@ export async function registerContentType(required) {
|
|
|
45
46
|
return { ok: false, error: new InvalidFieldKindError(`field '${field.name}' has kind '${field.kind}', not one of the closed field-kind enum`) };
|
|
46
47
|
}
|
|
47
48
|
}
|
|
49
|
+
// Guard 4b: a storage-only kind cannot be queryable. Placed strictly between guard 4 and guard 5
|
|
50
|
+
// so a bad kind still reports as a kind error, and a legal-but-unindexable kind is rejected
|
|
51
|
+
// BEFORE the cap count and long before `resolveFieldIndexTransition` could hand it to the index
|
|
52
|
+
// provisioner. This is the check that keeps a kind with no CAST target off the DDL path.
|
|
53
|
+
for (const field of input.fields) {
|
|
54
|
+
if (field.queryable && !isIndexableFieldKind(field.kind)) {
|
|
55
|
+
return {
|
|
56
|
+
ok: false,
|
|
57
|
+
error: new StorageOnlyFieldNotQueryableError(`field '${field.name}' has storage-only kind '${field.kind}' and cannot be queryable`),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
48
61
|
// Guard 5: queryable-field cap, submitted array alone.
|
|
49
62
|
if (countQueryableFields(input.fields) > QUERYABLE_FIELD_CAP) {
|
|
50
63
|
return { ok: false, error: new QueryableFieldCapExceededError(`content type '${input.key}' submits more than ${QUERYABLE_FIELD_CAP} queryable fields`) };
|
|
@@ -96,6 +109,7 @@ export async function updateContentTypeFields(required) {
|
|
|
96
109
|
principalId: input.actorId,
|
|
97
110
|
permission: "admin.collections.manage",
|
|
98
111
|
workspaceId: input.workspaceId,
|
|
112
|
+
entityType: "content-type",
|
|
99
113
|
});
|
|
100
114
|
if (!authResult.allowed) {
|
|
101
115
|
return { ok: false, error: new ForbiddenError(`principal '${input.actorId}' cannot update content type '${input.key}' (${authResult.reason})`) };
|
|
@@ -121,6 +135,18 @@ export async function updateContentTypeFields(required) {
|
|
|
121
135
|
return { ok: false, error: new InvalidFieldKindError(`field '${field.name}' has kind '${field.kind}', not one of the closed field-kind enum`) };
|
|
122
136
|
}
|
|
123
137
|
}
|
|
138
|
+
// Guard 4b: a storage-only kind cannot be queryable. Placed strictly between guard 4 and guard 5
|
|
139
|
+
// so a bad kind still reports as a kind error, and a legal-but-unindexable kind is rejected
|
|
140
|
+
// BEFORE the cap count and long before `resolveFieldIndexTransition` could hand it to the index
|
|
141
|
+
// provisioner. This is the check that keeps a kind with no CAST target off the DDL path.
|
|
142
|
+
for (const field of input.fields) {
|
|
143
|
+
if (field.queryable && !isIndexableFieldKind(field.kind)) {
|
|
144
|
+
return {
|
|
145
|
+
ok: false,
|
|
146
|
+
error: new StorageOnlyFieldNotQueryableError(`field '${field.name}' has storage-only kind '${field.kind}' and cannot be queryable`),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
}
|
|
124
150
|
if (countQueryableFields(input.fields) > QUERYABLE_FIELD_CAP) {
|
|
125
151
|
return { ok: false, error: new QueryableFieldCapExceededError(`content type '${input.key}' submits more than ${QUERYABLE_FIELD_CAP} queryable fields`) };
|
|
126
152
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-service.js","sourceRoot":"","sources":["../../src/content-types/write-service.ts"],"names":[],"mappings":"AACA,OAAO,EACL,wBAAwB,EACxB,cAAc,EACd,qBAAqB,EACrB,4BAA4B,EAC5B,sBAAsB,EACtB,8BAA8B,EAC9B,2BAA2B,EAC3B,eAAe,EACf,oBAAoB,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,2BAA2B,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AACjG,OAAO,EAML,sBAAsB,
|
|
1
|
+
{"version":3,"file":"write-service.js","sourceRoot":"","sources":["../../src/content-types/write-service.ts"],"names":[],"mappings":"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"}
|
package/dist/core/ports.d.ts
CHANGED
|
@@ -123,8 +123,18 @@ export interface OutboxPort {
|
|
|
123
123
|
claimPending(batchSize: number, nowIso: ISODateTime): Promise<OutboxRecord[]>;
|
|
124
124
|
/** Mark a row as delivered. */
|
|
125
125
|
markDelivered(id: UUID): Promise<void>;
|
|
126
|
-
/**
|
|
127
|
-
|
|
126
|
+
/**
|
|
127
|
+
* Mark a row as failed and set its next retry time.
|
|
128
|
+
*
|
|
129
|
+
* `nextStatus` is decided by the CALLER (the retry-policy owner, e.g. a worker that tracks an
|
|
130
|
+
* attempt cap) — an implementation must persist exactly what it is told, not re-derive the
|
|
131
|
+
* decision from the row's own stored `attempts` (2026-09-06: this parameter replaced that
|
|
132
|
+
* adapter-side re-derivation, mirroring `WebhookDeliveryRepoPort.markFailed`'s `nextStatus`
|
|
133
|
+
* shape in the Tovu host). `"pending"` re-enters the retry queue at `nextAttemptAt`; `"failed"`
|
|
134
|
+
* is terminal — `claimPending` only ever selects `"pending"` rows, so a `"failed"` row is
|
|
135
|
+
* permanently excluded from retry regardless of `nextAttemptAt`.
|
|
136
|
+
*/
|
|
137
|
+
markFailed(id: UUID, error: string, nextAttemptAt: ISODateTime, nextStatus: Extract<OutboxRecord["status"], "pending" | "failed">): Promise<void>;
|
|
128
138
|
}
|
|
129
139
|
/** Clock abstraction to make time deterministic in tests. */
|
|
130
140
|
export interface ClockPort {
|
package/dist/core/ports.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/core/ports.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../src/core/ports.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-validation.d.ts","sourceRoot":"","sources":["../../src/entries/field-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAwB,MAAM,2BAA2B,CAAC;AAE3F;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;
|
|
1
|
+
{"version":3,"file":"field-validation.d.ts","sourceRoot":"","sources":["../../src/entries/field-validation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAwB,MAAM,2BAA2B,CAAC;AAE3F;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,OAAO,CAAC;IACf,WAAW,EAAE,oBAAoB,EAAE,CAAC;CACrC;AA6HD;;;;;;;GAOG;AACH,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE;IACpD,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,UAAU,EAAE,OAAO,CAAC;IACpB,sLAAsL;IACtL,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,GAAG,oBAAoB,CAiCvB;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE;IACjD,KAAK,EAAE;QAAE,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/B,WAAW,EAAE;QAAE,MAAM,EAAE,mBAAmB,EAAE,CAAA;KAAE,CAAC;CAChD,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAY1B"}
|
|
@@ -1,18 +1,109 @@
|
|
|
1
1
|
function isPlainObject(value) {
|
|
2
2
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
3
|
}
|
|
4
|
+
/**
|
|
5
|
+
* Maximum nesting depth a `json` field's value may reach.
|
|
6
|
+
*
|
|
7
|
+
* A resource bound, not a product rule — the same role `MAX_FIELD_DEFS` plays in
|
|
8
|
+
* `content-types/field-defs.ts`. It is also what makes this check total: a self-referential value
|
|
9
|
+
* (`a.self = a`) is a legal JS object that `JSON.stringify` throws on, and it is the depth cap,
|
|
10
|
+
* not a visited-set, that guarantees this function terminates on one. Deliberately far above any
|
|
11
|
+
* plausible content payload so it can never act as a product constraint.
|
|
12
|
+
*/
|
|
13
|
+
const MAX_JSON_DEPTH = 32;
|
|
14
|
+
/**
|
|
15
|
+
* Maximum number of values (scalars, arrays and objects, counted together) one `json` field may
|
|
16
|
+
* contain. The second half of the termination guarantee above, and the bound that stops a
|
|
17
|
+
* pathological wide-but-shallow payload from making validation the expensive part of a write.
|
|
18
|
+
*/
|
|
19
|
+
const MAX_JSON_NODES = 10_000;
|
|
20
|
+
/**
|
|
21
|
+
* True only for objects that are structurally plain — prototype `Object.prototype` or `null`.
|
|
22
|
+
*
|
|
23
|
+
* Stricter than this module's {@link isPlainObject}, and deliberately so: a `Map`, `Set`, or class
|
|
24
|
+
* instance passes a `typeof === "object"` test and then `JSON.stringify`s to `{}`, silently
|
|
25
|
+
* discarding every value it held. A `Date` survives, but as a string — its type changes at the
|
|
26
|
+
* storage boundary, so a later read gets a different kind of value than the one written. Both are
|
|
27
|
+
* exactly the "accepted here, mangled downstream" class this check exists to reject.
|
|
28
|
+
*/
|
|
29
|
+
function isStructurallyPlainObject(value) {
|
|
30
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
31
|
+
return false;
|
|
32
|
+
const proto = Object.getPrototypeOf(value);
|
|
33
|
+
return proto === Object.prototype || proto === null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Verifies that a value is a JSON value — `null`, a boolean, a FINITE number, a string, an array
|
|
37
|
+
* of JSON values, or a plain object whose values are JSON values — within a bounded depth and node
|
|
38
|
+
* budget.
|
|
39
|
+
*
|
|
40
|
+
* This exists because "storage-only" means "not indexed", never "not checked". The obvious
|
|
41
|
+
* alternative — accepting every value for the `json` kind — is not a validator: it admits
|
|
42
|
+
* functions, `symbol`, `bigint`, `undefined`, `NaN`/`Infinity`, and circular references, each of
|
|
43
|
+
* which either throws inside `JSON.stringify` or is silently dropped/coerced by it, downstream of
|
|
44
|
+
* the validator whose entire job was to catch them. Rejecting them here turns a serialization
|
|
45
|
+
* crash (or a silent data loss) at the storage boundary into a named per-field validation error.
|
|
46
|
+
*
|
|
47
|
+
* Symbol-keyed properties are rejected rather than ignored for the same reason `field-defs.ts`
|
|
48
|
+
* rejects an unrecognized key instead of dropping it: `JSON.stringify` discards them, so accepting
|
|
49
|
+
* one would persist a value the caller did not get told was thrown away.
|
|
50
|
+
*
|
|
51
|
+
* @complexity O(n) in the number of contained values, hard-bounded by {@link MAX_JSON_NODES}, and
|
|
52
|
+
* O(d) stack depth bounded by {@link MAX_JSON_DEPTH}. Total on every input, including cyclic ones.
|
|
53
|
+
* @overallScore 100
|
|
54
|
+
*/
|
|
55
|
+
function isBoundedJsonValue(value, budget, depth = 0) {
|
|
56
|
+
if (depth > MAX_JSON_DEPTH)
|
|
57
|
+
return false;
|
|
58
|
+
if (budget.nodes <= 0)
|
|
59
|
+
return false;
|
|
60
|
+
budget.nodes -= 1;
|
|
61
|
+
if (value === null)
|
|
62
|
+
return true;
|
|
63
|
+
switch (typeof value) {
|
|
64
|
+
case "boolean":
|
|
65
|
+
case "string":
|
|
66
|
+
return true;
|
|
67
|
+
case "number":
|
|
68
|
+
// `NaN`/`Infinity` are numbers that `JSON.stringify` silently rewrites to `null` — a value
|
|
69
|
+
// that reads back as a different type than the one written.
|
|
70
|
+
return Number.isFinite(value);
|
|
71
|
+
case "object":
|
|
72
|
+
break;
|
|
73
|
+
default:
|
|
74
|
+
// `undefined`, `function`, `symbol`, `bigint`: dropped, dropped, dropped, and throws.
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(value)) {
|
|
78
|
+
return value.every((element) => isBoundedJsonValue(element, budget, depth + 1));
|
|
79
|
+
}
|
|
80
|
+
if (!isStructurallyPlainObject(value))
|
|
81
|
+
return false;
|
|
82
|
+
if (Object.getOwnPropertySymbols(value).length > 0)
|
|
83
|
+
return false;
|
|
84
|
+
return Object.values(value).every((entry) => isBoundedJsonValue(entry, budget, depth + 1));
|
|
85
|
+
}
|
|
4
86
|
/**
|
|
5
87
|
* Runtime-conformance check for one field's value against its declared kind. Loose by design
|
|
6
88
|
* (e.g. `datetime` accepts any string) — kind-conformance here is about JS runtime shape, not
|
|
7
89
|
* full ISO-8601/format validation, which is out of this package's scope.
|
|
8
90
|
*
|
|
9
|
-
*
|
|
91
|
+
* The `default: return false` arm is load-bearing: a kind added to `ContentTypeFieldKind` without
|
|
92
|
+
* an arm here does not fail the build, it produces a field that can be DECLARED but whose every
|
|
93
|
+
* value is rejected on write. Any future kind must be added here in the same change.
|
|
94
|
+
*
|
|
95
|
+
* @complexity O(1) for every scalar kind; O(n) bounded by `MAX_JSON_NODES` for `json`.
|
|
10
96
|
* @overallScore 100
|
|
11
97
|
*/
|
|
12
98
|
function conformsToKind(value, kind) {
|
|
13
99
|
switch (kind) {
|
|
14
100
|
case "text":
|
|
15
101
|
case "datetime":
|
|
102
|
+
// A foreign entity id. String-shaped exactly like `text`; referential integrity is NOT checked
|
|
103
|
+
// here and is not checked anywhere — this function is a pure runtime-shape check with no repo
|
|
104
|
+
// access, and giving it one would put an I/O dependency into a module whose header commits to
|
|
105
|
+
// having none. The gap is real and belongs to the application layer.
|
|
106
|
+
case "relation":
|
|
16
107
|
return typeof value === "string";
|
|
17
108
|
case "integer":
|
|
18
109
|
return typeof value === "number" && Number.isInteger(value);
|
|
@@ -20,6 +111,10 @@ function conformsToKind(value, kind) {
|
|
|
20
111
|
return typeof value === "number";
|
|
21
112
|
case "boolean":
|
|
22
113
|
return typeof value === "boolean";
|
|
114
|
+
// Storage-only: no scalar shape is imposed, but the value must still be something that
|
|
115
|
+
// survives the `JSON.stringify` boundary intact. See `isBoundedJsonValue`.
|
|
116
|
+
case "json":
|
|
117
|
+
return isBoundedJsonValue(value, { nodes: MAX_JSON_NODES });
|
|
23
118
|
default:
|
|
24
119
|
return false;
|
|
25
120
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-validation.js","sourceRoot":"","sources":["../../src/entries/field-validation.ts"],"names":[],"mappings":"AA0CA,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"field-validation.js","sourceRoot":"","sources":["../../src/entries/field-validation.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,10 +26,24 @@ import type { ActorIdentityInput, EntryRecord, OwningContentType, Result } from
|
|
|
26
26
|
* `errors.ts`/`field-validation.ts`/`types.ts` — never on `features/content-types`' write path,
|
|
27
27
|
* only its read-only `OwningContentType` type shape.
|
|
28
28
|
*/
|
|
29
|
+
/**
|
|
30
|
+
* `entityType`/`entityId` are threaded through so `createEntry`/`resolveExistingEntryForTransition`
|
|
31
|
+
* below can pass `entityType: "entry"` to `deps.authorize()` — matching every fronting HTTP route's
|
|
32
|
+
* own `entityType: "entry"` pre-check exactly. Before this, this chokepoint's calls omitted
|
|
33
|
+
* `entityType` entirely, so `identity/authorize.ts`'s evaluator (`resourceType != null &&
|
|
34
|
+
* resourceType !== context.entityType` never matches a missing `entityType`) denied a principal
|
|
35
|
+
* holding ONLY an entry-scoped grant with `resource_scope_mismatch`, even though the route's own
|
|
36
|
+
* pre-check — and any owner/unscoped grant — allowed the identical request. This chokepoint is also
|
|
37
|
+
* the ONLY authorization check the agent-tool surface ever reaches (see `agent-tools.ts`'s header:
|
|
38
|
+
* tools call these functions directly, never through an HTTP route), so it must be at least as
|
|
39
|
+
* expressive as the route, not merely consistent with it.
|
|
40
|
+
*/
|
|
29
41
|
export type AuthorizeFn = (params: {
|
|
30
42
|
principalId: string;
|
|
31
43
|
permission: string;
|
|
32
44
|
workspaceId: string;
|
|
45
|
+
entityType?: string | undefined;
|
|
46
|
+
entityId?: string | undefined;
|
|
33
47
|
}) => Promise<{
|
|
34
48
|
allowed: boolean;
|
|
35
49
|
reason: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-service.d.ts","sourceRoot":"","sources":["../../src/entries/write-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAWlD,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAE7F;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"write-service.d.ts","sourceRoot":"","sources":["../../src/entries/write-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,7 +19,7 @@ function delegationFields(input) {
|
|
|
19
19
|
*/
|
|
20
20
|
export async function createEntry(required) {
|
|
21
21
|
const { deps, input } = required;
|
|
22
|
-
const authResult = await deps.authorize({ principalId: input.actorId, permission: "admin.collections.manage", workspaceId: input.workspaceId });
|
|
22
|
+
const authResult = await deps.authorize({ principalId: input.actorId, permission: "admin.collections.manage", workspaceId: input.workspaceId, entityType: "entry" });
|
|
23
23
|
if (!authResult.allowed) {
|
|
24
24
|
return { ok: false, error: new ForbiddenError(`principal '${input.actorId}' cannot create an entry (${authResult.reason})`) };
|
|
25
25
|
}
|
|
@@ -82,7 +82,7 @@ export async function createEntry(required) {
|
|
|
82
82
|
* @overallScore 100
|
|
83
83
|
*/
|
|
84
84
|
async function resolveExistingEntryForTransition(deps, input) {
|
|
85
|
-
const authResult = await deps.authorize({ principalId: input.actorId, permission: "admin.collections.manage", workspaceId: input.workspaceId });
|
|
85
|
+
const authResult = await deps.authorize({ principalId: input.actorId, permission: "admin.collections.manage", workspaceId: input.workspaceId, entityType: "entry" });
|
|
86
86
|
if (!authResult.allowed) {
|
|
87
87
|
return { ok: false, error: new ForbiddenError(`principal '${input.actorId}' cannot modify entry '${input.id}' (${authResult.reason})`) };
|
|
88
88
|
}
|