@cosmicdrift/kumiko-guards 0.399.0 → 0.401.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.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-guards",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.401.0",
|
|
4
4
|
"description": "AST-based security guards for Kumiko repos: direct-fs/fetch, tenant escalation, admin-API, escape hatches and related checks, run over a shared ts-morph project.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"kumiko-pre-push": "./src/pre-push.sh"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@cosmicdrift/kumiko-types": "0.
|
|
39
|
+
"@cosmicdrift/kumiko-types": "0.401.0",
|
|
40
40
|
"ts-morph": "^28.0.0",
|
|
41
41
|
"zod": "^4.6.7"
|
|
42
42
|
},
|
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
"LICENSE"
|
|
53
53
|
],
|
|
54
54
|
"peerDependencies": {
|
|
55
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
55
|
+
"@cosmicdrift/kumiko-framework": "0.401.0"
|
|
56
56
|
},
|
|
57
57
|
"peerDependenciesMeta": {
|
|
58
58
|
"@cosmicdrift/kumiko-framework": {
|
|
@@ -60,6 +60,6 @@
|
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@cosmicdrift/kumiko-framework": "0.
|
|
63
|
+
"@cosmicdrift/kumiko-framework": "0.401.0"
|
|
64
64
|
}
|
|
65
65
|
}
|
|
@@ -48,6 +48,14 @@ function stringLiteralValue(obj: ObjectLiteralExpression, name: string): string
|
|
|
48
48
|
return init?.isKind(SyntaxKind.StringLiteral) ? init.getLiteralValue() : undefined;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
function booleanLiteralValue(obj: ObjectLiteralExpression, name: string): boolean | undefined {
|
|
52
|
+
const prop = obj.getProperty(name);
|
|
53
|
+
if (!prop?.isKind(SyntaxKind.PropertyAssignment)) return undefined;
|
|
54
|
+
const init = prop.getInitializer();
|
|
55
|
+
if (init?.isKind(SyntaxKind.TrueKeyword)) return true;
|
|
56
|
+
return init?.isKind(SyntaxKind.FalseKeyword) ? false : undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
51
59
|
function hasDeclaredProperty(obj: ObjectLiteralExpression, name: string): boolean {
|
|
52
60
|
const prop = obj.getProperty(name);
|
|
53
61
|
if (!prop?.isKind(SyntaxKind.PropertyAssignment)) return false;
|
|
@@ -55,7 +63,7 @@ function hasDeclaredProperty(obj: ObjectLiteralExpression, name: string): boolea
|
|
|
55
63
|
return init !== undefined && init.getKind() !== SyntaxKind.UndefinedKeyword;
|
|
56
64
|
}
|
|
57
65
|
|
|
58
|
-
// R2: a relatedList section with neither rowClick nor
|
|
66
|
+
// R2: a relatedList section with neither rowClick, rowActions nor readOnly renders a
|
|
59
67
|
// list nobody can act on.
|
|
60
68
|
function checkRelatedListSections(
|
|
61
69
|
root: ObjectLiteralExpression,
|
|
@@ -65,6 +73,7 @@ function checkRelatedListSections(
|
|
|
65
73
|
for (const obj of root.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)) {
|
|
66
74
|
if (stringLiteralValue(obj, "kind") !== "relatedList") continue;
|
|
67
75
|
if (hasIgnoreTag(obj, IGNORE_TAG)) continue;
|
|
76
|
+
if (booleanLiteralValue(obj, "readOnly") === true) continue;
|
|
68
77
|
if (hasDeclaredProperty(obj, "rowClick") || hasDeclaredProperty(obj, "rowActions")) continue;
|
|
69
78
|
violations.push({
|
|
70
79
|
file: sf.getFilePath(),
|
|
@@ -107,7 +116,7 @@ export const guard: AstGuard = {
|
|
|
107
116
|
name: "Screen-Conventions Guard",
|
|
108
117
|
scan: SCAN,
|
|
109
118
|
hint:
|
|
110
|
-
"relatedList sections need `rowClick` or `
|
|
119
|
+
"relatedList sections need `rowClick`, `rowActions` or `readOnly: true`; a rowAction label " +
|
|
111
120
|
'must not end in ".action.edit" ' +
|
|
112
121
|
'when the `id` is not "edit". ' +
|
|
113
122
|
`Justified exception: // ${IGNORE_TAG} <reason>`,
|